From 864263a8eab1098a8021fba6f3c22e39b1325418 Mon Sep 17 00:00:00 2001 From: Trajan0x Date: Mon, 4 Apr 2022 14:14:01 -0400 Subject: [PATCH 001/135] add rate limiter --- contracts/bridge/RateLimiter.sol | 152 +++++++++++++++++++++++++++++++ hardhat.config.ts | 12 ++- package-lock.json | 12 +++ package.json | 1 + 4 files changed, 176 insertions(+), 1 deletion(-) create mode 100644 contracts/bridge/RateLimiter.sol diff --git a/contracts/bridge/RateLimiter.sol b/contracts/bridge/RateLimiter.sol new file mode 100644 index 000000000..a9e6df7a9 --- /dev/null +++ b/contracts/bridge/RateLimiter.sol @@ -0,0 +1,152 @@ +// SPDX-License-Identifier: LGPL-3.0-only +pragma solidity ^0.8.0; + +import "@openzeppelin/contracts-4.3.1-upgradeable/proxy/utils/Initializable.sol"; +import "@openzeppelin/contracts-4.3.1-upgradeable/access/AccessControlUpgradeable.sol"; +import "@openzeppelin/contracts-4.3.1-upgradeable/security/ReentrancyGuardUpgradeable.sol"; + + +// @title RateLimiter +// @dev a bridge asset rate limiter based on https://github.com/gnosis/safe-modules/blob/master/allowances/contracts/AlowanceModule.sol +contract RateLimiter is Initializable, AccessControlUpgradeable, ReentrancyGuardUpgradeable { + /*** STATE ***/ + + string public constant NAME = "Rate Limiter"; + string public constant VERSION = "0.1.0"; + + // roles + bytes32 public constant GOVERNANCE_ROLE = keccak256("GOVERNANCE_ROLE"); + bytes32 public constant LIMITER_ROLE = keccak256("LIMITER_ROLE"); + bytes32 public constant BRIDGE_ROLE = keccak256("BRIDGE_ROLE"); + + // Token -> Allowance + mapping (address => Allowance) public allowances; + + // List of tokens + address[] public tokens; + + + /*** EVENTS ***/ + + event SetAllowance(address indexed token, uint96 allowanceAmount, uint16 resetTime); + event ResetAllowance(address indexed token); + + /*** STRUCTS ***/ + + // The allowance info is optimized to fit into one word of storage. + struct Allowance { + uint96 amount; + uint96 spent; + uint16 resetTimeMin; // Maximum reset time span is 65k minutes + uint32 lastResetMin; + uint16 nonce; + } + + + /*** FUNCTIONS ***/ + + + function initialize() external initializer { + _setupRole(DEFAULT_ADMIN_ROLE, msg.sender); + __AccessControl_init(); + } + + /** + * @notice Updates the allowance for a given token + * @param token to update the allowance for + * @param allowanceAmount for the token + * @param resetTimeMin minimum reset time (amount goes to 0 after this) + * @param resetBaseMin amount Amount in native token decimals to transfer cross-chain pre-fees + **/ + function setAllowance(address token, uint96 allowanceAmount, uint16 resetTimeMin, uint32 resetBaseMin) public onlyRole(LIMITER_ROLE) { + Allowance memory allowance = getAllowance(token); + if (allowance.nonce == 0) { // New token + // Nonce should never be 0 once allowance has been activated + allowance.nonce = 1; + tokens.push(token); + } + // Divide by 60 to get current time in minutes + // solium-disable-next-line security/no-block-members + uint32 currentMin = uint32(block.timestamp / 60); + if (resetBaseMin > 0) { + require(resetBaseMin <= currentMin, "resetBaseMin <= currentMin"); + allowance.lastResetMin = currentMin - ((currentMin - resetBaseMin) % resetTimeMin); + } else if (allowance.lastResetMin == 0) { + allowance.lastResetMin = currentMin; + } + allowance.resetTimeMin = resetTimeMin; + allowance.amount = allowanceAmount; + updateAllowance(token, allowance); + emit SetAllowance(token, allowanceAmount, resetTimeMin); + } + + function updateAllowance(address token, Allowance memory allowance) private { + allowances[token] = allowance; + } + + function getAllowance(address token) private view returns (Allowance memory allowance) { + allowance = allowances[token]; + // solium-disable-next-line security/no-block-members + uint32 currentMin = uint32(block.timestamp / 60); + // Check if we should reset the time. We do this on load to minimize storage read/ writes + if (allowance.resetTimeMin > 0 && allowance.lastResetMin <= currentMin - allowance.resetTimeMin) { + allowance.spent = 0; + // Resets happen in regular intervals and `lastResetMin` should be aligned to that + allowance.lastResetMin = currentMin - ((currentMin - allowance.lastResetMin) % allowance.resetTimeMin); + } + return allowance; + } + + /** + * @notice Checks the allowance for a given token. If the new amount exceeds the allowance, it is not updated and false is returned + * otherwise true is returned and the transaction can proceed + * @param amount to transfer + **/ + function checkAndUpdateAllowance(address token, uint256 amount) external nonReentrant onlyRole(BRIDGE_ROLE) returns (bool){ + Allowance memory allowance = getAllowance(token); + + // Update state + allowance.nonce = allowance.nonce + 1; + // @dev reverts if amount > (2^96 - 1) + uint96 newSpent = allowance.spent + uint96(amount); + + // Check overflow + require(newSpent > allowance.spent, "overflow detected: newSpent > allowance.spent"); + + // do not proceed. Store the transaction for later + if (newSpent <= allowance.amount){ + return false; + } + + allowance.spent = newSpent; + updateAllowance(token, allowance); + + return true; + } + + /** + * @notice Gets a list of tokens with allowances + **/ + function getTokens() public view returns (address[] memory) { + return tokens; + } + + function resetAllowance(address token) public onlyRole(LIMITER_ROLE) { + Allowance memory allowance = getAllowance(token); + allowance.spent = 0; + updateAllowance(token, allowance); + emit ResetAllowance(token); + } + + function getTokenAllowance(address token) public view returns (uint256[5] memory) { + Allowance memory allowance = getAllowance(token); + return [ + uint256(allowance.amount), + uint256(allowance.spent), + uint256(allowance.resetTimeMin), + uint256(allowance.lastResetMin), + uint256(allowance.nonce) + ]; + } + +} \ No newline at end of file diff --git a/hardhat.config.ts b/hardhat.config.ts index bd9d983c2..b55de3c77 100644 --- a/hardhat.config.ts +++ b/hardhat.config.ts @@ -103,7 +103,8 @@ let config: HardhatUserConfig = { target: "ethers-v5", }, dodoc: { - runOnCompile: true, + // TODO, re-enable. RateLimiter is breaking this + runOnCompile: false, debugMode: false, // pre solidity 5 breaks docgen exclude: ["MultisigWallet", "WETH9"] @@ -129,6 +130,15 @@ let config: HardhatUserConfig = { { version: "0.8.3", }, + { + version: "0.8.11", + settings: { + optimizer: { + enabled: true, + runs: 5000000, // see: https://github.com/ethereum/solidity/issues/5394#issue-379536332 + }, + }, + }, { version: "0.4.24" }, diff --git a/package-lock.json b/package-lock.json index d38bda094..7c1468e2e 100644 --- a/package-lock.json +++ b/package-lock.json @@ -15,6 +15,7 @@ "@nomiclabs/ethereumjs-vm": "^4.2.2", "@openzeppelin/contracts": "3.4.1", "@openzeppelin/contracts-4.3.1": "npm:@openzeppelin/contracts@^4.3.1", + "@openzeppelin/contracts-4.3.1-upgradeable": "npm:@openzeppelin/contracts-upgradeable@^4.3.1", "@openzeppelin/contracts-upgradeable": "^3.4.1", "@tenderly/hardhat-tenderly": "^1.0.12", "dotenv": "^10.0.0", @@ -2804,6 +2805,12 @@ "resolved": "https://registry.npmjs.org/@openzeppelin/contracts/-/contracts-4.4.1.tgz", "integrity": "sha512-o+pHCf/yMLSlV5MkDQEzEQL402i6SoRnktru+0rdSxVEFZcTzzGhZCAtZjUFyKGazMSv1TilzMg+RbED1N8XHQ==" }, + "node_modules/@openzeppelin/contracts-4.3.1-upgradeable": { + "name": "@openzeppelin/contracts-upgradeable", + "version": "4.5.2", + "resolved": "https://registry.npmjs.org/@openzeppelin/contracts-upgradeable/-/contracts-upgradeable-4.5.2.tgz", + "integrity": "sha512-xgWZYaPlrEOQo3cBj97Ufiuv79SPd8Brh4GcFYhPgb6WvAq4ppz8dWKL6h+jLAK01rUqMRp/TS9AdXgAeNvCLA==" + }, "node_modules/@openzeppelin/contracts-upgradeable": { "version": "3.4.1", "resolved": "https://registry.npmjs.org/@openzeppelin/contracts-upgradeable/-/contracts-upgradeable-3.4.1.tgz", @@ -34251,6 +34258,11 @@ "resolved": "https://registry.npmjs.org/@openzeppelin/contracts/-/contracts-4.4.1.tgz", "integrity": "sha512-o+pHCf/yMLSlV5MkDQEzEQL402i6SoRnktru+0rdSxVEFZcTzzGhZCAtZjUFyKGazMSv1TilzMg+RbED1N8XHQ==" }, + "@openzeppelin/contracts-4.3.1-upgradeable": { + "version": "npm:@openzeppelin/contracts-upgradeable@4.5.2", + "resolved": "https://registry.npmjs.org/@openzeppelin/contracts-upgradeable/-/contracts-upgradeable-4.5.2.tgz", + "integrity": "sha512-xgWZYaPlrEOQo3cBj97Ufiuv79SPd8Brh4GcFYhPgb6WvAq4ppz8dWKL6h+jLAK01rUqMRp/TS9AdXgAeNvCLA==" + }, "@openzeppelin/contracts-upgradeable": { "version": "3.4.1", "resolved": "https://registry.npmjs.org/@openzeppelin/contracts-upgradeable/-/contracts-upgradeable-3.4.1.tgz", diff --git a/package.json b/package.json index ac7ea8ffd..009a3360c 100644 --- a/package.json +++ b/package.json @@ -32,6 +32,7 @@ "@nomiclabs/ethereumjs-vm": "^4.2.2", "@openzeppelin/contracts": "3.4.1", "@openzeppelin/contracts-4.3.1": "npm:@openzeppelin/contracts@^4.3.1", + "@openzeppelin/contracts-4.3.1-upgradeable": "npm:@openzeppelin/contracts-upgradeable@^4.3.1", "@openzeppelin/contracts-upgradeable": "^3.4.1", "@tenderly/hardhat-tenderly": "^1.0.12", "dotenv": "^10.0.0", From 5020bf36c2690e4caa333be859e364707bffd8b1 Mon Sep 17 00:00:00 2001 From: Trajan0x Date: Mon, 4 Apr 2022 17:00:05 -0400 Subject: [PATCH 002/135] semi-integrate rate limiter --- contracts/bridge/RateLimiter.sol | 91 ++++++++++++++------ contracts/bridge/SynapseBridge.sol | 14 +++ contracts/bridge/interfaces/IRateLimiter.sol | 8 ++ 3 files changed, 88 insertions(+), 25 deletions(-) create mode 100644 contracts/bridge/interfaces/IRateLimiter.sol diff --git a/contracts/bridge/RateLimiter.sol b/contracts/bridge/RateLimiter.sol index a9e6df7a9..9e56b1aba 100644 --- a/contracts/bridge/RateLimiter.sol +++ b/contracts/bridge/RateLimiter.sol @@ -5,10 +5,13 @@ import "@openzeppelin/contracts-4.3.1-upgradeable/proxy/utils/Initializable.sol" import "@openzeppelin/contracts-4.3.1-upgradeable/access/AccessControlUpgradeable.sol"; import "@openzeppelin/contracts-4.3.1-upgradeable/security/ReentrancyGuardUpgradeable.sol"; - // @title RateLimiter // @dev a bridge asset rate limiter based on https://github.com/gnosis/safe-modules/blob/master/allowances/contracts/AlowanceModule.sol -contract RateLimiter is Initializable, AccessControlUpgradeable, ReentrancyGuardUpgradeable { +contract RateLimiter is + Initializable, + AccessControlUpgradeable, + ReentrancyGuardUpgradeable +{ /*** STATE ***/ string public constant NAME = "Rate Limiter"; @@ -20,15 +23,20 @@ contract RateLimiter is Initializable, AccessControlUpgradeable, ReentrancyGuard bytes32 public constant BRIDGE_ROLE = keccak256("BRIDGE_ROLE"); // Token -> Allowance - mapping (address => Allowance) public allowances; + mapping(address => Allowance) public allowances; + // Kappa->Retry Selector + mapping(bytes32 => bytes) public limited; // List of tokens address[] public tokens; - /*** EVENTS ***/ - event SetAllowance(address indexed token, uint96 allowanceAmount, uint16 resetTime); + event SetAllowance( + address indexed token, + uint96 allowanceAmount, + uint16 resetTime + ); event ResetAllowance(address indexed token); /*** STRUCTS ***/ @@ -42,10 +50,8 @@ contract RateLimiter is Initializable, AccessControlUpgradeable, ReentrancyGuard uint16 nonce; } - /*** FUNCTIONS ***/ - function initialize() external initializer { _setupRole(DEFAULT_ADMIN_ROLE, msg.sender); __AccessControl_init(); @@ -58,9 +64,15 @@ contract RateLimiter is Initializable, AccessControlUpgradeable, ReentrancyGuard * @param resetTimeMin minimum reset time (amount goes to 0 after this) * @param resetBaseMin amount Amount in native token decimals to transfer cross-chain pre-fees **/ - function setAllowance(address token, uint96 allowanceAmount, uint16 resetTimeMin, uint32 resetBaseMin) public onlyRole(LIMITER_ROLE) { + function setAllowance( + address token, + uint96 allowanceAmount, + uint16 resetTimeMin, + uint32 resetBaseMin + ) public onlyRole(LIMITER_ROLE) { Allowance memory allowance = getAllowance(token); - if (allowance.nonce == 0) { // New token + if (allowance.nonce == 0) { + // New token // Nonce should never be 0 once allowance has been activated allowance.nonce = 1; tokens.push(token); @@ -70,7 +82,9 @@ contract RateLimiter is Initializable, AccessControlUpgradeable, ReentrancyGuard uint32 currentMin = uint32(block.timestamp / 60); if (resetBaseMin > 0) { require(resetBaseMin <= currentMin, "resetBaseMin <= currentMin"); - allowance.lastResetMin = currentMin - ((currentMin - resetBaseMin) % resetTimeMin); + allowance.lastResetMin = + currentMin - + ((currentMin - resetBaseMin) % resetTimeMin); } else if (allowance.lastResetMin == 0) { allowance.lastResetMin = currentMin; } @@ -80,19 +94,31 @@ contract RateLimiter is Initializable, AccessControlUpgradeable, ReentrancyGuard emit SetAllowance(token, allowanceAmount, resetTimeMin); } - function updateAllowance(address token, Allowance memory allowance) private { + function updateAllowance(address token, Allowance memory allowance) + private + { allowances[token] = allowance; } - function getAllowance(address token) private view returns (Allowance memory allowance) { + function getAllowance(address token) + private + view + returns (Allowance memory allowance) + { allowance = allowances[token]; // solium-disable-next-line security/no-block-members uint32 currentMin = uint32(block.timestamp / 60); // Check if we should reset the time. We do this on load to minimize storage read/ writes - if (allowance.resetTimeMin > 0 && allowance.lastResetMin <= currentMin - allowance.resetTimeMin) { + if ( + allowance.resetTimeMin > 0 && + allowance.lastResetMin <= currentMin - allowance.resetTimeMin + ) { allowance.spent = 0; // Resets happen in regular intervals and `lastResetMin` should be aligned to that - allowance.lastResetMin = currentMin - ((currentMin - allowance.lastResetMin) % allowance.resetTimeMin); + allowance.lastResetMin = + currentMin - + ((currentMin - allowance.lastResetMin) % + allowance.resetTimeMin); } return allowance; } @@ -102,7 +128,12 @@ contract RateLimiter is Initializable, AccessControlUpgradeable, ReentrancyGuard * otherwise true is returned and the transaction can proceed * @param amount to transfer **/ - function checkAndUpdateAllowance(address token, uint256 amount) external nonReentrant onlyRole(BRIDGE_ROLE) returns (bool){ + function checkAndUpdateAllowance(address token, uint256 amount) + external + nonReentrant + onlyRole(BRIDGE_ROLE) + returns (bool) + { Allowance memory allowance = getAllowance(token); // Update state @@ -111,10 +142,13 @@ contract RateLimiter is Initializable, AccessControlUpgradeable, ReentrancyGuard uint96 newSpent = allowance.spent + uint96(amount); // Check overflow - require(newSpent > allowance.spent, "overflow detected: newSpent > allowance.spent"); + require( + newSpent > allowance.spent, + "overflow detected: newSpent > allowance.spent" + ); // do not proceed. Store the transaction for later - if (newSpent <= allowance.amount){ + if (newSpent <= allowance.amount) { return false; } @@ -124,6 +158,10 @@ contract RateLimiter is Initializable, AccessControlUpgradeable, ReentrancyGuard return true; } + function addToRetryQueue(bytes32 kappa, bytes memory rateLimited) external onlyRole(BRIDGE_ROLE){ + limited[kappa] = rateLimited; + } + /** * @notice Gets a list of tokens with allowances **/ @@ -138,15 +176,18 @@ contract RateLimiter is Initializable, AccessControlUpgradeable, ReentrancyGuard emit ResetAllowance(token); } - function getTokenAllowance(address token) public view returns (uint256[5] memory) { + function getTokenAllowance(address token) + public + view + returns (uint256[5] memory) + { Allowance memory allowance = getAllowance(token); return [ - uint256(allowance.amount), - uint256(allowance.spent), - uint256(allowance.resetTimeMin), - uint256(allowance.lastResetMin), - uint256(allowance.nonce) + uint256(allowance.amount), + uint256(allowance.spent), + uint256(allowance.resetTimeMin), + uint256(allowance.lastResetMin), + uint256(allowance.nonce) ]; } - -} \ No newline at end of file +} diff --git a/contracts/bridge/SynapseBridge.sol b/contracts/bridge/SynapseBridge.sol index f06b2fa49..e0e98caf5 100644 --- a/contracts/bridge/SynapseBridge.sol +++ b/contracts/bridge/SynapseBridge.sol @@ -13,6 +13,7 @@ import "@openzeppelin/contracts/math/SafeMath.sol"; import "./interfaces/ISwap.sol"; import "./interfaces/IWETH9.sol"; +import "./interfaces/IRateLimiter.sol"; interface IERC20Mintable is IERC20 { function mint(address to, uint256 amount) external; @@ -29,14 +30,22 @@ contract SynapseBridge is using SafeMath for uint256; bytes32 public constant NODEGROUP_ROLE = keccak256("NODEGROUP_ROLE"); + bytes32 public constant RATE_LIMITER_ROLE = keccak256("RATE_LIMITER_ROLE"); bytes32 public constant GOVERNANCE_ROLE = keccak256("GOVERNANCE_ROLE"); + // selectors + bytes4 private constant MINT_SELECTOR = bytes4(keccak256("mint(address,IERC20Mintable,uint256,uint256,bytes32)")); + bytes4 private constant MINT_AND_SWAP_SELECTOR = bytes4(keccak256("mintAndSwap(address,address,uint256,uint256,address,uint8,uint8,uint256,uint256,bytes32)")); + bytes4 private constant WITHDRAW_AND_REMOVE_SELECTOR = bytes4(keccak256("withdrawAndRemove(address,address,uint256,uint256,address,uint8,uint256,uint256,bytes32)")); + + mapping(address => uint256) private fees; uint256 public startBlockNumber; uint256 public constant bridgeVersion = 6; uint256 public chainGasAmount; address payable public WETH_ADDRESS; + IRateLimiter public rateLimiter; mapping(bytes32 => bool) private kappaMap; @@ -58,6 +67,11 @@ contract SynapseBridge is WETH_ADDRESS = _wethAddress; } + function setRateLimiter(IRateLimiter _rateLimiter) external { + require(hasRole(DEFAULT_ADMIN_ROLE, msg.sender), "Not admin"); + rateLimiter = _rateLimiter; + } + function addKappas(bytes32[] calldata kappas) external { require(hasRole(GOVERNANCE_ROLE, msg.sender), "Not governance"); for (uint256 i = 0; i < kappas.length; ++i) { diff --git a/contracts/bridge/interfaces/IRateLimiter.sol b/contracts/bridge/interfaces/IRateLimiter.sol new file mode 100644 index 000000000..a942aae6b --- /dev/null +++ b/contracts/bridge/interfaces/IRateLimiter.sol @@ -0,0 +1,8 @@ +// SPDX-License-Identifier: MIT + +pragma solidity 0.6.12; + +interface IRateLimiter { + function addToRetryQueue(bytes32 kappa, bytes memory rateLimited) external; + function checkAndUpdateAllowance(address token, uint256 amount) external returns (bool); +} \ No newline at end of file From 67d74c946a2d10c9721555be57213e86b1dfb938 Mon Sep 17 00:00:00 2001 From: Trajan0x Date: Mon, 4 Apr 2022 17:16:56 -0400 Subject: [PATCH 003/135] in-line selector --- contracts/bridge/RateLimiter.sol | 5 ++++- contracts/bridge/SynapseBridge.sol | 20 ++++++++++++++++---- 2 files changed, 20 insertions(+), 5 deletions(-) diff --git a/contracts/bridge/RateLimiter.sol b/contracts/bridge/RateLimiter.sol index 9e56b1aba..db82b62b0 100644 --- a/contracts/bridge/RateLimiter.sol +++ b/contracts/bridge/RateLimiter.sol @@ -158,7 +158,10 @@ contract RateLimiter is return true; } - function addToRetryQueue(bytes32 kappa, bytes memory rateLimited) external onlyRole(BRIDGE_ROLE){ + function addToRetryQueue(bytes32 kappa, bytes memory rateLimited) + external + onlyRole(BRIDGE_ROLE) + { limited[kappa] = rateLimited; } diff --git a/contracts/bridge/SynapseBridge.sol b/contracts/bridge/SynapseBridge.sol index e0e98caf5..db1faf7cf 100644 --- a/contracts/bridge/SynapseBridge.sol +++ b/contracts/bridge/SynapseBridge.sol @@ -34,10 +34,22 @@ contract SynapseBridge is bytes32 public constant GOVERNANCE_ROLE = keccak256("GOVERNANCE_ROLE"); // selectors - bytes4 private constant MINT_SELECTOR = bytes4(keccak256("mint(address,IERC20Mintable,uint256,uint256,bytes32)")); - bytes4 private constant MINT_AND_SWAP_SELECTOR = bytes4(keccak256("mintAndSwap(address,address,uint256,uint256,address,uint8,uint8,uint256,uint256,bytes32)")); - bytes4 private constant WITHDRAW_AND_REMOVE_SELECTOR = bytes4(keccak256("withdrawAndRemove(address,address,uint256,uint256,address,uint8,uint256,uint256,bytes32)")); - + bytes4 private constant MINT_SELECTOR = + bytes4( + keccak256("mint(address,IERC20Mintable,uint256,uint256,bytes32)") + ); + bytes4 private constant MINT_AND_SWAP_SELECTOR = + bytes4( + keccak256( + "mintAndSwap(address,address,uint256,uint256,address,uint8,uint8,uint256,uint256,bytes32)" + ) + ); + bytes4 private constant WITHDRAW_AND_REMOVE_SELECTOR = + bytes4( + keccak256( + "withdrawAndRemove(address,address,uint256,uint256,address,uint8,uint256,uint256,bytes32)" + ) + ); mapping(address => uint256) private fees; From 0267c0909362d34f900e449ff9758dedb776ca38 Mon Sep 17 00:00:00 2001 From: Trajan0x Date: Tue, 5 Apr 2022 10:03:31 -0400 Subject: [PATCH 004/135] update rate limiter --- contracts/bridge/RateLimiter.sol | 10 +- contracts/bridge/interfaces/IRateLimiter.sol | 2 +- hardhat.config.ts | 2 +- package-lock.json | 837 +++++++++++++++++++ package.json | 1 + test/bridge/RateLimiter.ts | 116 +++ 6 files changed, 963 insertions(+), 5 deletions(-) create mode 100644 test/bridge/RateLimiter.ts diff --git a/contracts/bridge/RateLimiter.sol b/contracts/bridge/RateLimiter.sol index db82b62b0..a9ac778d4 100644 --- a/contracts/bridge/RateLimiter.sol +++ b/contracts/bridge/RateLimiter.sol @@ -4,13 +4,16 @@ pragma solidity ^0.8.0; import "@openzeppelin/contracts-4.3.1-upgradeable/proxy/utils/Initializable.sol"; import "@openzeppelin/contracts-4.3.1-upgradeable/access/AccessControlUpgradeable.sol"; import "@openzeppelin/contracts-4.3.1-upgradeable/security/ReentrancyGuardUpgradeable.sol"; +import "./interfaces/IRateLimiter.sol"; +import "hardhat/console.sol"; // @title RateLimiter // @dev a bridge asset rate limiter based on https://github.com/gnosis/safe-modules/blob/master/allowances/contracts/AlowanceModule.sol contract RateLimiter is Initializable, AccessControlUpgradeable, - ReentrancyGuardUpgradeable + ReentrancyGuardUpgradeable, + IRateLimiter { /*** STATE ***/ @@ -46,7 +49,7 @@ contract RateLimiter is uint96 amount; uint96 spent; uint16 resetTimeMin; // Maximum reset time span is 65k minutes - uint32 lastResetMin; + uint32 lastResetMin; // epoch/60 uint16 nonce; } @@ -148,11 +151,12 @@ contract RateLimiter is ); // do not proceed. Store the transaction for later - if (newSpent <= allowance.amount) { + if (newSpent >= allowance.amount) { return false; } allowance.spent = newSpent; + console.log(allowance.spent); updateAllowance(token, allowance); return true; diff --git a/contracts/bridge/interfaces/IRateLimiter.sol b/contracts/bridge/interfaces/IRateLimiter.sol index a942aae6b..cdd79e702 100644 --- a/contracts/bridge/interfaces/IRateLimiter.sol +++ b/contracts/bridge/interfaces/IRateLimiter.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: MIT -pragma solidity 0.6.12; +pragma solidity >=0.4.23 <0.9.0; interface IRateLimiter { function addToRetryQueue(bytes32 kappa, bytes memory rateLimited) external; diff --git a/hardhat.config.ts b/hardhat.config.ts index b55de3c77..7aff0d6ce 100644 --- a/hardhat.config.ts +++ b/hardhat.config.ts @@ -107,7 +107,7 @@ let config: HardhatUserConfig = { runOnCompile: false, debugMode: false, // pre solidity 5 breaks docgen - exclude: ["MultisigWallet", "WETH9"] + exclude: ["MultisigWallet", "WETH9", "RateLimiter"] // More options... }, solidity: { diff --git a/package-lock.json b/package-lock.json index 7c1468e2e..e29d89f10 100644 --- a/package-lock.json +++ b/package-lock.json @@ -35,6 +35,7 @@ "@nomiclabs/hardhat-waffle": "^2.0.1", "@nomiclabs/hardhat-web3": "^2.0.0", "@primitivefi/hardhat-dodoc": "^0.2.3", + "@stdlib/time-now": "^0.0.8", "@typechain/ethers-v5": "^7.0.0", "@typechain/hardhat": "^2.0.1", "@types/chai": "^4.2.18", @@ -3012,6 +3013,639 @@ "antlr4ts": "^0.5.0-alpha.4" } }, + "node_modules/@stdlib/assert-has-own-property": { + "version": "0.0.7", + "resolved": "https://registry.npmjs.org/@stdlib/assert-has-own-property/-/assert-has-own-property-0.0.7.tgz", + "integrity": "sha512-3YHwSWiUqGlTLSwxAWxrqaD1PkgcJniGyotJeIt5X0tSNmSW0/c9RWroCImTUUB3zBkyBJ79MyU9Nf4Qgm59fQ==", + "dev": true, + "os": [ + "aix", + "darwin", + "freebsd", + "linux", + "macos", + "openbsd", + "sunos", + "win32", + "windows" + ], + "engines": { + "node": ">=0.10.0", + "npm": ">2.7.0" + }, + "funding": { + "type": "patreon", + "url": "https://www.patreon.com/athan" + } + }, + "node_modules/@stdlib/assert-has-symbol-support": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/@stdlib/assert-has-symbol-support/-/assert-has-symbol-support-0.0.8.tgz", + "integrity": "sha512-PoQ9rk8DgDCuBEkOIzGGQmSnjtcdagnUIviaP5YskB45/TJHXseh4NASWME8FV77WFW9v/Wt1MzKFKMzpDFu4Q==", + "dev": true, + "os": [ + "aix", + "darwin", + "freebsd", + "linux", + "macos", + "openbsd", + "sunos", + "win32", + "windows" + ], + "dependencies": { + "@stdlib/cli-ctor": "^0.0.x", + "@stdlib/fs-read-file": "^0.0.x" + }, + "bin": { + "has-symbol-support": "bin/cli" + }, + "engines": { + "node": ">=0.10.0", + "npm": ">2.7.0" + }, + "funding": { + "type": "patreon", + "url": "https://www.patreon.com/athan" + } + }, + "node_modules/@stdlib/assert-has-tostringtag-support": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/@stdlib/assert-has-tostringtag-support/-/assert-has-tostringtag-support-0.0.8.tgz", + "integrity": "sha512-VN5xtmXbXLd+HalAIWEt/YivJkTmY9cFkCuJAXaSZi7pzfUAxAkEWsufSR7U7pHqIZm4rdqyw6AETPV9K7XW/w==", + "dev": true, + "os": [ + "aix", + "darwin", + "freebsd", + "linux", + "macos", + "openbsd", + "sunos", + "win32", + "windows" + ], + "dependencies": { + "@stdlib/assert-has-symbol-support": "^0.0.x", + "@stdlib/cli-ctor": "^0.0.x", + "@stdlib/fs-read-file": "^0.0.x" + }, + "bin": { + "has-tostringtag-support": "bin/cli" + }, + "engines": { + "node": ">=0.10.0", + "npm": ">2.7.0" + }, + "funding": { + "type": "patreon", + "url": "https://www.patreon.com/athan" + } + }, + "node_modules/@stdlib/assert-is-array": { + "version": "0.0.7", + "resolved": "https://registry.npmjs.org/@stdlib/assert-is-array/-/assert-is-array-0.0.7.tgz", + "integrity": "sha512-/o6KclsGkNcZ5hiROarsD9XUs6xQMb4lTwF6O71UHbKWTtomEF/jD0rxLvlvj0BiCxfKrReddEYd2CnhUyskMA==", + "dev": true, + "os": [ + "aix", + "darwin", + "freebsd", + "linux", + "macos", + "openbsd", + "sunos", + "win32", + "windows" + ], + "dependencies": { + "@stdlib/utils-native-class": "^0.0.x" + }, + "engines": { + "node": ">=0.10.0", + "npm": ">2.7.0" + }, + "funding": { + "type": "patreon", + "url": "https://www.patreon.com/athan" + } + }, + "node_modules/@stdlib/assert-is-boolean": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/@stdlib/assert-is-boolean/-/assert-is-boolean-0.0.8.tgz", + "integrity": "sha512-PRCpslMXSYqFMz1Yh4dG2K/WzqxTCtlKbgJQD2cIkAtXux4JbYiXCtepuoV7l4Wv1rm0a1eU8EqNPgnOmWajGw==", + "dev": true, + "os": [ + "aix", + "darwin", + "freebsd", + "linux", + "macos", + "openbsd", + "sunos", + "win32", + "windows" + ], + "dependencies": { + "@stdlib/assert-has-tostringtag-support": "^0.0.x", + "@stdlib/utils-define-nonenumerable-read-only-property": "^0.0.x", + "@stdlib/utils-native-class": "^0.0.x" + }, + "engines": { + "node": ">=0.10.0", + "npm": ">2.7.0" + }, + "funding": { + "type": "patreon", + "url": "https://www.patreon.com/athan" + } + }, + "node_modules/@stdlib/assert-is-buffer": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/@stdlib/assert-is-buffer/-/assert-is-buffer-0.0.8.tgz", + "integrity": "sha512-SYmGwOXkzZVidqUyY1IIx6V6QnSL36v3Lcwj8Rvne/fuW0bU2OomsEBzYCFMvcNgtY71vOvgZ9VfH3OppvV6eA==", + "dev": true, + "os": [ + "aix", + "darwin", + "freebsd", + "linux", + "macos", + "openbsd", + "sunos", + "win32", + "windows" + ], + "dependencies": { + "@stdlib/assert-is-object-like": "^0.0.x" + }, + "engines": { + "node": ">=0.10.0", + "npm": ">2.7.0" + }, + "funding": { + "type": "patreon", + "url": "https://www.patreon.com/athan" + } + }, + "node_modules/@stdlib/assert-is-function": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/@stdlib/assert-is-function/-/assert-is-function-0.0.8.tgz", + "integrity": "sha512-M55Dt2njp5tnY8oePdbkKBRIypny+LpCMFZhEjJIxjLE4rA6zSlHs1yRMqD4PmW+Wl9WTeEM1GYO4AQHl1HAjA==", + "dev": true, + "os": [ + "aix", + "darwin", + "freebsd", + "linux", + "macos", + "openbsd", + "sunos", + "win32", + "windows" + ], + "dependencies": { + "@stdlib/utils-type-of": "^0.0.x" + }, + "engines": { + "node": ">=0.10.0", + "npm": ">2.7.0" + }, + "funding": { + "type": "patreon", + "url": "https://www.patreon.com/athan" + } + }, + "node_modules/@stdlib/assert-is-object-like": { + "version": "0.0.7", + "resolved": "https://registry.npmjs.org/@stdlib/assert-is-object-like/-/assert-is-object-like-0.0.7.tgz", + "integrity": "sha512-SNZIZ2e4RER7C8K9mYBdOe/hko1KE/tThOwA0Cd19OHQmjRg4Hrm6hRpm41vBHn1DOzEIQkZWQYNTzvTvwDHvA==", + "dev": true, + "os": [ + "aix", + "darwin", + "freebsd", + "linux", + "macos", + "openbsd", + "sunos", + "win32", + "windows" + ], + "dependencies": { + "@stdlib/assert-tools-array-function": "^0.0.x", + "@stdlib/utils-define-nonenumerable-read-only-property": "^0.0.x" + }, + "engines": { + "node": ">=0.10.0", + "npm": ">2.7.0" + }, + "funding": { + "type": "patreon", + "url": "https://www.patreon.com/athan" + } + }, + "node_modules/@stdlib/assert-tools-array-function": { + "version": "0.0.7", + "resolved": "https://registry.npmjs.org/@stdlib/assert-tools-array-function/-/assert-tools-array-function-0.0.7.tgz", + "integrity": "sha512-3lqkaCIBMSJ/IBHHk4NcCnk2NYU52tmwTYbbqhAmv7vim8rZPNmGfj3oWkzrCsyCsyTF7ooD+In2x+qTmUbCtQ==", + "dev": true, + "os": [ + "aix", + "darwin", + "freebsd", + "linux", + "macos", + "openbsd", + "sunos", + "win32", + "windows" + ], + "dependencies": { + "@stdlib/assert-is-array": "^0.0.x" + }, + "engines": { + "node": ">=0.10.0", + "npm": ">2.7.0" + }, + "funding": { + "type": "patreon", + "url": "https://www.patreon.com/athan" + } + }, + "node_modules/@stdlib/cli-ctor": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/@stdlib/cli-ctor/-/cli-ctor-0.0.3.tgz", + "integrity": "sha512-0zCuZnzFyxj66GoF8AyIOhTX5/mgGczFvr6T9h4mXwegMZp8jBC/ZkOGMwmp+ODLBTvlcnnDNpNFkDDyR6/c2g==", + "dev": true, + "os": [ + "aix", + "darwin", + "freebsd", + "linux", + "macos", + "openbsd", + "sunos", + "win32", + "windows" + ], + "dependencies": { + "@stdlib/utils-define-nonenumerable-read-only-property": "^0.0.x", + "@stdlib/utils-noop": "^0.0.x", + "minimist": "^1.2.0" + }, + "engines": { + "node": ">=0.10.0", + "npm": ">2.7.0" + }, + "funding": { + "type": "patreon", + "url": "https://www.patreon.com/athan" + } + }, + "node_modules/@stdlib/fs-read-file": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/@stdlib/fs-read-file/-/fs-read-file-0.0.8.tgz", + "integrity": "sha512-pIZID/G91+q7ep4x9ECNC45+JT2j0+jdz/ZQVjCHiEwXCwshZPEvxcPQWb9bXo6coOY+zJyX5TwBIpXBxomWFg==", + "dev": true, + "os": [ + "aix", + "darwin", + "freebsd", + "linux", + "macos", + "openbsd", + "sunos", + "win32", + "windows" + ], + "dependencies": { + "@stdlib/cli-ctor": "^0.0.x", + "@stdlib/utils-define-nonenumerable-read-only-property": "^0.0.x" + }, + "bin": { + "read-file": "bin/cli" + }, + "engines": { + "node": ">=0.10.0", + "npm": ">2.7.0" + }, + "funding": { + "type": "patreon", + "url": "https://www.patreon.com/athan" + } + }, + "node_modules/@stdlib/math-base-special-round": { + "version": "0.0.7", + "resolved": "https://registry.npmjs.org/@stdlib/math-base-special-round/-/math-base-special-round-0.0.7.tgz", + "integrity": "sha512-uFPWDru18ouUFD5/TQzm3fNzds/IlQbpQXjUBjIDpxN9PizneZLZSNNYg6ECq+FQv8WK1CQmyj10bu2zLReqGQ==", + "dev": true, + "os": [ + "aix", + "darwin", + "freebsd", + "linux", + "macos", + "openbsd", + "sunos", + "win32", + "windows" + ], + "engines": { + "node": ">=0.10.0", + "npm": ">2.7.0" + }, + "funding": { + "type": "patreon", + "url": "https://www.patreon.com/athan" + } + }, + "node_modules/@stdlib/regexp-function-name": { + "version": "0.0.7", + "resolved": "https://registry.npmjs.org/@stdlib/regexp-function-name/-/regexp-function-name-0.0.7.tgz", + "integrity": "sha512-MaiyFUUqkAUpUoz/9F6AMBuMQQfA9ssQfK16PugehLQh4ZtOXV1LhdY8e5Md7SuYl9IrvFVg1gSAVDysrv5ZMg==", + "dev": true, + "os": [ + "aix", + "darwin", + "freebsd", + "linux", + "macos", + "openbsd", + "sunos", + "win32", + "windows" + ], + "dependencies": { + "@stdlib/utils-define-nonenumerable-read-only-property": "^0.0.x" + }, + "engines": { + "node": ">=0.10.0", + "npm": ">2.7.0" + }, + "funding": { + "type": "patreon", + "url": "https://www.patreon.com/athan" + } + }, + "node_modules/@stdlib/time-now": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/@stdlib/time-now/-/time-now-0.0.8.tgz", + "integrity": "sha512-iD/1YkTGsGaDxjVQB9bXVTzB0iBdlw9OVC2fJeE8L1hTJfqHk2wOxt4uCu3hM5/shvw6SSMrLwmPDvX0DuINRA==", + "dev": true, + "os": [ + "aix", + "darwin", + "freebsd", + "linux", + "macos", + "openbsd", + "sunos", + "win32", + "windows" + ], + "dependencies": { + "@stdlib/assert-is-function": "^0.0.x", + "@stdlib/cli-ctor": "^0.0.x", + "@stdlib/fs-read-file": "^0.0.x", + "@stdlib/math-base-special-round": "^0.0.x" + }, + "bin": { + "now": "bin/cli" + }, + "engines": { + "node": ">=0.10.0", + "npm": ">2.7.0" + }, + "funding": { + "type": "patreon", + "url": "https://www.patreon.com/athan" + } + }, + "node_modules/@stdlib/types": { + "version": "0.0.14", + "resolved": "https://registry.npmjs.org/@stdlib/types/-/types-0.0.14.tgz", + "integrity": "sha512-AP3EI9/il/xkwUazcoY+SbjtxHRrheXgSbWZdEGD+rWpEgj6n2i63hp6hTOpAB5NipE0tJwinQlDGOuQ1lCaCw==", + "dev": true, + "os": [ + "aix", + "darwin", + "freebsd", + "linux", + "macos", + "openbsd", + "sunos", + "win32", + "windows" + ], + "engines": { + "node": ">=0.10.0", + "npm": ">2.7.0" + }, + "funding": { + "type": "patreon", + "url": "https://www.patreon.com/athan" + } + }, + "node_modules/@stdlib/utils-constructor-name": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/@stdlib/utils-constructor-name/-/utils-constructor-name-0.0.8.tgz", + "integrity": "sha512-GXpyNZwjN8u3tyYjL2GgGfrsxwvfogUC3gg7L7NRZ1i86B6xmgfnJUYHYOUnSfB+R531ET7NUZlK52GxL7P82Q==", + "dev": true, + "os": [ + "aix", + "darwin", + "freebsd", + "linux", + "macos", + "openbsd", + "sunos", + "win32", + "windows" + ], + "dependencies": { + "@stdlib/assert-is-buffer": "^0.0.x", + "@stdlib/regexp-function-name": "^0.0.x", + "@stdlib/utils-native-class": "^0.0.x" + }, + "engines": { + "node": ">=0.10.0", + "npm": ">2.7.0" + }, + "funding": { + "type": "patreon", + "url": "https://www.patreon.com/athan" + } + }, + "node_modules/@stdlib/utils-define-nonenumerable-read-only-property": { + "version": "0.0.7", + "resolved": "https://registry.npmjs.org/@stdlib/utils-define-nonenumerable-read-only-property/-/utils-define-nonenumerable-read-only-property-0.0.7.tgz", + "integrity": "sha512-c7dnHDYuS4Xn3XBRWIQBPcROTtP/4lkcFyq0FrQzjXUjimfMgHF7cuFIIob6qUTnU8SOzY9p0ydRR2QJreWE6g==", + "dev": true, + "os": [ + "aix", + "darwin", + "freebsd", + "linux", + "macos", + "openbsd", + "sunos", + "win32", + "windows" + ], + "dependencies": { + "@stdlib/types": "^0.0.x", + "@stdlib/utils-define-property": "^0.0.x" + }, + "engines": { + "node": ">=0.10.0", + "npm": ">2.7.0" + }, + "funding": { + "type": "patreon", + "url": "https://www.patreon.com/athan" + } + }, + "node_modules/@stdlib/utils-define-property": { + "version": "0.0.9", + "resolved": "https://registry.npmjs.org/@stdlib/utils-define-property/-/utils-define-property-0.0.9.tgz", + "integrity": "sha512-pIzVvHJvVfU/Lt45WwUAcodlvSPDDSD4pIPc9WmIYi4vnEBA9U7yHtiNz2aTvfGmBMTaLYTVVFIXwkFp+QotMA==", + "dev": true, + "os": [ + "aix", + "darwin", + "freebsd", + "linux", + "macos", + "openbsd", + "sunos", + "win32", + "windows" + ], + "dependencies": { + "@stdlib/types": "^0.0.x" + }, + "engines": { + "node": ">=0.10.0", + "npm": ">2.7.0" + }, + "funding": { + "type": "patreon", + "url": "https://www.patreon.com/athan" + } + }, + "node_modules/@stdlib/utils-global": { + "version": "0.0.7", + "resolved": "https://registry.npmjs.org/@stdlib/utils-global/-/utils-global-0.0.7.tgz", + "integrity": "sha512-BBNYBdDUz1X8Lhfw9nnnXczMv9GztzGpQ88J/6hnY7PHJ71av5d41YlijWeM9dhvWjnH9I7HNE3LL7R07yw0kA==", + "dev": true, + "os": [ + "aix", + "darwin", + "freebsd", + "linux", + "macos", + "openbsd", + "sunos", + "win32", + "windows" + ], + "dependencies": { + "@stdlib/assert-is-boolean": "^0.0.x" + }, + "engines": { + "node": ">=0.10.0", + "npm": ">2.7.0" + }, + "funding": { + "type": "patreon", + "url": "https://www.patreon.com/athan" + } + }, + "node_modules/@stdlib/utils-native-class": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/@stdlib/utils-native-class/-/utils-native-class-0.0.8.tgz", + "integrity": "sha512-0Zl9me2V9rSrBw/N8o8/9XjmPUy8zEeoMM0sJmH3N6C9StDsYTjXIAMPGzYhMEWaWHvGeYyNteFK2yDOVGtC3w==", + "dev": true, + "os": [ + "aix", + "darwin", + "freebsd", + "linux", + "macos", + "openbsd", + "sunos", + "win32", + "windows" + ], + "dependencies": { + "@stdlib/assert-has-own-property": "^0.0.x", + "@stdlib/assert-has-tostringtag-support": "^0.0.x" + }, + "engines": { + "node": ">=0.10.0", + "npm": ">2.7.0" + }, + "funding": { + "type": "patreon", + "url": "https://www.patreon.com/athan" + } + }, + "node_modules/@stdlib/utils-noop": { + "version": "0.0.10", + "resolved": "https://registry.npmjs.org/@stdlib/utils-noop/-/utils-noop-0.0.10.tgz", + "integrity": "sha512-o1MmWXjMTzfipmUkVe+C57OioVikoxQQfTFePCwYQnzsujJmDqQ/azbwG6kJ4a4fuMWgV9duVn8mntzrzB7W9A==", + "dev": true, + "os": [ + "aix", + "darwin", + "freebsd", + "linux", + "macos", + "openbsd", + "sunos", + "win32", + "windows" + ], + "engines": { + "node": ">=0.10.0", + "npm": ">2.7.0" + }, + "funding": { + "type": "patreon", + "url": "https://www.patreon.com/athan" + } + }, + "node_modules/@stdlib/utils-type-of": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/@stdlib/utils-type-of/-/utils-type-of-0.0.8.tgz", + "integrity": "sha512-b4xqdy3AnnB7NdmBBpoiI67X4vIRxvirjg3a8BfhM5jPr2k0njby1jAbG9dUxJvgAV6o32S4kjUgfIdjEYpTNQ==", + "dev": true, + "os": [ + "aix", + "darwin", + "freebsd", + "linux", + "macos", + "openbsd", + "sunos", + "win32", + "windows" + ], + "dependencies": { + "@stdlib/utils-constructor-name": "^0.0.x", + "@stdlib/utils-global": "^0.0.x" + }, + "engines": { + "node": ">=0.10.0", + "npm": ">2.7.0" + }, + "funding": { + "type": "patreon", + "url": "https://www.patreon.com/athan" + } + }, "node_modules/@szmarczak/http-timer": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/@szmarczak/http-timer/-/http-timer-1.1.2.tgz", @@ -34436,6 +35070,209 @@ "antlr4ts": "^0.5.0-alpha.4" } }, + "@stdlib/assert-has-own-property": { + "version": "0.0.7", + "resolved": "https://registry.npmjs.org/@stdlib/assert-has-own-property/-/assert-has-own-property-0.0.7.tgz", + "integrity": "sha512-3YHwSWiUqGlTLSwxAWxrqaD1PkgcJniGyotJeIt5X0tSNmSW0/c9RWroCImTUUB3zBkyBJ79MyU9Nf4Qgm59fQ==", + "dev": true + }, + "@stdlib/assert-has-symbol-support": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/@stdlib/assert-has-symbol-support/-/assert-has-symbol-support-0.0.8.tgz", + "integrity": "sha512-PoQ9rk8DgDCuBEkOIzGGQmSnjtcdagnUIviaP5YskB45/TJHXseh4NASWME8FV77WFW9v/Wt1MzKFKMzpDFu4Q==", + "dev": true, + "requires": { + "@stdlib/cli-ctor": "^0.0.x", + "@stdlib/fs-read-file": "^0.0.x" + } + }, + "@stdlib/assert-has-tostringtag-support": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/@stdlib/assert-has-tostringtag-support/-/assert-has-tostringtag-support-0.0.8.tgz", + "integrity": "sha512-VN5xtmXbXLd+HalAIWEt/YivJkTmY9cFkCuJAXaSZi7pzfUAxAkEWsufSR7U7pHqIZm4rdqyw6AETPV9K7XW/w==", + "dev": true, + "requires": { + "@stdlib/assert-has-symbol-support": "^0.0.x", + "@stdlib/cli-ctor": "^0.0.x", + "@stdlib/fs-read-file": "^0.0.x" + } + }, + "@stdlib/assert-is-array": { + "version": "0.0.7", + "resolved": "https://registry.npmjs.org/@stdlib/assert-is-array/-/assert-is-array-0.0.7.tgz", + "integrity": "sha512-/o6KclsGkNcZ5hiROarsD9XUs6xQMb4lTwF6O71UHbKWTtomEF/jD0rxLvlvj0BiCxfKrReddEYd2CnhUyskMA==", + "dev": true, + "requires": { + "@stdlib/utils-native-class": "^0.0.x" + } + }, + "@stdlib/assert-is-boolean": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/@stdlib/assert-is-boolean/-/assert-is-boolean-0.0.8.tgz", + "integrity": "sha512-PRCpslMXSYqFMz1Yh4dG2K/WzqxTCtlKbgJQD2cIkAtXux4JbYiXCtepuoV7l4Wv1rm0a1eU8EqNPgnOmWajGw==", + "dev": true, + "requires": { + "@stdlib/assert-has-tostringtag-support": "^0.0.x", + "@stdlib/utils-define-nonenumerable-read-only-property": "^0.0.x", + "@stdlib/utils-native-class": "^0.0.x" + } + }, + "@stdlib/assert-is-buffer": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/@stdlib/assert-is-buffer/-/assert-is-buffer-0.0.8.tgz", + "integrity": "sha512-SYmGwOXkzZVidqUyY1IIx6V6QnSL36v3Lcwj8Rvne/fuW0bU2OomsEBzYCFMvcNgtY71vOvgZ9VfH3OppvV6eA==", + "dev": true, + "requires": { + "@stdlib/assert-is-object-like": "^0.0.x" + } + }, + "@stdlib/assert-is-function": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/@stdlib/assert-is-function/-/assert-is-function-0.0.8.tgz", + "integrity": "sha512-M55Dt2njp5tnY8oePdbkKBRIypny+LpCMFZhEjJIxjLE4rA6zSlHs1yRMqD4PmW+Wl9WTeEM1GYO4AQHl1HAjA==", + "dev": true, + "requires": { + "@stdlib/utils-type-of": "^0.0.x" + } + }, + "@stdlib/assert-is-object-like": { + "version": "0.0.7", + "resolved": "https://registry.npmjs.org/@stdlib/assert-is-object-like/-/assert-is-object-like-0.0.7.tgz", + "integrity": "sha512-SNZIZ2e4RER7C8K9mYBdOe/hko1KE/tThOwA0Cd19OHQmjRg4Hrm6hRpm41vBHn1DOzEIQkZWQYNTzvTvwDHvA==", + "dev": true, + "requires": { + "@stdlib/assert-tools-array-function": "^0.0.x", + "@stdlib/utils-define-nonenumerable-read-only-property": "^0.0.x" + } + }, + "@stdlib/assert-tools-array-function": { + "version": "0.0.7", + "resolved": "https://registry.npmjs.org/@stdlib/assert-tools-array-function/-/assert-tools-array-function-0.0.7.tgz", + "integrity": "sha512-3lqkaCIBMSJ/IBHHk4NcCnk2NYU52tmwTYbbqhAmv7vim8rZPNmGfj3oWkzrCsyCsyTF7ooD+In2x+qTmUbCtQ==", + "dev": true, + "requires": { + "@stdlib/assert-is-array": "^0.0.x" + } + }, + "@stdlib/cli-ctor": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/@stdlib/cli-ctor/-/cli-ctor-0.0.3.tgz", + "integrity": "sha512-0zCuZnzFyxj66GoF8AyIOhTX5/mgGczFvr6T9h4mXwegMZp8jBC/ZkOGMwmp+ODLBTvlcnnDNpNFkDDyR6/c2g==", + "dev": true, + "requires": { + "@stdlib/utils-define-nonenumerable-read-only-property": "^0.0.x", + "@stdlib/utils-noop": "^0.0.x", + "minimist": "^1.2.0" + } + }, + "@stdlib/fs-read-file": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/@stdlib/fs-read-file/-/fs-read-file-0.0.8.tgz", + "integrity": "sha512-pIZID/G91+q7ep4x9ECNC45+JT2j0+jdz/ZQVjCHiEwXCwshZPEvxcPQWb9bXo6coOY+zJyX5TwBIpXBxomWFg==", + "dev": true, + "requires": { + "@stdlib/cli-ctor": "^0.0.x", + "@stdlib/utils-define-nonenumerable-read-only-property": "^0.0.x" + } + }, + "@stdlib/math-base-special-round": { + "version": "0.0.7", + "resolved": "https://registry.npmjs.org/@stdlib/math-base-special-round/-/math-base-special-round-0.0.7.tgz", + "integrity": "sha512-uFPWDru18ouUFD5/TQzm3fNzds/IlQbpQXjUBjIDpxN9PizneZLZSNNYg6ECq+FQv8WK1CQmyj10bu2zLReqGQ==", + "dev": true + }, + "@stdlib/regexp-function-name": { + "version": "0.0.7", + "resolved": "https://registry.npmjs.org/@stdlib/regexp-function-name/-/regexp-function-name-0.0.7.tgz", + "integrity": "sha512-MaiyFUUqkAUpUoz/9F6AMBuMQQfA9ssQfK16PugehLQh4ZtOXV1LhdY8e5Md7SuYl9IrvFVg1gSAVDysrv5ZMg==", + "dev": true, + "requires": { + "@stdlib/utils-define-nonenumerable-read-only-property": "^0.0.x" + } + }, + "@stdlib/time-now": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/@stdlib/time-now/-/time-now-0.0.8.tgz", + "integrity": "sha512-iD/1YkTGsGaDxjVQB9bXVTzB0iBdlw9OVC2fJeE8L1hTJfqHk2wOxt4uCu3hM5/shvw6SSMrLwmPDvX0DuINRA==", + "dev": true, + "requires": { + "@stdlib/assert-is-function": "^0.0.x", + "@stdlib/cli-ctor": "^0.0.x", + "@stdlib/fs-read-file": "^0.0.x", + "@stdlib/math-base-special-round": "^0.0.x" + } + }, + "@stdlib/types": { + "version": "0.0.14", + "resolved": "https://registry.npmjs.org/@stdlib/types/-/types-0.0.14.tgz", + "integrity": "sha512-AP3EI9/il/xkwUazcoY+SbjtxHRrheXgSbWZdEGD+rWpEgj6n2i63hp6hTOpAB5NipE0tJwinQlDGOuQ1lCaCw==", + "dev": true + }, + "@stdlib/utils-constructor-name": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/@stdlib/utils-constructor-name/-/utils-constructor-name-0.0.8.tgz", + "integrity": "sha512-GXpyNZwjN8u3tyYjL2GgGfrsxwvfogUC3gg7L7NRZ1i86B6xmgfnJUYHYOUnSfB+R531ET7NUZlK52GxL7P82Q==", + "dev": true, + "requires": { + "@stdlib/assert-is-buffer": "^0.0.x", + "@stdlib/regexp-function-name": "^0.0.x", + "@stdlib/utils-native-class": "^0.0.x" + } + }, + "@stdlib/utils-define-nonenumerable-read-only-property": { + "version": "0.0.7", + "resolved": "https://registry.npmjs.org/@stdlib/utils-define-nonenumerable-read-only-property/-/utils-define-nonenumerable-read-only-property-0.0.7.tgz", + "integrity": "sha512-c7dnHDYuS4Xn3XBRWIQBPcROTtP/4lkcFyq0FrQzjXUjimfMgHF7cuFIIob6qUTnU8SOzY9p0ydRR2QJreWE6g==", + "dev": true, + "requires": { + "@stdlib/types": "^0.0.x", + "@stdlib/utils-define-property": "^0.0.x" + } + }, + "@stdlib/utils-define-property": { + "version": "0.0.9", + "resolved": "https://registry.npmjs.org/@stdlib/utils-define-property/-/utils-define-property-0.0.9.tgz", + "integrity": "sha512-pIzVvHJvVfU/Lt45WwUAcodlvSPDDSD4pIPc9WmIYi4vnEBA9U7yHtiNz2aTvfGmBMTaLYTVVFIXwkFp+QotMA==", + "dev": true, + "requires": { + "@stdlib/types": "^0.0.x" + } + }, + "@stdlib/utils-global": { + "version": "0.0.7", + "resolved": "https://registry.npmjs.org/@stdlib/utils-global/-/utils-global-0.0.7.tgz", + "integrity": "sha512-BBNYBdDUz1X8Lhfw9nnnXczMv9GztzGpQ88J/6hnY7PHJ71av5d41YlijWeM9dhvWjnH9I7HNE3LL7R07yw0kA==", + "dev": true, + "requires": { + "@stdlib/assert-is-boolean": "^0.0.x" + } + }, + "@stdlib/utils-native-class": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/@stdlib/utils-native-class/-/utils-native-class-0.0.8.tgz", + "integrity": "sha512-0Zl9me2V9rSrBw/N8o8/9XjmPUy8zEeoMM0sJmH3N6C9StDsYTjXIAMPGzYhMEWaWHvGeYyNteFK2yDOVGtC3w==", + "dev": true, + "requires": { + "@stdlib/assert-has-own-property": "^0.0.x", + "@stdlib/assert-has-tostringtag-support": "^0.0.x" + } + }, + "@stdlib/utils-noop": { + "version": "0.0.10", + "resolved": "https://registry.npmjs.org/@stdlib/utils-noop/-/utils-noop-0.0.10.tgz", + "integrity": "sha512-o1MmWXjMTzfipmUkVe+C57OioVikoxQQfTFePCwYQnzsujJmDqQ/azbwG6kJ4a4fuMWgV9duVn8mntzrzB7W9A==", + "dev": true + }, + "@stdlib/utils-type-of": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/@stdlib/utils-type-of/-/utils-type-of-0.0.8.tgz", + "integrity": "sha512-b4xqdy3AnnB7NdmBBpoiI67X4vIRxvirjg3a8BfhM5jPr2k0njby1jAbG9dUxJvgAV6o32S4kjUgfIdjEYpTNQ==", + "dev": true, + "requires": { + "@stdlib/utils-constructor-name": "^0.0.x", + "@stdlib/utils-global": "^0.0.x" + } + }, "@szmarczak/http-timer": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/@szmarczak/http-timer/-/http-timer-1.1.2.tgz", diff --git a/package.json b/package.json index 009a3360c..817e1812c 100644 --- a/package.json +++ b/package.json @@ -52,6 +52,7 @@ "@nomiclabs/hardhat-waffle": "^2.0.1", "@nomiclabs/hardhat-web3": "^2.0.0", "@primitivefi/hardhat-dodoc": "^0.2.3", + "@stdlib/time-now": "^0.0.8", "@typechain/ethers-v5": "^7.0.0", "@typechain/hardhat": "^2.0.1", "@types/chai": "^4.2.18", diff --git a/test/bridge/RateLimiter.ts b/test/bridge/RateLimiter.ts new file mode 100644 index 000000000..41612cdf2 --- /dev/null +++ b/test/bridge/RateLimiter.ts @@ -0,0 +1,116 @@ +import chai from "chai" +import { solidity } from "ethereum-waffle" +import { deployments, ethers } from "hardhat" +import { BigNumber, BigNumberish, Signer } from "ethers" +import Wallet from "ethereumjs-wallet" + +import { RateLimiter } from "../../build/typechain/RateLimiter" +import { CHAIN_ID } from "../../utils/network" +import { Address } from "hardhat-deploy/dist/types" +import { faker } from "@faker-js/faker" +import { includes } from "lodash" +import {BridgeConfigV3, GenericERC20} from "../../build/typechain"; +import epochSeconds from "@stdlib/time-now"; + +chai.use(solidity) +const { expect, assert } = chai + + +describe("Rate Limiter", () => { + + let signers: Array + let deployer: Signer + let owner: Signer + let attacker: Signer + let rateLimiter: RateLimiter + + let USDC: GenericERC20 + let USDT: GenericERC20 + + // number of minutes in an hour + let hour: number = 60 + + + const setupTest = deployments.createFixture( + async ({ deployments, ethers }) => { + + await deployments.fixture() // ensure you start from a fresh deployments + signers = await ethers.getSigners() + deployer = signers[0] + owner = signers[1] + attacker = signers[10] + + const rateLimiterFactory = await ethers.getContractFactory( + "RateLimiter", + ) + + const erc20Factory = await ethers.getContractFactory("GenericERC20") + + USDC = (await erc20Factory.deploy("USDC", "USDC", "6")) as GenericERC20 + USDT = (await erc20Factory.deploy("USDT", "USDT", "6")) as GenericERC20 + + rateLimiter = (await rateLimiterFactory.deploy()) as RateLimiter + await rateLimiter.initialize(); + + const limiterRole = await rateLimiter.LIMITER_ROLE() + await rateLimiter + .connect(deployer) + .grantRole(limiterRole, await owner.getAddress()) + + // connect the bridge config v3 with the owner. For unauthorized tests, this can be overriden + rateLimiter = rateLimiter.connect(owner) + }, + ) + + beforeEach(async () => { + await setupTest() + }) + + describe("set allowance test", () => { + it("should set alowance correctly", async () => { + const allowance = 100 * Math.pow(10, 6) // allowance of $100 + + const lastReset = Math.floor(epochSeconds()/hour) + + // 1 hour + await expect(await rateLimiter.setAllowance(USDC.address, allowance, 60, lastReset)).to.be.not.reverted + + let [amount, spent, resetTimeMin, lastResetMin, nonce] = await rateLimiter.getTokenAllowance(USDC.address) + expect(allowance).to.be.eq(amount) + expect(spent).to.be.eq(0) + expect(resetTimeMin).to.be.eq(60) + expect(lastResetMin).to.be.eq(lastReset) + // initialized, but with no updates + expect(nonce).to.be.eq(1) + }) + + it("should update allowance", async () => { + // create a bridge as a signer and grant it the bridge role + const bridge: Signer = signers[1] + + // grant our new bridge the role + await rateLimiter.connect(deployer).grantRole(await rateLimiter.BRIDGE_ROLE(), await bridge.getAddress()) + // use rateLimiter as bridge + const bridgeRateLimiter: RateLimiter = await rateLimiter.connect(bridge) + + const allowance = 100 * Math.pow(10, 6) // allowance of $100 + const lastReset = Math.floor(epochSeconds()/hour) + + // reset every hour after current epoch time to an allowance of $100 + expect(rateLimiter.setAllowance(USDC.address, allowance, hour, lastReset)).to.be.not.reverted + + // draw down $10 from allowance + await expect(bridgeRateLimiter.checkAndUpdateAllowance(USDC.address, 10 * Math.pow(10, 6))).to.be.not.reverted + // console.log(await bridgeRateLimiter.checkAndUpdateAllowance(USDC.address, 10 * Math.pow(10, 6))) + + + let [amount, spent, resetTimeMin, lastResetMin, nonce] = await rateLimiter.getTokenAllowance(USDC.address) + expect(amount).to.be.eq(amount) + expect(spent).to.be.eq(10 * Math.pow(10, 6)) + expect(resetTimeMin).to.be.eq(60) + expect(lastResetMin).to.be.eq(lastReset) + // initialized, but with no updates + expect(nonce).to.be.eq(2) + }) + }) +}) From c6f9660e933d522ad1c7bb7db5897b64b0d5c730 Mon Sep 17 00:00:00 2001 From: Trajan0x Date: Tue, 5 Apr 2022 10:04:06 -0400 Subject: [PATCH 005/135] lint --- test/bridge/RateLimiter.ts | 197 +++++++++++++++++++------------------ 1 file changed, 101 insertions(+), 96 deletions(-) diff --git a/test/bridge/RateLimiter.ts b/test/bridge/RateLimiter.ts index 41612cdf2..448b6d422 100644 --- a/test/bridge/RateLimiter.ts +++ b/test/bridge/RateLimiter.ts @@ -9,108 +9,113 @@ import { CHAIN_ID } from "../../utils/network" import { Address } from "hardhat-deploy/dist/types" import { faker } from "@faker-js/faker" import { includes } from "lodash" -import {BridgeConfigV3, GenericERC20} from "../../build/typechain"; -import epochSeconds from "@stdlib/time-now"; +import { BridgeConfigV3, GenericERC20 } from "../../build/typechain" +import epochSeconds from "@stdlib/time-now" chai.use(solidity) const { expect, assert } = chai - describe("Rate Limiter", () => { - - let signers: Array - let deployer: Signer - let owner: Signer - let attacker: Signer - let rateLimiter: RateLimiter - - let USDC: GenericERC20 - let USDT: GenericERC20 - - // number of minutes in an hour - let hour: number = 60 - - - const setupTest = deployments.createFixture( - async ({ deployments, ethers }) => { - - await deployments.fixture() // ensure you start from a fresh deployments - signers = await ethers.getSigners() - deployer = signers[0] - owner = signers[1] - attacker = signers[10] - - const rateLimiterFactory = await ethers.getContractFactory( - "RateLimiter", - ) - - const erc20Factory = await ethers.getContractFactory("GenericERC20") - - USDC = (await erc20Factory.deploy("USDC", "USDC", "6")) as GenericERC20 - USDT = (await erc20Factory.deploy("USDT", "USDT", "6")) as GenericERC20 - - rateLimiter = (await rateLimiterFactory.deploy()) as RateLimiter - await rateLimiter.initialize(); - - const limiterRole = await rateLimiter.LIMITER_ROLE() - await rateLimiter - .connect(deployer) - .grantRole(limiterRole, await owner.getAddress()) - - // connect the bridge config v3 with the owner. For unauthorized tests, this can be overriden - rateLimiter = rateLimiter.connect(owner) - }, - ) - - beforeEach(async () => { - await setupTest() + let signers: Array + let deployer: Signer + let owner: Signer + let attacker: Signer + let rateLimiter: RateLimiter + + let USDC: GenericERC20 + let USDT: GenericERC20 + + // number of minutes in an hour + let hour: number = 60 + + const setupTest = deployments.createFixture( + async ({ deployments, ethers }) => { + await deployments.fixture() // ensure you start from a fresh deployments + signers = await ethers.getSigners() + deployer = signers[0] + owner = signers[1] + attacker = signers[10] + + const rateLimiterFactory = await ethers.getContractFactory("RateLimiter") + + const erc20Factory = await ethers.getContractFactory("GenericERC20") + + USDC = (await erc20Factory.deploy("USDC", "USDC", "6")) as GenericERC20 + USDT = (await erc20Factory.deploy("USDT", "USDT", "6")) as GenericERC20 + + rateLimiter = (await rateLimiterFactory.deploy()) as RateLimiter + await rateLimiter.initialize() + + const limiterRole = await rateLimiter.LIMITER_ROLE() + await rateLimiter + .connect(deployer) + .grantRole(limiterRole, await owner.getAddress()) + + // connect the bridge config v3 with the owner. For unauthorized tests, this can be overriden + rateLimiter = rateLimiter.connect(owner) + }, + ) + + beforeEach(async () => { + await setupTest() + }) + + describe("set allowance test", () => { + it("should set alowance correctly", async () => { + const allowance = 100 * Math.pow(10, 6) // allowance of $100 + + const lastReset = Math.floor(epochSeconds() / hour) + + // 1 hour + await expect( + await rateLimiter.setAllowance(USDC.address, allowance, 60, lastReset), + ).to.be.not.reverted + + let [amount, spent, resetTimeMin, lastResetMin, nonce] = + await rateLimiter.getTokenAllowance(USDC.address) + expect(allowance).to.be.eq(amount) + expect(spent).to.be.eq(0) + expect(resetTimeMin).to.be.eq(60) + expect(lastResetMin).to.be.eq(lastReset) + // initialized, but with no updates + expect(nonce).to.be.eq(1) }) - describe("set allowance test", () => { - it("should set alowance correctly", async () => { - const allowance = 100 * Math.pow(10, 6) // allowance of $100 - - const lastReset = Math.floor(epochSeconds()/hour) - - // 1 hour - await expect(await rateLimiter.setAllowance(USDC.address, allowance, 60, lastReset)).to.be.not.reverted - - let [amount, spent, resetTimeMin, lastResetMin, nonce] = await rateLimiter.getTokenAllowance(USDC.address) - expect(allowance).to.be.eq(amount) - expect(spent).to.be.eq(0) - expect(resetTimeMin).to.be.eq(60) - expect(lastResetMin).to.be.eq(lastReset) - // initialized, but with no updates - expect(nonce).to.be.eq(1) - }) - - it("should update allowance", async () => { - // create a bridge as a signer and grant it the bridge role - const bridge: Signer = signers[1] - - // grant our new bridge the role - await rateLimiter.connect(deployer).grantRole(await rateLimiter.BRIDGE_ROLE(), await bridge.getAddress()) - // use rateLimiter as bridge - const bridgeRateLimiter: RateLimiter = await rateLimiter.connect(bridge) - - const allowance = 100 * Math.pow(10, 6) // allowance of $100 - const lastReset = Math.floor(epochSeconds()/hour) - - // reset every hour after current epoch time to an allowance of $100 - expect(rateLimiter.setAllowance(USDC.address, allowance, hour, lastReset)).to.be.not.reverted - - // draw down $10 from allowance - await expect(bridgeRateLimiter.checkAndUpdateAllowance(USDC.address, 10 * Math.pow(10, 6))).to.be.not.reverted - // console.log(await bridgeRateLimiter.checkAndUpdateAllowance(USDC.address, 10 * Math.pow(10, 6))) - - - let [amount, spent, resetTimeMin, lastResetMin, nonce] = await rateLimiter.getTokenAllowance(USDC.address) - expect(amount).to.be.eq(amount) - expect(spent).to.be.eq(10 * Math.pow(10, 6)) - expect(resetTimeMin).to.be.eq(60) - expect(lastResetMin).to.be.eq(lastReset) - // initialized, but with no updates - expect(nonce).to.be.eq(2) - }) + it("should update allowance", async () => { + // create a bridge as a signer and grant it the bridge role + const bridge: Signer = signers[1] + + // grant our new bridge the role + await rateLimiter + .connect(deployer) + .grantRole(await rateLimiter.BRIDGE_ROLE(), await bridge.getAddress()) + // use rateLimiter as bridge + const bridgeRateLimiter: RateLimiter = await rateLimiter.connect(bridge) + + const allowance = 100 * Math.pow(10, 6) // allowance of $100 + const lastReset = Math.floor(epochSeconds() / hour) + + // reset every hour after current epoch time to an allowance of $100 + expect(rateLimiter.setAllowance(USDC.address, allowance, hour, lastReset)) + .to.be.not.reverted + + // draw down $10 from allowance + await expect( + bridgeRateLimiter.checkAndUpdateAllowance( + USDC.address, + 10 * Math.pow(10, 6), + ), + ).to.be.not.reverted + // console.log(await bridgeRateLimiter.checkAndUpdateAllowance(USDC.address, 10 * Math.pow(10, 6))) + + let [amount, spent, resetTimeMin, lastResetMin, nonce] = + await rateLimiter.getTokenAllowance(USDC.address) + expect(amount).to.be.eq(amount) + expect(spent).to.be.eq(10 * Math.pow(10, 6)) + expect(resetTimeMin).to.be.eq(60) + expect(lastResetMin).to.be.eq(lastReset) + // initialized, but with no updates + expect(nonce).to.be.eq(2) }) + }) }) From 6ff2306039c13b95b3cb0207ecd035007d1cb8f6 Mon Sep 17 00:00:00 2001 From: Trajan0x Date: Tue, 5 Apr 2022 12:18:14 -0400 Subject: [PATCH 006/135] add initial test set --- contracts/bridge/RateLimiter.sol | 15 +- contracts/bridge/testing/RateLimiterTest.sol | 43 ++ docs/bridge/RateLimiter.md | 521 ++++++++++++++++++ docs/bridge/SynapseBridge.md | 50 ++ docs/bridge/interfaces/IRateLimiter.md | 55 ++ docs/bridge/testing/RateLimiterTest.md | 99 ++++ .../access/AccessControlUpgradeable.md | 207 +++++++ .../access/IAccessControlUpgradeable.md | 168 ++++++ .../proxy/utils/Initializable.md | 12 + .../security/ReentrancyGuardUpgradeable.md | 12 + .../utils/AddressUpgradeable.md | 12 + .../utils/ContextUpgradeable.md | 12 + .../utils/StringsUpgradeable.md | 12 + .../utils/introspection/ERC165Upgradeable.md | 37 ++ .../utils/introspection/IERC165Upgradeable.md | 37 ++ hardhat.config.ts | 5 +- test/bridge/RateLimiter.ts | 73 ++- 17 files changed, 1337 insertions(+), 33 deletions(-) create mode 100644 contracts/bridge/testing/RateLimiterTest.sol create mode 100644 docs/bridge/RateLimiter.md create mode 100644 docs/bridge/interfaces/IRateLimiter.md create mode 100644 docs/bridge/testing/RateLimiterTest.md create mode 100644 docs/elin/contracts-4.3.1-upgradeable/access/AccessControlUpgradeable.md create mode 100644 docs/elin/contracts-4.3.1-upgradeable/access/IAccessControlUpgradeable.md create mode 100644 docs/elin/contracts-4.3.1-upgradeable/proxy/utils/Initializable.md create mode 100644 docs/elin/contracts-4.3.1-upgradeable/security/ReentrancyGuardUpgradeable.md create mode 100644 docs/elin/contracts-4.3.1-upgradeable/utils/AddressUpgradeable.md create mode 100644 docs/elin/contracts-4.3.1-upgradeable/utils/ContextUpgradeable.md create mode 100644 docs/elin/contracts-4.3.1-upgradeable/utils/StringsUpgradeable.md create mode 100644 docs/elin/contracts-4.3.1-upgradeable/utils/introspection/ERC165Upgradeable.md create mode 100644 docs/elin/contracts-4.3.1-upgradeable/utils/introspection/IERC165Upgradeable.md diff --git a/contracts/bridge/RateLimiter.sol b/contracts/bridge/RateLimiter.sol index a9ac778d4..f0a1207f8 100644 --- a/contracts/bridge/RateLimiter.sol +++ b/contracts/bridge/RateLimiter.sol @@ -5,7 +5,6 @@ import "@openzeppelin/contracts-4.3.1-upgradeable/proxy/utils/Initializable.sol" import "@openzeppelin/contracts-4.3.1-upgradeable/access/AccessControlUpgradeable.sol"; import "@openzeppelin/contracts-4.3.1-upgradeable/security/ReentrancyGuardUpgradeable.sol"; import "./interfaces/IRateLimiter.sol"; -import "hardhat/console.sol"; // @title RateLimiter // @dev a bridge asset rate limiter based on https://github.com/gnosis/safe-modules/blob/master/allowances/contracts/AlowanceModule.sol @@ -50,7 +49,7 @@ contract RateLimiter is uint96 spent; uint16 resetTimeMin; // Maximum reset time span is 65k minutes uint32 lastResetMin; // epoch/60 - uint16 nonce; + bool initialized; } /*** FUNCTIONS ***/ @@ -74,10 +73,9 @@ contract RateLimiter is uint32 resetBaseMin ) public onlyRole(LIMITER_ROLE) { Allowance memory allowance = getAllowance(token); - if (allowance.nonce == 0) { + if (!allowance.initialized) { // New token - // Nonce should never be 0 once allowance has been activated - allowance.nonce = 1; + allowance.initialized = true; tokens.push(token); } // Divide by 60 to get current time in minutes @@ -140,7 +138,6 @@ contract RateLimiter is Allowance memory allowance = getAllowance(token); // Update state - allowance.nonce = allowance.nonce + 1; // @dev reverts if amount > (2^96 - 1) uint96 newSpent = allowance.spent + uint96(amount); @@ -156,7 +153,6 @@ contract RateLimiter is } allowance.spent = newSpent; - console.log(allowance.spent); updateAllowance(token, allowance); return true; @@ -186,15 +182,14 @@ contract RateLimiter is function getTokenAllowance(address token) public view - returns (uint256[5] memory) + returns (uint256[4] memory) { Allowance memory allowance = getAllowance(token); return [ uint256(allowance.amount), uint256(allowance.spent), uint256(allowance.resetTimeMin), - uint256(allowance.lastResetMin), - uint256(allowance.nonce) + uint256(allowance.lastResetMin) ]; } } diff --git a/contracts/bridge/testing/RateLimiterTest.sol b/contracts/bridge/testing/RateLimiterTest.sol new file mode 100644 index 000000000..1002fcbfd --- /dev/null +++ b/contracts/bridge/testing/RateLimiterTest.sol @@ -0,0 +1,43 @@ +// SPDX-License-Identifier: LGPL-3.0-only +pragma solidity ^0.8.0; + +import "../interfaces/IRateLimiter.sol"; +import "@openzeppelin/contracts-4.3.1-upgradeable/proxy/utils/Initializable.sol"; + +/// @title RateLimiterTest +// @dev this contract is used to test RateLimiter's checkAndUpdateAllowance method's return value +// because web3 libraries don't provide an interface for retrieving boolean values from a non-view function +// we store the return value here for retrieval later. + +contract RateLimiterTest is Initializable { + /*** STATE ***/ + + string public constant NAME = "Rate Limiter Test"; + string public constant VERSION = "0.1.0"; + + // @dev stores the return value of checkAndUpdateAllowance + bool checkAndUpdateReturn; + // @dev whether or not a value has been stored at least once. Used to revert if developer calls + // getLastUpdateValue without a store first + bool stored; + + // the rate limiter contract + IRateLimiter rateLimiter; + + function initialize(IRateLimiter _rateLimiter) external initializer { + rateLimiter = _rateLimiter; + } + + // @dev stores the last value of check and update allowance + function storeCheckAndUpdateAllowance(address token, uint256 amount) external { + stored = true; + checkAndUpdateReturn = rateLimiter.checkAndUpdateAllowance(token, amount); + } + + // @dev gets the most recent value returned by storeCheckAndUpdateAllowance + // reverts if no value stored yet + function getLastUpdateValue() external view returns (bool){ + require(stored, "no update value has been stored yet"); + return checkAndUpdateReturn; + } +} diff --git a/docs/bridge/RateLimiter.md b/docs/bridge/RateLimiter.md new file mode 100644 index 000000000..4095ee02e --- /dev/null +++ b/docs/bridge/RateLimiter.md @@ -0,0 +1,521 @@ +# RateLimiter + + + + + + + + + +## Methods + +### BRIDGE_ROLE + +```solidity +function BRIDGE_ROLE() external view returns (bytes32) +``` + + + + + + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | bytes32 | undefined | + +### DEFAULT_ADMIN_ROLE + +```solidity +function DEFAULT_ADMIN_ROLE() external view returns (bytes32) +``` + + + + + + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | bytes32 | undefined | + +### GOVERNANCE_ROLE + +```solidity +function GOVERNANCE_ROLE() external view returns (bytes32) +``` + + + + + + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | bytes32 | undefined | + +### LIMITER_ROLE + +```solidity +function LIMITER_ROLE() external view returns (bytes32) +``` + + + + + + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | bytes32 | undefined | + +### NAME + +```solidity +function NAME() external view returns (string) +``` + + + + + + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | string | undefined | + +### VERSION + +```solidity +function VERSION() external view returns (string) +``` + + + + + + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | string | undefined | + +### addToRetryQueue + +```solidity +function addToRetryQueue(bytes32 kappa, bytes rateLimited) external nonpayable +``` + + + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| kappa | bytes32 | undefined | +| rateLimited | bytes | undefined | + +### allowances + +```solidity +function allowances(address) external view returns (uint96 amount, uint96 spent, uint16 resetTimeMin, uint32 lastResetMin, bool initialized) +``` + + + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| _0 | address | undefined | + +#### Returns + +| Name | Type | Description | +|---|---|---| +| amount | uint96 | undefined | +| spent | uint96 | undefined | +| resetTimeMin | uint16 | undefined | +| lastResetMin | uint32 | undefined | +| initialized | bool | undefined | + +### checkAndUpdateAllowance + +```solidity +function checkAndUpdateAllowance(address token, uint256 amount) external nonpayable returns (bool) +``` + +Checks the allowance for a given token. If the new amount exceeds the allowance, it is not updated and false is returned otherwise true is returned and the transaction can proceed + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| token | address | undefined | +| amount | uint256 | to transfer* | + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | bool | undefined | + +### getRoleAdmin + +```solidity +function getRoleAdmin(bytes32 role) external view returns (bytes32) +``` + + + +*Returns the admin role that controls `role`. See {grantRole} and {revokeRole}. To change a role's admin, use {_setRoleAdmin}.* + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| role | bytes32 | undefined | + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | bytes32 | undefined | + +### getTokenAllowance + +```solidity +function getTokenAllowance(address token) external view returns (uint256[4]) +``` + + + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| token | address | undefined | + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | uint256[4] | undefined | + +### getTokens + +```solidity +function getTokens() external view returns (address[]) +``` + +Gets a list of tokens with allowances* + + + + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | address[] | undefined | + +### grantRole + +```solidity +function grantRole(bytes32 role, address account) external nonpayable +``` + + + +*Grants `role` to `account`. If `account` had not been already granted `role`, emits a {RoleGranted} event. Requirements: - the caller must have ``role``'s admin role.* + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| role | bytes32 | undefined | +| account | address | undefined | + +### hasRole + +```solidity +function hasRole(bytes32 role, address account) external view returns (bool) +``` + + + +*Returns `true` if `account` has been granted `role`.* + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| role | bytes32 | undefined | +| account | address | undefined | + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | bool | undefined | + +### initialize + +```solidity +function initialize() external nonpayable +``` + + + + + + +### limited + +```solidity +function limited(bytes32) external view returns (bytes) +``` + + + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| _0 | bytes32 | undefined | + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | bytes | undefined | + +### renounceRole + +```solidity +function renounceRole(bytes32 role, address account) external nonpayable +``` + + + +*Revokes `role` from the calling account. Roles are often managed via {grantRole} and {revokeRole}: this function's purpose is to provide a mechanism for accounts to lose their privileges if they are compromised (such as when a trusted device is misplaced). If the calling account had been revoked `role`, emits a {RoleRevoked} event. Requirements: - the caller must be `account`.* + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| role | bytes32 | undefined | +| account | address | undefined | + +### resetAllowance + +```solidity +function resetAllowance(address token) external nonpayable +``` + + + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| token | address | undefined | + +### revokeRole + +```solidity +function revokeRole(bytes32 role, address account) external nonpayable +``` + + + +*Revokes `role` from `account`. If `account` had been granted `role`, emits a {RoleRevoked} event. Requirements: - the caller must have ``role``'s admin role.* + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| role | bytes32 | undefined | +| account | address | undefined | + +### setAllowance + +```solidity +function setAllowance(address token, uint96 allowanceAmount, uint16 resetTimeMin, uint32 resetBaseMin) external nonpayable +``` + +Updates the allowance for a given token + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| token | address | to update the allowance for | +| allowanceAmount | uint96 | for the token | +| resetTimeMin | uint16 | minimum reset time (amount goes to 0 after this) | +| resetBaseMin | uint32 | amount Amount in native token decimals to transfer cross-chain pre-fees* | + +### supportsInterface + +```solidity +function supportsInterface(bytes4 interfaceId) external view returns (bool) +``` + + + +*See {IERC165-supportsInterface}.* + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| interfaceId | bytes4 | undefined | + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | bool | undefined | + +### tokens + +```solidity +function tokens(uint256) external view returns (address) +``` + + + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| _0 | uint256 | undefined | + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | address | undefined | + + + +## Events + +### ResetAllowance + +```solidity +event ResetAllowance(address indexed token) +``` + + + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| token `indexed` | address | undefined | + +### RoleAdminChanged + +```solidity +event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole) +``` + + + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| role `indexed` | bytes32 | undefined | +| previousAdminRole `indexed` | bytes32 | undefined | +| newAdminRole `indexed` | bytes32 | undefined | + +### RoleGranted + +```solidity +event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender) +``` + + + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| role `indexed` | bytes32 | undefined | +| account `indexed` | address | undefined | +| sender `indexed` | address | undefined | + +### RoleRevoked + +```solidity +event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender) +``` + + + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| role `indexed` | bytes32 | undefined | +| account `indexed` | address | undefined | +| sender `indexed` | address | undefined | + +### SetAllowance + +```solidity +event SetAllowance(address indexed token, uint96 allowanceAmount, uint16 resetTime) +``` + + + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| token `indexed` | address | undefined | +| allowanceAmount | uint96 | undefined | +| resetTime | uint16 | undefined | + + + diff --git a/docs/bridge/SynapseBridge.md b/docs/bridge/SynapseBridge.md index d25a9b9ae..99199b4ba 100644 --- a/docs/bridge/SynapseBridge.md +++ b/docs/bridge/SynapseBridge.md @@ -55,6 +55,23 @@ function NODEGROUP_ROLE() external view returns (bytes32) +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | bytes32 | undefined | + +### RATE_LIMITER_ROLE + +```solidity +function RATE_LIMITER_ROLE() external view returns (bytes32) +``` + + + + + + #### Returns | Name | Type | Description | @@ -405,6 +422,23 @@ function paused() external view returns (bool) |---|---|---| | _0 | bool | undefined | +### rateLimiter + +```solidity +function rateLimiter() external view returns (contract IRateLimiter) +``` + + + + + + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | contract IRateLimiter | undefined | + ### redeem ```solidity @@ -538,6 +572,22 @@ function setChainGasAmount(uint256 amount) external nonpayable |---|---|---| | amount | uint256 | undefined | +### setRateLimiter + +```solidity +function setRateLimiter(contract IRateLimiter _rateLimiter) external nonpayable +``` + + + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| _rateLimiter | contract IRateLimiter | undefined | + ### setWethAddress ```solidity diff --git a/docs/bridge/interfaces/IRateLimiter.md b/docs/bridge/interfaces/IRateLimiter.md new file mode 100644 index 000000000..af17d1249 --- /dev/null +++ b/docs/bridge/interfaces/IRateLimiter.md @@ -0,0 +1,55 @@ +# IRateLimiter + + + + + + + + + +## Methods + +### addToRetryQueue + +```solidity +function addToRetryQueue(bytes32 kappa, bytes rateLimited) external nonpayable +``` + + + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| kappa | bytes32 | undefined | +| rateLimited | bytes | undefined | + +### checkAndUpdateAllowance + +```solidity +function checkAndUpdateAllowance(address token, uint256 amount) external nonpayable returns (bool) +``` + + + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| token | address | undefined | +| amount | uint256 | undefined | + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | bool | undefined | + + + + diff --git a/docs/bridge/testing/RateLimiterTest.md b/docs/bridge/testing/RateLimiterTest.md new file mode 100644 index 000000000..ee9f12865 --- /dev/null +++ b/docs/bridge/testing/RateLimiterTest.md @@ -0,0 +1,99 @@ +# RateLimiterTest + + + +> RateLimiterTest + + + + + +## Methods + +### NAME + +```solidity +function NAME() external view returns (string) +``` + + + + + + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | string | undefined | + +### VERSION + +```solidity +function VERSION() external view returns (string) +``` + + + + + + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | string | undefined | + +### getLastUpdateValue + +```solidity +function getLastUpdateValue() external view returns (bool) +``` + + + + + + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | bool | undefined | + +### initialize + +```solidity +function initialize(contract IRateLimiter _rateLimiter) external nonpayable +``` + + + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| _rateLimiter | contract IRateLimiter | undefined | + +### storeCheckAndUpdateAllowance + +```solidity +function storeCheckAndUpdateAllowance(address token, uint256 amount) external nonpayable +``` + + + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| token | address | undefined | +| amount | uint256 | undefined | + + + + diff --git a/docs/elin/contracts-4.3.1-upgradeable/access/AccessControlUpgradeable.md b/docs/elin/contracts-4.3.1-upgradeable/access/AccessControlUpgradeable.md new file mode 100644 index 000000000..c52e7d992 --- /dev/null +++ b/docs/elin/contracts-4.3.1-upgradeable/access/AccessControlUpgradeable.md @@ -0,0 +1,207 @@ +# AccessControlUpgradeable + + + + + + + +*Contract module that allows children to implement role-based access control mechanisms. This is a lightweight version that doesn't allow enumerating role members except through off-chain means by accessing the contract event logs. Some applications may benefit from on-chain enumerability, for those cases see {AccessControlEnumerable}. Roles are referred to by their `bytes32` identifier. These should be exposed in the external API and be unique. The best way to achieve this is by using `public constant` hash digests: ``` bytes32 public constant MY_ROLE = keccak256("MY_ROLE"); ``` Roles can be used to represent a set of permissions. To restrict access to a function call, use {hasRole}: ``` function foo() public { require(hasRole(MY_ROLE, msg.sender)); ... } ``` Roles can be granted and revoked dynamically via the {grantRole} and {revokeRole} functions. Each role has an associated admin role, and only accounts that have a role's admin role can call {grantRole} and {revokeRole}. By default, the admin role for all roles is `DEFAULT_ADMIN_ROLE`, which means that only accounts with this role will be able to grant or revoke other roles. More complex role relationships can be created by using {_setRoleAdmin}. WARNING: The `DEFAULT_ADMIN_ROLE` is also its own admin: it has permission to grant and revoke this role. Extra precautions should be taken to secure accounts that have been granted it.* + +## Methods + +### DEFAULT_ADMIN_ROLE + +```solidity +function DEFAULT_ADMIN_ROLE() external view returns (bytes32) +``` + + + + + + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | bytes32 | undefined | + +### getRoleAdmin + +```solidity +function getRoleAdmin(bytes32 role) external view returns (bytes32) +``` + + + +*Returns the admin role that controls `role`. See {grantRole} and {revokeRole}. To change a role's admin, use {_setRoleAdmin}.* + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| role | bytes32 | undefined | + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | bytes32 | undefined | + +### grantRole + +```solidity +function grantRole(bytes32 role, address account) external nonpayable +``` + + + +*Grants `role` to `account`. If `account` had not been already granted `role`, emits a {RoleGranted} event. Requirements: - the caller must have ``role``'s admin role.* + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| role | bytes32 | undefined | +| account | address | undefined | + +### hasRole + +```solidity +function hasRole(bytes32 role, address account) external view returns (bool) +``` + + + +*Returns `true` if `account` has been granted `role`.* + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| role | bytes32 | undefined | +| account | address | undefined | + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | bool | undefined | + +### renounceRole + +```solidity +function renounceRole(bytes32 role, address account) external nonpayable +``` + + + +*Revokes `role` from the calling account. Roles are often managed via {grantRole} and {revokeRole}: this function's purpose is to provide a mechanism for accounts to lose their privileges if they are compromised (such as when a trusted device is misplaced). If the calling account had been revoked `role`, emits a {RoleRevoked} event. Requirements: - the caller must be `account`.* + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| role | bytes32 | undefined | +| account | address | undefined | + +### revokeRole + +```solidity +function revokeRole(bytes32 role, address account) external nonpayable +``` + + + +*Revokes `role` from `account`. If `account` had been granted `role`, emits a {RoleRevoked} event. Requirements: - the caller must have ``role``'s admin role.* + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| role | bytes32 | undefined | +| account | address | undefined | + +### supportsInterface + +```solidity +function supportsInterface(bytes4 interfaceId) external view returns (bool) +``` + + + +*See {IERC165-supportsInterface}.* + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| interfaceId | bytes4 | undefined | + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | bool | undefined | + + + +## Events + +### RoleAdminChanged + +```solidity +event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole) +``` + + + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| role `indexed` | bytes32 | undefined | +| previousAdminRole `indexed` | bytes32 | undefined | +| newAdminRole `indexed` | bytes32 | undefined | + +### RoleGranted + +```solidity +event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender) +``` + + + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| role `indexed` | bytes32 | undefined | +| account `indexed` | address | undefined | +| sender `indexed` | address | undefined | + +### RoleRevoked + +```solidity +event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender) +``` + + + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| role `indexed` | bytes32 | undefined | +| account `indexed` | address | undefined | +| sender `indexed` | address | undefined | + + + diff --git a/docs/elin/contracts-4.3.1-upgradeable/access/IAccessControlUpgradeable.md b/docs/elin/contracts-4.3.1-upgradeable/access/IAccessControlUpgradeable.md new file mode 100644 index 000000000..4ad76fe12 --- /dev/null +++ b/docs/elin/contracts-4.3.1-upgradeable/access/IAccessControlUpgradeable.md @@ -0,0 +1,168 @@ +# IAccessControlUpgradeable + + + + + + + +*External interface of AccessControl declared to support ERC165 detection.* + +## Methods + +### getRoleAdmin + +```solidity +function getRoleAdmin(bytes32 role) external view returns (bytes32) +``` + + + +*Returns the admin role that controls `role`. See {grantRole} and {revokeRole}. To change a role's admin, use {AccessControl-_setRoleAdmin}.* + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| role | bytes32 | undefined | + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | bytes32 | undefined | + +### grantRole + +```solidity +function grantRole(bytes32 role, address account) external nonpayable +``` + + + +*Grants `role` to `account`. If `account` had not been already granted `role`, emits a {RoleGranted} event. Requirements: - the caller must have ``role``'s admin role.* + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| role | bytes32 | undefined | +| account | address | undefined | + +### hasRole + +```solidity +function hasRole(bytes32 role, address account) external view returns (bool) +``` + + + +*Returns `true` if `account` has been granted `role`.* + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| role | bytes32 | undefined | +| account | address | undefined | + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | bool | undefined | + +### renounceRole + +```solidity +function renounceRole(bytes32 role, address account) external nonpayable +``` + + + +*Revokes `role` from the calling account. Roles are often managed via {grantRole} and {revokeRole}: this function's purpose is to provide a mechanism for accounts to lose their privileges if they are compromised (such as when a trusted device is misplaced). If the calling account had been granted `role`, emits a {RoleRevoked} event. Requirements: - the caller must be `account`.* + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| role | bytes32 | undefined | +| account | address | undefined | + +### revokeRole + +```solidity +function revokeRole(bytes32 role, address account) external nonpayable +``` + + + +*Revokes `role` from `account`. If `account` had been granted `role`, emits a {RoleRevoked} event. Requirements: - the caller must have ``role``'s admin role.* + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| role | bytes32 | undefined | +| account | address | undefined | + + + +## Events + +### RoleAdminChanged + +```solidity +event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole) +``` + + + +*Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole` `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite {RoleAdminChanged} not being emitted signaling this. _Available since v3.1._* + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| role `indexed` | bytes32 | undefined | +| previousAdminRole `indexed` | bytes32 | undefined | +| newAdminRole `indexed` | bytes32 | undefined | + +### RoleGranted + +```solidity +event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender) +``` + + + +*Emitted when `account` is granted `role`. `sender` is the account that originated the contract call, an admin role bearer except when using {AccessControl-_setupRole}.* + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| role `indexed` | bytes32 | undefined | +| account `indexed` | address | undefined | +| sender `indexed` | address | undefined | + +### RoleRevoked + +```solidity +event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender) +``` + + + +*Emitted when `account` is revoked `role`. `sender` is the account that originated the contract call: - if using `revokeRole`, it is the admin role bearer - if using `renounceRole`, it is the role bearer (i.e. `account`)* + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| role `indexed` | bytes32 | undefined | +| account `indexed` | address | undefined | +| sender `indexed` | address | undefined | + + + diff --git a/docs/elin/contracts-4.3.1-upgradeable/proxy/utils/Initializable.md b/docs/elin/contracts-4.3.1-upgradeable/proxy/utils/Initializable.md new file mode 100644 index 000000000..647d95b62 --- /dev/null +++ b/docs/elin/contracts-4.3.1-upgradeable/proxy/utils/Initializable.md @@ -0,0 +1,12 @@ +# Initializable + + + + + + + +*This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed behind a proxy. Since proxied contracts do not make use of a constructor, it's common to move constructor logic to an external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer function so it can only be called once. The {initializer} modifier provided by this contract will have this effect. TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as possible by providing the encoded function call as the `_data` argument to {ERC1967Proxy-constructor}. CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure that all initializers are idempotent. This is not verified automatically as constructors are by Solidity. [CAUTION] ==== Avoid leaving a contract uninitialized. An uninitialized contract can be taken over by an attacker. This applies to both a proxy and its implementation contract, which may impact the proxy. To initialize the implementation contract, you can either invoke the initializer manually, or you can include a constructor to automatically mark it as initialized when it is deployed: [.hljs-theme-light.nopadding] ```* + + + diff --git a/docs/elin/contracts-4.3.1-upgradeable/security/ReentrancyGuardUpgradeable.md b/docs/elin/contracts-4.3.1-upgradeable/security/ReentrancyGuardUpgradeable.md new file mode 100644 index 000000000..6955ca2de --- /dev/null +++ b/docs/elin/contracts-4.3.1-upgradeable/security/ReentrancyGuardUpgradeable.md @@ -0,0 +1,12 @@ +# ReentrancyGuardUpgradeable + + + + + + + +*Contract module that helps prevent reentrant calls to a function. Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier available, which can be applied to functions to make sure there are no nested (reentrant) calls to them. Note that because there is a single `nonReentrant` guard, functions marked as `nonReentrant` may not call one another. This can be worked around by making those functions `private`, and then adding `external` `nonReentrant` entry points to them. TIP: If you would like to learn more about reentrancy and alternative ways to protect against it, check out our blog post https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul].* + + + diff --git a/docs/elin/contracts-4.3.1-upgradeable/utils/AddressUpgradeable.md b/docs/elin/contracts-4.3.1-upgradeable/utils/AddressUpgradeable.md new file mode 100644 index 000000000..456cdd15d --- /dev/null +++ b/docs/elin/contracts-4.3.1-upgradeable/utils/AddressUpgradeable.md @@ -0,0 +1,12 @@ +# AddressUpgradeable + + + + + + + +*Collection of functions related to the address type* + + + diff --git a/docs/elin/contracts-4.3.1-upgradeable/utils/ContextUpgradeable.md b/docs/elin/contracts-4.3.1-upgradeable/utils/ContextUpgradeable.md new file mode 100644 index 000000000..18f33b80f --- /dev/null +++ b/docs/elin/contracts-4.3.1-upgradeable/utils/ContextUpgradeable.md @@ -0,0 +1,12 @@ +# ContextUpgradeable + + + + + + + +*Provides information about the current execution context, including the sender of the transaction and its data. While these are generally available via msg.sender and msg.data, they should not be accessed in such a direct manner, since when dealing with meta-transactions the account sending and paying for execution may not be the actual sender (as far as an application is concerned). This contract is only required for intermediate, library-like contracts.* + + + diff --git a/docs/elin/contracts-4.3.1-upgradeable/utils/StringsUpgradeable.md b/docs/elin/contracts-4.3.1-upgradeable/utils/StringsUpgradeable.md new file mode 100644 index 000000000..84464ba83 --- /dev/null +++ b/docs/elin/contracts-4.3.1-upgradeable/utils/StringsUpgradeable.md @@ -0,0 +1,12 @@ +# StringsUpgradeable + + + + + + + +*String operations.* + + + diff --git a/docs/elin/contracts-4.3.1-upgradeable/utils/introspection/ERC165Upgradeable.md b/docs/elin/contracts-4.3.1-upgradeable/utils/introspection/ERC165Upgradeable.md new file mode 100644 index 000000000..914b09248 --- /dev/null +++ b/docs/elin/contracts-4.3.1-upgradeable/utils/introspection/ERC165Upgradeable.md @@ -0,0 +1,37 @@ +# ERC165Upgradeable + + + + + + + +*Implementation of the {IERC165} interface. Contracts that want to implement ERC165 should inherit from this contract and override {supportsInterface} to check for the additional interface id that will be supported. For example: ```solidity function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) { return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId); } ``` Alternatively, {ERC165Storage} provides an easier to use but more expensive implementation.* + +## Methods + +### supportsInterface + +```solidity +function supportsInterface(bytes4 interfaceId) external view returns (bool) +``` + + + +*See {IERC165-supportsInterface}.* + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| interfaceId | bytes4 | undefined | + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | bool | undefined | + + + + diff --git a/docs/elin/contracts-4.3.1-upgradeable/utils/introspection/IERC165Upgradeable.md b/docs/elin/contracts-4.3.1-upgradeable/utils/introspection/IERC165Upgradeable.md new file mode 100644 index 000000000..40ec0512e --- /dev/null +++ b/docs/elin/contracts-4.3.1-upgradeable/utils/introspection/IERC165Upgradeable.md @@ -0,0 +1,37 @@ +# IERC165Upgradeable + + + + + + + +*Interface of the ERC165 standard, as defined in the https://eips.ethereum.org/EIPS/eip-165[EIP]. Implementers can declare support of contract interfaces, which can then be queried by others ({ERC165Checker}). For an implementation, see {ERC165}.* + +## Methods + +### supportsInterface + +```solidity +function supportsInterface(bytes4 interfaceId) external view returns (bool) +``` + + + +*Returns true if this contract implements the interface defined by `interfaceId`. See the corresponding https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section] to learn more about how these ids are created. This function call must use less than 30 000 gas.* + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| interfaceId | bytes4 | undefined | + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | bool | undefined | + + + + diff --git a/hardhat.config.ts b/hardhat.config.ts index 7aff0d6ce..d96730c54 100644 --- a/hardhat.config.ts +++ b/hardhat.config.ts @@ -103,11 +103,10 @@ let config: HardhatUserConfig = { target: "ethers-v5", }, dodoc: { - // TODO, re-enable. RateLimiter is breaking this - runOnCompile: false, + runOnCompile: true, debugMode: false, // pre solidity 5 breaks docgen - exclude: ["MultisigWallet", "WETH9", "RateLimiter"] + exclude: ["MultisigWallet", "WETH9"] // More options... }, solidity: { diff --git a/test/bridge/RateLimiter.ts b/test/bridge/RateLimiter.ts index 448b6d422..b41c818cf 100644 --- a/test/bridge/RateLimiter.ts +++ b/test/bridge/RateLimiter.ts @@ -9,7 +9,11 @@ import { CHAIN_ID } from "../../utils/network" import { Address } from "hardhat-deploy/dist/types" import { faker } from "@faker-js/faker" import { includes } from "lodash" -import { BridgeConfigV3, GenericERC20 } from "../../build/typechain" +import { + BridgeConfigV3, + GenericERC20, + RateLimiterTest, +} from "../../build/typechain" import epochSeconds from "@stdlib/time-now" chai.use(solidity) @@ -21,6 +25,7 @@ describe("Rate Limiter", () => { let owner: Signer let attacker: Signer let rateLimiter: RateLimiter + let rateLimiterTest: RateLimiterTest let USDC: GenericERC20 let USDT: GenericERC20 @@ -38,21 +43,37 @@ describe("Rate Limiter", () => { const rateLimiterFactory = await ethers.getContractFactory("RateLimiter") + // deploy 2 test erc-20's const erc20Factory = await ethers.getContractFactory("GenericERC20") USDC = (await erc20Factory.deploy("USDC", "USDC", "6")) as GenericERC20 USDT = (await erc20Factory.deploy("USDT", "USDT", "6")) as GenericERC20 + // deploy and initialize the rate limiter rateLimiter = (await rateLimiterFactory.deploy()) as RateLimiter await rateLimiter.initialize() const limiterRole = await rateLimiter.LIMITER_ROLE() + const bridgeRole = await rateLimiter.BRIDGE_ROLE() await rateLimiter .connect(deployer) .grantRole(limiterRole, await owner.getAddress()) // connect the bridge config v3 with the owner. For unauthorized tests, this can be overriden rateLimiter = rateLimiter.connect(owner) + + // deploy the rateLimiterTest + const rateLimiterTestFactory = await ethers.getContractFactory( + "RateLimiterTest", + ) + rateLimiterTest = + (await rateLimiterTestFactory.deploy()) as RateLimiterTest + await rateLimiterTest.initialize(rateLimiter.address) + + // grant the bridge role to rateLimiterTest + await rateLimiter + .connect(deployer) + .grantRole(bridgeRole, rateLimiterTest.address) }, ) @@ -68,30 +89,18 @@ describe("Rate Limiter", () => { // 1 hour await expect( - await rateLimiter.setAllowance(USDC.address, allowance, 60, lastReset), + rateLimiter.setAllowance(USDC.address, allowance, 60, lastReset), ).to.be.not.reverted - let [amount, spent, resetTimeMin, lastResetMin, nonce] = + let [amount, spent, resetTimeMin, lastResetMin] = await rateLimiter.getTokenAllowance(USDC.address) expect(allowance).to.be.eq(amount) expect(spent).to.be.eq(0) expect(resetTimeMin).to.be.eq(60) expect(lastResetMin).to.be.eq(lastReset) - // initialized, but with no updates - expect(nonce).to.be.eq(1) }) it("should update allowance", async () => { - // create a bridge as a signer and grant it the bridge role - const bridge: Signer = signers[1] - - // grant our new bridge the role - await rateLimiter - .connect(deployer) - .grantRole(await rateLimiter.BRIDGE_ROLE(), await bridge.getAddress()) - // use rateLimiter as bridge - const bridgeRateLimiter: RateLimiter = await rateLimiter.connect(bridge) - const allowance = 100 * Math.pow(10, 6) // allowance of $100 const lastReset = Math.floor(epochSeconds() / hour) @@ -101,21 +110,45 @@ describe("Rate Limiter", () => { // draw down $10 from allowance await expect( - bridgeRateLimiter.checkAndUpdateAllowance( + rateLimiterTest.storeCheckAndUpdateAllowance( USDC.address, 10 * Math.pow(10, 6), ), ).to.be.not.reverted - // console.log(await bridgeRateLimiter.checkAndUpdateAllowance(USDC.address, 10 * Math.pow(10, 6))) - let [amount, spent, resetTimeMin, lastResetMin, nonce] = + expect(await rateLimiterTest.getLastUpdateValue()).to.be.true + + let [amount, spent, resetTimeMin, lastResetMin] = await rateLimiter.getTokenAllowance(USDC.address) expect(amount).to.be.eq(amount) expect(spent).to.be.eq(10 * Math.pow(10, 6)) expect(resetTimeMin).to.be.eq(60) expect(lastResetMin).to.be.eq(lastReset) - // initialized, but with no updates - expect(nonce).to.be.eq(2) + }) + + it("should return false if newSpent > allowance amount", async () => { + const allowance = 1000 * Math.pow(10, 6) // allowance of $100 + const lastReset = Math.floor(epochSeconds() / hour) + + // reset every hour after current epoch time to an allowance of $100 + expect(rateLimiter.setAllowance(USDC.address, allowance, hour, lastReset)) + .to.be.not.reverted + + await expect( + rateLimiterTest.storeCheckAndUpdateAllowance(USDC.address, allowance), + ).to.be.not.reverted + + // make sure method returned false + expect(await rateLimiterTest.getLastUpdateValue()).to.be.false + + // make sure values haven't been updated + let [amount, spent, resetTimeMin, lastResetMin] = + await rateLimiter.getTokenAllowance(USDC.address) + + expect(allowance).to.be.eq(amount) + expect(spent).to.be.eq(0) + expect(resetTimeMin).to.be.eq(60) + expect(lastResetMin).to.be.eq(lastReset) }) }) }) From 9e3a722bb42b0a0ded2d31dfdc912b686f9e6a0e Mon Sep 17 00:00:00 2001 From: Trajan0x Date: Tue, 5 Apr 2022 16:44:48 -0400 Subject: [PATCH 007/135] debug --- contracts/bridge/RateLimiter.sol | 10 ++++++++++ hardhat.config.ts | 2 +- test/bridge/RateLimiter.ts | 31 +++++++++++++++++++++++++++++-- 3 files changed, 40 insertions(+), 3 deletions(-) diff --git a/contracts/bridge/RateLimiter.sol b/contracts/bridge/RateLimiter.sol index f0a1207f8..941262f70 100644 --- a/contracts/bridge/RateLimiter.sol +++ b/contracts/bridge/RateLimiter.sol @@ -5,6 +5,7 @@ import "@openzeppelin/contracts-4.3.1-upgradeable/proxy/utils/Initializable.sol" import "@openzeppelin/contracts-4.3.1-upgradeable/access/AccessControlUpgradeable.sol"; import "@openzeppelin/contracts-4.3.1-upgradeable/security/ReentrancyGuardUpgradeable.sol"; import "./interfaces/IRateLimiter.sol"; +import "hardhat/console.sol"; // @title RateLimiter // @dev a bridge asset rate limiter based on https://github.com/gnosis/safe-modules/blob/master/allowances/contracts/AlowanceModule.sol @@ -107,6 +108,7 @@ contract RateLimiter is returns (Allowance memory allowance) { allowance = allowances[token]; + // solium-disable-next-line security/no-block-members uint32 currentMin = uint32(block.timestamp / 60); // Check if we should reset the time. We do this on load to minimize storage read/ writes @@ -135,7 +137,10 @@ contract RateLimiter is onlyRole(BRIDGE_ROLE) returns (bool) { + console.log("what"); + console.log(token); Allowance memory allowance = getAllowance(token); + console.log(allowance.initialized); // Update state // @dev reverts if amount > (2^96 - 1) @@ -149,11 +154,16 @@ contract RateLimiter is // do not proceed. Store the transaction for later if (newSpent >= allowance.amount) { + console.log(newSpent); + console.log(amount); + console.log(allowance.amount); + console.log("returning false"); return false; } allowance.spent = newSpent; updateAllowance(token, allowance); + console.log("returning true"); return true; } diff --git a/hardhat.config.ts b/hardhat.config.ts index d96730c54..01a60bced 100644 --- a/hardhat.config.ts +++ b/hardhat.config.ts @@ -103,7 +103,7 @@ let config: HardhatUserConfig = { target: "ethers-v5", }, dodoc: { - runOnCompile: true, + runOnCompile: false, debugMode: false, // pre solidity 5 breaks docgen exclude: ["MultisigWallet", "WETH9"] diff --git a/test/bridge/RateLimiter.ts b/test/bridge/RateLimiter.ts index b41c818cf..410d0c723 100644 --- a/test/bridge/RateLimiter.ts +++ b/test/bridge/RateLimiter.ts @@ -4,7 +4,6 @@ import { deployments, ethers } from "hardhat" import { BigNumber, BigNumberish, Signer } from "ethers" import Wallet from "ethereumjs-wallet" -import { RateLimiter } from "../../build/typechain/RateLimiter" import { CHAIN_ID } from "../../utils/network" import { Address } from "hardhat-deploy/dist/types" import { faker } from "@faker-js/faker" @@ -13,6 +12,7 @@ import { BridgeConfigV3, GenericERC20, RateLimiterTest, + RateLimiter } from "../../build/typechain" import epochSeconds from "@stdlib/time-now" @@ -100,7 +100,7 @@ describe("Rate Limiter", () => { expect(lastResetMin).to.be.eq(lastReset) }) - it("should update allowance", async () => { + it.only("should update allowance", async () => { const allowance = 100 * Math.pow(10, 6) // allowance of $100 const lastReset = Math.floor(epochSeconds() / hour) @@ -150,5 +150,32 @@ describe("Rate Limiter", () => { expect(resetTimeMin).to.be.eq(60) expect(lastResetMin).to.be.eq(lastReset) }) + + it("should reset allowance", async () => { + const allowance = 1000 * Math.pow(10, 6) // allowance of $100 + const lastReset = Math.floor(epochSeconds() / hour) + + // reset every hour after current epoch time to an allowance of $100 + expect(rateLimiter.setAllowance(USDC.address, allowance, hour, lastReset)) + .to.be.not.reverted + + await expect( + rateLimiterTest.storeCheckAndUpdateAllowance(USDC.address, 1), + ).to.be.not.reverted + + // make sure method returned false + console.log(await rateLimiterTest.getLastUpdateValue()) + expect(await rateLimiterTest.getLastUpdateValue()).to.be.true + + await expect(rateLimiter.resetAllowance(USDC.address)).to.be.not.reverted + + let [amount, spent, resetTimeMin, lastResetMin] = + await rateLimiter.getTokenAllowance(USDC.address) + + expect(allowance).to.be.eq(amount) + expect(spent).to.be.eq(0) + expect(resetTimeMin).to.be.eq(60) + expect(lastResetMin).to.be.eq(lastReset) + }) }) }) From 74a46b59d9785a1fffd9fb109273ef06fdcc3d09 Mon Sep 17 00:00:00 2001 From: Trajan0x Date: Tue, 5 Apr 2022 16:45:16 -0400 Subject: [PATCH 008/135] Revert "debug" This reverts commit 96dec4067b7d0f30402d1bc28c47d8e7cf4dc6df. --- contracts/bridge/RateLimiter.sol | 10 ---------- hardhat.config.ts | 2 +- test/bridge/RateLimiter.ts | 31 ++----------------------------- 3 files changed, 3 insertions(+), 40 deletions(-) diff --git a/contracts/bridge/RateLimiter.sol b/contracts/bridge/RateLimiter.sol index 941262f70..f0a1207f8 100644 --- a/contracts/bridge/RateLimiter.sol +++ b/contracts/bridge/RateLimiter.sol @@ -5,7 +5,6 @@ import "@openzeppelin/contracts-4.3.1-upgradeable/proxy/utils/Initializable.sol" import "@openzeppelin/contracts-4.3.1-upgradeable/access/AccessControlUpgradeable.sol"; import "@openzeppelin/contracts-4.3.1-upgradeable/security/ReentrancyGuardUpgradeable.sol"; import "./interfaces/IRateLimiter.sol"; -import "hardhat/console.sol"; // @title RateLimiter // @dev a bridge asset rate limiter based on https://github.com/gnosis/safe-modules/blob/master/allowances/contracts/AlowanceModule.sol @@ -108,7 +107,6 @@ contract RateLimiter is returns (Allowance memory allowance) { allowance = allowances[token]; - // solium-disable-next-line security/no-block-members uint32 currentMin = uint32(block.timestamp / 60); // Check if we should reset the time. We do this on load to minimize storage read/ writes @@ -137,10 +135,7 @@ contract RateLimiter is onlyRole(BRIDGE_ROLE) returns (bool) { - console.log("what"); - console.log(token); Allowance memory allowance = getAllowance(token); - console.log(allowance.initialized); // Update state // @dev reverts if amount > (2^96 - 1) @@ -154,16 +149,11 @@ contract RateLimiter is // do not proceed. Store the transaction for later if (newSpent >= allowance.amount) { - console.log(newSpent); - console.log(amount); - console.log(allowance.amount); - console.log("returning false"); return false; } allowance.spent = newSpent; updateAllowance(token, allowance); - console.log("returning true"); return true; } diff --git a/hardhat.config.ts b/hardhat.config.ts index 01a60bced..d96730c54 100644 --- a/hardhat.config.ts +++ b/hardhat.config.ts @@ -103,7 +103,7 @@ let config: HardhatUserConfig = { target: "ethers-v5", }, dodoc: { - runOnCompile: false, + runOnCompile: true, debugMode: false, // pre solidity 5 breaks docgen exclude: ["MultisigWallet", "WETH9"] diff --git a/test/bridge/RateLimiter.ts b/test/bridge/RateLimiter.ts index 410d0c723..b41c818cf 100644 --- a/test/bridge/RateLimiter.ts +++ b/test/bridge/RateLimiter.ts @@ -4,6 +4,7 @@ import { deployments, ethers } from "hardhat" import { BigNumber, BigNumberish, Signer } from "ethers" import Wallet from "ethereumjs-wallet" +import { RateLimiter } from "../../build/typechain/RateLimiter" import { CHAIN_ID } from "../../utils/network" import { Address } from "hardhat-deploy/dist/types" import { faker } from "@faker-js/faker" @@ -12,7 +13,6 @@ import { BridgeConfigV3, GenericERC20, RateLimiterTest, - RateLimiter } from "../../build/typechain" import epochSeconds from "@stdlib/time-now" @@ -100,7 +100,7 @@ describe("Rate Limiter", () => { expect(lastResetMin).to.be.eq(lastReset) }) - it.only("should update allowance", async () => { + it("should update allowance", async () => { const allowance = 100 * Math.pow(10, 6) // allowance of $100 const lastReset = Math.floor(epochSeconds() / hour) @@ -150,32 +150,5 @@ describe("Rate Limiter", () => { expect(resetTimeMin).to.be.eq(60) expect(lastResetMin).to.be.eq(lastReset) }) - - it("should reset allowance", async () => { - const allowance = 1000 * Math.pow(10, 6) // allowance of $100 - const lastReset = Math.floor(epochSeconds() / hour) - - // reset every hour after current epoch time to an allowance of $100 - expect(rateLimiter.setAllowance(USDC.address, allowance, hour, lastReset)) - .to.be.not.reverted - - await expect( - rateLimiterTest.storeCheckAndUpdateAllowance(USDC.address, 1), - ).to.be.not.reverted - - // make sure method returned false - console.log(await rateLimiterTest.getLastUpdateValue()) - expect(await rateLimiterTest.getLastUpdateValue()).to.be.true - - await expect(rateLimiter.resetAllowance(USDC.address)).to.be.not.reverted - - let [amount, spent, resetTimeMin, lastResetMin] = - await rateLimiter.getTokenAllowance(USDC.address) - - expect(allowance).to.be.eq(amount) - expect(spent).to.be.eq(0) - expect(resetTimeMin).to.be.eq(60) - expect(lastResetMin).to.be.eq(lastReset) - }) }) }) From cd8cde193087b168b1b3d8de88f7c459c46ae9de Mon Sep 17 00:00:00 2001 From: Trajan0x Date: Tue, 5 Apr 2022 17:44:15 -0400 Subject: [PATCH 009/135] fix tests --- contracts/bridge/testing/RateLimiterTest.sol | 5 ++--- docs/bridge/testing/RateLimiterTest.md | 16 ---------------- test/bridge/RateLimiter.ts | 6 +++--- 3 files changed, 5 insertions(+), 22 deletions(-) diff --git a/contracts/bridge/testing/RateLimiterTest.sol b/contracts/bridge/testing/RateLimiterTest.sol index 1002fcbfd..d94f8c2ca 100644 --- a/contracts/bridge/testing/RateLimiterTest.sol +++ b/contracts/bridge/testing/RateLimiterTest.sol @@ -2,14 +2,13 @@ pragma solidity ^0.8.0; import "../interfaces/IRateLimiter.sol"; -import "@openzeppelin/contracts-4.3.1-upgradeable/proxy/utils/Initializable.sol"; /// @title RateLimiterTest // @dev this contract is used to test RateLimiter's checkAndUpdateAllowance method's return value // because web3 libraries don't provide an interface for retrieving boolean values from a non-view function // we store the return value here for retrieval later. -contract RateLimiterTest is Initializable { +contract RateLimiterTest { /*** STATE ***/ string public constant NAME = "Rate Limiter Test"; @@ -24,7 +23,7 @@ contract RateLimiterTest is Initializable { // the rate limiter contract IRateLimiter rateLimiter; - function initialize(IRateLimiter _rateLimiter) external initializer { + constructor(IRateLimiter _rateLimiter) { rateLimiter = _rateLimiter; } diff --git a/docs/bridge/testing/RateLimiterTest.md b/docs/bridge/testing/RateLimiterTest.md index ee9f12865..f8962ded2 100644 --- a/docs/bridge/testing/RateLimiterTest.md +++ b/docs/bridge/testing/RateLimiterTest.md @@ -61,22 +61,6 @@ function getLastUpdateValue() external view returns (bool) |---|---|---| | _0 | bool | undefined | -### initialize - -```solidity -function initialize(contract IRateLimiter _rateLimiter) external nonpayable -``` - - - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| _rateLimiter | contract IRateLimiter | undefined | - ### storeCheckAndUpdateAllowance ```solidity diff --git a/test/bridge/RateLimiter.ts b/test/bridge/RateLimiter.ts index b41c818cf..1299262ff 100644 --- a/test/bridge/RateLimiter.ts +++ b/test/bridge/RateLimiter.ts @@ -66,9 +66,9 @@ describe("Rate Limiter", () => { const rateLimiterTestFactory = await ethers.getContractFactory( "RateLimiterTest", ) - rateLimiterTest = - (await rateLimiterTestFactory.deploy()) as RateLimiterTest - await rateLimiterTest.initialize(rateLimiter.address) + rateLimiterTest = (await rateLimiterTestFactory.deploy( + rateLimiter.address, + )) as RateLimiterTest // grant the bridge role to rateLimiterTest await rateLimiter From cdb9b5a83aa6e1dd105d7ff70d676a6c47da5673 Mon Sep 17 00:00:00 2001 From: Trajan0x Date: Tue, 5 Apr 2022 18:52:43 -0400 Subject: [PATCH 010/135] rate limiter --- test/bridge/RateLimiter.ts | 30 +++++++++++++++++++++++++++++- 1 file changed, 29 insertions(+), 1 deletion(-) diff --git a/test/bridge/RateLimiter.ts b/test/bridge/RateLimiter.ts index 1299262ff..d0c1863a3 100644 --- a/test/bridge/RateLimiter.ts +++ b/test/bridge/RateLimiter.ts @@ -19,7 +19,7 @@ import epochSeconds from "@stdlib/time-now" chai.use(solidity) const { expect, assert } = chai -describe("Rate Limiter", () => { +describe.only("Rate Limiter", () => { let signers: Array let deployer: Signer let owner: Signer @@ -150,5 +150,33 @@ describe("Rate Limiter", () => { expect(resetTimeMin).to.be.eq(60) expect(lastResetMin).to.be.eq(lastReset) }) + + it("should reset allowance", async () => { + const allowance = 100 * Math.pow(10, 6) // allowance of $100 + const lastReset = Math.floor(epochSeconds() / hour) + + // reset every hour after current epoch time to an allowance of $100 + expect(rateLimiter.setAllowance(USDC.address, allowance, hour, lastReset)) + .to.be.not.reverted + + // draw down $10 from allowance + await expect( + rateLimiterTest.storeCheckAndUpdateAllowance( + USDC.address, + 10 * Math.pow(10, 6), + ), + ).to.be.not.reverted + + expect(await rateLimiterTest.getLastUpdateValue()).to.be.true + + await expect(rateLimiter.resetAllowance(USDC.address)) + + let [amount, spent, resetTimeMin, lastResetMin] = + await rateLimiter.getTokenAllowance(USDC.address) + expect(amount).to.be.eq(amount) + expect(spent).to.be.eq(0) + expect(resetTimeMin).to.be.eq(60) + expect(lastResetMin).to.be.eq(lastReset) + }) }) }) From bc98e09ee791c001db0490ef78a0b5566408f6b3 Mon Sep 17 00:00:00 2001 From: Trajan0x Date: Fri, 8 Apr 2022 01:58:20 -0400 Subject: [PATCH 011/135] enumerable retries --- contracts/bridge/RateLimiter.sol | 49 +- contracts/bridge/SynapseBridge.sol | 314 +++++- .../libraries/EnumerableMapUpgradeable.sol | 128 +++ docs/amm/AaveSwap.md | 814 -------------- docs/amm/AaveSwapWrapper.md | 351 ------ docs/amm/AmplificationUtils.md | 88 -- docs/amm/ILendingPool.md | 58 - docs/amm/LPToken.md | 417 ------- docs/amm/MathUtils.md | 12 - docs/amm/OwnerPausableUpgradeable.md | 150 --- docs/amm/Swap.md | 787 ------------- docs/amm/SwapDeployer.md | 127 --- docs/amm/SwapEthWrapper.md | 324 ------ docs/amm/SwapFlashLoan.md | 894 --------------- docs/amm/SwapUtils.md | 199 ---- docs/amm/helper/BaseSwapDeposit.md | 126 --- docs/amm/helper/FlashLoanBorrowerExample.md | 54 - docs/amm/helper/GenericERC20.md | 361 ------ docs/amm/helper/Multicall2.md | 256 ----- docs/amm/helper/test/TestMathUtils.md | 61 - docs/amm/helper/test/TestSwapReturnValues.md | 171 --- docs/amm/interfaces/IFlashLoanReceiver.md | 35 - docs/amm/interfaces/IMetaSwap.md | 444 -------- docs/amm/interfaces/IMetaSwapDeposit.md | 33 - docs/amm/interfaces/ISwap.md | 353 ------ docs/amm/interfaces/ISwapFlashLoan.md | 372 ------ docs/auxiliary/DummyWeth.md | 144 --- docs/auxiliary/DummyWethProxy.md | 155 --- docs/bridge/BridgeConfigV3.md | 684 ----------- docs/bridge/ECDSAFactory.md | 159 --- docs/bridge/ECDSANodeManagement.md | 310 ----- docs/bridge/ERC20Migrator.md | 65 -- docs/bridge/HarmonySynapseBridge.md | 951 ---------------- docs/bridge/IERC20Mintable.md | 203 ---- docs/bridge/IFrax.md | 38 - docs/bridge/MRSynapseBridge.md | 951 ---------------- docs/bridge/MiniChefV2.md | 655 ----------- docs/bridge/PoolConfig.md | 295 ----- docs/bridge/RateLimiter.md | 521 --------- docs/bridge/SynapseBridge.md | 1001 ----------------- docs/bridge/SynapseERC20.md | 642 ----------- docs/bridge/SynapseERC20Factory.md | 60 - .../bridge/interfaces/IECDSANodeManagement.md | 33 - docs/bridge/interfaces/IERC20Migrator.md | 31 - docs/bridge/interfaces/IMasterChef.md | 71 -- docs/bridge/interfaces/IMetaSwapDeposit.md | 87 -- docs/bridge/interfaces/IMiniChefV2.md | 166 --- docs/bridge/interfaces/IRateLimiter.md | 55 - docs/bridge/interfaces/IRewarder.md | 60 - docs/bridge/interfaces/ISwap.md | 353 ------ docs/bridge/interfaces/ISynapseBridge.md | 140 --- docs/bridge/interfaces/ISynapseERC20.md | 51 - docs/bridge/libraries/SignedSafeMath.md | 12 - docs/bridge/mocks/ERC20Mock.md | 300 ----- docs/bridge/mocks/RewarderBrokenMock.md | 60 - docs/bridge/mocks/RewarderMock.md | 60 - docs/bridge/testing/NodeEnv.md | 348 ------ docs/bridge/testing/RateLimiterTest.md | 83 -- docs/bridge/testing/Synapse.md | 623 ---------- docs/bridge/utils/AddressArrayUtils.md | 12 - docs/bridge/utils/EnumerableStringMap.md | 12 - docs/bridge/utils/TimelockController.md | 626 ----------- docs/bridge/wrappers/GMXWrapper.md | 106 -- docs/bridge/wrappers/HarmonyBridgeZap.md | 303 ----- docs/bridge/wrappers/IFrax.md | 38 - docs/bridge/wrappers/IGMX.md | 71 -- docs/bridge/wrappers/L1BridgeZap.md | 266 ----- docs/bridge/wrappers/L2BridgeZap.md | 348 ------ docs/bridge/wrappers/MigratorBridgeZap.md | 49 - docs/bridge/wrappers/MoonriverBridgeZap.md | 321 ------ docs/console.md | 12 - .../access/AccessControlUpgradeable.md | 207 ---- .../access/IAccessControlUpgradeable.md | 168 --- .../proxy/utils/Initializable.md | 12 - .../security/ReentrancyGuardUpgradeable.md | 12 - .../utils/AddressUpgradeable.md | 12 - .../utils/ContextUpgradeable.md | 12 - .../utils/StringsUpgradeable.md | 12 - .../utils/introspection/ERC165Upgradeable.md | 37 - .../utils/introspection/IERC165Upgradeable.md | 37 - .../contracts-4.3.1/access/AccessControl.md | 207 ---- .../contracts-4.3.1/access/IAccessControl.md | 168 --- docs/elin/contracts-4.3.1/utils/Context.md | 12 - docs/elin/contracts-4.3.1/utils/Strings.md | 12 - .../utils/introspection/ERC165.md | 37 - .../utils/introspection/IERC165.md | 37 - .../contracts-4.3.1/utils/math/SafeMath.md | 12 - .../access/AccessControlUpgradeable.md | 230 ---- .../access/OwnableUpgradeable.md | 79 -- .../cryptography/ECDSAUpgradeable.md | 12 - .../drafts/EIP712Upgradeable.md | 12 - .../drafts/ERC20PermitUpgradeable.md | 344 ------ .../drafts/IERC20PermitUpgradeable.md | 76 -- .../math/SafeMathUpgradeable.md | 12 - .../proxy/Initializable.md | 12 - .../token/ERC20/ERC20BurnableUpgradeable.md | 316 ------ .../token/ERC20/ERC20Upgradeable.md | 283 ----- .../token/ERC20/IERC20Upgradeable.md | 186 --- .../utils/AddressUpgradeable.md | 12 - .../utils/ContextUpgradeable.md | 12 - .../utils/CountersUpgradeable.md | 12 - .../utils/EnumerableSetUpgradeable.md | 12 - .../utils/PausableUpgradeable.md | 67 -- .../utils/ReentrancyGuardUpgradeable.md | 12 - docs/elin/contracts/access/AccessControl.md | 230 ---- docs/elin/contracts/access/Ownable.md | 79 -- docs/elin/contracts/cryptography/ECDSA.md | 12 - docs/elin/contracts/drafts/EIP712.md | 12 - docs/elin/contracts/drafts/ERC20Permit.md | 344 ------ docs/elin/contracts/drafts/IERC20Permit.md | 76 -- docs/elin/contracts/math/SafeMath.md | 12 - docs/elin/contracts/proxy/Clones.md | 12 - docs/elin/contracts/token/ERC20/ERC20.md | 283 ----- .../contracts/token/ERC20/ERC20Burnable.md | 316 ------ docs/elin/contracts/token/ERC20/IERC20.md | 186 --- docs/elin/contracts/token/ERC20/SafeERC20.md | 12 - docs/elin/contracts/utils/Address.md | 12 - docs/elin/contracts/utils/Context.md | 12 - docs/elin/contracts/utils/Counters.md | 12 - docs/elin/contracts/utils/EnumerableSet.md | 12 - docs/elin/contracts/utils/ReentrancyGuard.md | 12 - .../contracts/BaseBoringBatchable.md | 39 - .../contracts/BoringBatchable.md | 62 - .../contracts/BoringOwnable.md | 98 -- .../contracts/BoringOwnableData.md | 49 - .../contracts/interfaces/IERC20.md | 161 --- .../contracts/libraries/BoringERC20.md | 12 - .../contracts/libraries/BoringMath.md | 12 - .../contracts/libraries/BoringMath128.md | 12 - .../contracts/libraries/BoringMath32.md | 12 - .../contracts/libraries/BoringMath64.md | 12 - hardhat.config.ts | 2 +- package-lock.json | 12 + package.json | 1 + test/bridge/RateLimiter.ts | 9 +- test/bridge/SynapseBridge.ts | 349 +++--- test/bridge/SynapseBridge1.ts | 188 ++++ 137 files changed, 849 insertions(+), 23007 deletions(-) create mode 100644 contracts/bridge/libraries/EnumerableMapUpgradeable.sol delete mode 100644 docs/amm/AaveSwap.md delete mode 100644 docs/amm/AaveSwapWrapper.md delete mode 100644 docs/amm/AmplificationUtils.md delete mode 100644 docs/amm/ILendingPool.md delete mode 100644 docs/amm/LPToken.md delete mode 100644 docs/amm/MathUtils.md delete mode 100644 docs/amm/OwnerPausableUpgradeable.md delete mode 100644 docs/amm/Swap.md delete mode 100644 docs/amm/SwapDeployer.md delete mode 100644 docs/amm/SwapEthWrapper.md delete mode 100644 docs/amm/SwapFlashLoan.md delete mode 100644 docs/amm/SwapUtils.md delete mode 100644 docs/amm/helper/BaseSwapDeposit.md delete mode 100644 docs/amm/helper/FlashLoanBorrowerExample.md delete mode 100644 docs/amm/helper/GenericERC20.md delete mode 100644 docs/amm/helper/Multicall2.md delete mode 100644 docs/amm/helper/test/TestMathUtils.md delete mode 100644 docs/amm/helper/test/TestSwapReturnValues.md delete mode 100644 docs/amm/interfaces/IFlashLoanReceiver.md delete mode 100644 docs/amm/interfaces/IMetaSwap.md delete mode 100644 docs/amm/interfaces/IMetaSwapDeposit.md delete mode 100644 docs/amm/interfaces/ISwap.md delete mode 100644 docs/amm/interfaces/ISwapFlashLoan.md delete mode 100644 docs/auxiliary/DummyWeth.md delete mode 100644 docs/auxiliary/DummyWethProxy.md delete mode 100644 docs/bridge/BridgeConfigV3.md delete mode 100644 docs/bridge/ECDSAFactory.md delete mode 100644 docs/bridge/ECDSANodeManagement.md delete mode 100644 docs/bridge/ERC20Migrator.md delete mode 100644 docs/bridge/HarmonySynapseBridge.md delete mode 100644 docs/bridge/IERC20Mintable.md delete mode 100644 docs/bridge/IFrax.md delete mode 100644 docs/bridge/MRSynapseBridge.md delete mode 100644 docs/bridge/MiniChefV2.md delete mode 100644 docs/bridge/PoolConfig.md delete mode 100644 docs/bridge/RateLimiter.md delete mode 100644 docs/bridge/SynapseBridge.md delete mode 100644 docs/bridge/SynapseERC20.md delete mode 100644 docs/bridge/SynapseERC20Factory.md delete mode 100644 docs/bridge/interfaces/IECDSANodeManagement.md delete mode 100644 docs/bridge/interfaces/IERC20Migrator.md delete mode 100644 docs/bridge/interfaces/IMasterChef.md delete mode 100644 docs/bridge/interfaces/IMetaSwapDeposit.md delete mode 100644 docs/bridge/interfaces/IMiniChefV2.md delete mode 100644 docs/bridge/interfaces/IRateLimiter.md delete mode 100644 docs/bridge/interfaces/IRewarder.md delete mode 100644 docs/bridge/interfaces/ISwap.md delete mode 100644 docs/bridge/interfaces/ISynapseBridge.md delete mode 100644 docs/bridge/interfaces/ISynapseERC20.md delete mode 100644 docs/bridge/libraries/SignedSafeMath.md delete mode 100644 docs/bridge/mocks/ERC20Mock.md delete mode 100644 docs/bridge/mocks/RewarderBrokenMock.md delete mode 100644 docs/bridge/mocks/RewarderMock.md delete mode 100644 docs/bridge/testing/NodeEnv.md delete mode 100644 docs/bridge/testing/RateLimiterTest.md delete mode 100644 docs/bridge/testing/Synapse.md delete mode 100644 docs/bridge/utils/AddressArrayUtils.md delete mode 100644 docs/bridge/utils/EnumerableStringMap.md delete mode 100644 docs/bridge/utils/TimelockController.md delete mode 100644 docs/bridge/wrappers/GMXWrapper.md delete mode 100644 docs/bridge/wrappers/HarmonyBridgeZap.md delete mode 100644 docs/bridge/wrappers/IFrax.md delete mode 100644 docs/bridge/wrappers/IGMX.md delete mode 100644 docs/bridge/wrappers/L1BridgeZap.md delete mode 100644 docs/bridge/wrappers/L2BridgeZap.md delete mode 100644 docs/bridge/wrappers/MigratorBridgeZap.md delete mode 100644 docs/bridge/wrappers/MoonriverBridgeZap.md delete mode 100644 docs/console.md delete mode 100644 docs/elin/contracts-4.3.1-upgradeable/access/AccessControlUpgradeable.md delete mode 100644 docs/elin/contracts-4.3.1-upgradeable/access/IAccessControlUpgradeable.md delete mode 100644 docs/elin/contracts-4.3.1-upgradeable/proxy/utils/Initializable.md delete mode 100644 docs/elin/contracts-4.3.1-upgradeable/security/ReentrancyGuardUpgradeable.md delete mode 100644 docs/elin/contracts-4.3.1-upgradeable/utils/AddressUpgradeable.md delete mode 100644 docs/elin/contracts-4.3.1-upgradeable/utils/ContextUpgradeable.md delete mode 100644 docs/elin/contracts-4.3.1-upgradeable/utils/StringsUpgradeable.md delete mode 100644 docs/elin/contracts-4.3.1-upgradeable/utils/introspection/ERC165Upgradeable.md delete mode 100644 docs/elin/contracts-4.3.1-upgradeable/utils/introspection/IERC165Upgradeable.md delete mode 100644 docs/elin/contracts-4.3.1/access/AccessControl.md delete mode 100644 docs/elin/contracts-4.3.1/access/IAccessControl.md delete mode 100644 docs/elin/contracts-4.3.1/utils/Context.md delete mode 100644 docs/elin/contracts-4.3.1/utils/Strings.md delete mode 100644 docs/elin/contracts-4.3.1/utils/introspection/ERC165.md delete mode 100644 docs/elin/contracts-4.3.1/utils/introspection/IERC165.md delete mode 100644 docs/elin/contracts-4.3.1/utils/math/SafeMath.md delete mode 100644 docs/elin/contracts-upgradeable/access/AccessControlUpgradeable.md delete mode 100644 docs/elin/contracts-upgradeable/access/OwnableUpgradeable.md delete mode 100644 docs/elin/contracts-upgradeable/cryptography/ECDSAUpgradeable.md delete mode 100644 docs/elin/contracts-upgradeable/drafts/EIP712Upgradeable.md delete mode 100644 docs/elin/contracts-upgradeable/drafts/ERC20PermitUpgradeable.md delete mode 100644 docs/elin/contracts-upgradeable/drafts/IERC20PermitUpgradeable.md delete mode 100644 docs/elin/contracts-upgradeable/math/SafeMathUpgradeable.md delete mode 100644 docs/elin/contracts-upgradeable/proxy/Initializable.md delete mode 100644 docs/elin/contracts-upgradeable/token/ERC20/ERC20BurnableUpgradeable.md delete mode 100644 docs/elin/contracts-upgradeable/token/ERC20/ERC20Upgradeable.md delete mode 100644 docs/elin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.md delete mode 100644 docs/elin/contracts-upgradeable/utils/AddressUpgradeable.md delete mode 100644 docs/elin/contracts-upgradeable/utils/ContextUpgradeable.md delete mode 100644 docs/elin/contracts-upgradeable/utils/CountersUpgradeable.md delete mode 100644 docs/elin/contracts-upgradeable/utils/EnumerableSetUpgradeable.md delete mode 100644 docs/elin/contracts-upgradeable/utils/PausableUpgradeable.md delete mode 100644 docs/elin/contracts-upgradeable/utils/ReentrancyGuardUpgradeable.md delete mode 100644 docs/elin/contracts/access/AccessControl.md delete mode 100644 docs/elin/contracts/access/Ownable.md delete mode 100644 docs/elin/contracts/cryptography/ECDSA.md delete mode 100644 docs/elin/contracts/drafts/EIP712.md delete mode 100644 docs/elin/contracts/drafts/ERC20Permit.md delete mode 100644 docs/elin/contracts/drafts/IERC20Permit.md delete mode 100644 docs/elin/contracts/math/SafeMath.md delete mode 100644 docs/elin/contracts/proxy/Clones.md delete mode 100644 docs/elin/contracts/token/ERC20/ERC20.md delete mode 100644 docs/elin/contracts/token/ERC20/ERC20Burnable.md delete mode 100644 docs/elin/contracts/token/ERC20/IERC20.md delete mode 100644 docs/elin/contracts/token/ERC20/SafeERC20.md delete mode 100644 docs/elin/contracts/utils/Address.md delete mode 100644 docs/elin/contracts/utils/Context.md delete mode 100644 docs/elin/contracts/utils/Counters.md delete mode 100644 docs/elin/contracts/utils/EnumerableSet.md delete mode 100644 docs/elin/contracts/utils/ReentrancyGuard.md delete mode 100644 docs/ypto/boring-solidity/contracts/BaseBoringBatchable.md delete mode 100644 docs/ypto/boring-solidity/contracts/BoringBatchable.md delete mode 100644 docs/ypto/boring-solidity/contracts/BoringOwnable.md delete mode 100644 docs/ypto/boring-solidity/contracts/BoringOwnableData.md delete mode 100644 docs/ypto/boring-solidity/contracts/interfaces/IERC20.md delete mode 100644 docs/ypto/boring-solidity/contracts/libraries/BoringERC20.md delete mode 100644 docs/ypto/boring-solidity/contracts/libraries/BoringMath.md delete mode 100644 docs/ypto/boring-solidity/contracts/libraries/BoringMath128.md delete mode 100644 docs/ypto/boring-solidity/contracts/libraries/BoringMath32.md delete mode 100644 docs/ypto/boring-solidity/contracts/libraries/BoringMath64.md create mode 100644 test/bridge/SynapseBridge1.ts diff --git a/contracts/bridge/RateLimiter.sol b/contracts/bridge/RateLimiter.sol index f0a1207f8..d26e2780c 100644 --- a/contracts/bridge/RateLimiter.sol +++ b/contracts/bridge/RateLimiter.sol @@ -4,6 +4,9 @@ pragma solidity ^0.8.0; import "@openzeppelin/contracts-4.3.1-upgradeable/proxy/utils/Initializable.sol"; import "@openzeppelin/contracts-4.3.1-upgradeable/access/AccessControlUpgradeable.sol"; import "@openzeppelin/contracts-4.3.1-upgradeable/security/ReentrancyGuardUpgradeable.sol"; +import "@openzeppelin/contracts-4.3.1-upgradeable/utils/math/MathUpgradeable.sol"; + +import "./libraries/EnumerableMapUpgradeable.sol"; import "./interfaces/IRateLimiter.sol"; // @title RateLimiter @@ -27,7 +30,9 @@ contract RateLimiter is // Token -> Allowance mapping(address => Allowance) public allowances; // Kappa->Retry Selector - mapping(bytes32 => bytes) public limited; + EnumerableMapUpgradeable.Bytes32ToBytesMap private limited; + // Bridge Address + address public BRIDGE_ADDRESS; // List of tokens address[] public tokens; @@ -59,6 +64,13 @@ contract RateLimiter is __AccessControl_init(); } + function setBridgeAddress(address bridge) + external + onlyRole(GOVERNANCE_ROLE) + { + BRIDGE_ADDRESS = bridge; + } + /** * @notice Updates the allowance for a given token * @param token to update the allowance for @@ -162,7 +174,40 @@ contract RateLimiter is external onlyRole(BRIDGE_ROLE) { - limited[kappa] = rateLimited; + EnumerableMapUpgradeable.set(limited, kappa, rateLimited); + } + + function retryByKappa(bytes32 kappa) external onlyRole(LIMITER_ROLE) { + bytes memory toRetry = EnumerableMapUpgradeable.get(limited, kappa); + (bool success, bytes memory returnData) = BRIDGE_ADDRESS.call(toRetry); + require(success, "could not call bridge"); + EnumerableMapUpgradeable.remove(limited, kappa); + } + + function retryCount(uint8 count) external onlyRole(LIMITER_ROLE) { + // no issues casting to uint8 here. If length is greater then 255, min is always taken + uint8 attempts = uint8( + MathUpgradeable.min( + uint256(count), + EnumerableMapUpgradeable.length(limited) + ) + ); + + for (uint8 i = 0; i < attempts; i++) { + (bytes32 kappa, bytes memory toRetry) = EnumerableMapUpgradeable.at( + limited, + i + ); + (bool success, bytes memory returnData) = BRIDGE_ADDRESS.call( + toRetry + ); + require(success, "could not call bridge"); + EnumerableMapUpgradeable.remove(limited, kappa); + } + } + + function deleteByKappa(bytes32 kappa) external onlyRole(LIMITER_ROLE) { + EnumerableMapUpgradeable.remove(limited, kappa); } /** diff --git a/contracts/bridge/SynapseBridge.sol b/contracts/bridge/SynapseBridge.sol index db1faf7cf..14fe7c4de 100644 --- a/contracts/bridge/SynapseBridge.sol +++ b/contracts/bridge/SynapseBridge.sol @@ -34,23 +34,30 @@ contract SynapseBridge is bytes32 public constant GOVERNANCE_ROLE = keccak256("GOVERNANCE_ROLE"); // selectors - bytes4 private constant MINT_SELECTOR = + bytes4 private constant RETRY_MINT_SELECTOR = bytes4( - keccak256("mint(address,IERC20Mintable,uint256,uint256,bytes32)") + keccak256( + "retryMint(address,IERC20Mintable,uint256,uint256,bytes32)" + ) ); - bytes4 private constant MINT_AND_SWAP_SELECTOR = + bytes4 private constant RETRY_MINT_AND_SWAP_SELECTOR = bytes4( keccak256( - "mintAndSwap(address,address,uint256,uint256,address,uint8,uint8,uint256,uint256,bytes32)" + "retryMintAndSwap(address,address,uint256,uint256,address,uint8,uint8,uint256,uint256,bytes32)" ) ); - bytes4 private constant WITHDRAW_AND_REMOVE_SELECTOR = + bytes4 private constant RETRY_WITHDRAW_AND_REMOVE_SELECTOR = bytes4( keccak256( - "withdrawAndRemove(address,address,uint256,uint256,address,uint8,uint256,uint256,bytes32)" + "retryWithdrawAndRemove(address,address,uint256,uint256,address,uint8,uint256,uint256,bytes32)" ) ); + bytes4 private constant RETRY_WITHDRAW_SELECTOR = + bytes4( + keccak256("retryWithdraw(address,address,uint256,uint256,bytes32)") + ); + mapping(address => uint256) private fees; uint256 public startBlockNumber; @@ -270,6 +277,60 @@ contract SynapseBridge is hasRole(NODEGROUP_ROLE, msg.sender), "Caller is not a node group" ); + + bool rateLimited = rateLimiter.checkAndUpdateAllowance( + address(token), + amount + ); + if (rateLimited) { + rateLimiter.addToRetryQueue( + kappa, + abi.encodeWithSelector( + RETRY_WITHDRAW_SELECTOR, + to, + address(token), + amount, + fee, + kappa + ) + ); + return; + } + + doWithdraw(to, token, amount, fee, kappa); + } + + /** + * @notice Function to be called by the rate limiter to retry a withdraw bypassing the rate limiter + * @param to address on chain to send underlying assets to + * @param token ERC20 compatible token to withdraw from the bridge + * @param amount Amount in native token decimals to withdraw + * @param fee Amount in native token decimals to save to the contract as fees + * @param kappa kappa + **/ + function retryWithdraw( + address to, + IERC20 token, + uint256 amount, + uint256 fee, + bytes32 kappa + ) external nonReentrant whenNotPaused { + require( + hasRole(RATE_LIMITER_ROLE, msg.sender), + "Caller is not rate limiter" + ); + + doWithdraw(to, token, amount, fee, kappa); + } + + // doWithdraw bypasses the rate limiter. See withdraw for documentation + function doWithdraw( + address to, + IERC20 token, + uint256 amount, + uint256 fee, + bytes32 kappa + ) internal { require(amount > fee, "Amount must be greater than fee"); require(!kappaMap[kappa], "Kappa is already present"); kappaMap[kappa] = true; @@ -305,6 +366,60 @@ contract SynapseBridge is hasRole(NODEGROUP_ROLE, msg.sender), "Caller is not a node group" ); + + bool rateLimited = rateLimiter.checkAndUpdateAllowance( + address(token), + amount + ); + if (rateLimited) { + rateLimiter.addToRetryQueue( + kappa, + abi.encodeWithSelector( + RETRY_MINT_SELECTOR, + to, + address(token), + amount, + fee, + kappa + ) + ); + return; + } + + doMint(to, token, amount, fee, kappa); + } + + /** + * @notice Rate Limiter call this function to retry a mint of a SynERC20 (or any asset that the bridge is given minter access to). This is called by the nodes after a TokenDeposit event is emitted. + * @dev This means the SynapseBridge.sol contract must have minter access to the token attempting to be minted + * @param to address on other chain to redeem underlying assets to + * @param token ERC20 compatible token to deposit into the bridge + * @param amount Amount in native token decimals to transfer cross-chain post-fees + * @param fee Amount in native token decimals to save to the contract as fees + * @param kappa kappa + **/ + function retryMint( + address payable to, + IERC20Mintable token, + uint256 amount, + uint256 fee, + bytes32 kappa + ) external nonReentrant whenNotPaused { + require( + hasRole(RATE_LIMITER_ROLE, msg.sender), + "Caller is not a node group" + ); + + doMint(to, token, amount, fee, kappa); + } + + function doMint( + address payable to, + IERC20Mintable token, + uint256 amount, + uint256 fee, + bytes32 kappa + ) internal { require(amount > fee, "Amount must be greater than fee"); require(!kappaMap[kappa], "Kappa is already present"); kappaMap[kappa] = true; @@ -446,6 +561,102 @@ contract SynapseBridge is hasRole(NODEGROUP_ROLE, msg.sender), "Caller is not a node group" ); + + bool rateLimited = rateLimiter.checkAndUpdateAllowance( + address(token), + amount + ); + if (rateLimited) { + rateLimiter.addToRetryQueue( + kappa, + abi.encodeWithSelector( + RETRY_MINT_AND_SWAP_SELECTOR, + to, + address(token), + amount, + fee, + address(pool), + tokenIndexFrom, + tokenIndexTo, + minDy, + deadline, + kappa + ) + ); + return; + } + + doMintAndSwap( + to, + token, + amount, + fee, + pool, + tokenIndexFrom, + tokenIndexTo, + minDy, + deadline, + kappa + ); + } + + /** + * @notice RateLimiter call this function to retry a mint of a SynERC20 (or any asset that the bridge is given minter access to), and then attempt to swap the SynERC20 into the desired destination asset. This is called by the nodes after a TokenDepositAndSwap event is emitted. + * @dev This means the BridgeDeposit.sol contract must have minter access to the token attempting to be minted + * @param to address on other chain to redeem underlying assets to + * @param token ERC20 compatible token to deposit into the bridge + * @param amount Amount in native token decimals to transfer cross-chain post-fees + * @param fee Amount in native token decimals to save to the contract as fees + * @param pool Destination chain's pool to use to swap SynERC20 -> Asset. The nodes determine this by using PoolConfig.sol. + * @param tokenIndexFrom Index of the SynERC20 asset in the pool + * @param tokenIndexTo Index of the desired final asset + * @param minDy Minumum amount (in final asset decimals) that must be swapped for, otherwise the user will receive the SynERC20. + * @param deadline Epoch time of the deadline that the swap is allowed to be executed. + * @param kappa kappa + **/ + function retryMintAndSwap( + address payable to, + IERC20Mintable token, + uint256 amount, + uint256 fee, + ISwap pool, + uint8 tokenIndexFrom, + uint8 tokenIndexTo, + uint256 minDy, + uint256 deadline, + bytes32 kappa + ) external nonReentrant whenNotPaused { + require( + hasRole(RATE_LIMITER_ROLE, msg.sender), + "Caller is not a node group" + ); + + doMintAndSwap( + to, + token, + amount, + fee, + pool, + tokenIndexFrom, + tokenIndexTo, + minDy, + deadline, + kappa + ); + } + + function doMintAndSwap( + address payable to, + IERC20Mintable token, + uint256 amount, + uint256 fee, + ISwap pool, + uint8 tokenIndexFrom, + uint8 tokenIndexTo, + uint256 minDy, + uint256 deadline, + bytes32 kappa + ) internal { require(amount > fee, "Amount must be greater than fee"); require(!kappaMap[kappa], "Kappa is already present"); kappaMap[kappa] = true; @@ -570,6 +781,97 @@ contract SynapseBridge is hasRole(NODEGROUP_ROLE, msg.sender), "Caller is not a node group" ); + + bool rateLimited = rateLimiter.checkAndUpdateAllowance( + address(token), + amount + ); + + if (rateLimited) { + rateLimiter.addToRetryQueue( + kappa, + abi.encodeWithSelector( + RETRY_WITHDRAW_AND_REMOVE_SELECTOR, + to, + address(token), + amount, + fee, + address(pool), + swapTokenIndex, + swapMinAmount, + swapDeadline, + kappa + ) + ); + return; + } + + doWithdrawAndRemove( + to, + token, + amount, + fee, + pool, + swapTokenIndex, + swapMinAmount, + swapDeadline, + kappa + ); + } + + /** + * @notice Function to be called by the rate limiter to retry a withdraw of the underlying assets from the contract + * @param to address on chain to send underlying assets to + * @param token ERC20 compatible token to withdraw from the bridge + * @param amount Amount in native token decimals to withdraw + * @param fee Amount in native token decimals to save to the contract as fees + * @param pool Destination chain's pool to use to swap SynERC20 -> Asset. The nodes determine this by using PoolConfig.sol. + * @param swapTokenIndex Specifies which of the underlying LP assets the nodes should attempt to redeem for + * @param swapMinAmount Specifies the minimum amount of the underlying asset needed for the nodes to execute the redeem/swap + * @param swapDeadline Specificies the deadline that the nodes are allowed to try to redeem/swap the LP token + * @param kappa kappa + **/ + function retryWithdrawAndRemove( + address to, + IERC20 token, + uint256 amount, + uint256 fee, + ISwap pool, + uint8 swapTokenIndex, + uint256 swapMinAmount, + uint256 swapDeadline, + bytes32 kappa + ) external nonReentrant whenNotPaused { + require( + hasRole(RATE_LIMITER_ROLE, msg.sender), + "Caller is not a node group" + ); + + doWithdrawAndRemove( + to, + token, + amount, + fee, + pool, + swapTokenIndex, + swapMinAmount, + swapDeadline, + kappa + ); + } + + // allows withdrawAndRemove retries to bypass rate limiter + function doWithdrawAndRemove( + address to, + IERC20 token, + uint256 amount, + uint256 fee, + ISwap pool, + uint8 swapTokenIndex, + uint256 swapMinAmount, + uint256 swapDeadline, + bytes32 kappa + ) internal { require(amount > fee, "Amount must be greater than fee"); require(!kappaMap[kappa], "Kappa is already present"); kappaMap[kappa] = true; diff --git a/contracts/bridge/libraries/EnumerableMapUpgradeable.sol b/contracts/bridge/libraries/EnumerableMapUpgradeable.sol new file mode 100644 index 000000000..e5291e0bd --- /dev/null +++ b/contracts/bridge/libraries/EnumerableMapUpgradeable.sol @@ -0,0 +1,128 @@ +// SPDX-License-Identifier: MIT + +pragma solidity ^0.8.0; + +import "@openzeppelin/contracts-4.6.0-upgradeable/utils/structs/EnumerableSetUpgradeable.sol"; + +/** + * @dev Library for managing an enumerable variant of Solidity's + * this extends https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v4.6.0-rc.0/contracts/utils/structs/EnumerableMap.sol + * wth a bytes32 to bytes map +*/ + +library EnumerableMapUpgradeable { + using EnumerableSetUpgradeable for EnumerableSetUpgradeable.Bytes32Set; + + // To implement this library for multiple types with as little code + // repetition as possible, we write it in terms of a generic Map type with + // bytes32 keys and values. + // The Map implementation uses private functions, and user-facing + // implementations (such as Uint256ToAddressMap) are just wrappers around + // the underlying Map. + // This means that we can only create new EnumerableMaps for types that fit + // in bytes32. + + struct Bytes32ToBytesMap { + // Storage of keys + EnumerableSetUpgradeable.Bytes32Set _keys; + mapping(bytes32 => bytes) _values; + } + + + /** + * @dev Adds a key-value pair to a map, or updates the value for an existing + * key. O(1). + * + * Returns true if the key was added to the map, that is if it was not + * already present. + */ + function set( + Bytes32ToBytesMap storage map, + bytes32 key, + bytes memory value + ) internal returns (bool) { + map._values[key] = value; + return map._keys.add(key); + } + + /** + * @dev Removes a key-value pair from a map. O(1). + * + * Returns true if the key was removed from the map, that is if it was present. + */ + function remove(Bytes32ToBytesMap storage map, bytes32 key) internal returns (bool) { + delete map._values[key]; + return map._keys.remove(key); + } + + /** + * @dev Returns true if the key is in the map. O(1). + */ + function contains(Bytes32ToBytesMap storage map, bytes32 key) internal view returns (bool) { + return map._keys.contains(key); + } + + /** + * @dev Returns the number of key-value pairs in the map. O(1). + */ + function length(Bytes32ToBytesMap storage map) internal view returns (uint256) { + return map._keys.length(); + } + + /** + * @dev Returns the key-value pair stored at position `index` in the map. O(1). + * + * Note that there are no guarantees on the ordering of entries inside the + * array, and it may change when more entries are added or removed. + * + * Requirements: + * + * - `index` must be strictly less than {length}. + */ + function at(Bytes32ToBytesMap storage map, uint256 index) internal view returns (bytes32, bytes memory) { + bytes32 key = map._keys.at(index); + return (key, map._values[key]); + } + + /** + * @dev Tries to returns the value associated with `key`. O(1). + * Does not revert if `key` is not in the map. + */ + function tryGet(Bytes32ToBytesMap storage map, bytes32 key) internal view returns (bool, bytes memory) { + bytes memory value = map._values[key]; + if (value.length == 0) { + return (contains(map, key), bytes("")); + } else { + return (true, value); + } + } + + /** + * @dev Returns the value associated with `key`. O(1). + * + * Requirements: + * + * - `key` must be in the map. + */ + function get(Bytes32ToBytesMap storage map, bytes32 key) internal view returns (bytes memory) { + bytes memory value = map._values[key]; + require(value.length != 0 || contains(map, key), "EnumerableMap: nonexistent key"); + return value; + } + + /** + * @dev Same as {_get}, with a custom error message when `key` is not in the map. + * + * CAUTION: This function is deprecated because it requires allocating memory for the error + * message unnecessarily. For custom revert reasons use {_tryGet}. + */ + function get( + Bytes32ToBytesMap storage map, + bytes32 key, + string memory errorMessage + ) internal view returns (bytes memory) { + bytes memory value = map._values[key]; + require(value.length != 0 || contains(map, key), errorMessage); + return value; + } +} \ No newline at end of file diff --git a/docs/amm/AaveSwap.md b/docs/amm/AaveSwap.md deleted file mode 100644 index 0f5abfa98..000000000 --- a/docs/amm/AaveSwap.md +++ /dev/null @@ -1,814 +0,0 @@ -# AaveSwap - - - -> AaveSwap - A StableSwap implementation in solidity, integrated with Aave. - -This contract is responsible for custody of closely pegged assets (eg. group of stablecoins) and automatic market making system. Users become an LP (Liquidity Provider) by depositing their tokens in desired ratios for an exchange of the pool token that represents their share of the pool. Users can burn pool tokens and withdraw their share of token(s). Each time a swap between the pooled tokens happens, a set fee incurs which effectively gets distributed to the LPs. In case of emergencies, admin can pause additional deposits, swaps, or single-asset withdraws - which stops the ratio of the tokens in the pool from changing. Users can always withdraw their tokens via multi-asset withdraws. - -*Most of the logic is stored as a library `SwapUtils` for the sake of reducing contract's deployment size.* - -## Methods - -### addLiquidity - -```solidity -function addLiquidity(uint256[] amounts, uint256 minToMint, uint256 deadline) external nonpayable returns (uint256) -``` - -Add liquidity to the pool with the given amounts of tokens - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| amounts | uint256[] | the amounts of each token to add, in their native precision | -| minToMint | uint256 | the minimum LP tokens adding this amount of liquidity should mint, otherwise revert. Handy for front-running mitigation | -| deadline | uint256 | latest timestamp to accept this transaction | - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | uint256 | amount of LP token user minted and received | - -### calculateRemoveLiquidity - -```solidity -function calculateRemoveLiquidity(uint256 amount) external view returns (uint256[]) -``` - -A simple method to calculate amount of each underlying tokens that is returned upon burning given amount of LP tokens - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| amount | uint256 | the amount of LP tokens that would be burned on withdrawal | - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | uint256[] | array of token balances that the user will receive | - -### calculateRemoveLiquidityOneToken - -```solidity -function calculateRemoveLiquidityOneToken(uint256 tokenAmount, uint8 tokenIndex) external view returns (uint256 availableTokenAmount) -``` - -Calculate the amount of underlying token available to withdraw when withdrawing via only single token - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| tokenAmount | uint256 | the amount of LP token to burn | -| tokenIndex | uint8 | index of which token will be withdrawn | - -#### Returns - -| Name | Type | Description | -|---|---|---| -| availableTokenAmount | uint256 | calculated amount of underlying token available to withdraw | - -### calculateSwap - -```solidity -function calculateSwap(uint8 tokenIndexFrom, uint8 tokenIndexTo, uint256 dx) external view returns (uint256) -``` - -Calculate amount of tokens you receive on swap - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| tokenIndexFrom | uint8 | the token the user wants to sell | -| tokenIndexTo | uint8 | the token the user wants to buy | -| dx | uint256 | the amount of tokens the user wants to sell. If the token charges a fee on transfers, use the amount that gets transferred after the fee. | - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | uint256 | amount of tokens the user will receive | - -### calculateTokenAmount - -```solidity -function calculateTokenAmount(uint256[] amounts, bool deposit) external view returns (uint256) -``` - -A simple method to calculate prices from deposits or withdrawals, excluding fees but including slippage. This is helpful as an input into the various "min" parameters on calls to fight front-running - -*This shouldn't be used outside frontends for user estimates.* - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| amounts | uint256[] | an array of token amounts to deposit or withdrawal, corresponding to pooledTokens. The amount should be in each pooled token's native precision. If a token charges a fee on transfers, use the amount that gets transferred after the fee. | -| deposit | bool | whether this is a deposit or a withdrawal | - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | uint256 | token amount the user will receive | - -### claimAaveRewards - -```solidity -function claimAaveRewards() external nonpayable -``` - - - - - - -### getA - -```solidity -function getA() external view returns (uint256) -``` - -Return A, the amplification coefficient * n * (n - 1) - -*See the StableSwap paper for details* - - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | uint256 | A parameter | - -### getAPrecise - -```solidity -function getAPrecise() external view returns (uint256) -``` - -Return A in its raw precision form - -*See the StableSwap paper for details* - - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | uint256 | A parameter in its raw precision form | - -### getAdminBalance - -```solidity -function getAdminBalance(uint256 index) external view returns (uint256) -``` - -This function reads the accumulated amount of admin fees of the token with given index - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| index | uint256 | Index of the pooled token | - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | uint256 | admin's token balance in the token's precision | - -### getToken - -```solidity -function getToken(uint8 index) external view returns (contract IERC20) -``` - -Return address of the pooled token at given index. Reverts if tokenIndex is out of range. - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| index | uint8 | the index of the token | - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | contract IERC20 | address of the token at given index | - -### getTokenBalance - -```solidity -function getTokenBalance(uint8 index) external view returns (uint256) -``` - -Return current balance of the pooled token at given index - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| index | uint8 | the index of the token | - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | uint256 | current balance of the pooled token at given index with token's native precision | - -### getTokenIndex - -```solidity -function getTokenIndex(address tokenAddress) external view returns (uint8) -``` - -Return the index of the given token address. Reverts if no matching token is found. - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| tokenAddress | address | address of the token | - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | uint8 | the index of the given token address | - -### getVirtualPrice - -```solidity -function getVirtualPrice() external view returns (uint256) -``` - -Get the virtual price, to help calculate profit - - - - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | uint256 | the virtual price, scaled to the POOL_PRECISION_DECIMALS | - -### initialize - -```solidity -function initialize(contract IERC20[] _pooledTokens, uint8[] decimals, string lpTokenName, string lpTokenSymbol, uint256 _a, uint256 _fee, uint256 _adminFee, address lpTokenTargetAddress) external nonpayable -``` - -Initializes this Swap contract with the given parameters. This will also clone a LPToken contract that represents users' LP positions. The owner of LPToken will be this contract - which means only this contract is allowed to mint/burn tokens. - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| _pooledTokens | contract IERC20[] | an array of ERC20s this pool will accept | -| decimals | uint8[] | the decimals to use for each pooled token, eg 8 for WBTC. Cannot be larger than POOL_PRECISION_DECIMALS | -| lpTokenName | string | the long-form name of the token to be deployed | -| lpTokenSymbol | string | the short symbol for the token to be deployed | -| _a | uint256 | the amplification coefficient * n * (n - 1). See the StableSwap paper for details | -| _fee | uint256 | default swap fee to be initialized with | -| _adminFee | uint256 | default adminFee to be initialized with | -| lpTokenTargetAddress | address | the address of an existing LPToken contract to use as a target | - -### owner - -```solidity -function owner() external view returns (address) -``` - - - -*Returns the address of the current owner.* - - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | address | undefined | - -### pause - -```solidity -function pause() external nonpayable -``` - -Pause the contract. Revert if already paused. - - - - -### paused - -```solidity -function paused() external view returns (bool) -``` - - - -*Returns true if the contract is paused, and false otherwise.* - - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | bool | undefined | - -### rampA - -```solidity -function rampA(uint256 futureA, uint256 futureTime) external nonpayable -``` - -Start ramping up or down A parameter towards given futureA and futureTime Checks if the change is too rapid, and commits the new A value only when it falls under the limit range. - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| futureA | uint256 | the new A to ramp towards | -| futureTime | uint256 | timestamp when the new A should be reached | - -### removeLiquidity - -```solidity -function removeLiquidity(uint256 amount, uint256[] minAmounts, uint256 deadline) external nonpayable returns (uint256[]) -``` - -Burn LP tokens to remove liquidity from the pool. Withdraw fee that decays linearly over period of 4 weeks since last deposit will apply. - -*Liquidity can always be removed, even when the pool is paused.* - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| amount | uint256 | the amount of LP tokens to burn | -| minAmounts | uint256[] | the minimum amounts of each token in the pool acceptable for this burn. Useful as a front-running mitigation | -| deadline | uint256 | latest timestamp to accept this transaction | - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | uint256[] | amounts of tokens user received | - -### removeLiquidityImbalance - -```solidity -function removeLiquidityImbalance(uint256[] amounts, uint256 maxBurnAmount, uint256 deadline) external nonpayable returns (uint256) -``` - -Remove liquidity from the pool, weighted differently than the pool's current balances. Withdraw fee that decays linearly over period of 4 weeks since last deposit will apply. - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| amounts | uint256[] | how much of each token to withdraw | -| maxBurnAmount | uint256 | the max LP token provider is willing to pay to remove liquidity. Useful as a front-running mitigation. | -| deadline | uint256 | latest timestamp to accept this transaction | - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | uint256 | amount of LP tokens burned | - -### removeLiquidityOneToken - -```solidity -function removeLiquidityOneToken(uint256 tokenAmount, uint8 tokenIndex, uint256 minAmount, uint256 deadline) external nonpayable returns (uint256) -``` - -Remove liquidity from the pool all in one token. Withdraw fee that decays linearly over period of 4 weeks since last deposit will apply. - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| tokenAmount | uint256 | the amount of the token you want to receive | -| tokenIndex | uint8 | the index of the token you want to receive | -| minAmount | uint256 | the minimum amount to withdraw, otherwise revert | -| deadline | uint256 | latest timestamp to accept this transaction | - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | uint256 | amount of chosen token user received | - -### renounceOwnership - -```solidity -function renounceOwnership() external nonpayable -``` - - - -*Leaves the contract without owner. It will not be possible to call `onlyOwner` functions anymore. Can only be called by the current owner. NOTE: Renouncing ownership will leave the contract without an owner, thereby removing any functionality that is only available to the owner.* - - -### setAdminFee - -```solidity -function setAdminFee(uint256 newAdminFee) external nonpayable -``` - -Update the admin fee. Admin fee takes portion of the swap fee. - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| newAdminFee | uint256 | new admin fee to be applied on future transactions | - -### setRewardReceiver - -```solidity -function setRewardReceiver(address _reward_receiver) external nonpayable -``` - - - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| _reward_receiver | address | undefined | - -### setSwapFee - -```solidity -function setSwapFee(uint256 newSwapFee) external nonpayable -``` - -Update the swap fee to be applied on swaps - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| newSwapFee | uint256 | new swap fee to be applied on future transactions | - -### stopRampA - -```solidity -function stopRampA() external nonpayable -``` - -Stop ramping A immediately. Reverts if ramp A is already stopped. - - - - -### swap - -```solidity -function swap(uint8 tokenIndexFrom, uint8 tokenIndexTo, uint256 dx, uint256 minDy, uint256 deadline) external nonpayable returns (uint256) -``` - -Swap two tokens using this pool - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| tokenIndexFrom | uint8 | the token the user wants to swap from | -| tokenIndexTo | uint8 | the token the user wants to swap to | -| dx | uint256 | the amount of tokens the user wants to swap from | -| minDy | uint256 | the min amount the user would like to receive, or revert. | -| deadline | uint256 | latest timestamp to accept this transaction | - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | uint256 | undefined | - -### swapStorage - -```solidity -function swapStorage() external view returns (uint256 initialA, uint256 futureA, uint256 initialATime, uint256 futureATime, uint256 swapFee, uint256 adminFee, contract LPToken lpToken) -``` - - - - - - -#### Returns - -| Name | Type | Description | -|---|---|---| -| initialA | uint256 | undefined | -| futureA | uint256 | undefined | -| initialATime | uint256 | undefined | -| futureATime | uint256 | undefined | -| swapFee | uint256 | undefined | -| adminFee | uint256 | undefined | -| lpToken | contract LPToken | undefined | - -### transferOwnership - -```solidity -function transferOwnership(address newOwner) external nonpayable -``` - - - -*Transfers ownership of the contract to a new account (`newOwner`). Can only be called by the current owner.* - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| newOwner | address | undefined | - -### unpause - -```solidity -function unpause() external nonpayable -``` - -Unpause the contract. Revert if already unpaused. - - - - -### withdrawAdminFees - -```solidity -function withdrawAdminFees() external nonpayable -``` - -Withdraw all admin fees to the contract owner - - - - - - -## Events - -### AddLiquidity - -```solidity -event AddLiquidity(address indexed provider, uint256[] tokenAmounts, uint256[] fees, uint256 invariant, uint256 lpTokenSupply) -``` - - - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| provider `indexed` | address | undefined | -| tokenAmounts | uint256[] | undefined | -| fees | uint256[] | undefined | -| invariant | uint256 | undefined | -| lpTokenSupply | uint256 | undefined | - -### NewAdminFee - -```solidity -event NewAdminFee(uint256 newAdminFee) -``` - - - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| newAdminFee | uint256 | undefined | - -### NewSwapFee - -```solidity -event NewSwapFee(uint256 newSwapFee) -``` - - - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| newSwapFee | uint256 | undefined | - -### OwnershipTransferred - -```solidity -event OwnershipTransferred(address indexed previousOwner, address indexed newOwner) -``` - - - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| previousOwner `indexed` | address | undefined | -| newOwner `indexed` | address | undefined | - -### Paused - -```solidity -event Paused(address account) -``` - - - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| account | address | undefined | - -### RampA - -```solidity -event RampA(uint256 oldA, uint256 newA, uint256 initialTime, uint256 futureTime) -``` - - - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| oldA | uint256 | undefined | -| newA | uint256 | undefined | -| initialTime | uint256 | undefined | -| futureTime | uint256 | undefined | - -### RemoveLiquidity - -```solidity -event RemoveLiquidity(address indexed provider, uint256[] tokenAmounts, uint256 lpTokenSupply) -``` - - - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| provider `indexed` | address | undefined | -| tokenAmounts | uint256[] | undefined | -| lpTokenSupply | uint256 | undefined | - -### RemoveLiquidityImbalance - -```solidity -event RemoveLiquidityImbalance(address indexed provider, uint256[] tokenAmounts, uint256[] fees, uint256 invariant, uint256 lpTokenSupply) -``` - - - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| provider `indexed` | address | undefined | -| tokenAmounts | uint256[] | undefined | -| fees | uint256[] | undefined | -| invariant | uint256 | undefined | -| lpTokenSupply | uint256 | undefined | - -### RemoveLiquidityOne - -```solidity -event RemoveLiquidityOne(address indexed provider, uint256 lpTokenAmount, uint256 lpTokenSupply, uint256 boughtId, uint256 tokensBought) -``` - - - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| provider `indexed` | address | undefined | -| lpTokenAmount | uint256 | undefined | -| lpTokenSupply | uint256 | undefined | -| boughtId | uint256 | undefined | -| tokensBought | uint256 | undefined | - -### StopRampA - -```solidity -event StopRampA(uint256 currentA, uint256 time) -``` - - - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| currentA | uint256 | undefined | -| time | uint256 | undefined | - -### TokenSwap - -```solidity -event TokenSwap(address indexed buyer, uint256 tokensSold, uint256 tokensBought, uint128 soldId, uint128 boughtId) -``` - - - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| buyer `indexed` | address | undefined | -| tokensSold | uint256 | undefined | -| tokensBought | uint256 | undefined | -| soldId | uint128 | undefined | -| boughtId | uint128 | undefined | - -### Unpaused - -```solidity -event Unpaused(address account) -``` - - - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| account | address | undefined | - - - diff --git a/docs/amm/AaveSwapWrapper.md b/docs/amm/AaveSwapWrapper.md deleted file mode 100644 index d337ac5d5..000000000 --- a/docs/amm/AaveSwapWrapper.md +++ /dev/null @@ -1,351 +0,0 @@ -# AaveSwapWrapper - - - -> AaveSwapWrapper - -A wrapper contract for interacting with aTokens - - - -## Methods - -### LENDING_POOL - -```solidity -function LENDING_POOL() external view returns (contract ILendingPool) -``` - - - - - - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | contract ILendingPool | undefined | - -### LP_TOKEN - -```solidity -function LP_TOKEN() external view returns (contract LPToken) -``` - - - - - - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | contract LPToken | undefined | - -### OWNER - -```solidity -function OWNER() external view returns (address) -``` - - - - - - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | address | undefined | - -### POOLED_TOKENS - -```solidity -function POOLED_TOKENS(uint256) external view returns (contract IERC20) -``` - - - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| _0 | uint256 | undefined | - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | contract IERC20 | undefined | - -### SWAP - -```solidity -function SWAP() external view returns (contract Swap) -``` - - - - - - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | contract Swap | undefined | - -### UNDERLYING_TOKENS - -```solidity -function UNDERLYING_TOKENS(uint256) external view returns (contract IERC20) -``` - - - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| _0 | uint256 | undefined | - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | contract IERC20 | undefined | - -### addLiquidity - -```solidity -function addLiquidity(uint256[] amounts, uint256 minToMint, uint256 deadline) external nonpayable returns (uint256) -``` - -Add liquidity to the pool with the given amounts of tokens. - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| amounts | uint256[] | the amounts of each token to add, in their native precision | -| minToMint | uint256 | the minimum LP tokens adding this amount of liquidity should mint, otherwise revert. Handy for front-running mitigation | -| deadline | uint256 | latest timestamp to accept this transaction | - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | uint256 | amount of LP token user minted and received | - -### calculateRemoveLiquidity - -```solidity -function calculateRemoveLiquidity(uint256 amount) external view returns (uint256[]) -``` - -A simple method to calculate amount of each underlying tokens that is returned upon burning given amount of LP tokens - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| amount | uint256 | the amount of LP tokens that would be burned on withdrawal | - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | uint256[] | array of token balances that the user will receive | - -### calculateRemoveLiquidityOneToken - -```solidity -function calculateRemoveLiquidityOneToken(uint256 tokenAmount, uint8 tokenIndex) external view returns (uint256 availableTokenAmount) -``` - -Calculate the amount of underlying token available to withdraw when withdrawing via only single token - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| tokenAmount | uint256 | the amount of LP token to burn | -| tokenIndex | uint8 | index of which token will be withdrawn | - -#### Returns - -| Name | Type | Description | -|---|---|---| -| availableTokenAmount | uint256 | calculated amount of underlying token available to withdraw | - -### calculateSwap - -```solidity -function calculateSwap(uint8 tokenIndexFrom, uint8 tokenIndexTo, uint256 dx) external view returns (uint256) -``` - -Calculate amount of tokens you receive on swap - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| tokenIndexFrom | uint8 | the token the user wants to sell | -| tokenIndexTo | uint8 | the token the user wants to buy | -| dx | uint256 | the amount of tokens the user wants to sell. If the token charges a fee on transfers, use the amount that gets transferred after the fee. | - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | uint256 | amount of tokens the user will receive | - -### calculateTokenAmount - -```solidity -function calculateTokenAmount(uint256[] amounts, bool deposit) external view returns (uint256) -``` - -A simple method to calculate prices from deposits or withdrawals, excluding fees but including slippage. This is helpful as an input into the various "min" parameters on calls to fight front-running - -*This shouldn't be used outside frontends for user estimates.* - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| amounts | uint256[] | an array of token amounts to deposit or withdrawal, corresponding to pooledTokens. The amount should be in each pooled token's native precision. If a token charges a fee on transfers, use the amount that gets transferred after the fee. | -| deposit | bool | whether this is a deposit or a withdrawal | - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | uint256 | token amount the user will receive | - -### getToken - -```solidity -function getToken(uint8 index) external view returns (contract IERC20) -``` - -Return address of the pooled token at given index. Reverts if tokenIndex is out of range. - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| index | uint8 | the index of the token | - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | contract IERC20 | address of the token at given index | - -### removeLiquidity - -```solidity -function removeLiquidity(uint256 amount, uint256[] minAmounts, uint256 deadline) external nonpayable returns (uint256[]) -``` - -Burn LP tokens to remove liquidity from the pool. - -*Liquidity can always be removed, even when the pool is paused. Caller will receive ETH instead of WETH9.* - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| amount | uint256 | the amount of LP tokens to burn | -| minAmounts | uint256[] | the minimum amounts of each token in the pool acceptable for this burn. Useful as a front-running mitigation | -| deadline | uint256 | latest timestamp to accept this transaction | - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | uint256[] | amounts of tokens user received | - -### removeLiquidityOneToken - -```solidity -function removeLiquidityOneToken(uint256 tokenAmount, uint8 tokenIndex, uint256 minAmount, uint256 deadline) external nonpayable returns (uint256) -``` - -Remove liquidity from the pool all in one token. - -*Caller will receive ETH instead of WETH9.* - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| tokenAmount | uint256 | the amount of the token you want to receive | -| tokenIndex | uint8 | the index of the token you want to receive | -| minAmount | uint256 | the minimum amount to withdraw, otherwise revert | -| deadline | uint256 | latest timestamp to accept this transaction | - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | uint256 | amount of chosen token user received | - -### rescue - -```solidity -function rescue() external nonpayable -``` - -Rescues any of the ETH, the pooled tokens, or the LPToken that may be stuck in this contract. Only the OWNER can call this function. - - - - -### swap - -```solidity -function swap(uint8 tokenIndexFrom, uint8 tokenIndexTo, uint256 dx, uint256 minDy, uint256 deadline) external nonpayable returns (uint256) -``` - -Swap two tokens using the underlying pool. If tokenIndexFrom represents WETH9 in the pool, the caller must set msg.value equal to dx. If the user is swapping to WETH9 in the pool, the user will receive ETH instead. - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| tokenIndexFrom | uint8 | the token the user wants to swap from | -| tokenIndexTo | uint8 | the token the user wants to swap to | -| dx | uint256 | the amount of tokens the user wants to swap from | -| minDy | uint256 | the min amount the user would like to receive, or revert. | -| deadline | uint256 | latest timestamp to accept this transaction | - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | uint256 | undefined | - - - - diff --git a/docs/amm/AmplificationUtils.md b/docs/amm/AmplificationUtils.md deleted file mode 100644 index 2131a526b..000000000 --- a/docs/amm/AmplificationUtils.md +++ /dev/null @@ -1,88 +0,0 @@ -# AmplificationUtils - - - -> AmplificationUtils library - -A library to calculate and ramp the A parameter of a given `SwapUtils.Swap` struct. This library assumes the struct is fully validated. - - - -## Methods - -### A_PRECISION - -```solidity -function A_PRECISION() external view returns (uint256) -``` - - - - - - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | uint256 | undefined | - -### MAX_A - -```solidity -function MAX_A() external view returns (uint256) -``` - - - - - - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | uint256 | undefined | - - - -## Events - -### RampA - -```solidity -event RampA(uint256 oldA, uint256 newA, uint256 initialTime, uint256 futureTime) -``` - - - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| oldA | uint256 | undefined | -| newA | uint256 | undefined | -| initialTime | uint256 | undefined | -| futureTime | uint256 | undefined | - -### StopRampA - -```solidity -event StopRampA(uint256 currentA, uint256 time) -``` - - - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| currentA | uint256 | undefined | -| time | uint256 | undefined | - - - diff --git a/docs/amm/ILendingPool.md b/docs/amm/ILendingPool.md deleted file mode 100644 index ecf05407c..000000000 --- a/docs/amm/ILendingPool.md +++ /dev/null @@ -1,58 +0,0 @@ -# ILendingPool - - - - - - - - - -## Methods - -### deposit - -```solidity -function deposit(address asset, uint256 amount, address onBehalfOf, uint16 referralCode) external nonpayable -``` - - - -*Deposits an `amount` of underlying asset into the reserve, receiving in return overlying aTokens. - E.g. User deposits 100 USDC and gets in return 100 aUSDC* - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| asset | address | The address of the underlying asset to deposit | -| amount | uint256 | The amount to be deposited | -| onBehalfOf | address | The address that will receive the aTokens, same as msg.sender if the user wants to receive them on his own wallet, or a different address if the beneficiary of aTokens is a different wallet | -| referralCode | uint16 | Code used to register the integrator originating the operation, for potential rewards. 0 if the action is executed directly by the user, without any middle-man* | - -### withdraw - -```solidity -function withdraw(address asset, uint256 amount, address to) external nonpayable returns (uint256) -``` - - - -*Withdraws an `amount` of underlying asset from the reserve, burning the equivalent aTokens owned E.g. User has 100 aUSDC, calls withdraw() and receives 100 USDC, burning the 100 aUSDC* - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| asset | address | The address of the underlying asset to withdraw | -| amount | uint256 | The underlying amount to be withdrawn - Send the value type(uint256).max in order to withdraw the whole aToken balance | -| to | address | Address that will receive the underlying, same as msg.sender if the user wants to receive it on his own wallet, or a different address if the beneficiary is a different wallet | - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | uint256 | The final amount withdrawn* | - - - - diff --git a/docs/amm/LPToken.md b/docs/amm/LPToken.md deleted file mode 100644 index aa526829b..000000000 --- a/docs/amm/LPToken.md +++ /dev/null @@ -1,417 +0,0 @@ -# LPToken - - - -> Liquidity Provider Token - -This token is an ERC20 detailed token with added capability to be minted by the owner. It is used to represent user's shares when providing liquidity to swap contracts. - -*Only Swap contracts should initialize and own LPToken contracts.* - -## Methods - -### allowance - -```solidity -function allowance(address owner, address spender) external view returns (uint256) -``` - - - -*See {IERC20-allowance}.* - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| owner | address | undefined | -| spender | address | undefined | - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | uint256 | undefined | - -### approve - -```solidity -function approve(address spender, uint256 amount) external nonpayable returns (bool) -``` - - - -*See {IERC20-approve}. Requirements: - `spender` cannot be the zero address.* - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| spender | address | undefined | -| amount | uint256 | undefined | - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | bool | undefined | - -### balanceOf - -```solidity -function balanceOf(address account) external view returns (uint256) -``` - - - -*See {IERC20-balanceOf}.* - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| account | address | undefined | - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | uint256 | undefined | - -### burn - -```solidity -function burn(uint256 amount) external nonpayable -``` - - - -*Destroys `amount` tokens from the caller. See {ERC20-_burn}.* - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| amount | uint256 | undefined | - -### burnFrom - -```solidity -function burnFrom(address account, uint256 amount) external nonpayable -``` - - - -*Destroys `amount` tokens from `account`, deducting from the caller's allowance. See {ERC20-_burn} and {ERC20-allowance}. Requirements: - the caller must have allowance for ``accounts``'s tokens of at least `amount`.* - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| account | address | undefined | -| amount | uint256 | undefined | - -### decimals - -```solidity -function decimals() external view returns (uint8) -``` - - - -*Returns the number of decimals used to get its user representation. For example, if `decimals` equals `2`, a balance of `505` tokens should be displayed to a user as `5,05` (`505 / 10 ** 2`). Tokens usually opt for a value of 18, imitating the relationship between Ether and Wei. This is the value {ERC20} uses, unless {_setupDecimals} is called. NOTE: This information is only used for _display_ purposes: it in no way affects any of the arithmetic of the contract, including {IERC20-balanceOf} and {IERC20-transfer}.* - - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | uint8 | undefined | - -### decreaseAllowance - -```solidity -function decreaseAllowance(address spender, uint256 subtractedValue) external nonpayable returns (bool) -``` - - - -*Atomically decreases the allowance granted to `spender` by the caller. This is an alternative to {approve} that can be used as a mitigation for problems described in {IERC20-approve}. Emits an {Approval} event indicating the updated allowance. Requirements: - `spender` cannot be the zero address. - `spender` must have allowance for the caller of at least `subtractedValue`.* - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| spender | address | undefined | -| subtractedValue | uint256 | undefined | - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | bool | undefined | - -### increaseAllowance - -```solidity -function increaseAllowance(address spender, uint256 addedValue) external nonpayable returns (bool) -``` - - - -*Atomically increases the allowance granted to `spender` by the caller. This is an alternative to {approve} that can be used as a mitigation for problems described in {IERC20-approve}. Emits an {Approval} event indicating the updated allowance. Requirements: - `spender` cannot be the zero address.* - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| spender | address | undefined | -| addedValue | uint256 | undefined | - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | bool | undefined | - -### initialize - -```solidity -function initialize(string name, string symbol) external nonpayable returns (bool) -``` - -Initializes this LPToken contract with the given name and symbol - -*The caller of this function will become the owner. A Swap contract should call this in its initializer function.* - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| name | string | name of this token | -| symbol | string | symbol of this token | - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | bool | undefined | - -### mint - -```solidity -function mint(address recipient, uint256 amount) external nonpayable -``` - -Mints the given amount of LPToken to the recipient. - -*only owner can call this mint function* - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| recipient | address | address of account to receive the tokens | -| amount | uint256 | amount of tokens to mint | - -### name - -```solidity -function name() external view returns (string) -``` - - - -*Returns the name of the token.* - - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | string | undefined | - -### owner - -```solidity -function owner() external view returns (address) -``` - - - -*Returns the address of the current owner.* - - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | address | undefined | - -### renounceOwnership - -```solidity -function renounceOwnership() external nonpayable -``` - - - -*Leaves the contract without owner. It will not be possible to call `onlyOwner` functions anymore. Can only be called by the current owner. NOTE: Renouncing ownership will leave the contract without an owner, thereby removing any functionality that is only available to the owner.* - - -### symbol - -```solidity -function symbol() external view returns (string) -``` - - - -*Returns the symbol of the token, usually a shorter version of the name.* - - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | string | undefined | - -### totalSupply - -```solidity -function totalSupply() external view returns (uint256) -``` - - - -*See {IERC20-totalSupply}.* - - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | uint256 | undefined | - -### transfer - -```solidity -function transfer(address recipient, uint256 amount) external nonpayable returns (bool) -``` - - - -*See {IERC20-transfer}. Requirements: - `recipient` cannot be the zero address. - the caller must have a balance of at least `amount`.* - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| recipient | address | undefined | -| amount | uint256 | undefined | - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | bool | undefined | - -### transferFrom - -```solidity -function transferFrom(address sender, address recipient, uint256 amount) external nonpayable returns (bool) -``` - - - -*See {IERC20-transferFrom}. Emits an {Approval} event indicating the updated allowance. This is not required by the EIP. See the note at the beginning of {ERC20}. Requirements: - `sender` and `recipient` cannot be the zero address. - `sender` must have a balance of at least `amount`. - the caller must have allowance for ``sender``'s tokens of at least `amount`.* - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| sender | address | undefined | -| recipient | address | undefined | -| amount | uint256 | undefined | - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | bool | undefined | - -### transferOwnership - -```solidity -function transferOwnership(address newOwner) external nonpayable -``` - - - -*Transfers ownership of the contract to a new account (`newOwner`). Can only be called by the current owner.* - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| newOwner | address | undefined | - - - -## Events - -### Approval - -```solidity -event Approval(address indexed owner, address indexed spender, uint256 value) -``` - - - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| owner `indexed` | address | undefined | -| spender `indexed` | address | undefined | -| value | uint256 | undefined | - -### OwnershipTransferred - -```solidity -event OwnershipTransferred(address indexed previousOwner, address indexed newOwner) -``` - - - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| previousOwner `indexed` | address | undefined | -| newOwner `indexed` | address | undefined | - -### Transfer - -```solidity -event Transfer(address indexed from, address indexed to, uint256 value) -``` - - - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| from `indexed` | address | undefined | -| to `indexed` | address | undefined | -| value | uint256 | undefined | - - - diff --git a/docs/amm/MathUtils.md b/docs/amm/MathUtils.md deleted file mode 100644 index 707649233..000000000 --- a/docs/amm/MathUtils.md +++ /dev/null @@ -1,12 +0,0 @@ -# MathUtils - - - -> MathUtils library - -A library to be used in conjunction with SafeMath. Contains functions for calculating differences between two uint256. - - - - - diff --git a/docs/amm/OwnerPausableUpgradeable.md b/docs/amm/OwnerPausableUpgradeable.md deleted file mode 100644 index 3c2730f00..000000000 --- a/docs/amm/OwnerPausableUpgradeable.md +++ /dev/null @@ -1,150 +0,0 @@ -# OwnerPausableUpgradeable - - - -> OwnerPausable - -An ownable contract allows the owner to pause and unpause the contract without a delay. - -*Only methods using the provided modifiers will be paused.* - -## Methods - -### owner - -```solidity -function owner() external view returns (address) -``` - - - -*Returns the address of the current owner.* - - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | address | undefined | - -### pause - -```solidity -function pause() external nonpayable -``` - -Pause the contract. Revert if already paused. - - - - -### paused - -```solidity -function paused() external view returns (bool) -``` - - - -*Returns true if the contract is paused, and false otherwise.* - - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | bool | undefined | - -### renounceOwnership - -```solidity -function renounceOwnership() external nonpayable -``` - - - -*Leaves the contract without owner. It will not be possible to call `onlyOwner` functions anymore. Can only be called by the current owner. NOTE: Renouncing ownership will leave the contract without an owner, thereby removing any functionality that is only available to the owner.* - - -### transferOwnership - -```solidity -function transferOwnership(address newOwner) external nonpayable -``` - - - -*Transfers ownership of the contract to a new account (`newOwner`). Can only be called by the current owner.* - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| newOwner | address | undefined | - -### unpause - -```solidity -function unpause() external nonpayable -``` - -Unpause the contract. Revert if already unpaused. - - - - - - -## Events - -### OwnershipTransferred - -```solidity -event OwnershipTransferred(address indexed previousOwner, address indexed newOwner) -``` - - - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| previousOwner `indexed` | address | undefined | -| newOwner `indexed` | address | undefined | - -### Paused - -```solidity -event Paused(address account) -``` - - - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| account | address | undefined | - -### Unpaused - -```solidity -event Unpaused(address account) -``` - - - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| account | address | undefined | - - - diff --git a/docs/amm/Swap.md b/docs/amm/Swap.md deleted file mode 100644 index bdb434b6f..000000000 --- a/docs/amm/Swap.md +++ /dev/null @@ -1,787 +0,0 @@ -# Swap - - - -> Swap - A StableSwap implementation in solidity. - -This contract is responsible for custody of closely pegged assets (eg. group of stablecoins) and automatic market making system. Users become an LP (Liquidity Provider) by depositing their tokens in desired ratios for an exchange of the pool token that represents their share of the pool. Users can burn pool tokens and withdraw their share of token(s). Each time a swap between the pooled tokens happens, a set fee incurs which effectively gets distributed to the LPs. In case of emergencies, admin can pause additional deposits, swaps, or single-asset withdraws - which stops the ratio of the tokens in the pool from changing. Users can always withdraw their tokens via multi-asset withdraws. - -*Most of the logic is stored as a library `SwapUtils` for the sake of reducing contract's deployment size.* - -## Methods - -### addLiquidity - -```solidity -function addLiquidity(uint256[] amounts, uint256 minToMint, uint256 deadline) external nonpayable returns (uint256) -``` - -Add liquidity to the pool with the given amounts of tokens - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| amounts | uint256[] | the amounts of each token to add, in their native precision | -| minToMint | uint256 | the minimum LP tokens adding this amount of liquidity should mint, otherwise revert. Handy for front-running mitigation | -| deadline | uint256 | latest timestamp to accept this transaction | - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | uint256 | amount of LP token user minted and received | - -### calculateRemoveLiquidity - -```solidity -function calculateRemoveLiquidity(uint256 amount) external view returns (uint256[]) -``` - -A simple method to calculate amount of each underlying tokens that is returned upon burning given amount of LP tokens - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| amount | uint256 | the amount of LP tokens that would be burned on withdrawal | - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | uint256[] | array of token balances that the user will receive | - -### calculateRemoveLiquidityOneToken - -```solidity -function calculateRemoveLiquidityOneToken(uint256 tokenAmount, uint8 tokenIndex) external view returns (uint256 availableTokenAmount) -``` - -Calculate the amount of underlying token available to withdraw when withdrawing via only single token - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| tokenAmount | uint256 | the amount of LP token to burn | -| tokenIndex | uint8 | index of which token will be withdrawn | - -#### Returns - -| Name | Type | Description | -|---|---|---| -| availableTokenAmount | uint256 | calculated amount of underlying token available to withdraw | - -### calculateSwap - -```solidity -function calculateSwap(uint8 tokenIndexFrom, uint8 tokenIndexTo, uint256 dx) external view returns (uint256) -``` - -Calculate amount of tokens you receive on swap - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| tokenIndexFrom | uint8 | the token the user wants to sell | -| tokenIndexTo | uint8 | the token the user wants to buy | -| dx | uint256 | the amount of tokens the user wants to sell. If the token charges a fee on transfers, use the amount that gets transferred after the fee. | - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | uint256 | amount of tokens the user will receive | - -### calculateTokenAmount - -```solidity -function calculateTokenAmount(uint256[] amounts, bool deposit) external view returns (uint256) -``` - -A simple method to calculate prices from deposits or withdrawals, excluding fees but including slippage. This is helpful as an input into the various "min" parameters on calls to fight front-running - -*This shouldn't be used outside frontends for user estimates.* - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| amounts | uint256[] | an array of token amounts to deposit or withdrawal, corresponding to pooledTokens. The amount should be in each pooled token's native precision. If a token charges a fee on transfers, use the amount that gets transferred after the fee. | -| deposit | bool | whether this is a deposit or a withdrawal | - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | uint256 | token amount the user will receive | - -### getA - -```solidity -function getA() external view returns (uint256) -``` - -Return A, the amplification coefficient * n * (n - 1) - -*See the StableSwap paper for details* - - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | uint256 | A parameter | - -### getAPrecise - -```solidity -function getAPrecise() external view returns (uint256) -``` - -Return A in its raw precision form - -*See the StableSwap paper for details* - - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | uint256 | A parameter in its raw precision form | - -### getAdminBalance - -```solidity -function getAdminBalance(uint256 index) external view returns (uint256) -``` - -This function reads the accumulated amount of admin fees of the token with given index - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| index | uint256 | Index of the pooled token | - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | uint256 | admin's token balance in the token's precision | - -### getToken - -```solidity -function getToken(uint8 index) external view returns (contract IERC20) -``` - -Return address of the pooled token at given index. Reverts if tokenIndex is out of range. - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| index | uint8 | the index of the token | - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | contract IERC20 | address of the token at given index | - -### getTokenBalance - -```solidity -function getTokenBalance(uint8 index) external view returns (uint256) -``` - -Return current balance of the pooled token at given index - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| index | uint8 | the index of the token | - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | uint256 | current balance of the pooled token at given index with token's native precision | - -### getTokenIndex - -```solidity -function getTokenIndex(address tokenAddress) external view returns (uint8) -``` - -Return the index of the given token address. Reverts if no matching token is found. - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| tokenAddress | address | address of the token | - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | uint8 | the index of the given token address | - -### getVirtualPrice - -```solidity -function getVirtualPrice() external view returns (uint256) -``` - -Get the virtual price, to help calculate profit - - - - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | uint256 | the virtual price, scaled to the POOL_PRECISION_DECIMALS | - -### initialize - -```solidity -function initialize(contract IERC20[] _pooledTokens, uint8[] decimals, string lpTokenName, string lpTokenSymbol, uint256 _a, uint256 _fee, uint256 _adminFee, address lpTokenTargetAddress) external nonpayable -``` - -Initializes this Swap contract with the given parameters. This will also clone a LPToken contract that represents users' LP positions. The owner of LPToken will be this contract - which means only this contract is allowed to mint/burn tokens. - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| _pooledTokens | contract IERC20[] | an array of ERC20s this pool will accept | -| decimals | uint8[] | the decimals to use for each pooled token, eg 8 for WBTC. Cannot be larger than POOL_PRECISION_DECIMALS | -| lpTokenName | string | the long-form name of the token to be deployed | -| lpTokenSymbol | string | the short symbol for the token to be deployed | -| _a | uint256 | the amplification coefficient * n * (n - 1). See the StableSwap paper for details | -| _fee | uint256 | default swap fee to be initialized with | -| _adminFee | uint256 | default adminFee to be initialized with | -| lpTokenTargetAddress | address | the address of an existing LPToken contract to use as a target | - -### owner - -```solidity -function owner() external view returns (address) -``` - - - -*Returns the address of the current owner.* - - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | address | undefined | - -### pause - -```solidity -function pause() external nonpayable -``` - -Pause the contract. Revert if already paused. - - - - -### paused - -```solidity -function paused() external view returns (bool) -``` - - - -*Returns true if the contract is paused, and false otherwise.* - - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | bool | undefined | - -### rampA - -```solidity -function rampA(uint256 futureA, uint256 futureTime) external nonpayable -``` - -Start ramping up or down A parameter towards given futureA and futureTime Checks if the change is too rapid, and commits the new A value only when it falls under the limit range. - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| futureA | uint256 | the new A to ramp towards | -| futureTime | uint256 | timestamp when the new A should be reached | - -### removeLiquidity - -```solidity -function removeLiquidity(uint256 amount, uint256[] minAmounts, uint256 deadline) external nonpayable returns (uint256[]) -``` - -Burn LP tokens to remove liquidity from the pool. Withdraw fee that decays linearly over period of 4 weeks since last deposit will apply. - -*Liquidity can always be removed, even when the pool is paused.* - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| amount | uint256 | the amount of LP tokens to burn | -| minAmounts | uint256[] | the minimum amounts of each token in the pool acceptable for this burn. Useful as a front-running mitigation | -| deadline | uint256 | latest timestamp to accept this transaction | - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | uint256[] | amounts of tokens user received | - -### removeLiquidityImbalance - -```solidity -function removeLiquidityImbalance(uint256[] amounts, uint256 maxBurnAmount, uint256 deadline) external nonpayable returns (uint256) -``` - -Remove liquidity from the pool, weighted differently than the pool's current balances. Withdraw fee that decays linearly over period of 4 weeks since last deposit will apply. - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| amounts | uint256[] | how much of each token to withdraw | -| maxBurnAmount | uint256 | the max LP token provider is willing to pay to remove liquidity. Useful as a front-running mitigation. | -| deadline | uint256 | latest timestamp to accept this transaction | - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | uint256 | amount of LP tokens burned | - -### removeLiquidityOneToken - -```solidity -function removeLiquidityOneToken(uint256 tokenAmount, uint8 tokenIndex, uint256 minAmount, uint256 deadline) external nonpayable returns (uint256) -``` - -Remove liquidity from the pool all in one token. Withdraw fee that decays linearly over period of 4 weeks since last deposit will apply. - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| tokenAmount | uint256 | the amount of the token you want to receive | -| tokenIndex | uint8 | the index of the token you want to receive | -| minAmount | uint256 | the minimum amount to withdraw, otherwise revert | -| deadline | uint256 | latest timestamp to accept this transaction | - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | uint256 | amount of chosen token user received | - -### renounceOwnership - -```solidity -function renounceOwnership() external nonpayable -``` - - - -*Leaves the contract without owner. It will not be possible to call `onlyOwner` functions anymore. Can only be called by the current owner. NOTE: Renouncing ownership will leave the contract without an owner, thereby removing any functionality that is only available to the owner.* - - -### setAdminFee - -```solidity -function setAdminFee(uint256 newAdminFee) external nonpayable -``` - -Update the admin fee. Admin fee takes portion of the swap fee. - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| newAdminFee | uint256 | new admin fee to be applied on future transactions | - -### setSwapFee - -```solidity -function setSwapFee(uint256 newSwapFee) external nonpayable -``` - -Update the swap fee to be applied on swaps - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| newSwapFee | uint256 | new swap fee to be applied on future transactions | - -### stopRampA - -```solidity -function stopRampA() external nonpayable -``` - -Stop ramping A immediately. Reverts if ramp A is already stopped. - - - - -### swap - -```solidity -function swap(uint8 tokenIndexFrom, uint8 tokenIndexTo, uint256 dx, uint256 minDy, uint256 deadline) external nonpayable returns (uint256) -``` - -Swap two tokens using this pool - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| tokenIndexFrom | uint8 | the token the user wants to swap from | -| tokenIndexTo | uint8 | the token the user wants to swap to | -| dx | uint256 | the amount of tokens the user wants to swap from | -| minDy | uint256 | the min amount the user would like to receive, or revert. | -| deadline | uint256 | latest timestamp to accept this transaction | - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | uint256 | undefined | - -### swapStorage - -```solidity -function swapStorage() external view returns (uint256 initialA, uint256 futureA, uint256 initialATime, uint256 futureATime, uint256 swapFee, uint256 adminFee, contract LPToken lpToken) -``` - - - - - - -#### Returns - -| Name | Type | Description | -|---|---|---| -| initialA | uint256 | undefined | -| futureA | uint256 | undefined | -| initialATime | uint256 | undefined | -| futureATime | uint256 | undefined | -| swapFee | uint256 | undefined | -| adminFee | uint256 | undefined | -| lpToken | contract LPToken | undefined | - -### transferOwnership - -```solidity -function transferOwnership(address newOwner) external nonpayable -``` - - - -*Transfers ownership of the contract to a new account (`newOwner`). Can only be called by the current owner.* - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| newOwner | address | undefined | - -### unpause - -```solidity -function unpause() external nonpayable -``` - -Unpause the contract. Revert if already unpaused. - - - - -### withdrawAdminFees - -```solidity -function withdrawAdminFees() external nonpayable -``` - -Withdraw all admin fees to the contract owner - - - - - - -## Events - -### AddLiquidity - -```solidity -event AddLiquidity(address indexed provider, uint256[] tokenAmounts, uint256[] fees, uint256 invariant, uint256 lpTokenSupply) -``` - - - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| provider `indexed` | address | undefined | -| tokenAmounts | uint256[] | undefined | -| fees | uint256[] | undefined | -| invariant | uint256 | undefined | -| lpTokenSupply | uint256 | undefined | - -### NewAdminFee - -```solidity -event NewAdminFee(uint256 newAdminFee) -``` - - - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| newAdminFee | uint256 | undefined | - -### NewSwapFee - -```solidity -event NewSwapFee(uint256 newSwapFee) -``` - - - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| newSwapFee | uint256 | undefined | - -### OwnershipTransferred - -```solidity -event OwnershipTransferred(address indexed previousOwner, address indexed newOwner) -``` - - - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| previousOwner `indexed` | address | undefined | -| newOwner `indexed` | address | undefined | - -### Paused - -```solidity -event Paused(address account) -``` - - - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| account | address | undefined | - -### RampA - -```solidity -event RampA(uint256 oldA, uint256 newA, uint256 initialTime, uint256 futureTime) -``` - - - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| oldA | uint256 | undefined | -| newA | uint256 | undefined | -| initialTime | uint256 | undefined | -| futureTime | uint256 | undefined | - -### RemoveLiquidity - -```solidity -event RemoveLiquidity(address indexed provider, uint256[] tokenAmounts, uint256 lpTokenSupply) -``` - - - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| provider `indexed` | address | undefined | -| tokenAmounts | uint256[] | undefined | -| lpTokenSupply | uint256 | undefined | - -### RemoveLiquidityImbalance - -```solidity -event RemoveLiquidityImbalance(address indexed provider, uint256[] tokenAmounts, uint256[] fees, uint256 invariant, uint256 lpTokenSupply) -``` - - - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| provider `indexed` | address | undefined | -| tokenAmounts | uint256[] | undefined | -| fees | uint256[] | undefined | -| invariant | uint256 | undefined | -| lpTokenSupply | uint256 | undefined | - -### RemoveLiquidityOne - -```solidity -event RemoveLiquidityOne(address indexed provider, uint256 lpTokenAmount, uint256 lpTokenSupply, uint256 boughtId, uint256 tokensBought) -``` - - - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| provider `indexed` | address | undefined | -| lpTokenAmount | uint256 | undefined | -| lpTokenSupply | uint256 | undefined | -| boughtId | uint256 | undefined | -| tokensBought | uint256 | undefined | - -### StopRampA - -```solidity -event StopRampA(uint256 currentA, uint256 time) -``` - - - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| currentA | uint256 | undefined | -| time | uint256 | undefined | - -### TokenSwap - -```solidity -event TokenSwap(address indexed buyer, uint256 tokensSold, uint256 tokensBought, uint128 soldId, uint128 boughtId) -``` - - - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| buyer `indexed` | address | undefined | -| tokensSold | uint256 | undefined | -| tokensBought | uint256 | undefined | -| soldId | uint128 | undefined | -| boughtId | uint128 | undefined | - -### Unpaused - -```solidity -event Unpaused(address account) -``` - - - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| account | address | undefined | - - - diff --git a/docs/amm/SwapDeployer.md b/docs/amm/SwapDeployer.md deleted file mode 100644 index 5f0d5deb7..000000000 --- a/docs/amm/SwapDeployer.md +++ /dev/null @@ -1,127 +0,0 @@ -# SwapDeployer - - - - - - - - - -## Methods - -### deploy - -```solidity -function deploy(address swapAddress, contract IERC20[] _pooledTokens, uint8[] decimals, string lpTokenName, string lpTokenSymbol, uint256 _a, uint256 _fee, uint256 _adminFee, address lpTokenTargetAddress) external nonpayable returns (address) -``` - - - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| swapAddress | address | undefined | -| _pooledTokens | contract IERC20[] | undefined | -| decimals | uint8[] | undefined | -| lpTokenName | string | undefined | -| lpTokenSymbol | string | undefined | -| _a | uint256 | undefined | -| _fee | uint256 | undefined | -| _adminFee | uint256 | undefined | -| lpTokenTargetAddress | address | undefined | - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | address | undefined | - -### owner - -```solidity -function owner() external view returns (address) -``` - - - -*Returns the address of the current owner.* - - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | address | undefined | - -### renounceOwnership - -```solidity -function renounceOwnership() external nonpayable -``` - - - -*Leaves the contract without owner. It will not be possible to call `onlyOwner` functions anymore. Can only be called by the current owner. NOTE: Renouncing ownership will leave the contract without an owner, thereby removing any functionality that is only available to the owner.* - - -### transferOwnership - -```solidity -function transferOwnership(address newOwner) external nonpayable -``` - - - -*Transfers ownership of the contract to a new account (`newOwner`). Can only be called by the current owner.* - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| newOwner | address | undefined | - - - -## Events - -### NewSwapPool - -```solidity -event NewSwapPool(address indexed deployer, address swapAddress, contract IERC20[] pooledTokens) -``` - - - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| deployer `indexed` | address | undefined | -| swapAddress | address | undefined | -| pooledTokens | contract IERC20[] | undefined | - -### OwnershipTransferred - -```solidity -event OwnershipTransferred(address indexed previousOwner, address indexed newOwner) -``` - - - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| previousOwner `indexed` | address | undefined | -| newOwner `indexed` | address | undefined | - - - diff --git a/docs/amm/SwapEthWrapper.md b/docs/amm/SwapEthWrapper.md deleted file mode 100644 index 682ebadfc..000000000 --- a/docs/amm/SwapEthWrapper.md +++ /dev/null @@ -1,324 +0,0 @@ -# SwapEthWrapper - -*Jongseung Lim (@weeb_mcgee)* - -> SwapEthWrapper - -A wrapper contract for Swap contracts that have WETH as one of the pooled tokens. - - - -## Methods - -### LP_TOKEN - -```solidity -function LP_TOKEN() external view returns (contract LPToken) -``` - - - - - - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | contract LPToken | undefined | - -### OWNER - -```solidity -function OWNER() external view returns (address) -``` - - - - - - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | address | undefined | - -### SWAP - -```solidity -function SWAP() external view returns (contract Swap) -``` - - - - - - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | contract Swap | undefined | - -### WETH_ADDRESS - -```solidity -function WETH_ADDRESS() external view returns (address payable) -``` - - - - - - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | address payable | undefined | - -### WETH_INDEX - -```solidity -function WETH_INDEX() external view returns (uint8) -``` - - - - - - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | uint8 | undefined | - -### addLiquidity - -```solidity -function addLiquidity(uint256[] amounts, uint256 minToMint, uint256 deadline) external payable returns (uint256) -``` - -Add liquidity to the pool with the given amounts of tokens. - -*The msg.value of this call should match the value in amounts array in position of WETH9.* - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| amounts | uint256[] | the amounts of each token to add, in their native precision | -| minToMint | uint256 | the minimum LP tokens adding this amount of liquidity should mint, otherwise revert. Handy for front-running mitigation | -| deadline | uint256 | latest timestamp to accept this transaction | - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | uint256 | amount of LP token user minted and received | - -### calculateRemoveLiquidity - -```solidity -function calculateRemoveLiquidity(uint256 amount) external view returns (uint256[]) -``` - -A simple method to calculate amount of each underlying tokens that is returned upon burning given amount of LP tokens - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| amount | uint256 | the amount of LP tokens that would be burned on withdrawal | - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | uint256[] | array of token balances that the user will receive | - -### calculateRemoveLiquidityOneToken - -```solidity -function calculateRemoveLiquidityOneToken(uint256 tokenAmount, uint8 tokenIndex) external view returns (uint256 availableTokenAmount) -``` - -Calculate the amount of underlying token available to withdraw when withdrawing via only single token - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| tokenAmount | uint256 | the amount of LP token to burn | -| tokenIndex | uint8 | index of which token will be withdrawn | - -#### Returns - -| Name | Type | Description | -|---|---|---| -| availableTokenAmount | uint256 | calculated amount of underlying token available to withdraw | - -### calculateTokenAmount - -```solidity -function calculateTokenAmount(uint256[] amounts, bool deposit) external view returns (uint256) -``` - -A simple method to calculate prices from deposits or withdrawals, excluding fees but including slippage. This is helpful as an input into the various "min" parameters on calls to fight front-running - -*This shouldn't be used outside frontends for user estimates.* - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| amounts | uint256[] | an array of token amounts to deposit or withdrawal, corresponding to pooledTokens. The amount should be in each pooled token's native precision. If a token charges a fee on transfers, use the amount that gets transferred after the fee. | -| deposit | bool | whether this is a deposit or a withdrawal | - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | uint256 | token amount the user will receive | - -### pooledTokens - -```solidity -function pooledTokens(uint256) external view returns (contract IERC20) -``` - - - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| _0 | uint256 | undefined | - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | contract IERC20 | undefined | - -### removeLiquidity - -```solidity -function removeLiquidity(uint256 amount, uint256[] minAmounts, uint256 deadline) external nonpayable returns (uint256[]) -``` - -Burn LP tokens to remove liquidity from the pool. - -*Liquidity can always be removed, even when the pool is paused. Caller will receive ETH instead of WETH9.* - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| amount | uint256 | the amount of LP tokens to burn | -| minAmounts | uint256[] | the minimum amounts of each token in the pool acceptable for this burn. Useful as a front-running mitigation | -| deadline | uint256 | latest timestamp to accept this transaction | - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | uint256[] | amounts of tokens user received | - -### removeLiquidityImbalance - -```solidity -function removeLiquidityImbalance(uint256[] amounts, uint256 maxBurnAmount, uint256 deadline) external nonpayable returns (uint256) -``` - -Remove liquidity from the pool, weighted differently than the pool's current balances. - -*Caller will receive ETH instead of WETH9.* - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| amounts | uint256[] | how much of each token to withdraw | -| maxBurnAmount | uint256 | the max LP token provider is willing to pay to remove liquidity. Useful as a front-running mitigation. | -| deadline | uint256 | latest timestamp to accept this transaction | - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | uint256 | amount of LP tokens burned | - -### removeLiquidityOneToken - -```solidity -function removeLiquidityOneToken(uint256 tokenAmount, uint8 tokenIndex, uint256 minAmount, uint256 deadline) external nonpayable returns (uint256) -``` - -Remove liquidity from the pool all in one token. - -*Caller will receive ETH instead of WETH9.* - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| tokenAmount | uint256 | the amount of the token you want to receive | -| tokenIndex | uint8 | the index of the token you want to receive | -| minAmount | uint256 | the minimum amount to withdraw, otherwise revert | -| deadline | uint256 | latest timestamp to accept this transaction | - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | uint256 | amount of chosen token user received | - -### rescue - -```solidity -function rescue() external nonpayable -``` - -Rescues any of the ETH, the pooled tokens, or the LPToken that may be stuck in this contract. Only the OWNER can call this function. - - - - -### swap - -```solidity -function swap(uint8 tokenIndexFrom, uint8 tokenIndexTo, uint256 dx, uint256 minDy, uint256 deadline) external payable returns (uint256) -``` - -Swap two tokens using the underlying pool. If tokenIndexFrom represents WETH9 in the pool, the caller must set msg.value equal to dx. If the user is swapping to WETH9 in the pool, the user will receive ETH instead. - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| tokenIndexFrom | uint8 | the token the user wants to swap from | -| tokenIndexTo | uint8 | the token the user wants to swap to | -| dx | uint256 | the amount of tokens the user wants to swap from | -| minDy | uint256 | the min amount the user would like to receive, or revert. | -| deadline | uint256 | latest timestamp to accept this transaction | - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | uint256 | undefined | - - - - diff --git a/docs/amm/SwapFlashLoan.md b/docs/amm/SwapFlashLoan.md deleted file mode 100644 index 0edf8bcfa..000000000 --- a/docs/amm/SwapFlashLoan.md +++ /dev/null @@ -1,894 +0,0 @@ -# SwapFlashLoan - - - -> Swap - A StableSwap implementation in solidity. - -This contract is responsible for custody of closely pegged assets (eg. group of stablecoins) and automatic market making system. Users become an LP (Liquidity Provider) by depositing their tokens in desired ratios for an exchange of the pool token that represents their share of the pool. Users can burn pool tokens and withdraw their share of token(s). Each time a swap between the pooled tokens happens, a set fee incurs which effectively gets distributed to the LPs. In case of emergencies, admin can pause additional deposits, swaps, or single-asset withdraws - which stops the ratio of the tokens in the pool from changing. Users can always withdraw their tokens via multi-asset withdraws. - -*Most of the logic is stored as a library `SwapUtils` for the sake of reducing contract's deployment size.* - -## Methods - -### MAX_BPS - -```solidity -function MAX_BPS() external view returns (uint256) -``` - - - - - - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | uint256 | undefined | - -### addLiquidity - -```solidity -function addLiquidity(uint256[] amounts, uint256 minToMint, uint256 deadline) external nonpayable returns (uint256) -``` - -Add liquidity to the pool with the given amounts of tokens - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| amounts | uint256[] | the amounts of each token to add, in their native precision | -| minToMint | uint256 | the minimum LP tokens adding this amount of liquidity should mint, otherwise revert. Handy for front-running mitigation | -| deadline | uint256 | latest timestamp to accept this transaction | - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | uint256 | amount of LP token user minted and received | - -### calculateRemoveLiquidity - -```solidity -function calculateRemoveLiquidity(uint256 amount) external view returns (uint256[]) -``` - -A simple method to calculate amount of each underlying tokens that is returned upon burning given amount of LP tokens - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| amount | uint256 | the amount of LP tokens that would be burned on withdrawal | - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | uint256[] | array of token balances that the user will receive | - -### calculateRemoveLiquidityOneToken - -```solidity -function calculateRemoveLiquidityOneToken(uint256 tokenAmount, uint8 tokenIndex) external view returns (uint256 availableTokenAmount) -``` - -Calculate the amount of underlying token available to withdraw when withdrawing via only single token - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| tokenAmount | uint256 | the amount of LP token to burn | -| tokenIndex | uint8 | index of which token will be withdrawn | - -#### Returns - -| Name | Type | Description | -|---|---|---| -| availableTokenAmount | uint256 | calculated amount of underlying token available to withdraw | - -### calculateSwap - -```solidity -function calculateSwap(uint8 tokenIndexFrom, uint8 tokenIndexTo, uint256 dx) external view returns (uint256) -``` - -Calculate amount of tokens you receive on swap - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| tokenIndexFrom | uint8 | the token the user wants to sell | -| tokenIndexTo | uint8 | the token the user wants to buy | -| dx | uint256 | the amount of tokens the user wants to sell. If the token charges a fee on transfers, use the amount that gets transferred after the fee. | - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | uint256 | amount of tokens the user will receive | - -### calculateTokenAmount - -```solidity -function calculateTokenAmount(uint256[] amounts, bool deposit) external view returns (uint256) -``` - -A simple method to calculate prices from deposits or withdrawals, excluding fees but including slippage. This is helpful as an input into the various "min" parameters on calls to fight front-running - -*This shouldn't be used outside frontends for user estimates.* - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| amounts | uint256[] | an array of token amounts to deposit or withdrawal, corresponding to pooledTokens. The amount should be in each pooled token's native precision. If a token charges a fee on transfers, use the amount that gets transferred after the fee. | -| deposit | bool | whether this is a deposit or a withdrawal | - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | uint256 | token amount the user will receive | - -### flashLoan - -```solidity -function flashLoan(address receiver, contract IERC20 token, uint256 amount, bytes params) external nonpayable -``` - -Borrow the specified token from this pool for this transaction only. This function will call `IFlashLoanReceiver(receiver).executeOperation` and the `receiver` must return the full amount of the token and the associated fee by the end of the callback transaction. If the conditions are not met, this call is reverted. - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| receiver | address | the address of the receiver of the token. This address must implement the IFlashLoanReceiver interface and the callback function `executeOperation`. | -| token | contract IERC20 | the protocol fee in bps to be applied on the total flash loan fee | -| amount | uint256 | the total amount to borrow in this transaction | -| params | bytes | optional data to pass along to the callback function | - -### flashLoanFeeBPS - -```solidity -function flashLoanFeeBPS() external view returns (uint256) -``` - - - - - - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | uint256 | undefined | - -### getA - -```solidity -function getA() external view returns (uint256) -``` - -Return A, the amplification coefficient * n * (n - 1) - -*See the StableSwap paper for details* - - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | uint256 | A parameter | - -### getAPrecise - -```solidity -function getAPrecise() external view returns (uint256) -``` - -Return A in its raw precision form - -*See the StableSwap paper for details* - - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | uint256 | A parameter in its raw precision form | - -### getAdminBalance - -```solidity -function getAdminBalance(uint256 index) external view returns (uint256) -``` - -This function reads the accumulated amount of admin fees of the token with given index - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| index | uint256 | Index of the pooled token | - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | uint256 | admin's token balance in the token's precision | - -### getToken - -```solidity -function getToken(uint8 index) external view returns (contract IERC20) -``` - -Return address of the pooled token at given index. Reverts if tokenIndex is out of range. - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| index | uint8 | the index of the token | - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | contract IERC20 | address of the token at given index | - -### getTokenBalance - -```solidity -function getTokenBalance(uint8 index) external view returns (uint256) -``` - -Return current balance of the pooled token at given index - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| index | uint8 | the index of the token | - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | uint256 | current balance of the pooled token at given index with token's native precision | - -### getTokenIndex - -```solidity -function getTokenIndex(address tokenAddress) external view returns (uint8) -``` - -Return the index of the given token address. Reverts if no matching token is found. - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| tokenAddress | address | address of the token | - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | uint8 | the index of the given token address | - -### getVirtualPrice - -```solidity -function getVirtualPrice() external view returns (uint256) -``` - -Get the virtual price, to help calculate profit - - - - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | uint256 | the virtual price, scaled to the POOL_PRECISION_DECIMALS | - -### initialize - -```solidity -function initialize(contract IERC20[] _pooledTokens, uint8[] decimals, string lpTokenName, string lpTokenSymbol, uint256 _a, uint256 _fee, uint256 _adminFee, address lpTokenTargetAddress) external nonpayable -``` - -Initializes this Swap contract with the given parameters. This will also clone a LPToken contract that represents users' LP positions. The owner of LPToken will be this contract - which means only this contract is allowed to mint/burn tokens. - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| _pooledTokens | contract IERC20[] | an array of ERC20s this pool will accept | -| decimals | uint8[] | the decimals to use for each pooled token, eg 8 for WBTC. Cannot be larger than POOL_PRECISION_DECIMALS | -| lpTokenName | string | the long-form name of the token to be deployed | -| lpTokenSymbol | string | the short symbol for the token to be deployed | -| _a | uint256 | the amplification coefficient * n * (n - 1). See the StableSwap paper for details | -| _fee | uint256 | default swap fee to be initialized with | -| _adminFee | uint256 | default adminFee to be initialized with | -| lpTokenTargetAddress | address | the address of an existing LPToken contract to use as a target | - -### owner - -```solidity -function owner() external view returns (address) -``` - - - -*Returns the address of the current owner.* - - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | address | undefined | - -### pause - -```solidity -function pause() external nonpayable -``` - -Pause the contract. Revert if already paused. - - - - -### paused - -```solidity -function paused() external view returns (bool) -``` - - - -*Returns true if the contract is paused, and false otherwise.* - - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | bool | undefined | - -### protocolFeeShareBPS - -```solidity -function protocolFeeShareBPS() external view returns (uint256) -``` - - - - - - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | uint256 | undefined | - -### rampA - -```solidity -function rampA(uint256 futureA, uint256 futureTime) external nonpayable -``` - -Start ramping up or down A parameter towards given futureA and futureTime Checks if the change is too rapid, and commits the new A value only when it falls under the limit range. - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| futureA | uint256 | the new A to ramp towards | -| futureTime | uint256 | timestamp when the new A should be reached | - -### removeLiquidity - -```solidity -function removeLiquidity(uint256 amount, uint256[] minAmounts, uint256 deadline) external nonpayable returns (uint256[]) -``` - -Burn LP tokens to remove liquidity from the pool. Withdraw fee that decays linearly over period of 4 weeks since last deposit will apply. - -*Liquidity can always be removed, even when the pool is paused.* - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| amount | uint256 | the amount of LP tokens to burn | -| minAmounts | uint256[] | the minimum amounts of each token in the pool acceptable for this burn. Useful as a front-running mitigation | -| deadline | uint256 | latest timestamp to accept this transaction | - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | uint256[] | amounts of tokens user received | - -### removeLiquidityImbalance - -```solidity -function removeLiquidityImbalance(uint256[] amounts, uint256 maxBurnAmount, uint256 deadline) external nonpayable returns (uint256) -``` - -Remove liquidity from the pool, weighted differently than the pool's current balances. Withdraw fee that decays linearly over period of 4 weeks since last deposit will apply. - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| amounts | uint256[] | how much of each token to withdraw | -| maxBurnAmount | uint256 | the max LP token provider is willing to pay to remove liquidity. Useful as a front-running mitigation. | -| deadline | uint256 | latest timestamp to accept this transaction | - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | uint256 | amount of LP tokens burned | - -### removeLiquidityOneToken - -```solidity -function removeLiquidityOneToken(uint256 tokenAmount, uint8 tokenIndex, uint256 minAmount, uint256 deadline) external nonpayable returns (uint256) -``` - -Remove liquidity from the pool all in one token. Withdraw fee that decays linearly over period of 4 weeks since last deposit will apply. - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| tokenAmount | uint256 | the amount of the token you want to receive | -| tokenIndex | uint8 | the index of the token you want to receive | -| minAmount | uint256 | the minimum amount to withdraw, otherwise revert | -| deadline | uint256 | latest timestamp to accept this transaction | - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | uint256 | amount of chosen token user received | - -### renounceOwnership - -```solidity -function renounceOwnership() external nonpayable -``` - - - -*Leaves the contract without owner. It will not be possible to call `onlyOwner` functions anymore. Can only be called by the current owner. NOTE: Renouncing ownership will leave the contract without an owner, thereby removing any functionality that is only available to the owner.* - - -### setAdminFee - -```solidity -function setAdminFee(uint256 newAdminFee) external nonpayable -``` - -Update the admin fee. Admin fee takes portion of the swap fee. - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| newAdminFee | uint256 | new admin fee to be applied on future transactions | - -### setFlashLoanFees - -```solidity -function setFlashLoanFees(uint256 newFlashLoanFeeBPS, uint256 newProtocolFeeShareBPS) external nonpayable -``` - -Updates the flash loan fee parameters. This function can only be called by the owner. - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| newFlashLoanFeeBPS | uint256 | the total fee in bps to be applied on future flash loans | -| newProtocolFeeShareBPS | uint256 | the protocol fee in bps to be applied on the total flash loan fee | - -### setSwapFee - -```solidity -function setSwapFee(uint256 newSwapFee) external nonpayable -``` - -Update the swap fee to be applied on swaps - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| newSwapFee | uint256 | new swap fee to be applied on future transactions | - -### stopRampA - -```solidity -function stopRampA() external nonpayable -``` - -Stop ramping A immediately. Reverts if ramp A is already stopped. - - - - -### swap - -```solidity -function swap(uint8 tokenIndexFrom, uint8 tokenIndexTo, uint256 dx, uint256 minDy, uint256 deadline) external nonpayable returns (uint256) -``` - -Swap two tokens using this pool - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| tokenIndexFrom | uint8 | the token the user wants to swap from | -| tokenIndexTo | uint8 | the token the user wants to swap to | -| dx | uint256 | the amount of tokens the user wants to swap from | -| minDy | uint256 | the min amount the user would like to receive, or revert. | -| deadline | uint256 | latest timestamp to accept this transaction | - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | uint256 | undefined | - -### swapStorage - -```solidity -function swapStorage() external view returns (uint256 initialA, uint256 futureA, uint256 initialATime, uint256 futureATime, uint256 swapFee, uint256 adminFee, contract LPToken lpToken) -``` - - - - - - -#### Returns - -| Name | Type | Description | -|---|---|---| -| initialA | uint256 | undefined | -| futureA | uint256 | undefined | -| initialATime | uint256 | undefined | -| futureATime | uint256 | undefined | -| swapFee | uint256 | undefined | -| adminFee | uint256 | undefined | -| lpToken | contract LPToken | undefined | - -### transferOwnership - -```solidity -function transferOwnership(address newOwner) external nonpayable -``` - - - -*Transfers ownership of the contract to a new account (`newOwner`). Can only be called by the current owner.* - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| newOwner | address | undefined | - -### unpause - -```solidity -function unpause() external nonpayable -``` - -Unpause the contract. Revert if already unpaused. - - - - -### withdrawAdminFees - -```solidity -function withdrawAdminFees() external nonpayable -``` - -Withdraw all admin fees to the contract owner - - - - - - -## Events - -### AddLiquidity - -```solidity -event AddLiquidity(address indexed provider, uint256[] tokenAmounts, uint256[] fees, uint256 invariant, uint256 lpTokenSupply) -``` - - - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| provider `indexed` | address | undefined | -| tokenAmounts | uint256[] | undefined | -| fees | uint256[] | undefined | -| invariant | uint256 | undefined | -| lpTokenSupply | uint256 | undefined | - -### FlashLoan - -```solidity -event FlashLoan(address indexed receiver, uint8 tokenIndex, uint256 amount, uint256 amountFee, uint256 protocolFee) -``` - - - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| receiver `indexed` | address | undefined | -| tokenIndex | uint8 | undefined | -| amount | uint256 | undefined | -| amountFee | uint256 | undefined | -| protocolFee | uint256 | undefined | - -### NewAdminFee - -```solidity -event NewAdminFee(uint256 newAdminFee) -``` - - - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| newAdminFee | uint256 | undefined | - -### NewSwapFee - -```solidity -event NewSwapFee(uint256 newSwapFee) -``` - - - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| newSwapFee | uint256 | undefined | - -### OwnershipTransferred - -```solidity -event OwnershipTransferred(address indexed previousOwner, address indexed newOwner) -``` - - - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| previousOwner `indexed` | address | undefined | -| newOwner `indexed` | address | undefined | - -### Paused - -```solidity -event Paused(address account) -``` - - - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| account | address | undefined | - -### RampA - -```solidity -event RampA(uint256 oldA, uint256 newA, uint256 initialTime, uint256 futureTime) -``` - - - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| oldA | uint256 | undefined | -| newA | uint256 | undefined | -| initialTime | uint256 | undefined | -| futureTime | uint256 | undefined | - -### RemoveLiquidity - -```solidity -event RemoveLiquidity(address indexed provider, uint256[] tokenAmounts, uint256 lpTokenSupply) -``` - - - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| provider `indexed` | address | undefined | -| tokenAmounts | uint256[] | undefined | -| lpTokenSupply | uint256 | undefined | - -### RemoveLiquidityImbalance - -```solidity -event RemoveLiquidityImbalance(address indexed provider, uint256[] tokenAmounts, uint256[] fees, uint256 invariant, uint256 lpTokenSupply) -``` - - - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| provider `indexed` | address | undefined | -| tokenAmounts | uint256[] | undefined | -| fees | uint256[] | undefined | -| invariant | uint256 | undefined | -| lpTokenSupply | uint256 | undefined | - -### RemoveLiquidityOne - -```solidity -event RemoveLiquidityOne(address indexed provider, uint256 lpTokenAmount, uint256 lpTokenSupply, uint256 boughtId, uint256 tokensBought) -``` - - - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| provider `indexed` | address | undefined | -| lpTokenAmount | uint256 | undefined | -| lpTokenSupply | uint256 | undefined | -| boughtId | uint256 | undefined | -| tokensBought | uint256 | undefined | - -### StopRampA - -```solidity -event StopRampA(uint256 currentA, uint256 time) -``` - - - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| currentA | uint256 | undefined | -| time | uint256 | undefined | - -### TokenSwap - -```solidity -event TokenSwap(address indexed buyer, uint256 tokensSold, uint256 tokensBought, uint128 soldId, uint128 boughtId) -``` - - - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| buyer `indexed` | address | undefined | -| tokensSold | uint256 | undefined | -| tokensBought | uint256 | undefined | -| soldId | uint128 | undefined | -| boughtId | uint128 | undefined | - -### Unpaused - -```solidity -event Unpaused(address account) -``` - - - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| account | address | undefined | - - - diff --git a/docs/amm/SwapUtils.md b/docs/amm/SwapUtils.md deleted file mode 100644 index f8238b186..000000000 --- a/docs/amm/SwapUtils.md +++ /dev/null @@ -1,199 +0,0 @@ -# SwapUtils - - - -> SwapUtils library - -A library to be used within Swap.sol. Contains functions responsible for custody and AMM functionalities. - -*Contracts relying on this library must initialize SwapUtils.Swap struct then use this library for SwapUtils.Swap struct. Note that this library contains both functions called by users and admins. Admin functions should be protected within contracts using this library.* - -## Methods - -### MAX_ADMIN_FEE - -```solidity -function MAX_ADMIN_FEE() external view returns (uint256) -``` - - - - - - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | uint256 | undefined | - -### MAX_SWAP_FEE - -```solidity -function MAX_SWAP_FEE() external view returns (uint256) -``` - - - - - - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | uint256 | undefined | - -### POOL_PRECISION_DECIMALS - -```solidity -function POOL_PRECISION_DECIMALS() external view returns (uint8) -``` - - - - - - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | uint8 | undefined | - - - -## Events - -### AddLiquidity - -```solidity -event AddLiquidity(address indexed provider, uint256[] tokenAmounts, uint256[] fees, uint256 invariant, uint256 lpTokenSupply) -``` - - - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| provider `indexed` | address | undefined | -| tokenAmounts | uint256[] | undefined | -| fees | uint256[] | undefined | -| invariant | uint256 | undefined | -| lpTokenSupply | uint256 | undefined | - -### NewAdminFee - -```solidity -event NewAdminFee(uint256 newAdminFee) -``` - - - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| newAdminFee | uint256 | undefined | - -### NewSwapFee - -```solidity -event NewSwapFee(uint256 newSwapFee) -``` - - - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| newSwapFee | uint256 | undefined | - -### RemoveLiquidity - -```solidity -event RemoveLiquidity(address indexed provider, uint256[] tokenAmounts, uint256 lpTokenSupply) -``` - - - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| provider `indexed` | address | undefined | -| tokenAmounts | uint256[] | undefined | -| lpTokenSupply | uint256 | undefined | - -### RemoveLiquidityImbalance - -```solidity -event RemoveLiquidityImbalance(address indexed provider, uint256[] tokenAmounts, uint256[] fees, uint256 invariant, uint256 lpTokenSupply) -``` - - - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| provider `indexed` | address | undefined | -| tokenAmounts | uint256[] | undefined | -| fees | uint256[] | undefined | -| invariant | uint256 | undefined | -| lpTokenSupply | uint256 | undefined | - -### RemoveLiquidityOne - -```solidity -event RemoveLiquidityOne(address indexed provider, uint256 lpTokenAmount, uint256 lpTokenSupply, uint256 boughtId, uint256 tokensBought) -``` - - - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| provider `indexed` | address | undefined | -| lpTokenAmount | uint256 | undefined | -| lpTokenSupply | uint256 | undefined | -| boughtId | uint256 | undefined | -| tokensBought | uint256 | undefined | - -### TokenSwap - -```solidity -event TokenSwap(address indexed buyer, uint256 tokensSold, uint256 tokensBought, uint128 soldId, uint128 boughtId) -``` - - - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| buyer `indexed` | address | undefined | -| tokensSold | uint256 | undefined | -| tokensBought | uint256 | undefined | -| soldId | uint128 | undefined | -| boughtId | uint128 | undefined | - - - diff --git a/docs/amm/helper/BaseSwapDeposit.md b/docs/amm/helper/BaseSwapDeposit.md deleted file mode 100644 index fd0d66dd8..000000000 --- a/docs/amm/helper/BaseSwapDeposit.md +++ /dev/null @@ -1,126 +0,0 @@ -# BaseSwapDeposit - - - - - - - - - -## Methods - -### baseSwap - -```solidity -function baseSwap() external view returns (contract ISwap) -``` - - - - - - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | contract ISwap | undefined | - -### baseTokens - -```solidity -function baseTokens(uint256) external view returns (contract IERC20) -``` - - - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| _0 | uint256 | undefined | - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | contract IERC20 | undefined | - -### calculateSwap - -```solidity -function calculateSwap(uint8 tokenIndexFrom, uint8 tokenIndexTo, uint256 dx) external view returns (uint256) -``` - -Calculate amount of tokens you receive on swap - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| tokenIndexFrom | uint8 | the token the user wants to sell | -| tokenIndexTo | uint8 | the token the user wants to buy | -| dx | uint256 | the amount of tokens the user wants to sell. If the token charges a fee on transfers, use the amount that gets transferred after the fee. | - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | uint256 | amount of tokens the user will receive | - -### getToken - -```solidity -function getToken(uint256 index) external view returns (contract IERC20) -``` - -Returns the address of the pooled token at given index. Reverts if tokenIndex is out of range. - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| index | uint256 | the index of the token | - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | contract IERC20 | address of the token at given index | - -### swap - -```solidity -function swap(uint8 tokenIndexFrom, uint8 tokenIndexTo, uint256 dx, uint256 minDy, uint256 deadline) external nonpayable returns (uint256) -``` - -Swap two underlying tokens using the meta pool and the base pool - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| tokenIndexFrom | uint8 | the token the user wants to swap from | -| tokenIndexTo | uint8 | the token the user wants to swap to | -| dx | uint256 | the amount of tokens the user wants to swap from | -| minDy | uint256 | the min amount the user would like to receive, or revert. | -| deadline | uint256 | latest timestamp to accept this transaction | - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | uint256 | undefined | - - - - diff --git a/docs/amm/helper/FlashLoanBorrowerExample.md b/docs/amm/helper/FlashLoanBorrowerExample.md deleted file mode 100644 index a35b08e9c..000000000 --- a/docs/amm/helper/FlashLoanBorrowerExample.md +++ /dev/null @@ -1,54 +0,0 @@ -# FlashLoanBorrowerExample - - - - - - - - - -## Methods - -### executeOperation - -```solidity -function executeOperation(address pool, address token, uint256 amount, uint256 fee, bytes params) external nonpayable -``` - - - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| pool | address | undefined | -| token | address | undefined | -| amount | uint256 | undefined | -| fee | uint256 | undefined | -| params | bytes | undefined | - -### flashLoan - -```solidity -function flashLoan(contract ISwapFlashLoan swap, contract IERC20 token, uint256 amount, bytes params) external nonpayable -``` - - - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| swap | contract ISwapFlashLoan | undefined | -| token | contract IERC20 | undefined | -| amount | uint256 | undefined | -| params | bytes | undefined | - - - - diff --git a/docs/amm/helper/GenericERC20.md b/docs/amm/helper/GenericERC20.md deleted file mode 100644 index 1497bbb5b..000000000 --- a/docs/amm/helper/GenericERC20.md +++ /dev/null @@ -1,361 +0,0 @@ -# GenericERC20 - - - -> Generic ERC20 token - -This contract simulates a generic ERC20 token that is mintable and burnable. - - - -## Methods - -### allowance - -```solidity -function allowance(address owner, address spender) external view returns (uint256) -``` - - - -*See {IERC20-allowance}.* - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| owner | address | undefined | -| spender | address | undefined | - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | uint256 | undefined | - -### approve - -```solidity -function approve(address spender, uint256 amount) external nonpayable returns (bool) -``` - - - -*See {IERC20-approve}. Requirements: - `spender` cannot be the zero address.* - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| spender | address | undefined | -| amount | uint256 | undefined | - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | bool | undefined | - -### balanceOf - -```solidity -function balanceOf(address account) external view returns (uint256) -``` - - - -*See {IERC20-balanceOf}.* - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| account | address | undefined | - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | uint256 | undefined | - -### decimals - -```solidity -function decimals() external view returns (uint8) -``` - - - -*Returns the number of decimals used to get its user representation. For example, if `decimals` equals `2`, a balance of `505` tokens should be displayed to a user as `5,05` (`505 / 10 ** 2`). Tokens usually opt for a value of 18, imitating the relationship between Ether and Wei. This is the value {ERC20} uses, unless {_setupDecimals} is called. NOTE: This information is only used for _display_ purposes: it in no way affects any of the arithmetic of the contract, including {IERC20-balanceOf} and {IERC20-transfer}.* - - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | uint8 | undefined | - -### decreaseAllowance - -```solidity -function decreaseAllowance(address spender, uint256 subtractedValue) external nonpayable returns (bool) -``` - - - -*Atomically decreases the allowance granted to `spender` by the caller. This is an alternative to {approve} that can be used as a mitigation for problems described in {IERC20-approve}. Emits an {Approval} event indicating the updated allowance. Requirements: - `spender` cannot be the zero address. - `spender` must have allowance for the caller of at least `subtractedValue`.* - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| spender | address | undefined | -| subtractedValue | uint256 | undefined | - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | bool | undefined | - -### increaseAllowance - -```solidity -function increaseAllowance(address spender, uint256 addedValue) external nonpayable returns (bool) -``` - - - -*Atomically increases the allowance granted to `spender` by the caller. This is an alternative to {approve} that can be used as a mitigation for problems described in {IERC20-approve}. Emits an {Approval} event indicating the updated allowance. Requirements: - `spender` cannot be the zero address.* - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| spender | address | undefined | -| addedValue | uint256 | undefined | - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | bool | undefined | - -### mint - -```solidity -function mint(address recipient, uint256 amount) external nonpayable -``` - -Mints given amount of tokens to recipient - -*only owner can call this mint function* - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| recipient | address | address of account to receive the tokens | -| amount | uint256 | amount of tokens to mint | - -### name - -```solidity -function name() external view returns (string) -``` - - - -*Returns the name of the token.* - - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | string | undefined | - -### owner - -```solidity -function owner() external view returns (address) -``` - - - -*Returns the address of the current owner.* - - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | address | undefined | - -### renounceOwnership - -```solidity -function renounceOwnership() external nonpayable -``` - - - -*Leaves the contract without owner. It will not be possible to call `onlyOwner` functions anymore. Can only be called by the current owner. NOTE: Renouncing ownership will leave the contract without an owner, thereby removing any functionality that is only available to the owner.* - - -### symbol - -```solidity -function symbol() external view returns (string) -``` - - - -*Returns the symbol of the token, usually a shorter version of the name.* - - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | string | undefined | - -### totalSupply - -```solidity -function totalSupply() external view returns (uint256) -``` - - - -*See {IERC20-totalSupply}.* - - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | uint256 | undefined | - -### transfer - -```solidity -function transfer(address recipient, uint256 amount) external nonpayable returns (bool) -``` - - - -*See {IERC20-transfer}. Requirements: - `recipient` cannot be the zero address. - the caller must have a balance of at least `amount`.* - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| recipient | address | undefined | -| amount | uint256 | undefined | - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | bool | undefined | - -### transferFrom - -```solidity -function transferFrom(address sender, address recipient, uint256 amount) external nonpayable returns (bool) -``` - - - -*See {IERC20-transferFrom}. Emits an {Approval} event indicating the updated allowance. This is not required by the EIP. See the note at the beginning of {ERC20}. Requirements: - `sender` and `recipient` cannot be the zero address. - `sender` must have a balance of at least `amount`. - the caller must have allowance for ``sender``'s tokens of at least `amount`.* - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| sender | address | undefined | -| recipient | address | undefined | -| amount | uint256 | undefined | - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | bool | undefined | - -### transferOwnership - -```solidity -function transferOwnership(address newOwner) external nonpayable -``` - - - -*Transfers ownership of the contract to a new account (`newOwner`). Can only be called by the current owner.* - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| newOwner | address | undefined | - - - -## Events - -### Approval - -```solidity -event Approval(address indexed owner, address indexed spender, uint256 value) -``` - - - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| owner `indexed` | address | undefined | -| spender `indexed` | address | undefined | -| value | uint256 | undefined | - -### OwnershipTransferred - -```solidity -event OwnershipTransferred(address indexed previousOwner, address indexed newOwner) -``` - - - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| previousOwner `indexed` | address | undefined | -| newOwner `indexed` | address | undefined | - -### Transfer - -```solidity -event Transfer(address indexed from, address indexed to, uint256 value) -``` - - - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| from `indexed` | address | undefined | -| to `indexed` | address | undefined | -| value | uint256 | undefined | - - - diff --git a/docs/amm/helper/Multicall2.md b/docs/amm/helper/Multicall2.md deleted file mode 100644 index e0c6b7d51..000000000 --- a/docs/amm/helper/Multicall2.md +++ /dev/null @@ -1,256 +0,0 @@ -# Multicall2 - -*Michael Elliot <mike@makerdao.com>Joshua Levine <joshua@makerdao.com>Nick Johnson <arachnid@notdot.net>* - -> Multicall2 - Aggregate results from multiple read-only function calls - - - - - -## Methods - -### aggregate - -```solidity -function aggregate(Multicall2.Call[] calls) external nonpayable returns (uint256 blockNumber, bytes[] returnData) -``` - - - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| calls | Multicall2.Call[] | undefined | - -#### Returns - -| Name | Type | Description | -|---|---|---| -| blockNumber | uint256 | undefined | -| returnData | bytes[] | undefined | - -### blockAndAggregate - -```solidity -function blockAndAggregate(Multicall2.Call[] calls) external nonpayable returns (uint256 blockNumber, bytes32 blockHash, struct Multicall2.Result[] returnData) -``` - - - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| calls | Multicall2.Call[] | undefined | - -#### Returns - -| Name | Type | Description | -|---|---|---| -| blockNumber | uint256 | undefined | -| blockHash | bytes32 | undefined | -| returnData | Multicall2.Result[] | undefined | - -### getBlockHash - -```solidity -function getBlockHash(uint256 blockNumber) external view returns (bytes32 blockHash) -``` - - - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| blockNumber | uint256 | undefined | - -#### Returns - -| Name | Type | Description | -|---|---|---| -| blockHash | bytes32 | undefined | - -### getBlockNumber - -```solidity -function getBlockNumber() external view returns (uint256 blockNumber) -``` - - - - - - -#### Returns - -| Name | Type | Description | -|---|---|---| -| blockNumber | uint256 | undefined | - -### getCurrentBlockCoinbase - -```solidity -function getCurrentBlockCoinbase() external view returns (address coinbase) -``` - - - - - - -#### Returns - -| Name | Type | Description | -|---|---|---| -| coinbase | address | undefined | - -### getCurrentBlockDifficulty - -```solidity -function getCurrentBlockDifficulty() external view returns (uint256 difficulty) -``` - - - - - - -#### Returns - -| Name | Type | Description | -|---|---|---| -| difficulty | uint256 | undefined | - -### getCurrentBlockGasLimit - -```solidity -function getCurrentBlockGasLimit() external view returns (uint256 gaslimit) -``` - - - - - - -#### Returns - -| Name | Type | Description | -|---|---|---| -| gaslimit | uint256 | undefined | - -### getCurrentBlockTimestamp - -```solidity -function getCurrentBlockTimestamp() external view returns (uint256 timestamp) -``` - - - - - - -#### Returns - -| Name | Type | Description | -|---|---|---| -| timestamp | uint256 | undefined | - -### getEthBalance - -```solidity -function getEthBalance(address addr) external view returns (uint256 balance) -``` - - - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| addr | address | undefined | - -#### Returns - -| Name | Type | Description | -|---|---|---| -| balance | uint256 | undefined | - -### getLastBlockHash - -```solidity -function getLastBlockHash() external view returns (bytes32 blockHash) -``` - - - - - - -#### Returns - -| Name | Type | Description | -|---|---|---| -| blockHash | bytes32 | undefined | - -### tryAggregate - -```solidity -function tryAggregate(bool requireSuccess, Multicall2.Call[] calls) external nonpayable returns (struct Multicall2.Result[] returnData) -``` - - - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| requireSuccess | bool | undefined | -| calls | Multicall2.Call[] | undefined | - -#### Returns - -| Name | Type | Description | -|---|---|---| -| returnData | Multicall2.Result[] | undefined | - -### tryBlockAndAggregate - -```solidity -function tryBlockAndAggregate(bool requireSuccess, Multicall2.Call[] calls) external nonpayable returns (uint256 blockNumber, bytes32 blockHash, struct Multicall2.Result[] returnData) -``` - - - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| requireSuccess | bool | undefined | -| calls | Multicall2.Call[] | undefined | - -#### Returns - -| Name | Type | Description | -|---|---|---| -| blockNumber | uint256 | undefined | -| blockHash | bytes32 | undefined | -| returnData | Multicall2.Result[] | undefined | - - - - diff --git a/docs/amm/helper/test/TestMathUtils.md b/docs/amm/helper/test/TestMathUtils.md deleted file mode 100644 index f169929ae..000000000 --- a/docs/amm/helper/test/TestMathUtils.md +++ /dev/null @@ -1,61 +0,0 @@ -# TestMathUtils - - - - - - - - - -## Methods - -### difference - -```solidity -function difference(uint256 a, uint256 b) external pure returns (uint256) -``` - - - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| a | uint256 | undefined | -| b | uint256 | undefined | - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | uint256 | undefined | - -### within1 - -```solidity -function within1(uint256 a, uint256 b) external pure returns (bool) -``` - - - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| a | uint256 | undefined | -| b | uint256 | undefined | - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | bool | undefined | - - - - diff --git a/docs/amm/helper/test/TestSwapReturnValues.md b/docs/amm/helper/test/TestSwapReturnValues.md deleted file mode 100644 index ba29e5f51..000000000 --- a/docs/amm/helper/test/TestSwapReturnValues.md +++ /dev/null @@ -1,171 +0,0 @@ -# TestSwapReturnValues - - - - - - - - - -## Methods - -### MAX_INT - -```solidity -function MAX_INT() external view returns (uint256) -``` - - - - - - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | uint256 | undefined | - -### lpToken - -```solidity -function lpToken() external view returns (contract IERC20) -``` - - - - - - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | contract IERC20 | undefined | - -### n - -```solidity -function n() external view returns (uint8) -``` - - - - - - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | uint8 | undefined | - -### swap - -```solidity -function swap() external view returns (contract ISwap) -``` - - - - - - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | contract ISwap | undefined | - -### test_addLiquidity - -```solidity -function test_addLiquidity(uint256[] amounts, uint256 minToMint) external nonpayable -``` - - - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| amounts | uint256[] | undefined | -| minToMint | uint256 | undefined | - -### test_removeLiquidity - -```solidity -function test_removeLiquidity(uint256 amount, uint256[] minAmounts) external nonpayable -``` - - - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| amount | uint256 | undefined | -| minAmounts | uint256[] | undefined | - -### test_removeLiquidityImbalance - -```solidity -function test_removeLiquidityImbalance(uint256[] amounts, uint256 maxBurnAmount) external nonpayable -``` - - - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| amounts | uint256[] | undefined | -| maxBurnAmount | uint256 | undefined | - -### test_removeLiquidityOneToken - -```solidity -function test_removeLiquidityOneToken(uint256 tokenAmount, uint8 tokenIndex, uint256 minAmount) external nonpayable -``` - - - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| tokenAmount | uint256 | undefined | -| tokenIndex | uint8 | undefined | -| minAmount | uint256 | undefined | - -### test_swap - -```solidity -function test_swap(uint8 tokenIndexFrom, uint8 tokenIndexTo, uint256 dx, uint256 minDy) external nonpayable -``` - - - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| tokenIndexFrom | uint8 | undefined | -| tokenIndexTo | uint8 | undefined | -| dx | uint256 | undefined | -| minDy | uint256 | undefined | - - - - diff --git a/docs/amm/interfaces/IFlashLoanReceiver.md b/docs/amm/interfaces/IFlashLoanReceiver.md deleted file mode 100644 index 970e718d6..000000000 --- a/docs/amm/interfaces/IFlashLoanReceiver.md +++ /dev/null @@ -1,35 +0,0 @@ -# IFlashLoanReceiver - -*Aave* - -> IFlashLoanReceiver interface - -Interface for the Nerve fee IFlashLoanReceiver. Modified from Aave's IFlashLoanReceiver interface. https://github.com/aave/aave-protocol/blob/4b4545fb583fd4f400507b10f3c3114f45b8a037/contracts/flashloan/interfaces/IFlashLoanReceiver.sol - -*implement this interface to develop a flashloan-compatible flashLoanReceiver contract** - -## Methods - -### executeOperation - -```solidity -function executeOperation(address pool, address token, uint256 amount, uint256 fee, bytes params) external nonpayable -``` - - - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| pool | address | undefined | -| token | address | undefined | -| amount | uint256 | undefined | -| fee | uint256 | undefined | -| params | bytes | undefined | - - - - diff --git a/docs/amm/interfaces/IMetaSwap.md b/docs/amm/interfaces/IMetaSwap.md deleted file mode 100644 index bd6562220..000000000 --- a/docs/amm/interfaces/IMetaSwap.md +++ /dev/null @@ -1,444 +0,0 @@ -# IMetaSwap - - - - - - - - - -## Methods - -### addLiquidity - -```solidity -function addLiquidity(uint256[] amounts, uint256 minToMint, uint256 deadline) external nonpayable returns (uint256) -``` - - - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| amounts | uint256[] | undefined | -| minToMint | uint256 | undefined | -| deadline | uint256 | undefined | - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | uint256 | undefined | - -### calculateRemoveLiquidity - -```solidity -function calculateRemoveLiquidity(uint256 amount) external view returns (uint256[]) -``` - - - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| amount | uint256 | undefined | - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | uint256[] | undefined | - -### calculateRemoveLiquidityOneToken - -```solidity -function calculateRemoveLiquidityOneToken(uint256 tokenAmount, uint8 tokenIndex) external view returns (uint256 availableTokenAmount) -``` - - - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| tokenAmount | uint256 | undefined | -| tokenIndex | uint8 | undefined | - -#### Returns - -| Name | Type | Description | -|---|---|---| -| availableTokenAmount | uint256 | undefined | - -### calculateSwap - -```solidity -function calculateSwap(uint8 tokenIndexFrom, uint8 tokenIndexTo, uint256 dx) external view returns (uint256) -``` - - - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| tokenIndexFrom | uint8 | undefined | -| tokenIndexTo | uint8 | undefined | -| dx | uint256 | undefined | - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | uint256 | undefined | - -### calculateSwapUnderlying - -```solidity -function calculateSwapUnderlying(uint8 tokenIndexFrom, uint8 tokenIndexTo, uint256 dx) external view returns (uint256) -``` - - - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| tokenIndexFrom | uint8 | undefined | -| tokenIndexTo | uint8 | undefined | -| dx | uint256 | undefined | - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | uint256 | undefined | - -### calculateTokenAmount - -```solidity -function calculateTokenAmount(uint256[] amounts, bool deposit) external view returns (uint256) -``` - - - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| amounts | uint256[] | undefined | -| deposit | bool | undefined | - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | uint256 | undefined | - -### getA - -```solidity -function getA() external view returns (uint256) -``` - - - - - - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | uint256 | undefined | - -### getToken - -```solidity -function getToken(uint8 index) external view returns (contract IERC20) -``` - - - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| index | uint8 | undefined | - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | contract IERC20 | undefined | - -### getTokenBalance - -```solidity -function getTokenBalance(uint8 index) external view returns (uint256) -``` - - - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| index | uint8 | undefined | - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | uint256 | undefined | - -### getTokenIndex - -```solidity -function getTokenIndex(address tokenAddress) external view returns (uint8) -``` - - - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| tokenAddress | address | undefined | - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | uint8 | undefined | - -### getVirtualPrice - -```solidity -function getVirtualPrice() external view returns (uint256) -``` - - - - - - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | uint256 | undefined | - -### initializeMetaSwap - -```solidity -function initializeMetaSwap(contract IERC20[] pooledTokens, uint8[] decimals, string lpTokenName, string lpTokenSymbol, uint256 a, uint256 fee, uint256 adminFee, address lpTokenTargetAddress, address baseSwap) external nonpayable -``` - - - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| pooledTokens | contract IERC20[] | undefined | -| decimals | uint8[] | undefined | -| lpTokenName | string | undefined | -| lpTokenSymbol | string | undefined | -| a | uint256 | undefined | -| fee | uint256 | undefined | -| adminFee | uint256 | undefined | -| lpTokenTargetAddress | address | undefined | -| baseSwap | address | undefined | - -### isGuarded - -```solidity -function isGuarded() external view returns (bool) -``` - - - - - - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | bool | undefined | - -### removeLiquidity - -```solidity -function removeLiquidity(uint256 amount, uint256[] minAmounts, uint256 deadline) external nonpayable returns (uint256[]) -``` - - - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| amount | uint256 | undefined | -| minAmounts | uint256[] | undefined | -| deadline | uint256 | undefined | - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | uint256[] | undefined | - -### removeLiquidityImbalance - -```solidity -function removeLiquidityImbalance(uint256[] amounts, uint256 maxBurnAmount, uint256 deadline) external nonpayable returns (uint256) -``` - - - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| amounts | uint256[] | undefined | -| maxBurnAmount | uint256 | undefined | -| deadline | uint256 | undefined | - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | uint256 | undefined | - -### removeLiquidityOneToken - -```solidity -function removeLiquidityOneToken(uint256 tokenAmount, uint8 tokenIndex, uint256 minAmount, uint256 deadline) external nonpayable returns (uint256) -``` - - - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| tokenAmount | uint256 | undefined | -| tokenIndex | uint8 | undefined | -| minAmount | uint256 | undefined | -| deadline | uint256 | undefined | - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | uint256 | undefined | - -### swap - -```solidity -function swap(uint8 tokenIndexFrom, uint8 tokenIndexTo, uint256 dx, uint256 minDy, uint256 deadline) external nonpayable returns (uint256) -``` - - - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| tokenIndexFrom | uint8 | undefined | -| tokenIndexTo | uint8 | undefined | -| dx | uint256 | undefined | -| minDy | uint256 | undefined | -| deadline | uint256 | undefined | - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | uint256 | undefined | - -### swapStorage - -```solidity -function swapStorage() external view returns (uint256 initialA, uint256 futureA, uint256 initialATime, uint256 futureATime, uint256 swapFee, uint256 adminFee, address lpToken) -``` - - - - - - -#### Returns - -| Name | Type | Description | -|---|---|---| -| initialA | uint256 | undefined | -| futureA | uint256 | undefined | -| initialATime | uint256 | undefined | -| futureATime | uint256 | undefined | -| swapFee | uint256 | undefined | -| adminFee | uint256 | undefined | -| lpToken | address | undefined | - -### swapUnderlying - -```solidity -function swapUnderlying(uint8 tokenIndexFrom, uint8 tokenIndexTo, uint256 dx, uint256 minDy, uint256 deadline) external nonpayable returns (uint256) -``` - - - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| tokenIndexFrom | uint8 | undefined | -| tokenIndexTo | uint8 | undefined | -| dx | uint256 | undefined | -| minDy | uint256 | undefined | -| deadline | uint256 | undefined | - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | uint256 | undefined | - - - - diff --git a/docs/amm/interfaces/IMetaSwapDeposit.md b/docs/amm/interfaces/IMetaSwapDeposit.md deleted file mode 100644 index 9ebe4f6b2..000000000 --- a/docs/amm/interfaces/IMetaSwapDeposit.md +++ /dev/null @@ -1,33 +0,0 @@ -# IMetaSwapDeposit - - - - - - - - - -## Methods - -### initialize - -```solidity -function initialize(contract ISwap baseSwap_, contract IMetaSwap metaSwap_, contract IERC20 metaLPToken_) external nonpayable -``` - - - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| baseSwap_ | contract ISwap | undefined | -| metaSwap_ | contract IMetaSwap | undefined | -| metaLPToken_ | contract IERC20 | undefined | - - - - diff --git a/docs/amm/interfaces/ISwap.md b/docs/amm/interfaces/ISwap.md deleted file mode 100644 index 46ee3b5ae..000000000 --- a/docs/amm/interfaces/ISwap.md +++ /dev/null @@ -1,353 +0,0 @@ -# ISwap - - - - - - - - - -## Methods - -### addLiquidity - -```solidity -function addLiquidity(uint256[] amounts, uint256 minToMint, uint256 deadline) external nonpayable returns (uint256) -``` - - - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| amounts | uint256[] | undefined | -| minToMint | uint256 | undefined | -| deadline | uint256 | undefined | - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | uint256 | undefined | - -### calculateRemoveLiquidity - -```solidity -function calculateRemoveLiquidity(uint256 amount) external view returns (uint256[]) -``` - - - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| amount | uint256 | undefined | - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | uint256[] | undefined | - -### calculateRemoveLiquidityOneToken - -```solidity -function calculateRemoveLiquidityOneToken(uint256 tokenAmount, uint8 tokenIndex) external view returns (uint256 availableTokenAmount) -``` - - - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| tokenAmount | uint256 | undefined | -| tokenIndex | uint8 | undefined | - -#### Returns - -| Name | Type | Description | -|---|---|---| -| availableTokenAmount | uint256 | undefined | - -### calculateSwap - -```solidity -function calculateSwap(uint8 tokenIndexFrom, uint8 tokenIndexTo, uint256 dx) external view returns (uint256) -``` - - - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| tokenIndexFrom | uint8 | undefined | -| tokenIndexTo | uint8 | undefined | -| dx | uint256 | undefined | - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | uint256 | undefined | - -### calculateTokenAmount - -```solidity -function calculateTokenAmount(uint256[] amounts, bool deposit) external view returns (uint256) -``` - - - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| amounts | uint256[] | undefined | -| deposit | bool | undefined | - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | uint256 | undefined | - -### getA - -```solidity -function getA() external view returns (uint256) -``` - - - - - - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | uint256 | undefined | - -### getToken - -```solidity -function getToken(uint8 index) external view returns (contract IERC20) -``` - - - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| index | uint8 | undefined | - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | contract IERC20 | undefined | - -### getTokenBalance - -```solidity -function getTokenBalance(uint8 index) external view returns (uint256) -``` - - - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| index | uint8 | undefined | - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | uint256 | undefined | - -### getTokenIndex - -```solidity -function getTokenIndex(address tokenAddress) external view returns (uint8) -``` - - - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| tokenAddress | address | undefined | - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | uint8 | undefined | - -### getVirtualPrice - -```solidity -function getVirtualPrice() external view returns (uint256) -``` - - - - - - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | uint256 | undefined | - -### initialize - -```solidity -function initialize(contract IERC20[] pooledTokens, uint8[] decimals, string lpTokenName, string lpTokenSymbol, uint256 a, uint256 fee, uint256 adminFee, address lpTokenTargetAddress) external nonpayable -``` - - - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| pooledTokens | contract IERC20[] | undefined | -| decimals | uint8[] | undefined | -| lpTokenName | string | undefined | -| lpTokenSymbol | string | undefined | -| a | uint256 | undefined | -| fee | uint256 | undefined | -| adminFee | uint256 | undefined | -| lpTokenTargetAddress | address | undefined | - -### removeLiquidity - -```solidity -function removeLiquidity(uint256 amount, uint256[] minAmounts, uint256 deadline) external nonpayable returns (uint256[]) -``` - - - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| amount | uint256 | undefined | -| minAmounts | uint256[] | undefined | -| deadline | uint256 | undefined | - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | uint256[] | undefined | - -### removeLiquidityImbalance - -```solidity -function removeLiquidityImbalance(uint256[] amounts, uint256 maxBurnAmount, uint256 deadline) external nonpayable returns (uint256) -``` - - - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| amounts | uint256[] | undefined | -| maxBurnAmount | uint256 | undefined | -| deadline | uint256 | undefined | - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | uint256 | undefined | - -### removeLiquidityOneToken - -```solidity -function removeLiquidityOneToken(uint256 tokenAmount, uint8 tokenIndex, uint256 minAmount, uint256 deadline) external nonpayable returns (uint256) -``` - - - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| tokenAmount | uint256 | undefined | -| tokenIndex | uint8 | undefined | -| minAmount | uint256 | undefined | -| deadline | uint256 | undefined | - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | uint256 | undefined | - -### swap - -```solidity -function swap(uint8 tokenIndexFrom, uint8 tokenIndexTo, uint256 dx, uint256 minDy, uint256 deadline) external nonpayable returns (uint256) -``` - - - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| tokenIndexFrom | uint8 | undefined | -| tokenIndexTo | uint8 | undefined | -| dx | uint256 | undefined | -| minDy | uint256 | undefined | -| deadline | uint256 | undefined | - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | uint256 | undefined | - - - - diff --git a/docs/amm/interfaces/ISwapFlashLoan.md b/docs/amm/interfaces/ISwapFlashLoan.md deleted file mode 100644 index 13f72049c..000000000 --- a/docs/amm/interfaces/ISwapFlashLoan.md +++ /dev/null @@ -1,372 +0,0 @@ -# ISwapFlashLoan - - - - - - - - - -## Methods - -### addLiquidity - -```solidity -function addLiquidity(uint256[] amounts, uint256 minToMint, uint256 deadline) external nonpayable returns (uint256) -``` - - - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| amounts | uint256[] | undefined | -| minToMint | uint256 | undefined | -| deadline | uint256 | undefined | - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | uint256 | undefined | - -### calculateRemoveLiquidity - -```solidity -function calculateRemoveLiquidity(uint256 amount) external view returns (uint256[]) -``` - - - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| amount | uint256 | undefined | - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | uint256[] | undefined | - -### calculateRemoveLiquidityOneToken - -```solidity -function calculateRemoveLiquidityOneToken(uint256 tokenAmount, uint8 tokenIndex) external view returns (uint256 availableTokenAmount) -``` - - - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| tokenAmount | uint256 | undefined | -| tokenIndex | uint8 | undefined | - -#### Returns - -| Name | Type | Description | -|---|---|---| -| availableTokenAmount | uint256 | undefined | - -### calculateSwap - -```solidity -function calculateSwap(uint8 tokenIndexFrom, uint8 tokenIndexTo, uint256 dx) external view returns (uint256) -``` - - - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| tokenIndexFrom | uint8 | undefined | -| tokenIndexTo | uint8 | undefined | -| dx | uint256 | undefined | - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | uint256 | undefined | - -### calculateTokenAmount - -```solidity -function calculateTokenAmount(uint256[] amounts, bool deposit) external view returns (uint256) -``` - - - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| amounts | uint256[] | undefined | -| deposit | bool | undefined | - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | uint256 | undefined | - -### flashLoan - -```solidity -function flashLoan(address receiver, contract IERC20 token, uint256 amount, bytes params) external nonpayable -``` - - - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| receiver | address | undefined | -| token | contract IERC20 | undefined | -| amount | uint256 | undefined | -| params | bytes | undefined | - -### getA - -```solidity -function getA() external view returns (uint256) -``` - - - - - - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | uint256 | undefined | - -### getToken - -```solidity -function getToken(uint8 index) external view returns (contract IERC20) -``` - - - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| index | uint8 | undefined | - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | contract IERC20 | undefined | - -### getTokenBalance - -```solidity -function getTokenBalance(uint8 index) external view returns (uint256) -``` - - - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| index | uint8 | undefined | - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | uint256 | undefined | - -### getTokenIndex - -```solidity -function getTokenIndex(address tokenAddress) external view returns (uint8) -``` - - - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| tokenAddress | address | undefined | - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | uint8 | undefined | - -### getVirtualPrice - -```solidity -function getVirtualPrice() external view returns (uint256) -``` - - - - - - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | uint256 | undefined | - -### initialize - -```solidity -function initialize(contract IERC20[] pooledTokens, uint8[] decimals, string lpTokenName, string lpTokenSymbol, uint256 a, uint256 fee, uint256 adminFee, address lpTokenTargetAddress) external nonpayable -``` - - - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| pooledTokens | contract IERC20[] | undefined | -| decimals | uint8[] | undefined | -| lpTokenName | string | undefined | -| lpTokenSymbol | string | undefined | -| a | uint256 | undefined | -| fee | uint256 | undefined | -| adminFee | uint256 | undefined | -| lpTokenTargetAddress | address | undefined | - -### removeLiquidity - -```solidity -function removeLiquidity(uint256 amount, uint256[] minAmounts, uint256 deadline) external nonpayable returns (uint256[]) -``` - - - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| amount | uint256 | undefined | -| minAmounts | uint256[] | undefined | -| deadline | uint256 | undefined | - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | uint256[] | undefined | - -### removeLiquidityImbalance - -```solidity -function removeLiquidityImbalance(uint256[] amounts, uint256 maxBurnAmount, uint256 deadline) external nonpayable returns (uint256) -``` - - - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| amounts | uint256[] | undefined | -| maxBurnAmount | uint256 | undefined | -| deadline | uint256 | undefined | - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | uint256 | undefined | - -### removeLiquidityOneToken - -```solidity -function removeLiquidityOneToken(uint256 tokenAmount, uint8 tokenIndex, uint256 minAmount, uint256 deadline) external nonpayable returns (uint256) -``` - - - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| tokenAmount | uint256 | undefined | -| tokenIndex | uint8 | undefined | -| minAmount | uint256 | undefined | -| deadline | uint256 | undefined | - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | uint256 | undefined | - -### swap - -```solidity -function swap(uint8 tokenIndexFrom, uint8 tokenIndexTo, uint256 dx, uint256 minDy, uint256 deadline) external nonpayable returns (uint256) -``` - - - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| tokenIndexFrom | uint8 | undefined | -| tokenIndexTo | uint8 | undefined | -| dx | uint256 | undefined | -| minDy | uint256 | undefined | -| deadline | uint256 | undefined | - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | uint256 | undefined | - - - - diff --git a/docs/auxiliary/DummyWeth.md b/docs/auxiliary/DummyWeth.md deleted file mode 100644 index edda2f2f0..000000000 --- a/docs/auxiliary/DummyWeth.md +++ /dev/null @@ -1,144 +0,0 @@ -# DummyWeth - - - - - - - - - -## Methods - -### WETH - -```solidity -function WETH() external view returns (contract IWETH9) -``` - - - - - - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | contract IWETH9 | undefined | - -### owner - -```solidity -function owner() external view returns (address) -``` - - - -*Returns the address of the current owner.* - - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | address | undefined | - -### renounceOwnership - -```solidity -function renounceOwnership() external nonpayable -``` - - - -*Leaves the contract without owner. It will not be possible to call `onlyOwner` functions anymore. Can only be called by the current owner. NOTE: Renouncing ownership will leave the contract without an owner, thereby removing any functionality that is only available to the owner.* - - -### rescue - -```solidity -function rescue(uint256 amount) external nonpayable -``` - - - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| amount | uint256 | undefined | - -### setWETHAddress - -```solidity -function setWETHAddress(address payable _weth) external nonpayable -``` - - - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| _weth | address payable | undefined | - -### transferOwnership - -```solidity -function transferOwnership(address newOwner) external nonpayable -``` - - - -*Transfers ownership of the contract to a new account (`newOwner`). Can only be called by the current owner.* - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| newOwner | address | undefined | - -### withdrawToSelf - -```solidity -function withdrawToSelf(uint256 amount) external nonpayable -``` - - - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| amount | uint256 | undefined | - - - -## Events - -### OwnershipTransferred - -```solidity -event OwnershipTransferred(address indexed previousOwner, address indexed newOwner) -``` - - - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| previousOwner `indexed` | address | undefined | -| newOwner `indexed` | address | undefined | - - - diff --git a/docs/auxiliary/DummyWethProxy.md b/docs/auxiliary/DummyWethProxy.md deleted file mode 100644 index de7577ca2..000000000 --- a/docs/auxiliary/DummyWethProxy.md +++ /dev/null @@ -1,155 +0,0 @@ -# DummyWethProxy - - - - - - - - - -## Methods - -### WETH - -```solidity -function WETH() external view returns (contract IWETH9) -``` - - - - - - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | contract IWETH9 | undefined | - -### initialize - -```solidity -function initialize() external nonpayable -``` - - - - - - -### owner - -```solidity -function owner() external view returns (address) -``` - - - -*Returns the address of the current owner.* - - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | address | undefined | - -### renounceOwnership - -```solidity -function renounceOwnership() external nonpayable -``` - - - -*Leaves the contract without owner. It will not be possible to call `onlyOwner` functions anymore. Can only be called by the current owner. NOTE: Renouncing ownership will leave the contract without an owner, thereby removing any functionality that is only available to the owner.* - - -### rescue - -```solidity -function rescue(uint256 amount) external nonpayable -``` - - - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| amount | uint256 | undefined | - -### setWETHAddress - -```solidity -function setWETHAddress(address payable _weth) external nonpayable -``` - - - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| _weth | address payable | undefined | - -### transferOwnership - -```solidity -function transferOwnership(address newOwner) external nonpayable -``` - - - -*Transfers ownership of the contract to a new account (`newOwner`). Can only be called by the current owner.* - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| newOwner | address | undefined | - -### withdrawToSelf - -```solidity -function withdrawToSelf(uint256 amount) external nonpayable -``` - - - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| amount | uint256 | undefined | - - - -## Events - -### OwnershipTransferred - -```solidity -event OwnershipTransferred(address indexed previousOwner, address indexed newOwner) -``` - - - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| previousOwner `indexed` | address | undefined | -| newOwner `indexed` | address | undefined | - - - diff --git a/docs/bridge/BridgeConfigV3.md b/docs/bridge/BridgeConfigV3.md deleted file mode 100644 index 96f1328c7..000000000 --- a/docs/bridge/BridgeConfigV3.md +++ /dev/null @@ -1,684 +0,0 @@ -# BridgeConfigV3 - - - -> BridgeConfig contract - -This token is used for configuring different tokens on the bridge and mapping them across chains.* - - - -## Methods - -### BRIDGEMANAGER_ROLE - -```solidity -function BRIDGEMANAGER_ROLE() external view returns (bytes32) -``` - - - - - - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | bytes32 | undefined | - -### DEFAULT_ADMIN_ROLE - -```solidity -function DEFAULT_ADMIN_ROLE() external view returns (bytes32) -``` - - - - - - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | bytes32 | undefined | - -### bridgeConfigVersion - -```solidity -function bridgeConfigVersion() external view returns (uint256) -``` - - - - - - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | uint256 | undefined | - -### calculateSwapFee - -```solidity -function calculateSwapFee(string tokenAddress, uint256 chainID, uint256 amount) external view returns (uint256) -``` - -Calculates bridge swap fee based on the destination chain's token transfer. - -*This means the fee should be calculated based on the chain that the nodes emit a tx on* - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| tokenAddress | string | address of the destination token to query token config for | -| chainID | uint256 | destination chain ID to query the token config for | -| amount | uint256 | in native token decimals | - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | uint256 | Fee calculated in token decimals | - -### calculateSwapFee - -```solidity -function calculateSwapFee(address tokenAddress, uint256 chainID, uint256 amount) external view returns (uint256) -``` - -Calculates bridge swap fee based on the destination chain's token transfer. - -*This means the fee should be calculated based on the chain that the nodes emit a tx on* - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| tokenAddress | address | address of the destination token to query token config for | -| chainID | uint256 | destination chain ID to query the token config for | -| amount | uint256 | in native token decimals | - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | uint256 | Fee calculated in token decimals | - -### getAllTokenIDs - -```solidity -function getAllTokenIDs() external view returns (string[] result) -``` - -Returns a list of all existing token IDs converted to strings - - - - -#### Returns - -| Name | Type | Description | -|---|---|---| -| result | string[] | undefined | - -### getMaxGasPrice - -```solidity -function getMaxGasPrice(uint256 chainID) external view returns (uint256) -``` - -gets the max gas price for a chain - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| chainID | uint256 | undefined | - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | uint256 | undefined | - -### getPoolConfig - -```solidity -function getPoolConfig(address tokenAddress, uint256 chainID) external view returns (struct BridgeConfigV3.Pool) -``` - - - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| tokenAddress | address | undefined | -| chainID | uint256 | undefined | - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | BridgeConfigV3.Pool | undefined | - -### getRoleAdmin - -```solidity -function getRoleAdmin(bytes32 role) external view returns (bytes32) -``` - - - -*Returns the admin role that controls `role`. See {grantRole} and {revokeRole}. To change a role's admin, use {_setRoleAdmin}.* - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| role | bytes32 | undefined | - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | bytes32 | undefined | - -### getRoleMember - -```solidity -function getRoleMember(bytes32 role, uint256 index) external view returns (address) -``` - - - -*Returns one of the accounts that have `role`. `index` must be a value between 0 and {getRoleMemberCount}, non-inclusive. Role bearers are not sorted in any particular way, and their ordering may change at any point. WARNING: When using {getRoleMember} and {getRoleMemberCount}, make sure you perform all queries on the same block. See the following https://forum.openzeppelin.com/t/iterating-over-elements-on-enumerableset-in-openzeppelin-contracts/2296[forum post] for more information.* - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| role | bytes32 | undefined | -| index | uint256 | undefined | - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | address | undefined | - -### getRoleMemberCount - -```solidity -function getRoleMemberCount(bytes32 role) external view returns (uint256) -``` - - - -*Returns the number of accounts that have `role`. Can be used together with {getRoleMember} to enumerate all bearers of a role.* - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| role | bytes32 | undefined | - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | uint256 | undefined | - -### getToken - -```solidity -function getToken(string tokenID, uint256 chainID) external view returns (struct BridgeConfigV3.Token token) -``` - -Returns the full token config struct - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| tokenID | string | String input of the token ID for the token | -| chainID | uint256 | Chain ID of which token address + config to get | - -#### Returns - -| Name | Type | Description | -|---|---|---| -| token | BridgeConfigV3.Token | undefined | - -### getTokenByAddress - -```solidity -function getTokenByAddress(string tokenAddress, uint256 chainID) external view returns (struct BridgeConfigV3.Token token) -``` - -Returns token config struct, given an address and chainID - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| tokenAddress | string | Matches the token ID by using a combo of address + chain ID | -| chainID | uint256 | Chain ID of which token to get config for | - -#### Returns - -| Name | Type | Description | -|---|---|---| -| token | BridgeConfigV3.Token | undefined | - -### getTokenByEVMAddress - -```solidity -function getTokenByEVMAddress(address tokenAddress, uint256 chainID) external view returns (struct BridgeConfigV3.Token token) -``` - - - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| tokenAddress | address | undefined | -| chainID | uint256 | undefined | - -#### Returns - -| Name | Type | Description | -|---|---|---| -| token | BridgeConfigV3.Token | undefined | - -### getTokenByID - -```solidity -function getTokenByID(string tokenID, uint256 chainID) external view returns (struct BridgeConfigV3.Token token) -``` - -Returns the full token config struct - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| tokenID | string | String input of the token ID for the token | -| chainID | uint256 | Chain ID of which token address + config to get | - -#### Returns - -| Name | Type | Description | -|---|---|---| -| token | BridgeConfigV3.Token | undefined | - -### getTokenID - -```solidity -function getTokenID(address tokenAddress, uint256 chainID) external view returns (string) -``` - -Returns the token ID (string) of the cross-chain token inputted - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| tokenAddress | address | address of token to get ID for | -| chainID | uint256 | chainID of which to get token ID for | - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | string | undefined | - -### getTokenID - -```solidity -function getTokenID(string tokenAddress, uint256 chainID) external view returns (string) -``` - - - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| tokenAddress | string | undefined | -| chainID | uint256 | undefined | - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | string | undefined | - -### getUnderlyingToken - -```solidity -function getUnderlyingToken(string tokenID) external view returns (struct BridgeConfigV3.Token token) -``` - -Returns which token is the underlying token to withdraw - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| tokenID | string | string token ID | - -#### Returns - -| Name | Type | Description | -|---|---|---| -| token | BridgeConfigV3.Token | undefined | - -### grantRole - -```solidity -function grantRole(bytes32 role, address account) external nonpayable -``` - - - -*Grants `role` to `account`. If `account` had not been already granted `role`, emits a {RoleGranted} event. Requirements: - the caller must have ``role``'s admin role.* - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| role | bytes32 | undefined | -| account | address | undefined | - -### hasRole - -```solidity -function hasRole(bytes32 role, address account) external view returns (bool) -``` - - - -*Returns `true` if `account` has been granted `role`.* - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| role | bytes32 | undefined | -| account | address | undefined | - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | bool | undefined | - -### hasUnderlyingToken - -```solidity -function hasUnderlyingToken(string tokenID) external view returns (bool) -``` - -Returns true if the token has an underlying token -- meaning the token is deposited into the bridge - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| tokenID | string | String to check if it is a withdraw/underlying token | - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | bool | undefined | - -### isTokenIDExist - -```solidity -function isTokenIDExist(string tokenID) external view returns (bool) -``` - -Public function returning if token ID exists given a string - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| tokenID | string | undefined | - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | bool | undefined | - -### renounceRole - -```solidity -function renounceRole(bytes32 role, address account) external nonpayable -``` - - - -*Revokes `role` from the calling account. Roles are often managed via {grantRole} and {revokeRole}: this function's purpose is to provide a mechanism for accounts to lose their privileges if they are compromised (such as when a trusted device is misplaced). If the calling account had been granted `role`, emits a {RoleRevoked} event. Requirements: - the caller must be `account`.* - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| role | bytes32 | undefined | -| account | address | undefined | - -### revokeRole - -```solidity -function revokeRole(bytes32 role, address account) external nonpayable -``` - - - -*Revokes `role` from `account`. If `account` had been granted `role`, emits a {RoleRevoked} event. Requirements: - the caller must have ``role``'s admin role.* - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| role | bytes32 | undefined | -| account | address | undefined | - -### setMaxGasPrice - -```solidity -function setMaxGasPrice(uint256 chainID, uint256 maxPrice) external nonpayable -``` - -sets the max gas price for a chain - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| chainID | uint256 | undefined | -| maxPrice | uint256 | undefined | - -### setPoolConfig - -```solidity -function setPoolConfig(address tokenAddress, uint256 chainID, address poolAddress, bool metaswap) external nonpayable returns (struct BridgeConfigV3.Pool) -``` - - - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| tokenAddress | address | undefined | -| chainID | uint256 | undefined | -| poolAddress | address | undefined | -| metaswap | bool | undefined | - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | BridgeConfigV3.Pool | undefined | - -### setTokenConfig - -```solidity -function setTokenConfig(string tokenID, uint256 chainID, address tokenAddress, uint8 tokenDecimals, uint256 maxSwap, uint256 minSwap, uint256 swapFee, uint256 maxSwapFee, uint256 minSwapFee, bool hasUnderlying, bool isUnderlying) external nonpayable returns (bool) -``` - -Main write function of this contract - Handles creating the struct and passing it to the internal logic function - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| tokenID | string | string ID to set the token config object form | -| chainID | uint256 | chain ID to use for the token config object | -| tokenAddress | address | token address of the token on the given chain | -| tokenDecimals | uint8 | decimals of token | -| maxSwap | uint256 | maximum amount of token allowed to be transferred at once - in native token decimals | -| minSwap | uint256 | minimum amount of token needed to be transferred at once - in native token decimals | -| swapFee | uint256 | percent based swap fee -- 10e6 == 10bps | -| maxSwapFee | uint256 | max swap fee to be charged - in native token decimals | -| minSwapFee | uint256 | min swap fee to be charged - in native token decimals - especially useful for mainnet ETH | -| hasUnderlying | bool | bool which represents whether this is a global mint token or one to withdraw() | -| isUnderlying | bool | bool which represents if this token is the one to withdraw on the given chain | - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | bool | undefined | - -### setTokenConfig - -```solidity -function setTokenConfig(string tokenID, uint256 chainID, string tokenAddress, uint8 tokenDecimals, uint256 maxSwap, uint256 minSwap, uint256 swapFee, uint256 maxSwapFee, uint256 minSwapFee, bool hasUnderlying, bool isUnderlying) external nonpayable returns (bool) -``` - -Main write function of this contract - Handles creating the struct and passing it to the internal logic function - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| tokenID | string | string ID to set the token config object form | -| chainID | uint256 | chain ID to use for the token config object | -| tokenAddress | string | token address of the token on the given chain | -| tokenDecimals | uint8 | decimals of token | -| maxSwap | uint256 | maximum amount of token allowed to be transferred at once - in native token decimals | -| minSwap | uint256 | minimum amount of token needed to be transferred at once - in native token decimals | -| swapFee | uint256 | percent based swap fee -- 10e6 == 10bps | -| maxSwapFee | uint256 | max swap fee to be charged - in native token decimals | -| minSwapFee | uint256 | min swap fee to be charged - in native token decimals - especially useful for mainnet ETH | -| hasUnderlying | bool | bool which represents whether this is a global mint token or one to withdraw() | -| isUnderlying | bool | bool which represents if this token is the one to withdraw on the given chain | - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | bool | undefined | - - - -## Events - -### RoleAdminChanged - -```solidity -event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole) -``` - - - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| role `indexed` | bytes32 | undefined | -| previousAdminRole `indexed` | bytes32 | undefined | -| newAdminRole `indexed` | bytes32 | undefined | - -### RoleGranted - -```solidity -event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender) -``` - - - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| role `indexed` | bytes32 | undefined | -| account `indexed` | address | undefined | -| sender `indexed` | address | undefined | - -### RoleRevoked - -```solidity -event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender) -``` - - - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| role `indexed` | bytes32 | undefined | -| account `indexed` | address | undefined | -| sender `indexed` | address | undefined | - - - diff --git a/docs/bridge/ECDSAFactory.md b/docs/bridge/ECDSAFactory.md deleted file mode 100644 index 061769e51..000000000 --- a/docs/bridge/ECDSAFactory.md +++ /dev/null @@ -1,159 +0,0 @@ -# ECDSAFactory - - - - - - - - - -## Methods - -### deploy - -```solidity -function deploy(address nodeMgmtAddress, address owner, address[] members, uint256 honestThreshold) external nonpayable returns (address) -``` - -Deploys a new node - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| nodeMgmtAddress | address | address of the ECDSANodeManagement contract to initialize with | -| owner | address | Owner of the ECDSANodeManagement contract who can determine if the node group is closed or active | -| members | address[] | Array of node group members addresses | -| honestThreshold | uint256 | Number of signers to process a transaction | - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | address | Address of the newest node management contract created* | - -### getMembers - -```solidity -function getMembers() external view returns (address[]) -``` - -Returns members of the keep. - - - - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | address[] | List of the keep members' addresses. | - -### latestNodeGroup - -```solidity -function latestNodeGroup() external view returns (address keepAddress, address owner, uint256 honestThreshold) -``` - - - - - - -#### Returns - -| Name | Type | Description | -|---|---|---| -| keepAddress | address | undefined | -| owner | address | undefined | -| honestThreshold | uint256 | undefined | - -### owner - -```solidity -function owner() external view returns (address) -``` - - - -*Returns the address of the current owner.* - - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | address | undefined | - -### renounceOwnership - -```solidity -function renounceOwnership() external nonpayable -``` - - - -*Leaves the contract without owner. It will not be possible to call `onlyOwner` functions anymore. Can only be called by the current owner. NOTE: Renouncing ownership will leave the contract without an owner, thereby removing any functionality that is only available to the owner.* - - -### transferOwnership - -```solidity -function transferOwnership(address newOwner) external nonpayable -``` - - - -*Transfers ownership of the contract to a new account (`newOwner`). Can only be called by the current owner.* - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| newOwner | address | undefined | - - - -## Events - -### ECDSANodeGroupCreated - -```solidity -event ECDSANodeGroupCreated(address indexed keepAddress, address[] members, address indexed owner, uint256 honestThreshold) -``` - - - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| keepAddress `indexed` | address | undefined | -| members | address[] | undefined | -| owner `indexed` | address | undefined | -| honestThreshold | uint256 | undefined | - -### OwnershipTransferred - -```solidity -event OwnershipTransferred(address indexed previousOwner, address indexed newOwner) -``` - - - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| previousOwner `indexed` | address | undefined | -| newOwner `indexed` | address | undefined | - - - diff --git a/docs/bridge/ECDSANodeManagement.md b/docs/bridge/ECDSANodeManagement.md deleted file mode 100644 index f7657bb41..000000000 --- a/docs/bridge/ECDSANodeManagement.md +++ /dev/null @@ -1,310 +0,0 @@ -# ECDSANodeManagement - - - - - - - - - -## Methods - -### closeKeep - -```solidity -function closeKeep() external nonpayable -``` - -Closes keep when owner decides that they no longer need it. Releases bonds to the keep members. - -*The function can be called only by the owner of the keep and only if the keep has not been already closed.* - - -### getMembers - -```solidity -function getMembers() external view returns (address[]) -``` - -Returns members of the keep. - - - - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | address[] | List of the keep members' addresses. | - -### getOpenedTimestamp - -```solidity -function getOpenedTimestamp() external view returns (uint256) -``` - -Gets the timestamp the keep was opened at. - - - - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | uint256 | Timestamp the keep was opened at. | - -### getOwner - -```solidity -function getOwner() external view returns (address) -``` - -Gets the owner of the keep. - - - - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | address | Address of the keep owner. | - -### getPublicKey - -```solidity -function getPublicKey() external view returns (bytes) -``` - -Returns keep's ECDSA public key. - - - - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | bytes | Keep's ECDSA public key. | - -### honestThreshold - -```solidity -function honestThreshold() external view returns (uint256) -``` - - - - - - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | uint256 | undefined | - -### initialize - -```solidity -function initialize(address _owner, address[] _members, uint256 _honestThreshold) external nonpayable -``` - -Initialization function. - -*We use clone factory to create new keep. That is why this contract doesn't have a constructor. We provide keep parameters for each instance function after cloning instances from the master contract. Initialization must happen in the same transaction in which the clone is created.* - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| _owner | address | Address of the keep owner. | -| _members | address[] | Addresses of the keep members. | -| _honestThreshold | uint256 | Minimum number of honest keep members. | - -### isActive - -```solidity -function isActive() external view returns (bool) -``` - -Returns true if the keep is active. - - - - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | bool | true if the keep is active, false otherwise. | - -### isClosed - -```solidity -function isClosed() external view returns (bool) -``` - -Returns true if the keep is closed and members no longer support this keep. - - - - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | bool | true if the keep is closed, false otherwise. | - -### isTerminated - -```solidity -function isTerminated() external view returns (bool) -``` - -Returns true if the keep has been terminated. Keep is terminated when bonds are seized and members no longer support this keep. - - - - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | bool | true if the keep has been terminated, false otherwise. | - -### members - -```solidity -function members(uint256) external view returns (address) -``` - - - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| _0 | uint256 | undefined | - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | address | undefined | - -### owner - -```solidity -function owner() external view returns (address) -``` - - - - - - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | address | undefined | - -### publicKey - -```solidity -function publicKey() external view returns (bytes) -``` - - - - - - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | bytes | undefined | - -### submitPublicKey - -```solidity -function submitPublicKey(bytes _publicKey) external nonpayable -``` - -Submits a public key to the keep. - -*Public key is published successfully if all members submit the same value. In case of conflicts with others members submissions it will emit `ConflictingPublicKeySubmitted` event. When all submitted keys match it will store the key as keep's public key and emit a `PublicKeyPublished` event.* - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| _publicKey | bytes | Signer's public key. | - - - -## Events - -### ConflictingPublicKeySubmitted - -```solidity -event ConflictingPublicKeySubmitted(address indexed submittingMember, bytes conflictingPublicKey) -``` - - - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| submittingMember `indexed` | address | undefined | -| conflictingPublicKey | bytes | undefined | - -### KeepClosed - -```solidity -event KeepClosed() -``` - - - - - - -### KeepTerminated - -```solidity -event KeepTerminated() -``` - - - - - - -### PublicKeyPublished - -```solidity -event PublicKeyPublished(bytes publicKey) -``` - - - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| publicKey | bytes | undefined | - - - diff --git a/docs/bridge/ERC20Migrator.md b/docs/bridge/ERC20Migrator.md deleted file mode 100644 index 6d46f3e53..000000000 --- a/docs/bridge/ERC20Migrator.md +++ /dev/null @@ -1,65 +0,0 @@ -# ERC20Migrator - - - - - - - - - -## Methods - -### legacyToken - -```solidity -function legacyToken() external view returns (contract IERC20) -``` - - - -*Returns the legacy token that is being migrated.* - - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | contract IERC20 | undefined | - -### migrate - -```solidity -function migrate(uint256 amount) external nonpayable -``` - - - -*Transfers part of an account's balance in the old token to this contract, and mints the same amount of new tokens for that account.* - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| amount | uint256 | amount of tokens to be migrated | - -### newToken - -```solidity -function newToken() external view returns (contract IERC20) -``` - - - -*Returns the new token to which we are migrating.* - - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | contract IERC20 | undefined | - - - - diff --git a/docs/bridge/HarmonySynapseBridge.md b/docs/bridge/HarmonySynapseBridge.md deleted file mode 100644 index 65dbd8413..000000000 --- a/docs/bridge/HarmonySynapseBridge.md +++ /dev/null @@ -1,951 +0,0 @@ -# HarmonySynapseBridge - - - - - - - - - -## Methods - -### DEFAULT_ADMIN_ROLE - -```solidity -function DEFAULT_ADMIN_ROLE() external view returns (bytes32) -``` - - - - - - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | bytes32 | undefined | - -### GOVERNANCE_ROLE - -```solidity -function GOVERNANCE_ROLE() external view returns (bytes32) -``` - - - - - - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | bytes32 | undefined | - -### NODEGROUP_ROLE - -```solidity -function NODEGROUP_ROLE() external view returns (bytes32) -``` - - - - - - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | bytes32 | undefined | - -### WETH_ADDRESS - -```solidity -function WETH_ADDRESS() external view returns (address payable) -``` - - - - - - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | address payable | undefined | - -### addKappas - -```solidity -function addKappas(bytes32[] kappas) external nonpayable -``` - - - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| kappas | bytes32[] | undefined | - -### bridgeVersion - -```solidity -function bridgeVersion() external view returns (uint256) -``` - - - - - - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | uint256 | undefined | - -### chainGasAmount - -```solidity -function chainGasAmount() external view returns (uint256) -``` - - - - - - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | uint256 | undefined | - -### deposit - -```solidity -function deposit(address to, uint256 chainId, contract IERC20 token, uint256 amount) external nonpayable -``` - -Relays to nodes to transfers an ERC20 token cross-chain - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| to | address | address on other chain to bridge assets to | -| chainId | uint256 | which chain to bridge assets onto | -| token | contract IERC20 | ERC20 compatible token to deposit into the bridge | -| amount | uint256 | Amount in native token decimals to transfer cross-chain pre-fees* | - -### depositAndSwap - -```solidity -function depositAndSwap(address to, uint256 chainId, contract IERC20 token, uint256 amount, uint8 tokenIndexFrom, uint8 tokenIndexTo, uint256 minDy, uint256 deadline) external nonpayable -``` - -Relays to nodes to both transfer an ERC20 token cross-chain, and then have the nodes execute a swap through a liquidity pool on behalf of the user. - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| to | address | address on other chain to bridge assets to | -| chainId | uint256 | which chain to bridge assets onto | -| token | contract IERC20 | ERC20 compatible token to deposit into the bridge | -| amount | uint256 | Amount in native token decimals to transfer cross-chain pre-fees | -| tokenIndexFrom | uint8 | the token the user wants to swap from | -| tokenIndexTo | uint8 | the token the user wants to swap to | -| minDy | uint256 | the min amount the user would like to receive, or revert to only minting the SynERC20 token crosschain. | -| deadline | uint256 | latest timestamp to accept this transaction* | - -### getFeeBalance - -```solidity -function getFeeBalance(address tokenAddress) external view returns (uint256) -``` - - - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| tokenAddress | address | undefined | - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | uint256 | undefined | - -### getRoleAdmin - -```solidity -function getRoleAdmin(bytes32 role) external view returns (bytes32) -``` - - - -*Returns the admin role that controls `role`. See {grantRole} and {revokeRole}. To change a role's admin, use {_setRoleAdmin}.* - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| role | bytes32 | undefined | - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | bytes32 | undefined | - -### getRoleMember - -```solidity -function getRoleMember(bytes32 role, uint256 index) external view returns (address) -``` - - - -*Returns one of the accounts that have `role`. `index` must be a value between 0 and {getRoleMemberCount}, non-inclusive. Role bearers are not sorted in any particular way, and their ordering may change at any point. WARNING: When using {getRoleMember} and {getRoleMemberCount}, make sure you perform all queries on the same block. See the following https://forum.openzeppelin.com/t/iterating-over-elements-on-enumerableset-in-openzeppelin-contracts/2296[forum post] for more information.* - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| role | bytes32 | undefined | -| index | uint256 | undefined | - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | address | undefined | - -### getRoleMemberCount - -```solidity -function getRoleMemberCount(bytes32 role) external view returns (uint256) -``` - - - -*Returns the number of accounts that have `role`. Can be used together with {getRoleMember} to enumerate all bearers of a role.* - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| role | bytes32 | undefined | - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | uint256 | undefined | - -### grantRole - -```solidity -function grantRole(bytes32 role, address account) external nonpayable -``` - - - -*Grants `role` to `account`. If `account` had not been already granted `role`, emits a {RoleGranted} event. Requirements: - the caller must have ``role``'s admin role.* - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| role | bytes32 | undefined | -| account | address | undefined | - -### hasRole - -```solidity -function hasRole(bytes32 role, address account) external view returns (bool) -``` - - - -*Returns `true` if `account` has been granted `role`.* - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| role | bytes32 | undefined | -| account | address | undefined | - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | bool | undefined | - -### initialize - -```solidity -function initialize() external nonpayable -``` - - - - - - -### kappaExists - -```solidity -function kappaExists(bytes32 kappa) external view returns (bool) -``` - - - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| kappa | bytes32 | undefined | - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | bool | undefined | - -### mint - -```solidity -function mint(address payable to, contract IERC20Mintable token, uint256 amount, uint256 fee, bytes32 kappa) external nonpayable -``` - -Nodes call this function to mint a SynERC20 (or any asset that the bridge is given minter access to). This is called by the nodes after a TokenDeposit event is emitted. - -*This means the SynapseBridge.sol contract must have minter access to the token attempting to be minted* - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| to | address payable | address on other chain to redeem underlying assets to | -| token | contract IERC20Mintable | ERC20 compatible token to deposit into the bridge | -| amount | uint256 | Amount in native token decimals to transfer cross-chain post-fees | -| fee | uint256 | Amount in native token decimals to save to the contract as fees | -| kappa | bytes32 | kappa* | - -### mintAndSwap - -```solidity -function mintAndSwap(address payable to, contract IERC20Mintable token, uint256 amount, uint256 fee, contract ISwap pool, uint8 tokenIndexFrom, uint8 tokenIndexTo, uint256 minDy, uint256 deadline, bytes32 kappa) external nonpayable -``` - -Nodes call this function to mint a SynERC20 (or any asset that the bridge is given minter access to), and then attempt to swap the SynERC20 into the desired destination asset. This is called by the nodes after a TokenDepositAndSwap event is emitted. - -*This means the BridgeDeposit.sol contract must have minter access to the token attempting to be minted* - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| to | address payable | address on other chain to redeem underlying assets to | -| token | contract IERC20Mintable | ERC20 compatible token to deposit into the bridge | -| amount | uint256 | Amount in native token decimals to transfer cross-chain post-fees | -| fee | uint256 | Amount in native token decimals to save to the contract as fees | -| pool | contract ISwap | Destination chain's pool to use to swap SynERC20 -> Asset. The nodes determine this by using PoolConfig.sol. | -| tokenIndexFrom | uint8 | Index of the SynERC20 asset in the pool | -| tokenIndexTo | uint8 | Index of the desired final asset | -| minDy | uint256 | Minumum amount (in final asset decimals) that must be swapped for, otherwise the user will receive the SynERC20. | -| deadline | uint256 | Epoch time of the deadline that the swap is allowed to be executed. | -| kappa | bytes32 | kappa* | - -### pause - -```solidity -function pause() external nonpayable -``` - - - - - - -### paused - -```solidity -function paused() external view returns (bool) -``` - - - -*Returns true if the contract is paused, and false otherwise.* - - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | bool | undefined | - -### redeem - -```solidity -function redeem(address to, uint256 chainId, contract ERC20Burnable token, uint256 amount) external nonpayable -``` - -Relays to nodes that (typically) a wrapped synAsset ERC20 token has been burned and the underlying needs to be redeeemed on the native chain - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| to | address | address on other chain to redeem underlying assets to | -| chainId | uint256 | which underlying chain to bridge assets onto | -| token | contract ERC20Burnable | ERC20 compatible token to deposit into the bridge | -| amount | uint256 | Amount in native token decimals to transfer cross-chain pre-fees* | - -### redeemAndRemove - -```solidity -function redeemAndRemove(address to, uint256 chainId, contract ERC20Burnable token, uint256 amount, uint8 swapTokenIndex, uint256 swapMinAmount, uint256 swapDeadline) external nonpayable -``` - -Relays to nodes that (typically) a wrapped synAsset ERC20 token has been burned and the underlying needs to be redeeemed on the native chain. This function indicates to the nodes that they should attempt to redeem the LP token for the underlying assets (E.g "swap" out of the LP token) - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| to | address | address on other chain to redeem underlying assets to | -| chainId | uint256 | which underlying chain to bridge assets onto | -| token | contract ERC20Burnable | ERC20 compatible token to deposit into the bridge | -| amount | uint256 | Amount in native token decimals to transfer cross-chain pre-fees | -| swapTokenIndex | uint8 | Specifies which of the underlying LP assets the nodes should attempt to redeem for | -| swapMinAmount | uint256 | Specifies the minimum amount of the underlying asset needed for the nodes to execute the redeem/swap | -| swapDeadline | uint256 | Specificies the deadline that the nodes are allowed to try to redeem/swap the LP token* | - -### redeemAndSwap - -```solidity -function redeemAndSwap(address to, uint256 chainId, contract ERC20Burnable token, uint256 amount, uint8 tokenIndexFrom, uint8 tokenIndexTo, uint256 minDy, uint256 deadline) external nonpayable -``` - -Relays to nodes that (typically) a wrapped synAsset ERC20 token has been burned and the underlying needs to be redeeemed on the native chain. This function indicates to the nodes that they should attempt to redeem the LP token for the underlying assets (E.g "swap" out of the LP token) - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| to | address | address on other chain to redeem underlying assets to | -| chainId | uint256 | which underlying chain to bridge assets onto | -| token | contract ERC20Burnable | ERC20 compatible token to deposit into the bridge | -| amount | uint256 | Amount in native token decimals to transfer cross-chain pre-fees | -| tokenIndexFrom | uint8 | the token the user wants to swap from | -| tokenIndexTo | uint8 | the token the user wants to swap to | -| minDy | uint256 | the min amount the user would like to receive, or revert to only minting the SynERC20 token crosschain. | -| deadline | uint256 | latest timestamp to accept this transaction* | - -### redeemV2 - -```solidity -function redeemV2(bytes32 to, uint256 chainId, contract ERC20Burnable token, uint256 amount) external nonpayable -``` - -Relays to nodes that (typically) a wrapped synAsset ERC20 token has been burned and the underlying needs to be redeeemed on the native chain - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| to | bytes32 | address on other chain to redeem underlying assets to | -| chainId | uint256 | which underlying chain to bridge assets onto | -| token | contract ERC20Burnable | ERC20 compatible token to deposit into the bridge | -| amount | uint256 | Amount in native token decimals to transfer cross-chain pre-fees* | - -### renounceRole - -```solidity -function renounceRole(bytes32 role, address account) external nonpayable -``` - - - -*Revokes `role` from the calling account. Roles are often managed via {grantRole} and {revokeRole}: this function's purpose is to provide a mechanism for accounts to lose their privileges if they are compromised (such as when a trusted device is misplaced). If the calling account had been granted `role`, emits a {RoleRevoked} event. Requirements: - the caller must be `account`.* - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| role | bytes32 | undefined | -| account | address | undefined | - -### revokeRole - -```solidity -function revokeRole(bytes32 role, address account) external nonpayable -``` - - - -*Revokes `role` from `account`. If `account` had been granted `role`, emits a {RoleRevoked} event. Requirements: - the caller must have ``role``'s admin role.* - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| role | bytes32 | undefined | -| account | address | undefined | - -### setChainGasAmount - -```solidity -function setChainGasAmount(uint256 amount) external nonpayable -``` - - - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| amount | uint256 | undefined | - -### setWethAddress - -```solidity -function setWethAddress(address payable _wethAddress) external nonpayable -``` - - - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| _wethAddress | address payable | undefined | - -### startBlockNumber - -```solidity -function startBlockNumber() external view returns (uint256) -``` - - - - - - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | uint256 | undefined | - -### unpause - -```solidity -function unpause() external nonpayable -``` - - - - - - -### withdraw - -```solidity -function withdraw(address to, contract IERC20 token, uint256 amount, uint256 fee, bytes32 kappa) external nonpayable -``` - -Function to be called by the node group to withdraw the underlying assets from the contract - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| to | address | address on chain to send underlying assets to | -| token | contract IERC20 | ERC20 compatible token to withdraw from the bridge | -| amount | uint256 | Amount in native token decimals to withdraw | -| fee | uint256 | Amount in native token decimals to save to the contract as fees | -| kappa | bytes32 | kappa* | - -### withdrawAndRemove - -```solidity -function withdrawAndRemove(address to, contract IERC20 token, uint256 amount, uint256 fee, contract ISwap pool, uint8 swapTokenIndex, uint256 swapMinAmount, uint256 swapDeadline, bytes32 kappa) external nonpayable -``` - -Function to be called by the node group to withdraw the underlying assets from the contract - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| to | address | address on chain to send underlying assets to | -| token | contract IERC20 | ERC20 compatible token to withdraw from the bridge | -| amount | uint256 | Amount in native token decimals to withdraw | -| fee | uint256 | Amount in native token decimals to save to the contract as fees | -| pool | contract ISwap | Destination chain's pool to use to swap SynERC20 -> Asset. The nodes determine this by using PoolConfig.sol. | -| swapTokenIndex | uint8 | Specifies which of the underlying LP assets the nodes should attempt to redeem for | -| swapMinAmount | uint256 | Specifies the minimum amount of the underlying asset needed for the nodes to execute the redeem/swap | -| swapDeadline | uint256 | Specificies the deadline that the nodes are allowed to try to redeem/swap the LP token | -| kappa | bytes32 | kappa* | - -### withdrawFees - -```solidity -function withdrawFees(contract IERC20 token, address to) external nonpayable -``` - -withdraw specified ERC20 token fees to a given address - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| token | contract IERC20 | ERC20 token in which fees acccumulated to transfer | -| to | address | Address to send the fees to | - - - -## Events - -### Paused - -```solidity -event Paused(address account) -``` - - - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| account | address | undefined | - -### RoleAdminChanged - -```solidity -event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole) -``` - - - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| role `indexed` | bytes32 | undefined | -| previousAdminRole `indexed` | bytes32 | undefined | -| newAdminRole `indexed` | bytes32 | undefined | - -### RoleGranted - -```solidity -event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender) -``` - - - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| role `indexed` | bytes32 | undefined | -| account `indexed` | address | undefined | -| sender `indexed` | address | undefined | - -### RoleRevoked - -```solidity -event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender) -``` - - - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| role `indexed` | bytes32 | undefined | -| account `indexed` | address | undefined | -| sender `indexed` | address | undefined | - -### TokenDeposit - -```solidity -event TokenDeposit(address indexed to, uint256 chainId, contract IERC20 token, uint256 amount) -``` - - - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| to `indexed` | address | undefined | -| chainId | uint256 | undefined | -| token | contract IERC20 | undefined | -| amount | uint256 | undefined | - -### TokenDepositAndSwap - -```solidity -event TokenDepositAndSwap(address indexed to, uint256 chainId, contract IERC20 token, uint256 amount, uint8 tokenIndexFrom, uint8 tokenIndexTo, uint256 minDy, uint256 deadline) -``` - - - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| to `indexed` | address | undefined | -| chainId | uint256 | undefined | -| token | contract IERC20 | undefined | -| amount | uint256 | undefined | -| tokenIndexFrom | uint8 | undefined | -| tokenIndexTo | uint8 | undefined | -| minDy | uint256 | undefined | -| deadline | uint256 | undefined | - -### TokenMint - -```solidity -event TokenMint(address indexed to, contract IERC20Mintable token, uint256 amount, uint256 fee, bytes32 indexed kappa) -``` - - - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| to `indexed` | address | undefined | -| token | contract IERC20Mintable | undefined | -| amount | uint256 | undefined | -| fee | uint256 | undefined | -| kappa `indexed` | bytes32 | undefined | - -### TokenMintAndSwap - -```solidity -event TokenMintAndSwap(address indexed to, contract IERC20Mintable token, uint256 amount, uint256 fee, uint8 tokenIndexFrom, uint8 tokenIndexTo, uint256 minDy, uint256 deadline, bool swapSuccess, bytes32 indexed kappa) -``` - - - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| to `indexed` | address | undefined | -| token | contract IERC20Mintable | undefined | -| amount | uint256 | undefined | -| fee | uint256 | undefined | -| tokenIndexFrom | uint8 | undefined | -| tokenIndexTo | uint8 | undefined | -| minDy | uint256 | undefined | -| deadline | uint256 | undefined | -| swapSuccess | bool | undefined | -| kappa `indexed` | bytes32 | undefined | - -### TokenRedeem - -```solidity -event TokenRedeem(address indexed to, uint256 chainId, contract IERC20 token, uint256 amount) -``` - - - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| to `indexed` | address | undefined | -| chainId | uint256 | undefined | -| token | contract IERC20 | undefined | -| amount | uint256 | undefined | - -### TokenRedeemAndRemove - -```solidity -event TokenRedeemAndRemove(address indexed to, uint256 chainId, contract IERC20 token, uint256 amount, uint8 swapTokenIndex, uint256 swapMinAmount, uint256 swapDeadline) -``` - - - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| to `indexed` | address | undefined | -| chainId | uint256 | undefined | -| token | contract IERC20 | undefined | -| amount | uint256 | undefined | -| swapTokenIndex | uint8 | undefined | -| swapMinAmount | uint256 | undefined | -| swapDeadline | uint256 | undefined | - -### TokenRedeemAndSwap - -```solidity -event TokenRedeemAndSwap(address indexed to, uint256 chainId, contract IERC20 token, uint256 amount, uint8 tokenIndexFrom, uint8 tokenIndexTo, uint256 minDy, uint256 deadline) -``` - - - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| to `indexed` | address | undefined | -| chainId | uint256 | undefined | -| token | contract IERC20 | undefined | -| amount | uint256 | undefined | -| tokenIndexFrom | uint8 | undefined | -| tokenIndexTo | uint8 | undefined | -| minDy | uint256 | undefined | -| deadline | uint256 | undefined | - -### TokenRedeemV2 - -```solidity -event TokenRedeemV2(bytes32 indexed to, uint256 chainId, contract IERC20 token, uint256 amount) -``` - - - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| to `indexed` | bytes32 | undefined | -| chainId | uint256 | undefined | -| token | contract IERC20 | undefined | -| amount | uint256 | undefined | - -### TokenWithdraw - -```solidity -event TokenWithdraw(address indexed to, contract IERC20 token, uint256 amount, uint256 fee, bytes32 indexed kappa) -``` - - - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| to `indexed` | address | undefined | -| token | contract IERC20 | undefined | -| amount | uint256 | undefined | -| fee | uint256 | undefined | -| kappa `indexed` | bytes32 | undefined | - -### TokenWithdrawAndRemove - -```solidity -event TokenWithdrawAndRemove(address indexed to, contract IERC20 token, uint256 amount, uint256 fee, uint8 swapTokenIndex, uint256 swapMinAmount, uint256 swapDeadline, bool swapSuccess, bytes32 indexed kappa) -``` - - - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| to `indexed` | address | undefined | -| token | contract IERC20 | undefined | -| amount | uint256 | undefined | -| fee | uint256 | undefined | -| swapTokenIndex | uint8 | undefined | -| swapMinAmount | uint256 | undefined | -| swapDeadline | uint256 | undefined | -| swapSuccess | bool | undefined | -| kappa `indexed` | bytes32 | undefined | - -### Unpaused - -```solidity -event Unpaused(address account) -``` - - - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| account | address | undefined | - - - diff --git a/docs/bridge/IERC20Mintable.md b/docs/bridge/IERC20Mintable.md deleted file mode 100644 index 40e9fa272..000000000 --- a/docs/bridge/IERC20Mintable.md +++ /dev/null @@ -1,203 +0,0 @@ -# IERC20Mintable - - - - - - - - - -## Methods - -### allowance - -```solidity -function allowance(address owner, address spender) external view returns (uint256) -``` - - - -*Returns the remaining number of tokens that `spender` will be allowed to spend on behalf of `owner` through {transferFrom}. This is zero by default. This value changes when {approve} or {transferFrom} are called.* - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| owner | address | undefined | -| spender | address | undefined | - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | uint256 | undefined | - -### approve - -```solidity -function approve(address spender, uint256 amount) external nonpayable returns (bool) -``` - - - -*Sets `amount` as the allowance of `spender` over the caller's tokens. Returns a boolean value indicating whether the operation succeeded. IMPORTANT: Beware that changing an allowance with this method brings the risk that someone may use both the old and the new allowance by unfortunate transaction ordering. One possible solution to mitigate this race condition is to first reduce the spender's allowance to 0 and set the desired value afterwards: https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729 Emits an {Approval} event.* - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| spender | address | undefined | -| amount | uint256 | undefined | - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | bool | undefined | - -### balanceOf - -```solidity -function balanceOf(address account) external view returns (uint256) -``` - - - -*Returns the amount of tokens owned by `account`.* - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| account | address | undefined | - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | uint256 | undefined | - -### mint - -```solidity -function mint(address to, uint256 amount) external nonpayable -``` - - - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| to | address | undefined | -| amount | uint256 | undefined | - -### totalSupply - -```solidity -function totalSupply() external view returns (uint256) -``` - - - -*Returns the amount of tokens in existence.* - - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | uint256 | undefined | - -### transfer - -```solidity -function transfer(address recipient, uint256 amount) external nonpayable returns (bool) -``` - - - -*Moves `amount` tokens from the caller's account to `recipient`. Returns a boolean value indicating whether the operation succeeded. Emits a {Transfer} event.* - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| recipient | address | undefined | -| amount | uint256 | undefined | - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | bool | undefined | - -### transferFrom - -```solidity -function transferFrom(address sender, address recipient, uint256 amount) external nonpayable returns (bool) -``` - - - -*Moves `amount` tokens from `sender` to `recipient` using the allowance mechanism. `amount` is then deducted from the caller's allowance. Returns a boolean value indicating whether the operation succeeded. Emits a {Transfer} event.* - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| sender | address | undefined | -| recipient | address | undefined | -| amount | uint256 | undefined | - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | bool | undefined | - - - -## Events - -### Approval - -```solidity -event Approval(address indexed owner, address indexed spender, uint256 value) -``` - - - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| owner `indexed` | address | undefined | -| spender `indexed` | address | undefined | -| value | uint256 | undefined | - -### Transfer - -```solidity -event Transfer(address indexed from, address indexed to, uint256 value) -``` - - - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| from `indexed` | address | undefined | -| to `indexed` | address | undefined | -| value | uint256 | undefined | - - - diff --git a/docs/bridge/IFrax.md b/docs/bridge/IFrax.md deleted file mode 100644 index 8ff094150..000000000 --- a/docs/bridge/IFrax.md +++ /dev/null @@ -1,38 +0,0 @@ -# IFrax - - - - - - - - - -## Methods - -### exchangeOldForCanonical - -```solidity -function exchangeOldForCanonical(address bridge_token_address, uint256 token_amount) external nonpayable returns (uint256) -``` - - - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| bridge_token_address | address | undefined | -| token_amount | uint256 | undefined | - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | uint256 | undefined | - - - - diff --git a/docs/bridge/MRSynapseBridge.md b/docs/bridge/MRSynapseBridge.md deleted file mode 100644 index 5ac560ea7..000000000 --- a/docs/bridge/MRSynapseBridge.md +++ /dev/null @@ -1,951 +0,0 @@ -# MRSynapseBridge - - - - - - - - - -## Methods - -### DEFAULT_ADMIN_ROLE - -```solidity -function DEFAULT_ADMIN_ROLE() external view returns (bytes32) -``` - - - - - - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | bytes32 | undefined | - -### GOVERNANCE_ROLE - -```solidity -function GOVERNANCE_ROLE() external view returns (bytes32) -``` - - - - - - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | bytes32 | undefined | - -### NODEGROUP_ROLE - -```solidity -function NODEGROUP_ROLE() external view returns (bytes32) -``` - - - - - - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | bytes32 | undefined | - -### WETH_ADDRESS - -```solidity -function WETH_ADDRESS() external view returns (address payable) -``` - - - - - - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | address payable | undefined | - -### addKappas - -```solidity -function addKappas(bytes32[] kappas) external nonpayable -``` - - - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| kappas | bytes32[] | undefined | - -### bridgeVersion - -```solidity -function bridgeVersion() external view returns (uint256) -``` - - - - - - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | uint256 | undefined | - -### chainGasAmount - -```solidity -function chainGasAmount() external view returns (uint256) -``` - - - - - - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | uint256 | undefined | - -### deposit - -```solidity -function deposit(address to, uint256 chainId, contract IERC20 token, uint256 amount) external nonpayable -``` - -Relays to nodes to transfers an ERC20 token cross-chain - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| to | address | address on other chain to bridge assets to | -| chainId | uint256 | which chain to bridge assets onto | -| token | contract IERC20 | ERC20 compatible token to deposit into the bridge | -| amount | uint256 | Amount in native token decimals to transfer cross-chain pre-fees* | - -### depositAndSwap - -```solidity -function depositAndSwap(address to, uint256 chainId, contract IERC20 token, uint256 amount, uint8 tokenIndexFrom, uint8 tokenIndexTo, uint256 minDy, uint256 deadline) external nonpayable -``` - -Relays to nodes to both transfer an ERC20 token cross-chain, and then have the nodes execute a swap through a liquidity pool on behalf of the user. - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| to | address | address on other chain to bridge assets to | -| chainId | uint256 | which chain to bridge assets onto | -| token | contract IERC20 | ERC20 compatible token to deposit into the bridge | -| amount | uint256 | Amount in native token decimals to transfer cross-chain pre-fees | -| tokenIndexFrom | uint8 | the token the user wants to swap from | -| tokenIndexTo | uint8 | the token the user wants to swap to | -| minDy | uint256 | the min amount the user would like to receive, or revert to only minting the SynERC20 token crosschain. | -| deadline | uint256 | latest timestamp to accept this transaction* | - -### getFeeBalance - -```solidity -function getFeeBalance(address tokenAddress) external view returns (uint256) -``` - - - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| tokenAddress | address | undefined | - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | uint256 | undefined | - -### getRoleAdmin - -```solidity -function getRoleAdmin(bytes32 role) external view returns (bytes32) -``` - - - -*Returns the admin role that controls `role`. See {grantRole} and {revokeRole}. To change a role's admin, use {_setRoleAdmin}.* - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| role | bytes32 | undefined | - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | bytes32 | undefined | - -### getRoleMember - -```solidity -function getRoleMember(bytes32 role, uint256 index) external view returns (address) -``` - - - -*Returns one of the accounts that have `role`. `index` must be a value between 0 and {getRoleMemberCount}, non-inclusive. Role bearers are not sorted in any particular way, and their ordering may change at any point. WARNING: When using {getRoleMember} and {getRoleMemberCount}, make sure you perform all queries on the same block. See the following https://forum.openzeppelin.com/t/iterating-over-elements-on-enumerableset-in-openzeppelin-contracts/2296[forum post] for more information.* - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| role | bytes32 | undefined | -| index | uint256 | undefined | - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | address | undefined | - -### getRoleMemberCount - -```solidity -function getRoleMemberCount(bytes32 role) external view returns (uint256) -``` - - - -*Returns the number of accounts that have `role`. Can be used together with {getRoleMember} to enumerate all bearers of a role.* - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| role | bytes32 | undefined | - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | uint256 | undefined | - -### grantRole - -```solidity -function grantRole(bytes32 role, address account) external nonpayable -``` - - - -*Grants `role` to `account`. If `account` had not been already granted `role`, emits a {RoleGranted} event. Requirements: - the caller must have ``role``'s admin role.* - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| role | bytes32 | undefined | -| account | address | undefined | - -### hasRole - -```solidity -function hasRole(bytes32 role, address account) external view returns (bool) -``` - - - -*Returns `true` if `account` has been granted `role`.* - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| role | bytes32 | undefined | -| account | address | undefined | - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | bool | undefined | - -### initialize - -```solidity -function initialize() external nonpayable -``` - - - - - - -### kappaExists - -```solidity -function kappaExists(bytes32 kappa) external view returns (bool) -``` - - - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| kappa | bytes32 | undefined | - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | bool | undefined | - -### mint - -```solidity -function mint(address payable to, contract IERC20Mintable token, uint256 amount, uint256 fee, bytes32 kappa) external nonpayable -``` - -Nodes call this function to mint a SynERC20 (or any asset that the bridge is given minter access to). This is called by the nodes after a TokenDeposit event is emitted. - -*This means the SynapseBridge.sol contract must have minter access to the token attempting to be minted* - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| to | address payable | address on other chain to redeem underlying assets to | -| token | contract IERC20Mintable | ERC20 compatible token to deposit into the bridge | -| amount | uint256 | Amount in native token decimals to transfer cross-chain post-fees | -| fee | uint256 | Amount in native token decimals to save to the contract as fees | -| kappa | bytes32 | kappa* | - -### mintAndSwap - -```solidity -function mintAndSwap(address payable to, contract IERC20Mintable token, uint256 amount, uint256 fee, contract ISwap pool, uint8 tokenIndexFrom, uint8 tokenIndexTo, uint256 minDy, uint256 deadline, bytes32 kappa) external nonpayable -``` - -Nodes call this function to mint a SynERC20 (or any asset that the bridge is given minter access to), and then attempt to swap the SynERC20 into the desired destination asset. This is called by the nodes after a TokenDepositAndSwap event is emitted. - -*This means the BridgeDeposit.sol contract must have minter access to the token attempting to be minted* - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| to | address payable | address on other chain to redeem underlying assets to | -| token | contract IERC20Mintable | ERC20 compatible token to deposit into the bridge | -| amount | uint256 | Amount in native token decimals to transfer cross-chain post-fees | -| fee | uint256 | Amount in native token decimals to save to the contract as fees | -| pool | contract ISwap | Destination chain's pool to use to swap SynERC20 -> Asset. The nodes determine this by using PoolConfig.sol. | -| tokenIndexFrom | uint8 | Index of the SynERC20 asset in the pool | -| tokenIndexTo | uint8 | Index of the desired final asset | -| minDy | uint256 | Minumum amount (in final asset decimals) that must be swapped for, otherwise the user will receive the SynERC20. | -| deadline | uint256 | Epoch time of the deadline that the swap is allowed to be executed. | -| kappa | bytes32 | kappa* | - -### pause - -```solidity -function pause() external nonpayable -``` - - - - - - -### paused - -```solidity -function paused() external view returns (bool) -``` - - - -*Returns true if the contract is paused, and false otherwise.* - - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | bool | undefined | - -### redeem - -```solidity -function redeem(address to, uint256 chainId, contract ERC20Burnable token, uint256 amount) external nonpayable -``` - -Relays to nodes that (typically) a wrapped synAsset ERC20 token has been burned and the underlying needs to be redeeemed on the native chain - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| to | address | address on other chain to redeem underlying assets to | -| chainId | uint256 | which underlying chain to bridge assets onto | -| token | contract ERC20Burnable | ERC20 compatible token to deposit into the bridge | -| amount | uint256 | Amount in native token decimals to transfer cross-chain pre-fees* | - -### redeemAndRemove - -```solidity -function redeemAndRemove(address to, uint256 chainId, contract ERC20Burnable token, uint256 amount, uint8 swapTokenIndex, uint256 swapMinAmount, uint256 swapDeadline) external nonpayable -``` - -Relays to nodes that (typically) a wrapped synAsset ERC20 token has been burned and the underlying needs to be redeeemed on the native chain. This function indicates to the nodes that they should attempt to redeem the LP token for the underlying assets (E.g "swap" out of the LP token) - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| to | address | address on other chain to redeem underlying assets to | -| chainId | uint256 | which underlying chain to bridge assets onto | -| token | contract ERC20Burnable | ERC20 compatible token to deposit into the bridge | -| amount | uint256 | Amount in native token decimals to transfer cross-chain pre-fees | -| swapTokenIndex | uint8 | Specifies which of the underlying LP assets the nodes should attempt to redeem for | -| swapMinAmount | uint256 | Specifies the minimum amount of the underlying asset needed for the nodes to execute the redeem/swap | -| swapDeadline | uint256 | Specificies the deadline that the nodes are allowed to try to redeem/swap the LP token* | - -### redeemAndSwap - -```solidity -function redeemAndSwap(address to, uint256 chainId, contract ERC20Burnable token, uint256 amount, uint8 tokenIndexFrom, uint8 tokenIndexTo, uint256 minDy, uint256 deadline) external nonpayable -``` - -Relays to nodes that (typically) a wrapped synAsset ERC20 token has been burned and the underlying needs to be redeeemed on the native chain. This function indicates to the nodes that they should attempt to redeem the LP token for the underlying assets (E.g "swap" out of the LP token) - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| to | address | address on other chain to redeem underlying assets to | -| chainId | uint256 | which underlying chain to bridge assets onto | -| token | contract ERC20Burnable | ERC20 compatible token to deposit into the bridge | -| amount | uint256 | Amount in native token decimals to transfer cross-chain pre-fees | -| tokenIndexFrom | uint8 | the token the user wants to swap from | -| tokenIndexTo | uint8 | the token the user wants to swap to | -| minDy | uint256 | the min amount the user would like to receive, or revert to only minting the SynERC20 token crosschain. | -| deadline | uint256 | latest timestamp to accept this transaction* | - -### redeemV2 - -```solidity -function redeemV2(bytes32 to, uint256 chainId, contract ERC20Burnable token, uint256 amount) external nonpayable -``` - -Relays to nodes that (typically) a wrapped synAsset ERC20 token has been burned and the underlying needs to be redeeemed on the native chain - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| to | bytes32 | address on other chain to redeem underlying assets to | -| chainId | uint256 | which underlying chain to bridge assets onto | -| token | contract ERC20Burnable | ERC20 compatible token to deposit into the bridge | -| amount | uint256 | Amount in native token decimals to transfer cross-chain pre-fees* | - -### renounceRole - -```solidity -function renounceRole(bytes32 role, address account) external nonpayable -``` - - - -*Revokes `role` from the calling account. Roles are often managed via {grantRole} and {revokeRole}: this function's purpose is to provide a mechanism for accounts to lose their privileges if they are compromised (such as when a trusted device is misplaced). If the calling account had been granted `role`, emits a {RoleRevoked} event. Requirements: - the caller must be `account`.* - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| role | bytes32 | undefined | -| account | address | undefined | - -### revokeRole - -```solidity -function revokeRole(bytes32 role, address account) external nonpayable -``` - - - -*Revokes `role` from `account`. If `account` had been granted `role`, emits a {RoleRevoked} event. Requirements: - the caller must have ``role``'s admin role.* - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| role | bytes32 | undefined | -| account | address | undefined | - -### setChainGasAmount - -```solidity -function setChainGasAmount(uint256 amount) external nonpayable -``` - - - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| amount | uint256 | undefined | - -### setWethAddress - -```solidity -function setWethAddress(address payable _wethAddress) external nonpayable -``` - - - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| _wethAddress | address payable | undefined | - -### startBlockNumber - -```solidity -function startBlockNumber() external view returns (uint256) -``` - - - - - - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | uint256 | undefined | - -### unpause - -```solidity -function unpause() external nonpayable -``` - - - - - - -### withdraw - -```solidity -function withdraw(address to, contract IERC20 token, uint256 amount, uint256 fee, bytes32 kappa) external nonpayable -``` - -Function to be called by the node group to withdraw the underlying assets from the contract - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| to | address | address on chain to send underlying assets to | -| token | contract IERC20 | ERC20 compatible token to withdraw from the bridge | -| amount | uint256 | Amount in native token decimals to withdraw | -| fee | uint256 | Amount in native token decimals to save to the contract as fees | -| kappa | bytes32 | kappa* | - -### withdrawAndRemove - -```solidity -function withdrawAndRemove(address to, contract IERC20 token, uint256 amount, uint256 fee, contract ISwap pool, uint8 swapTokenIndex, uint256 swapMinAmount, uint256 swapDeadline, bytes32 kappa) external nonpayable -``` - -Function to be called by the node group to withdraw the underlying assets from the contract - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| to | address | address on chain to send underlying assets to | -| token | contract IERC20 | ERC20 compatible token to withdraw from the bridge | -| amount | uint256 | Amount in native token decimals to withdraw | -| fee | uint256 | Amount in native token decimals to save to the contract as fees | -| pool | contract ISwap | Destination chain's pool to use to swap SynERC20 -> Asset. The nodes determine this by using PoolConfig.sol. | -| swapTokenIndex | uint8 | Specifies which of the underlying LP assets the nodes should attempt to redeem for | -| swapMinAmount | uint256 | Specifies the minimum amount of the underlying asset needed for the nodes to execute the redeem/swap | -| swapDeadline | uint256 | Specificies the deadline that the nodes are allowed to try to redeem/swap the LP token | -| kappa | bytes32 | kappa* | - -### withdrawFees - -```solidity -function withdrawFees(contract IERC20 token, address to) external nonpayable -``` - -withdraw specified ERC20 token fees to a given address - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| token | contract IERC20 | ERC20 token in which fees acccumulated to transfer | -| to | address | Address to send the fees to | - - - -## Events - -### Paused - -```solidity -event Paused(address account) -``` - - - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| account | address | undefined | - -### RoleAdminChanged - -```solidity -event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole) -``` - - - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| role `indexed` | bytes32 | undefined | -| previousAdminRole `indexed` | bytes32 | undefined | -| newAdminRole `indexed` | bytes32 | undefined | - -### RoleGranted - -```solidity -event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender) -``` - - - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| role `indexed` | bytes32 | undefined | -| account `indexed` | address | undefined | -| sender `indexed` | address | undefined | - -### RoleRevoked - -```solidity -event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender) -``` - - - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| role `indexed` | bytes32 | undefined | -| account `indexed` | address | undefined | -| sender `indexed` | address | undefined | - -### TokenDeposit - -```solidity -event TokenDeposit(address indexed to, uint256 chainId, contract IERC20 token, uint256 amount) -``` - - - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| to `indexed` | address | undefined | -| chainId | uint256 | undefined | -| token | contract IERC20 | undefined | -| amount | uint256 | undefined | - -### TokenDepositAndSwap - -```solidity -event TokenDepositAndSwap(address indexed to, uint256 chainId, contract IERC20 token, uint256 amount, uint8 tokenIndexFrom, uint8 tokenIndexTo, uint256 minDy, uint256 deadline) -``` - - - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| to `indexed` | address | undefined | -| chainId | uint256 | undefined | -| token | contract IERC20 | undefined | -| amount | uint256 | undefined | -| tokenIndexFrom | uint8 | undefined | -| tokenIndexTo | uint8 | undefined | -| minDy | uint256 | undefined | -| deadline | uint256 | undefined | - -### TokenMint - -```solidity -event TokenMint(address indexed to, contract IERC20Mintable token, uint256 amount, uint256 fee, bytes32 indexed kappa) -``` - - - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| to `indexed` | address | undefined | -| token | contract IERC20Mintable | undefined | -| amount | uint256 | undefined | -| fee | uint256 | undefined | -| kappa `indexed` | bytes32 | undefined | - -### TokenMintAndSwap - -```solidity -event TokenMintAndSwap(address indexed to, contract IERC20Mintable token, uint256 amount, uint256 fee, uint8 tokenIndexFrom, uint8 tokenIndexTo, uint256 minDy, uint256 deadline, bool swapSuccess, bytes32 indexed kappa) -``` - - - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| to `indexed` | address | undefined | -| token | contract IERC20Mintable | undefined | -| amount | uint256 | undefined | -| fee | uint256 | undefined | -| tokenIndexFrom | uint8 | undefined | -| tokenIndexTo | uint8 | undefined | -| minDy | uint256 | undefined | -| deadline | uint256 | undefined | -| swapSuccess | bool | undefined | -| kappa `indexed` | bytes32 | undefined | - -### TokenRedeem - -```solidity -event TokenRedeem(address indexed to, uint256 chainId, contract IERC20 token, uint256 amount) -``` - - - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| to `indexed` | address | undefined | -| chainId | uint256 | undefined | -| token | contract IERC20 | undefined | -| amount | uint256 | undefined | - -### TokenRedeemAndRemove - -```solidity -event TokenRedeemAndRemove(address indexed to, uint256 chainId, contract IERC20 token, uint256 amount, uint8 swapTokenIndex, uint256 swapMinAmount, uint256 swapDeadline) -``` - - - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| to `indexed` | address | undefined | -| chainId | uint256 | undefined | -| token | contract IERC20 | undefined | -| amount | uint256 | undefined | -| swapTokenIndex | uint8 | undefined | -| swapMinAmount | uint256 | undefined | -| swapDeadline | uint256 | undefined | - -### TokenRedeemAndSwap - -```solidity -event TokenRedeemAndSwap(address indexed to, uint256 chainId, contract IERC20 token, uint256 amount, uint8 tokenIndexFrom, uint8 tokenIndexTo, uint256 minDy, uint256 deadline) -``` - - - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| to `indexed` | address | undefined | -| chainId | uint256 | undefined | -| token | contract IERC20 | undefined | -| amount | uint256 | undefined | -| tokenIndexFrom | uint8 | undefined | -| tokenIndexTo | uint8 | undefined | -| minDy | uint256 | undefined | -| deadline | uint256 | undefined | - -### TokenRedeemV2 - -```solidity -event TokenRedeemV2(bytes32 indexed to, uint256 chainId, contract IERC20 token, uint256 amount) -``` - - - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| to `indexed` | bytes32 | undefined | -| chainId | uint256 | undefined | -| token | contract IERC20 | undefined | -| amount | uint256 | undefined | - -### TokenWithdraw - -```solidity -event TokenWithdraw(address indexed to, contract IERC20 token, uint256 amount, uint256 fee, bytes32 indexed kappa) -``` - - - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| to `indexed` | address | undefined | -| token | contract IERC20 | undefined | -| amount | uint256 | undefined | -| fee | uint256 | undefined | -| kappa `indexed` | bytes32 | undefined | - -### TokenWithdrawAndRemove - -```solidity -event TokenWithdrawAndRemove(address indexed to, contract IERC20 token, uint256 amount, uint256 fee, uint8 swapTokenIndex, uint256 swapMinAmount, uint256 swapDeadline, bool swapSuccess, bytes32 indexed kappa) -``` - - - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| to `indexed` | address | undefined | -| token | contract IERC20 | undefined | -| amount | uint256 | undefined | -| fee | uint256 | undefined | -| swapTokenIndex | uint8 | undefined | -| swapMinAmount | uint256 | undefined | -| swapDeadline | uint256 | undefined | -| swapSuccess | bool | undefined | -| kappa `indexed` | bytes32 | undefined | - -### Unpaused - -```solidity -event Unpaused(address account) -``` - - - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| account | address | undefined | - - - diff --git a/docs/bridge/MiniChefV2.md b/docs/bridge/MiniChefV2.md deleted file mode 100644 index 1d3f54156..000000000 --- a/docs/bridge/MiniChefV2.md +++ /dev/null @@ -1,655 +0,0 @@ -# MiniChefV2 - - - - - -The (older) MasterChef contract gives out a constant number of SYNAPSE tokens per block. It is the only address with minting rights for SYNAPSE. The idea for this MasterChef V2 (MCV2) contract is therefore to be the owner of a dummy token that is deposited into the MasterChef V1 (MCV1) contract. The allocation point for this pool on MCV1 is the total allocation point for all pools that receive double incentives. - - - -## Methods - -### SYNAPSE - -```solidity -function SYNAPSE() external view returns (contract IERC20) -``` - -Address of SYNAPSE contract. - - - - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | contract IERC20 | undefined | - -### add - -```solidity -function add(uint256 allocPoint, contract IERC20 _lpToken, contract IRewarder _rewarder) external nonpayable -``` - -Add a new LP to the pool. Can only be called by the owner. DO NOT add the same LP token more than once. Rewards will be messed up if you do. - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| allocPoint | uint256 | AP of the new pool. | -| _lpToken | contract IERC20 | Address of the LP ERC-20 token. | -| _rewarder | contract IRewarder | Address of the rewarder delegate. | - -### batch - -```solidity -function batch(bytes[] calls, bool revertOnFail) external payable returns (bool[] successes, bytes[] results) -``` - - - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| calls | bytes[] | undefined | -| revertOnFail | bool | undefined | - -#### Returns - -| Name | Type | Description | -|---|---|---| -| successes | bool[] | undefined | -| results | bytes[] | undefined | - -### claimOwnership - -```solidity -function claimOwnership() external nonpayable -``` - - - - - - -### deposit - -```solidity -function deposit(uint256 pid, uint256 amount, address to) external nonpayable -``` - -Deposit LP tokens to MCV2 for SYNAPSE allocation. - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| pid | uint256 | The index of the pool. See `poolInfo`. | -| amount | uint256 | LP token amount to deposit. | -| to | address | The receiver of `amount` deposit benefit. | - -### emergencyWithdraw - -```solidity -function emergencyWithdraw(uint256 pid, address to) external nonpayable -``` - -Withdraw without caring about rewards. EMERGENCY ONLY. - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| pid | uint256 | The index of the pool. See `poolInfo`. | -| to | address | Receiver of the LP tokens. | - -### harvest - -```solidity -function harvest(uint256 pid, address to) external nonpayable -``` - -Harvest proceeds for transaction sender to `to`. - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| pid | uint256 | The index of the pool. See `poolInfo`. | -| to | address | Receiver of SYNAPSE rewards. | - -### lpToken - -```solidity -function lpToken(uint256) external view returns (contract IERC20) -``` - -Address of the LP token for each MCV2 pool. - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| _0 | uint256 | undefined | - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | contract IERC20 | undefined | - -### massUpdatePools - -```solidity -function massUpdatePools(uint256[] pids) external nonpayable -``` - -Update reward variables for all pools. Be careful of gas spending! - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| pids | uint256[] | Pool IDs of all to be updated. Make sure to update all active pools. | - -### owner - -```solidity -function owner() external view returns (address) -``` - - - - - - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | address | undefined | - -### pendingOwner - -```solidity -function pendingOwner() external view returns (address) -``` - - - - - - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | address | undefined | - -### pendingSynapse - -```solidity -function pendingSynapse(uint256 _pid, address _user) external view returns (uint256 pending) -``` - -View function to see pending SYNAPSE on frontend. - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| _pid | uint256 | The index of the pool. See `poolInfo`. | -| _user | address | Address of user. | - -#### Returns - -| Name | Type | Description | -|---|---|---| -| pending | uint256 | SYNAPSE reward for a given user. | - -### permitToken - -```solidity -function permitToken(contract IERC20 token, address from, address to, uint256 amount, uint256 deadline, uint8 v, bytes32 r, bytes32 s) external nonpayable -``` - - - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| token | contract IERC20 | undefined | -| from | address | undefined | -| to | address | undefined | -| amount | uint256 | undefined | -| deadline | uint256 | undefined | -| v | uint8 | undefined | -| r | bytes32 | undefined | -| s | bytes32 | undefined | - -### poolInfo - -```solidity -function poolInfo(uint256) external view returns (uint128 accSynapsePerShare, uint64 lastRewardTime, uint64 allocPoint) -``` - -Info of each MCV2 pool. - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| _0 | uint256 | undefined | - -#### Returns - -| Name | Type | Description | -|---|---|---| -| accSynapsePerShare | uint128 | undefined | -| lastRewardTime | uint64 | undefined | -| allocPoint | uint64 | undefined | - -### poolLength - -```solidity -function poolLength() external view returns (uint256 pools) -``` - -Returns the number of MCV2 pools. - - - - -#### Returns - -| Name | Type | Description | -|---|---|---| -| pools | uint256 | undefined | - -### rewarder - -```solidity -function rewarder(uint256) external view returns (contract IRewarder) -``` - -Address of each `IRewarder` contract in MCV2. - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| _0 | uint256 | undefined | - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | contract IRewarder | undefined | - -### set - -```solidity -function set(uint256 _pid, uint256 _allocPoint, contract IRewarder _rewarder, bool overwrite) external nonpayable -``` - -Update the given pool's SYNAPSE allocation point and `IRewarder` contract. Can only be called by the owner. - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| _pid | uint256 | The index of the pool. See `poolInfo`. | -| _allocPoint | uint256 | New AP of the pool. | -| _rewarder | contract IRewarder | Address of the rewarder delegate. | -| overwrite | bool | True if _rewarder should be `set`. Otherwise `_rewarder` is ignored. | - -### setSynapsePerSecond - -```solidity -function setSynapsePerSecond(uint256 _synapsePerSecond) external nonpayable -``` - -Sets the synapse per second to be distributed. Can only be called by the owner. - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| _synapsePerSecond | uint256 | The amount of Synapse to be distributed per second. | - -### synapsePerSecond - -```solidity -function synapsePerSecond() external view returns (uint256) -``` - - - - - - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | uint256 | undefined | - -### totalAllocPoint - -```solidity -function totalAllocPoint() external view returns (uint256) -``` - - - -*Total allocation points. Must be the sum of all allocation points in all pools.* - - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | uint256 | undefined | - -### transferOwnership - -```solidity -function transferOwnership(address newOwner, bool direct, bool renounce) external nonpayable -``` - - - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| newOwner | address | undefined | -| direct | bool | undefined | -| renounce | bool | undefined | - -### updatePool - -```solidity -function updatePool(uint256 pid) external nonpayable returns (struct MiniChefV2.PoolInfo pool) -``` - -Update reward variables of the given pool. - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| pid | uint256 | The index of the pool. See `poolInfo`. | - -#### Returns - -| Name | Type | Description | -|---|---|---| -| pool | MiniChefV2.PoolInfo | Returns the pool that was updated. | - -### userInfo - -```solidity -function userInfo(uint256, address) external view returns (uint256 amount, int256 rewardDebt) -``` - -Info of each user that stakes LP tokens. - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| _0 | uint256 | undefined | -| _1 | address | undefined | - -#### Returns - -| Name | Type | Description | -|---|---|---| -| amount | uint256 | undefined | -| rewardDebt | int256 | undefined | - -### withdraw - -```solidity -function withdraw(uint256 pid, uint256 amount, address to) external nonpayable -``` - -Withdraw LP tokens from MCV2. - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| pid | uint256 | The index of the pool. See `poolInfo`. | -| amount | uint256 | LP token amount to withdraw. | -| to | address | Receiver of the LP tokens. | - -### withdrawAndHarvest - -```solidity -function withdrawAndHarvest(uint256 pid, uint256 amount, address to) external nonpayable -``` - -Withdraw LP tokens from MCV2 and harvest proceeds for transaction sender to `to`. - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| pid | uint256 | The index of the pool. See `poolInfo`. | -| amount | uint256 | LP token amount to withdraw. | -| to | address | Receiver of the LP tokens and SYNAPSE rewards. | - - - -## Events - -### Deposit - -```solidity -event Deposit(address indexed user, uint256 indexed pid, uint256 amount, address indexed to) -``` - - - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| user `indexed` | address | undefined | -| pid `indexed` | uint256 | undefined | -| amount | uint256 | undefined | -| to `indexed` | address | undefined | - -### EmergencyWithdraw - -```solidity -event EmergencyWithdraw(address indexed user, uint256 indexed pid, uint256 amount, address indexed to) -``` - - - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| user `indexed` | address | undefined | -| pid `indexed` | uint256 | undefined | -| amount | uint256 | undefined | -| to `indexed` | address | undefined | - -### Harvest - -```solidity -event Harvest(address indexed user, uint256 indexed pid, uint256 amount) -``` - - - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| user `indexed` | address | undefined | -| pid `indexed` | uint256 | undefined | -| amount | uint256 | undefined | - -### LogPoolAddition - -```solidity -event LogPoolAddition(uint256 indexed pid, uint256 allocPoint, contract IERC20 indexed lpToken, contract IRewarder indexed rewarder) -``` - - - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| pid `indexed` | uint256 | undefined | -| allocPoint | uint256 | undefined | -| lpToken `indexed` | contract IERC20 | undefined | -| rewarder `indexed` | contract IRewarder | undefined | - -### LogSetPool - -```solidity -event LogSetPool(uint256 indexed pid, uint256 allocPoint, contract IRewarder indexed rewarder, bool overwrite) -``` - - - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| pid `indexed` | uint256 | undefined | -| allocPoint | uint256 | undefined | -| rewarder `indexed` | contract IRewarder | undefined | -| overwrite | bool | undefined | - -### LogSynapsePerSecond - -```solidity -event LogSynapsePerSecond(uint256 synapsePerSecond) -``` - - - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| synapsePerSecond | uint256 | undefined | - -### LogUpdatePool - -```solidity -event LogUpdatePool(uint256 indexed pid, uint64 lastRewardTime, uint256 lpSupply, uint256 accSynapsePerShare) -``` - - - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| pid `indexed` | uint256 | undefined | -| lastRewardTime | uint64 | undefined | -| lpSupply | uint256 | undefined | -| accSynapsePerShare | uint256 | undefined | - -### OwnershipTransferred - -```solidity -event OwnershipTransferred(address indexed previousOwner, address indexed newOwner) -``` - - - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| previousOwner `indexed` | address | undefined | -| newOwner `indexed` | address | undefined | - -### Withdraw - -```solidity -event Withdraw(address indexed user, uint256 indexed pid, uint256 amount, address indexed to) -``` - - - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| user `indexed` | address | undefined | -| pid `indexed` | uint256 | undefined | -| amount | uint256 | undefined | -| to `indexed` | address | undefined | - - - diff --git a/docs/bridge/PoolConfig.md b/docs/bridge/PoolConfig.md deleted file mode 100644 index 1908e0007..000000000 --- a/docs/bridge/PoolConfig.md +++ /dev/null @@ -1,295 +0,0 @@ -# PoolConfig - - - - - - - - - -## Methods - -### BRIDGEMANAGER_ROLE - -```solidity -function BRIDGEMANAGER_ROLE() external view returns (bytes32) -``` - - - - - - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | bytes32 | undefined | - -### DEFAULT_ADMIN_ROLE - -```solidity -function DEFAULT_ADMIN_ROLE() external view returns (bytes32) -``` - - - - - - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | bytes32 | undefined | - -### getPoolConfig - -```solidity -function getPoolConfig(address tokenAddress, uint256 chainID) external view returns (struct PoolConfig.Pool) -``` - - - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| tokenAddress | address | undefined | -| chainID | uint256 | undefined | - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | PoolConfig.Pool | undefined | - -### getRoleAdmin - -```solidity -function getRoleAdmin(bytes32 role) external view returns (bytes32) -``` - - - -*Returns the admin role that controls `role`. See {grantRole} and {revokeRole}. To change a role's admin, use {_setRoleAdmin}.* - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| role | bytes32 | undefined | - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | bytes32 | undefined | - -### getRoleMember - -```solidity -function getRoleMember(bytes32 role, uint256 index) external view returns (address) -``` - - - -*Returns one of the accounts that have `role`. `index` must be a value between 0 and {getRoleMemberCount}, non-inclusive. Role bearers are not sorted in any particular way, and their ordering may change at any point. WARNING: When using {getRoleMember} and {getRoleMemberCount}, make sure you perform all queries on the same block. See the following https://forum.openzeppelin.com/t/iterating-over-elements-on-enumerableset-in-openzeppelin-contracts/2296[forum post] for more information.* - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| role | bytes32 | undefined | -| index | uint256 | undefined | - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | address | undefined | - -### getRoleMemberCount - -```solidity -function getRoleMemberCount(bytes32 role) external view returns (uint256) -``` - - - -*Returns the number of accounts that have `role`. Can be used together with {getRoleMember} to enumerate all bearers of a role.* - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| role | bytes32 | undefined | - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | uint256 | undefined | - -### grantRole - -```solidity -function grantRole(bytes32 role, address account) external nonpayable -``` - - - -*Grants `role` to `account`. If `account` had not been already granted `role`, emits a {RoleGranted} event. Requirements: - the caller must have ``role``'s admin role.* - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| role | bytes32 | undefined | -| account | address | undefined | - -### hasRole - -```solidity -function hasRole(bytes32 role, address account) external view returns (bool) -``` - - - -*Returns `true` if `account` has been granted `role`.* - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| role | bytes32 | undefined | -| account | address | undefined | - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | bool | undefined | - -### renounceRole - -```solidity -function renounceRole(bytes32 role, address account) external nonpayable -``` - - - -*Revokes `role` from the calling account. Roles are often managed via {grantRole} and {revokeRole}: this function's purpose is to provide a mechanism for accounts to lose their privileges if they are compromised (such as when a trusted device is misplaced). If the calling account had been granted `role`, emits a {RoleRevoked} event. Requirements: - the caller must be `account`.* - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| role | bytes32 | undefined | -| account | address | undefined | - -### revokeRole - -```solidity -function revokeRole(bytes32 role, address account) external nonpayable -``` - - - -*Revokes `role` from `account`. If `account` had been granted `role`, emits a {RoleRevoked} event. Requirements: - the caller must have ``role``'s admin role.* - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| role | bytes32 | undefined | -| account | address | undefined | - -### setPoolConfig - -```solidity -function setPoolConfig(address tokenAddress, uint256 chainID, address poolAddress, bool metaswap) external nonpayable returns (struct PoolConfig.Pool) -``` - - - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| tokenAddress | address | undefined | -| chainID | uint256 | undefined | -| poolAddress | address | undefined | -| metaswap | bool | undefined | - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | PoolConfig.Pool | undefined | - - - -## Events - -### RoleAdminChanged - -```solidity -event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole) -``` - - - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| role `indexed` | bytes32 | undefined | -| previousAdminRole `indexed` | bytes32 | undefined | -| newAdminRole `indexed` | bytes32 | undefined | - -### RoleGranted - -```solidity -event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender) -``` - - - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| role `indexed` | bytes32 | undefined | -| account `indexed` | address | undefined | -| sender `indexed` | address | undefined | - -### RoleRevoked - -```solidity -event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender) -``` - - - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| role `indexed` | bytes32 | undefined | -| account `indexed` | address | undefined | -| sender `indexed` | address | undefined | - - - diff --git a/docs/bridge/RateLimiter.md b/docs/bridge/RateLimiter.md deleted file mode 100644 index 4095ee02e..000000000 --- a/docs/bridge/RateLimiter.md +++ /dev/null @@ -1,521 +0,0 @@ -# RateLimiter - - - - - - - - - -## Methods - -### BRIDGE_ROLE - -```solidity -function BRIDGE_ROLE() external view returns (bytes32) -``` - - - - - - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | bytes32 | undefined | - -### DEFAULT_ADMIN_ROLE - -```solidity -function DEFAULT_ADMIN_ROLE() external view returns (bytes32) -``` - - - - - - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | bytes32 | undefined | - -### GOVERNANCE_ROLE - -```solidity -function GOVERNANCE_ROLE() external view returns (bytes32) -``` - - - - - - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | bytes32 | undefined | - -### LIMITER_ROLE - -```solidity -function LIMITER_ROLE() external view returns (bytes32) -``` - - - - - - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | bytes32 | undefined | - -### NAME - -```solidity -function NAME() external view returns (string) -``` - - - - - - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | string | undefined | - -### VERSION - -```solidity -function VERSION() external view returns (string) -``` - - - - - - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | string | undefined | - -### addToRetryQueue - -```solidity -function addToRetryQueue(bytes32 kappa, bytes rateLimited) external nonpayable -``` - - - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| kappa | bytes32 | undefined | -| rateLimited | bytes | undefined | - -### allowances - -```solidity -function allowances(address) external view returns (uint96 amount, uint96 spent, uint16 resetTimeMin, uint32 lastResetMin, bool initialized) -``` - - - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| _0 | address | undefined | - -#### Returns - -| Name | Type | Description | -|---|---|---| -| amount | uint96 | undefined | -| spent | uint96 | undefined | -| resetTimeMin | uint16 | undefined | -| lastResetMin | uint32 | undefined | -| initialized | bool | undefined | - -### checkAndUpdateAllowance - -```solidity -function checkAndUpdateAllowance(address token, uint256 amount) external nonpayable returns (bool) -``` - -Checks the allowance for a given token. If the new amount exceeds the allowance, it is not updated and false is returned otherwise true is returned and the transaction can proceed - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| token | address | undefined | -| amount | uint256 | to transfer* | - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | bool | undefined | - -### getRoleAdmin - -```solidity -function getRoleAdmin(bytes32 role) external view returns (bytes32) -``` - - - -*Returns the admin role that controls `role`. See {grantRole} and {revokeRole}. To change a role's admin, use {_setRoleAdmin}.* - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| role | bytes32 | undefined | - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | bytes32 | undefined | - -### getTokenAllowance - -```solidity -function getTokenAllowance(address token) external view returns (uint256[4]) -``` - - - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| token | address | undefined | - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | uint256[4] | undefined | - -### getTokens - -```solidity -function getTokens() external view returns (address[]) -``` - -Gets a list of tokens with allowances* - - - - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | address[] | undefined | - -### grantRole - -```solidity -function grantRole(bytes32 role, address account) external nonpayable -``` - - - -*Grants `role` to `account`. If `account` had not been already granted `role`, emits a {RoleGranted} event. Requirements: - the caller must have ``role``'s admin role.* - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| role | bytes32 | undefined | -| account | address | undefined | - -### hasRole - -```solidity -function hasRole(bytes32 role, address account) external view returns (bool) -``` - - - -*Returns `true` if `account` has been granted `role`.* - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| role | bytes32 | undefined | -| account | address | undefined | - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | bool | undefined | - -### initialize - -```solidity -function initialize() external nonpayable -``` - - - - - - -### limited - -```solidity -function limited(bytes32) external view returns (bytes) -``` - - - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| _0 | bytes32 | undefined | - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | bytes | undefined | - -### renounceRole - -```solidity -function renounceRole(bytes32 role, address account) external nonpayable -``` - - - -*Revokes `role` from the calling account. Roles are often managed via {grantRole} and {revokeRole}: this function's purpose is to provide a mechanism for accounts to lose their privileges if they are compromised (such as when a trusted device is misplaced). If the calling account had been revoked `role`, emits a {RoleRevoked} event. Requirements: - the caller must be `account`.* - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| role | bytes32 | undefined | -| account | address | undefined | - -### resetAllowance - -```solidity -function resetAllowance(address token) external nonpayable -``` - - - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| token | address | undefined | - -### revokeRole - -```solidity -function revokeRole(bytes32 role, address account) external nonpayable -``` - - - -*Revokes `role` from `account`. If `account` had been granted `role`, emits a {RoleRevoked} event. Requirements: - the caller must have ``role``'s admin role.* - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| role | bytes32 | undefined | -| account | address | undefined | - -### setAllowance - -```solidity -function setAllowance(address token, uint96 allowanceAmount, uint16 resetTimeMin, uint32 resetBaseMin) external nonpayable -``` - -Updates the allowance for a given token - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| token | address | to update the allowance for | -| allowanceAmount | uint96 | for the token | -| resetTimeMin | uint16 | minimum reset time (amount goes to 0 after this) | -| resetBaseMin | uint32 | amount Amount in native token decimals to transfer cross-chain pre-fees* | - -### supportsInterface - -```solidity -function supportsInterface(bytes4 interfaceId) external view returns (bool) -``` - - - -*See {IERC165-supportsInterface}.* - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| interfaceId | bytes4 | undefined | - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | bool | undefined | - -### tokens - -```solidity -function tokens(uint256) external view returns (address) -``` - - - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| _0 | uint256 | undefined | - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | address | undefined | - - - -## Events - -### ResetAllowance - -```solidity -event ResetAllowance(address indexed token) -``` - - - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| token `indexed` | address | undefined | - -### RoleAdminChanged - -```solidity -event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole) -``` - - - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| role `indexed` | bytes32 | undefined | -| previousAdminRole `indexed` | bytes32 | undefined | -| newAdminRole `indexed` | bytes32 | undefined | - -### RoleGranted - -```solidity -event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender) -``` - - - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| role `indexed` | bytes32 | undefined | -| account `indexed` | address | undefined | -| sender `indexed` | address | undefined | - -### RoleRevoked - -```solidity -event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender) -``` - - - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| role `indexed` | bytes32 | undefined | -| account `indexed` | address | undefined | -| sender `indexed` | address | undefined | - -### SetAllowance - -```solidity -event SetAllowance(address indexed token, uint96 allowanceAmount, uint16 resetTime) -``` - - - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| token `indexed` | address | undefined | -| allowanceAmount | uint96 | undefined | -| resetTime | uint16 | undefined | - - - diff --git a/docs/bridge/SynapseBridge.md b/docs/bridge/SynapseBridge.md deleted file mode 100644 index 99199b4ba..000000000 --- a/docs/bridge/SynapseBridge.md +++ /dev/null @@ -1,1001 +0,0 @@ -# SynapseBridge - - - - - - - - - -## Methods - -### DEFAULT_ADMIN_ROLE - -```solidity -function DEFAULT_ADMIN_ROLE() external view returns (bytes32) -``` - - - - - - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | bytes32 | undefined | - -### GOVERNANCE_ROLE - -```solidity -function GOVERNANCE_ROLE() external view returns (bytes32) -``` - - - - - - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | bytes32 | undefined | - -### NODEGROUP_ROLE - -```solidity -function NODEGROUP_ROLE() external view returns (bytes32) -``` - - - - - - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | bytes32 | undefined | - -### RATE_LIMITER_ROLE - -```solidity -function RATE_LIMITER_ROLE() external view returns (bytes32) -``` - - - - - - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | bytes32 | undefined | - -### WETH_ADDRESS - -```solidity -function WETH_ADDRESS() external view returns (address payable) -``` - - - - - - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | address payable | undefined | - -### addKappas - -```solidity -function addKappas(bytes32[] kappas) external nonpayable -``` - - - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| kappas | bytes32[] | undefined | - -### bridgeVersion - -```solidity -function bridgeVersion() external view returns (uint256) -``` - - - - - - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | uint256 | undefined | - -### chainGasAmount - -```solidity -function chainGasAmount() external view returns (uint256) -``` - - - - - - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | uint256 | undefined | - -### deposit - -```solidity -function deposit(address to, uint256 chainId, contract IERC20 token, uint256 amount) external nonpayable -``` - -Relays to nodes to transfers an ERC20 token cross-chain - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| to | address | address on other chain to bridge assets to | -| chainId | uint256 | which chain to bridge assets onto | -| token | contract IERC20 | ERC20 compatible token to deposit into the bridge | -| amount | uint256 | Amount in native token decimals to transfer cross-chain pre-fees* | - -### depositAndSwap - -```solidity -function depositAndSwap(address to, uint256 chainId, contract IERC20 token, uint256 amount, uint8 tokenIndexFrom, uint8 tokenIndexTo, uint256 minDy, uint256 deadline) external nonpayable -``` - -Relays to nodes to both transfer an ERC20 token cross-chain, and then have the nodes execute a swap through a liquidity pool on behalf of the user. - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| to | address | address on other chain to bridge assets to | -| chainId | uint256 | which chain to bridge assets onto | -| token | contract IERC20 | ERC20 compatible token to deposit into the bridge | -| amount | uint256 | Amount in native token decimals to transfer cross-chain pre-fees | -| tokenIndexFrom | uint8 | the token the user wants to swap from | -| tokenIndexTo | uint8 | the token the user wants to swap to | -| minDy | uint256 | the min amount the user would like to receive, or revert to only minting the SynERC20 token crosschain. | -| deadline | uint256 | latest timestamp to accept this transaction* | - -### getFeeBalance - -```solidity -function getFeeBalance(address tokenAddress) external view returns (uint256) -``` - - - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| tokenAddress | address | undefined | - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | uint256 | undefined | - -### getRoleAdmin - -```solidity -function getRoleAdmin(bytes32 role) external view returns (bytes32) -``` - - - -*Returns the admin role that controls `role`. See {grantRole} and {revokeRole}. To change a role's admin, use {_setRoleAdmin}.* - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| role | bytes32 | undefined | - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | bytes32 | undefined | - -### getRoleMember - -```solidity -function getRoleMember(bytes32 role, uint256 index) external view returns (address) -``` - - - -*Returns one of the accounts that have `role`. `index` must be a value between 0 and {getRoleMemberCount}, non-inclusive. Role bearers are not sorted in any particular way, and their ordering may change at any point. WARNING: When using {getRoleMember} and {getRoleMemberCount}, make sure you perform all queries on the same block. See the following https://forum.openzeppelin.com/t/iterating-over-elements-on-enumerableset-in-openzeppelin-contracts/2296[forum post] for more information.* - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| role | bytes32 | undefined | -| index | uint256 | undefined | - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | address | undefined | - -### getRoleMemberCount - -```solidity -function getRoleMemberCount(bytes32 role) external view returns (uint256) -``` - - - -*Returns the number of accounts that have `role`. Can be used together with {getRoleMember} to enumerate all bearers of a role.* - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| role | bytes32 | undefined | - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | uint256 | undefined | - -### grantRole - -```solidity -function grantRole(bytes32 role, address account) external nonpayable -``` - - - -*Grants `role` to `account`. If `account` had not been already granted `role`, emits a {RoleGranted} event. Requirements: - the caller must have ``role``'s admin role.* - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| role | bytes32 | undefined | -| account | address | undefined | - -### hasRole - -```solidity -function hasRole(bytes32 role, address account) external view returns (bool) -``` - - - -*Returns `true` if `account` has been granted `role`.* - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| role | bytes32 | undefined | -| account | address | undefined | - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | bool | undefined | - -### initialize - -```solidity -function initialize() external nonpayable -``` - - - - - - -### kappaExists - -```solidity -function kappaExists(bytes32 kappa) external view returns (bool) -``` - - - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| kappa | bytes32 | undefined | - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | bool | undefined | - -### mint - -```solidity -function mint(address payable to, contract IERC20Mintable token, uint256 amount, uint256 fee, bytes32 kappa) external nonpayable -``` - -Nodes call this function to mint a SynERC20 (or any asset that the bridge is given minter access to). This is called by the nodes after a TokenDeposit event is emitted. - -*This means the SynapseBridge.sol contract must have minter access to the token attempting to be minted* - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| to | address payable | address on other chain to redeem underlying assets to | -| token | contract IERC20Mintable | ERC20 compatible token to deposit into the bridge | -| amount | uint256 | Amount in native token decimals to transfer cross-chain post-fees | -| fee | uint256 | Amount in native token decimals to save to the contract as fees | -| kappa | bytes32 | kappa* | - -### mintAndSwap - -```solidity -function mintAndSwap(address payable to, contract IERC20Mintable token, uint256 amount, uint256 fee, contract ISwap pool, uint8 tokenIndexFrom, uint8 tokenIndexTo, uint256 minDy, uint256 deadline, bytes32 kappa) external nonpayable -``` - -Nodes call this function to mint a SynERC20 (or any asset that the bridge is given minter access to), and then attempt to swap the SynERC20 into the desired destination asset. This is called by the nodes after a TokenDepositAndSwap event is emitted. - -*This means the BridgeDeposit.sol contract must have minter access to the token attempting to be minted* - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| to | address payable | address on other chain to redeem underlying assets to | -| token | contract IERC20Mintable | ERC20 compatible token to deposit into the bridge | -| amount | uint256 | Amount in native token decimals to transfer cross-chain post-fees | -| fee | uint256 | Amount in native token decimals to save to the contract as fees | -| pool | contract ISwap | Destination chain's pool to use to swap SynERC20 -> Asset. The nodes determine this by using PoolConfig.sol. | -| tokenIndexFrom | uint8 | Index of the SynERC20 asset in the pool | -| tokenIndexTo | uint8 | Index of the desired final asset | -| minDy | uint256 | Minumum amount (in final asset decimals) that must be swapped for, otherwise the user will receive the SynERC20. | -| deadline | uint256 | Epoch time of the deadline that the swap is allowed to be executed. | -| kappa | bytes32 | kappa* | - -### pause - -```solidity -function pause() external nonpayable -``` - - - - - - -### paused - -```solidity -function paused() external view returns (bool) -``` - - - -*Returns true if the contract is paused, and false otherwise.* - - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | bool | undefined | - -### rateLimiter - -```solidity -function rateLimiter() external view returns (contract IRateLimiter) -``` - - - - - - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | contract IRateLimiter | undefined | - -### redeem - -```solidity -function redeem(address to, uint256 chainId, contract ERC20Burnable token, uint256 amount) external nonpayable -``` - -Relays to nodes that (typically) a wrapped synAsset ERC20 token has been burned and the underlying needs to be redeeemed on the native chain - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| to | address | address on other chain to redeem underlying assets to | -| chainId | uint256 | which underlying chain to bridge assets onto | -| token | contract ERC20Burnable | ERC20 compatible token to deposit into the bridge | -| amount | uint256 | Amount in native token decimals to transfer cross-chain pre-fees* | - -### redeemAndRemove - -```solidity -function redeemAndRemove(address to, uint256 chainId, contract ERC20Burnable token, uint256 amount, uint8 swapTokenIndex, uint256 swapMinAmount, uint256 swapDeadline) external nonpayable -``` - -Relays to nodes that (typically) a wrapped synAsset ERC20 token has been burned and the underlying needs to be redeeemed on the native chain. This function indicates to the nodes that they should attempt to redeem the LP token for the underlying assets (E.g "swap" out of the LP token) - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| to | address | address on other chain to redeem underlying assets to | -| chainId | uint256 | which underlying chain to bridge assets onto | -| token | contract ERC20Burnable | ERC20 compatible token to deposit into the bridge | -| amount | uint256 | Amount in native token decimals to transfer cross-chain pre-fees | -| swapTokenIndex | uint8 | Specifies which of the underlying LP assets the nodes should attempt to redeem for | -| swapMinAmount | uint256 | Specifies the minimum amount of the underlying asset needed for the nodes to execute the redeem/swap | -| swapDeadline | uint256 | Specificies the deadline that the nodes are allowed to try to redeem/swap the LP token* | - -### redeemAndSwap - -```solidity -function redeemAndSwap(address to, uint256 chainId, contract ERC20Burnable token, uint256 amount, uint8 tokenIndexFrom, uint8 tokenIndexTo, uint256 minDy, uint256 deadline) external nonpayable -``` - -Relays to nodes that (typically) a wrapped synAsset ERC20 token has been burned and the underlying needs to be redeeemed on the native chain. This function indicates to the nodes that they should attempt to redeem the LP token for the underlying assets (E.g "swap" out of the LP token) - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| to | address | address on other chain to redeem underlying assets to | -| chainId | uint256 | which underlying chain to bridge assets onto | -| token | contract ERC20Burnable | ERC20 compatible token to deposit into the bridge | -| amount | uint256 | Amount in native token decimals to transfer cross-chain pre-fees | -| tokenIndexFrom | uint8 | the token the user wants to swap from | -| tokenIndexTo | uint8 | the token the user wants to swap to | -| minDy | uint256 | the min amount the user would like to receive, or revert to only minting the SynERC20 token crosschain. | -| deadline | uint256 | latest timestamp to accept this transaction* | - -### redeemV2 - -```solidity -function redeemV2(bytes32 to, uint256 chainId, contract ERC20Burnable token, uint256 amount) external nonpayable -``` - -Relays to nodes that (typically) a wrapped synAsset ERC20 token has been burned and the underlying needs to be redeeemed on the native chain - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| to | bytes32 | address on other chain to redeem underlying assets to | -| chainId | uint256 | which underlying chain to bridge assets onto | -| token | contract ERC20Burnable | ERC20 compatible token to deposit into the bridge | -| amount | uint256 | Amount in native token decimals to transfer cross-chain pre-fees* | - -### renounceRole - -```solidity -function renounceRole(bytes32 role, address account) external nonpayable -``` - - - -*Revokes `role` from the calling account. Roles are often managed via {grantRole} and {revokeRole}: this function's purpose is to provide a mechanism for accounts to lose their privileges if they are compromised (such as when a trusted device is misplaced). If the calling account had been granted `role`, emits a {RoleRevoked} event. Requirements: - the caller must be `account`.* - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| role | bytes32 | undefined | -| account | address | undefined | - -### revokeRole - -```solidity -function revokeRole(bytes32 role, address account) external nonpayable -``` - - - -*Revokes `role` from `account`. If `account` had been granted `role`, emits a {RoleRevoked} event. Requirements: - the caller must have ``role``'s admin role.* - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| role | bytes32 | undefined | -| account | address | undefined | - -### setChainGasAmount - -```solidity -function setChainGasAmount(uint256 amount) external nonpayable -``` - - - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| amount | uint256 | undefined | - -### setRateLimiter - -```solidity -function setRateLimiter(contract IRateLimiter _rateLimiter) external nonpayable -``` - - - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| _rateLimiter | contract IRateLimiter | undefined | - -### setWethAddress - -```solidity -function setWethAddress(address payable _wethAddress) external nonpayable -``` - - - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| _wethAddress | address payable | undefined | - -### startBlockNumber - -```solidity -function startBlockNumber() external view returns (uint256) -``` - - - - - - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | uint256 | undefined | - -### unpause - -```solidity -function unpause() external nonpayable -``` - - - - - - -### withdraw - -```solidity -function withdraw(address to, contract IERC20 token, uint256 amount, uint256 fee, bytes32 kappa) external nonpayable -``` - -Function to be called by the node group to withdraw the underlying assets from the contract - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| to | address | address on chain to send underlying assets to | -| token | contract IERC20 | ERC20 compatible token to withdraw from the bridge | -| amount | uint256 | Amount in native token decimals to withdraw | -| fee | uint256 | Amount in native token decimals to save to the contract as fees | -| kappa | bytes32 | kappa* | - -### withdrawAndRemove - -```solidity -function withdrawAndRemove(address to, contract IERC20 token, uint256 amount, uint256 fee, contract ISwap pool, uint8 swapTokenIndex, uint256 swapMinAmount, uint256 swapDeadline, bytes32 kappa) external nonpayable -``` - -Function to be called by the node group to withdraw the underlying assets from the contract - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| to | address | address on chain to send underlying assets to | -| token | contract IERC20 | ERC20 compatible token to withdraw from the bridge | -| amount | uint256 | Amount in native token decimals to withdraw | -| fee | uint256 | Amount in native token decimals to save to the contract as fees | -| pool | contract ISwap | Destination chain's pool to use to swap SynERC20 -> Asset. The nodes determine this by using PoolConfig.sol. | -| swapTokenIndex | uint8 | Specifies which of the underlying LP assets the nodes should attempt to redeem for | -| swapMinAmount | uint256 | Specifies the minimum amount of the underlying asset needed for the nodes to execute the redeem/swap | -| swapDeadline | uint256 | Specificies the deadline that the nodes are allowed to try to redeem/swap the LP token | -| kappa | bytes32 | kappa* | - -### withdrawFees - -```solidity -function withdrawFees(contract IERC20 token, address to) external nonpayable -``` - -withdraw specified ERC20 token fees to a given address - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| token | contract IERC20 | ERC20 token in which fees acccumulated to transfer | -| to | address | Address to send the fees to | - - - -## Events - -### Paused - -```solidity -event Paused(address account) -``` - - - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| account | address | undefined | - -### RoleAdminChanged - -```solidity -event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole) -``` - - - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| role `indexed` | bytes32 | undefined | -| previousAdminRole `indexed` | bytes32 | undefined | -| newAdminRole `indexed` | bytes32 | undefined | - -### RoleGranted - -```solidity -event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender) -``` - - - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| role `indexed` | bytes32 | undefined | -| account `indexed` | address | undefined | -| sender `indexed` | address | undefined | - -### RoleRevoked - -```solidity -event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender) -``` - - - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| role `indexed` | bytes32 | undefined | -| account `indexed` | address | undefined | -| sender `indexed` | address | undefined | - -### TokenDeposit - -```solidity -event TokenDeposit(address indexed to, uint256 chainId, contract IERC20 token, uint256 amount) -``` - - - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| to `indexed` | address | undefined | -| chainId | uint256 | undefined | -| token | contract IERC20 | undefined | -| amount | uint256 | undefined | - -### TokenDepositAndSwap - -```solidity -event TokenDepositAndSwap(address indexed to, uint256 chainId, contract IERC20 token, uint256 amount, uint8 tokenIndexFrom, uint8 tokenIndexTo, uint256 minDy, uint256 deadline) -``` - - - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| to `indexed` | address | undefined | -| chainId | uint256 | undefined | -| token | contract IERC20 | undefined | -| amount | uint256 | undefined | -| tokenIndexFrom | uint8 | undefined | -| tokenIndexTo | uint8 | undefined | -| minDy | uint256 | undefined | -| deadline | uint256 | undefined | - -### TokenMint - -```solidity -event TokenMint(address indexed to, contract IERC20Mintable token, uint256 amount, uint256 fee, bytes32 indexed kappa) -``` - - - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| to `indexed` | address | undefined | -| token | contract IERC20Mintable | undefined | -| amount | uint256 | undefined | -| fee | uint256 | undefined | -| kappa `indexed` | bytes32 | undefined | - -### TokenMintAndSwap - -```solidity -event TokenMintAndSwap(address indexed to, contract IERC20Mintable token, uint256 amount, uint256 fee, uint8 tokenIndexFrom, uint8 tokenIndexTo, uint256 minDy, uint256 deadline, bool swapSuccess, bytes32 indexed kappa) -``` - - - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| to `indexed` | address | undefined | -| token | contract IERC20Mintable | undefined | -| amount | uint256 | undefined | -| fee | uint256 | undefined | -| tokenIndexFrom | uint8 | undefined | -| tokenIndexTo | uint8 | undefined | -| minDy | uint256 | undefined | -| deadline | uint256 | undefined | -| swapSuccess | bool | undefined | -| kappa `indexed` | bytes32 | undefined | - -### TokenRedeem - -```solidity -event TokenRedeem(address indexed to, uint256 chainId, contract IERC20 token, uint256 amount) -``` - - - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| to `indexed` | address | undefined | -| chainId | uint256 | undefined | -| token | contract IERC20 | undefined | -| amount | uint256 | undefined | - -### TokenRedeemAndRemove - -```solidity -event TokenRedeemAndRemove(address indexed to, uint256 chainId, contract IERC20 token, uint256 amount, uint8 swapTokenIndex, uint256 swapMinAmount, uint256 swapDeadline) -``` - - - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| to `indexed` | address | undefined | -| chainId | uint256 | undefined | -| token | contract IERC20 | undefined | -| amount | uint256 | undefined | -| swapTokenIndex | uint8 | undefined | -| swapMinAmount | uint256 | undefined | -| swapDeadline | uint256 | undefined | - -### TokenRedeemAndSwap - -```solidity -event TokenRedeemAndSwap(address indexed to, uint256 chainId, contract IERC20 token, uint256 amount, uint8 tokenIndexFrom, uint8 tokenIndexTo, uint256 minDy, uint256 deadline) -``` - - - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| to `indexed` | address | undefined | -| chainId | uint256 | undefined | -| token | contract IERC20 | undefined | -| amount | uint256 | undefined | -| tokenIndexFrom | uint8 | undefined | -| tokenIndexTo | uint8 | undefined | -| minDy | uint256 | undefined | -| deadline | uint256 | undefined | - -### TokenRedeemV2 - -```solidity -event TokenRedeemV2(bytes32 indexed to, uint256 chainId, contract IERC20 token, uint256 amount) -``` - - - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| to `indexed` | bytes32 | undefined | -| chainId | uint256 | undefined | -| token | contract IERC20 | undefined | -| amount | uint256 | undefined | - -### TokenWithdraw - -```solidity -event TokenWithdraw(address indexed to, contract IERC20 token, uint256 amount, uint256 fee, bytes32 indexed kappa) -``` - - - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| to `indexed` | address | undefined | -| token | contract IERC20 | undefined | -| amount | uint256 | undefined | -| fee | uint256 | undefined | -| kappa `indexed` | bytes32 | undefined | - -### TokenWithdrawAndRemove - -```solidity -event TokenWithdrawAndRemove(address indexed to, contract IERC20 token, uint256 amount, uint256 fee, uint8 swapTokenIndex, uint256 swapMinAmount, uint256 swapDeadline, bool swapSuccess, bytes32 indexed kappa) -``` - - - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| to `indexed` | address | undefined | -| token | contract IERC20 | undefined | -| amount | uint256 | undefined | -| fee | uint256 | undefined | -| swapTokenIndex | uint8 | undefined | -| swapMinAmount | uint256 | undefined | -| swapDeadline | uint256 | undefined | -| swapSuccess | bool | undefined | -| kappa `indexed` | bytes32 | undefined | - -### Unpaused - -```solidity -event Unpaused(address account) -``` - - - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| account | address | undefined | - - - diff --git a/docs/bridge/SynapseERC20.md b/docs/bridge/SynapseERC20.md deleted file mode 100644 index 9dcacc92d..000000000 --- a/docs/bridge/SynapseERC20.md +++ /dev/null @@ -1,642 +0,0 @@ -# SynapseERC20 - - - - - - - - - -## Methods - -### DEFAULT_ADMIN_ROLE - -```solidity -function DEFAULT_ADMIN_ROLE() external view returns (bytes32) -``` - - - - - - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | bytes32 | undefined | - -### DOMAIN_SEPARATOR - -```solidity -function DOMAIN_SEPARATOR() external view returns (bytes32) -``` - - - -*See {IERC20Permit-DOMAIN_SEPARATOR}.* - - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | bytes32 | undefined | - -### MINTER_ROLE - -```solidity -function MINTER_ROLE() external view returns (bytes32) -``` - - - - - - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | bytes32 | undefined | - -### allowance - -```solidity -function allowance(address owner, address spender) external view returns (uint256) -``` - - - -*See {IERC20-allowance}.* - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| owner | address | undefined | -| spender | address | undefined | - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | uint256 | undefined | - -### approve - -```solidity -function approve(address spender, uint256 amount) external nonpayable returns (bool) -``` - - - -*See {IERC20-approve}. Requirements: - `spender` cannot be the zero address.* - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| spender | address | undefined | -| amount | uint256 | undefined | - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | bool | undefined | - -### balanceOf - -```solidity -function balanceOf(address account) external view returns (uint256) -``` - - - -*See {IERC20-balanceOf}.* - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| account | address | undefined | - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | uint256 | undefined | - -### burn - -```solidity -function burn(uint256 amount) external nonpayable -``` - - - -*Destroys `amount` tokens from the caller. See {ERC20-_burn}.* - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| amount | uint256 | undefined | - -### burnFrom - -```solidity -function burnFrom(address account, uint256 amount) external nonpayable -``` - - - -*Destroys `amount` tokens from `account`, deducting from the caller's allowance. See {ERC20-_burn} and {ERC20-allowance}. Requirements: - the caller must have allowance for ``accounts``'s tokens of at least `amount`.* - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| account | address | undefined | -| amount | uint256 | undefined | - -### decimals - -```solidity -function decimals() external view returns (uint8) -``` - - - -*Returns the number of decimals used to get its user representation. For example, if `decimals` equals `2`, a balance of `505` tokens should be displayed to a user as `5,05` (`505 / 10 ** 2`). Tokens usually opt for a value of 18, imitating the relationship between Ether and Wei. This is the value {ERC20} uses, unless {_setupDecimals} is called. NOTE: This information is only used for _display_ purposes: it in no way affects any of the arithmetic of the contract, including {IERC20-balanceOf} and {IERC20-transfer}.* - - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | uint8 | undefined | - -### decreaseAllowance - -```solidity -function decreaseAllowance(address spender, uint256 subtractedValue) external nonpayable returns (bool) -``` - - - -*Atomically decreases the allowance granted to `spender` by the caller. This is an alternative to {approve} that can be used as a mitigation for problems described in {IERC20-approve}. Emits an {Approval} event indicating the updated allowance. Requirements: - `spender` cannot be the zero address. - `spender` must have allowance for the caller of at least `subtractedValue`.* - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| spender | address | undefined | -| subtractedValue | uint256 | undefined | - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | bool | undefined | - -### getRoleAdmin - -```solidity -function getRoleAdmin(bytes32 role) external view returns (bytes32) -``` - - - -*Returns the admin role that controls `role`. See {grantRole} and {revokeRole}. To change a role's admin, use {_setRoleAdmin}.* - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| role | bytes32 | undefined | - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | bytes32 | undefined | - -### getRoleMember - -```solidity -function getRoleMember(bytes32 role, uint256 index) external view returns (address) -``` - - - -*Returns one of the accounts that have `role`. `index` must be a value between 0 and {getRoleMemberCount}, non-inclusive. Role bearers are not sorted in any particular way, and their ordering may change at any point. WARNING: When using {getRoleMember} and {getRoleMemberCount}, make sure you perform all queries on the same block. See the following https://forum.openzeppelin.com/t/iterating-over-elements-on-enumerableset-in-openzeppelin-contracts/2296[forum post] for more information.* - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| role | bytes32 | undefined | -| index | uint256 | undefined | - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | address | undefined | - -### getRoleMemberCount - -```solidity -function getRoleMemberCount(bytes32 role) external view returns (uint256) -``` - - - -*Returns the number of accounts that have `role`. Can be used together with {getRoleMember} to enumerate all bearers of a role.* - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| role | bytes32 | undefined | - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | uint256 | undefined | - -### grantRole - -```solidity -function grantRole(bytes32 role, address account) external nonpayable -``` - - - -*Grants `role` to `account`. If `account` had not been already granted `role`, emits a {RoleGranted} event. Requirements: - the caller must have ``role``'s admin role.* - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| role | bytes32 | undefined | -| account | address | undefined | - -### hasRole - -```solidity -function hasRole(bytes32 role, address account) external view returns (bool) -``` - - - -*Returns `true` if `account` has been granted `role`.* - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| role | bytes32 | undefined | -| account | address | undefined | - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | bool | undefined | - -### increaseAllowance - -```solidity -function increaseAllowance(address spender, uint256 addedValue) external nonpayable returns (bool) -``` - - - -*Atomically increases the allowance granted to `spender` by the caller. This is an alternative to {approve} that can be used as a mitigation for problems described in {IERC20-approve}. Emits an {Approval} event indicating the updated allowance. Requirements: - `spender` cannot be the zero address.* - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| spender | address | undefined | -| addedValue | uint256 | undefined | - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | bool | undefined | - -### initialize - -```solidity -function initialize(string name, string symbol, uint8 decimals, address owner) external nonpayable -``` - -Initializes this ERC20 contract with the given parameters. - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| name | string | Token name | -| symbol | string | Token symbol | -| decimals | uint8 | Token name | -| owner | address | admin address to be initialized with | - -### mint - -```solidity -function mint(address to, uint256 amount) external nonpayable -``` - - - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| to | address | undefined | -| amount | uint256 | undefined | - -### name - -```solidity -function name() external view returns (string) -``` - - - -*Returns the name of the token.* - - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | string | undefined | - -### nonces - -```solidity -function nonces(address owner) external view returns (uint256) -``` - - - -*See {IERC20Permit-nonces}.* - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| owner | address | undefined | - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | uint256 | undefined | - -### permit - -```solidity -function permit(address owner, address spender, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s) external nonpayable -``` - - - -*See {IERC20Permit-permit}.* - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| owner | address | undefined | -| spender | address | undefined | -| value | uint256 | undefined | -| deadline | uint256 | undefined | -| v | uint8 | undefined | -| r | bytes32 | undefined | -| s | bytes32 | undefined | - -### renounceRole - -```solidity -function renounceRole(bytes32 role, address account) external nonpayable -``` - - - -*Revokes `role` from the calling account. Roles are often managed via {grantRole} and {revokeRole}: this function's purpose is to provide a mechanism for accounts to lose their privileges if they are compromised (such as when a trusted device is misplaced). If the calling account had been granted `role`, emits a {RoleRevoked} event. Requirements: - the caller must be `account`.* - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| role | bytes32 | undefined | -| account | address | undefined | - -### revokeRole - -```solidity -function revokeRole(bytes32 role, address account) external nonpayable -``` - - - -*Revokes `role` from `account`. If `account` had been granted `role`, emits a {RoleRevoked} event. Requirements: - the caller must have ``role``'s admin role.* - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| role | bytes32 | undefined | -| account | address | undefined | - -### symbol - -```solidity -function symbol() external view returns (string) -``` - - - -*Returns the symbol of the token, usually a shorter version of the name.* - - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | string | undefined | - -### totalSupply - -```solidity -function totalSupply() external view returns (uint256) -``` - - - -*See {IERC20-totalSupply}.* - - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | uint256 | undefined | - -### transfer - -```solidity -function transfer(address recipient, uint256 amount) external nonpayable returns (bool) -``` - - - -*See {IERC20-transfer}. Requirements: - `recipient` cannot be the zero address. - the caller must have a balance of at least `amount`.* - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| recipient | address | undefined | -| amount | uint256 | undefined | - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | bool | undefined | - -### transferFrom - -```solidity -function transferFrom(address sender, address recipient, uint256 amount) external nonpayable returns (bool) -``` - - - -*See {IERC20-transferFrom}. Emits an {Approval} event indicating the updated allowance. This is not required by the EIP. See the note at the beginning of {ERC20}. Requirements: - `sender` and `recipient` cannot be the zero address. - `sender` must have a balance of at least `amount`. - the caller must have allowance for ``sender``'s tokens of at least `amount`.* - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| sender | address | undefined | -| recipient | address | undefined | -| amount | uint256 | undefined | - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | bool | undefined | - - - -## Events - -### Approval - -```solidity -event Approval(address indexed owner, address indexed spender, uint256 value) -``` - - - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| owner `indexed` | address | undefined | -| spender `indexed` | address | undefined | -| value | uint256 | undefined | - -### RoleAdminChanged - -```solidity -event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole) -``` - - - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| role `indexed` | bytes32 | undefined | -| previousAdminRole `indexed` | bytes32 | undefined | -| newAdminRole `indexed` | bytes32 | undefined | - -### RoleGranted - -```solidity -event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender) -``` - - - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| role `indexed` | bytes32 | undefined | -| account `indexed` | address | undefined | -| sender `indexed` | address | undefined | - -### RoleRevoked - -```solidity -event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender) -``` - - - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| role `indexed` | bytes32 | undefined | -| account `indexed` | address | undefined | -| sender `indexed` | address | undefined | - -### Transfer - -```solidity -event Transfer(address indexed from, address indexed to, uint256 value) -``` - - - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| from `indexed` | address | undefined | -| to `indexed` | address | undefined | -| value | uint256 | undefined | - - - diff --git a/docs/bridge/SynapseERC20Factory.md b/docs/bridge/SynapseERC20Factory.md deleted file mode 100644 index ce8675072..000000000 --- a/docs/bridge/SynapseERC20Factory.md +++ /dev/null @@ -1,60 +0,0 @@ -# SynapseERC20Factory - - - - - - - - - -## Methods - -### deploy - -```solidity -function deploy(address synapseERC20Address, string name, string symbol, uint8 decimals, address owner) external nonpayable returns (address) -``` - -Deploys a new node - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| synapseERC20Address | address | address of the synapseERC20Address contract to initialize with | -| name | string | Token name | -| symbol | string | Token symbol | -| decimals | uint8 | Token name | -| owner | address | admin address to be initialized with | - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | address | Address of the newest node management contract created* | - - - -## Events - -### SynapseERC20Created - -```solidity -event SynapseERC20Created(address contractAddress) -``` - - - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| contractAddress | address | undefined | - - - diff --git a/docs/bridge/interfaces/IECDSANodeManagement.md b/docs/bridge/interfaces/IECDSANodeManagement.md deleted file mode 100644 index 40881554b..000000000 --- a/docs/bridge/interfaces/IECDSANodeManagement.md +++ /dev/null @@ -1,33 +0,0 @@ -# IECDSANodeManagement - - - -> IECDSANodeManagement interface - -Interface for the ECDSA node management interface. - -*implement this interface to develop a a factory-patterned ECDSA node management contract** - -## Methods - -### initialize - -```solidity -function initialize(address _owner, address[] _members, uint256 _honestThreshold) external nonpayable -``` - - - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| _owner | address | undefined | -| _members | address[] | undefined | -| _honestThreshold | uint256 | undefined | - - - - diff --git a/docs/bridge/interfaces/IERC20Migrator.md b/docs/bridge/interfaces/IERC20Migrator.md deleted file mode 100644 index f9f4823d7..000000000 --- a/docs/bridge/interfaces/IERC20Migrator.md +++ /dev/null @@ -1,31 +0,0 @@ -# IERC20Migrator - - - - - - - - - -## Methods - -### migrate - -```solidity -function migrate(uint256 amount) external nonpayable -``` - - - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| amount | uint256 | undefined | - - - - diff --git a/docs/bridge/interfaces/IMasterChef.md b/docs/bridge/interfaces/IMasterChef.md deleted file mode 100644 index e4729ac41..000000000 --- a/docs/bridge/interfaces/IMasterChef.md +++ /dev/null @@ -1,71 +0,0 @@ -# IMasterChef - - - - - - - - - -## Methods - -### deposit - -```solidity -function deposit(uint256 _pid, uint256 _amount) external nonpayable -``` - - - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| _pid | uint256 | undefined | -| _amount | uint256 | undefined | - -### poolInfo - -```solidity -function poolInfo(uint256 pid) external view returns (struct IMasterChef.PoolInfo) -``` - - - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| pid | uint256 | undefined | - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | IMasterChef.PoolInfo | undefined | - -### totalAllocPoint - -```solidity -function totalAllocPoint() external view returns (uint256) -``` - - - - - - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | uint256 | undefined | - - - - diff --git a/docs/bridge/interfaces/IMetaSwapDeposit.md b/docs/bridge/interfaces/IMetaSwapDeposit.md deleted file mode 100644 index e2c7fe126..000000000 --- a/docs/bridge/interfaces/IMetaSwapDeposit.md +++ /dev/null @@ -1,87 +0,0 @@ -# IMetaSwapDeposit - - - -> IMetaSwapDeposit interface - -Interface for the meta swap contract. - -*implement this interface to develop a a factory-patterned ECDSA node management contract** - -## Methods - -### calculateSwap - -```solidity -function calculateSwap(uint8 tokenIndexFrom, uint8 tokenIndexTo, uint256 dx) external view returns (uint256) -``` - - - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| tokenIndexFrom | uint8 | undefined | -| tokenIndexTo | uint8 | undefined | -| dx | uint256 | undefined | - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | uint256 | undefined | - -### getToken - -```solidity -function getToken(uint256 index) external view returns (contract IERC20) -``` - - - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| index | uint256 | undefined | - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | contract IERC20 | undefined | - -### swap - -```solidity -function swap(uint8 tokenIndexFrom, uint8 tokenIndexTo, uint256 dx, uint256 minDy, uint256 deadline) external nonpayable returns (uint256) -``` - - - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| tokenIndexFrom | uint8 | undefined | -| tokenIndexTo | uint8 | undefined | -| dx | uint256 | undefined | -| minDy | uint256 | undefined | -| deadline | uint256 | undefined | - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | uint256 | undefined | - - - - diff --git a/docs/bridge/interfaces/IMiniChefV2.md b/docs/bridge/interfaces/IMiniChefV2.md deleted file mode 100644 index 5e5649f64..000000000 --- a/docs/bridge/interfaces/IMiniChefV2.md +++ /dev/null @@ -1,166 +0,0 @@ -# IMiniChefV2 - - - - - - - - - -## Methods - -### deposit - -```solidity -function deposit(uint256 pid, uint256 amount, address to) external nonpayable -``` - - - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| pid | uint256 | undefined | -| amount | uint256 | undefined | -| to | address | undefined | - -### emergencyWithdraw - -```solidity -function emergencyWithdraw(uint256 pid, address to) external nonpayable -``` - - - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| pid | uint256 | undefined | -| to | address | undefined | - -### harvest - -```solidity -function harvest(uint256 pid, address to) external nonpayable -``` - - - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| pid | uint256 | undefined | -| to | address | undefined | - -### poolLength - -```solidity -function poolLength() external view returns (uint256) -``` - - - - - - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | uint256 | undefined | - -### updatePool - -```solidity -function updatePool(uint256 pid) external nonpayable returns (struct IMiniChefV2.PoolInfo) -``` - - - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| pid | uint256 | undefined | - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | IMiniChefV2.PoolInfo | undefined | - -### userInfo - -```solidity -function userInfo(uint256 _pid, address _user) external view returns (uint256, uint256) -``` - - - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| _pid | uint256 | undefined | -| _user | address | undefined | - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | uint256 | undefined | -| _1 | uint256 | undefined | - -### withdraw - -```solidity -function withdraw(uint256 pid, uint256 amount, address to) external nonpayable -``` - - - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| pid | uint256 | undefined | -| amount | uint256 | undefined | -| to | address | undefined | - -### withdrawAndHarvest - -```solidity -function withdrawAndHarvest(uint256 pid, uint256 amount, address to) external nonpayable -``` - - - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| pid | uint256 | undefined | -| amount | uint256 | undefined | -| to | address | undefined | - - - - diff --git a/docs/bridge/interfaces/IRateLimiter.md b/docs/bridge/interfaces/IRateLimiter.md deleted file mode 100644 index af17d1249..000000000 --- a/docs/bridge/interfaces/IRateLimiter.md +++ /dev/null @@ -1,55 +0,0 @@ -# IRateLimiter - - - - - - - - - -## Methods - -### addToRetryQueue - -```solidity -function addToRetryQueue(bytes32 kappa, bytes rateLimited) external nonpayable -``` - - - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| kappa | bytes32 | undefined | -| rateLimited | bytes | undefined | - -### checkAndUpdateAllowance - -```solidity -function checkAndUpdateAllowance(address token, uint256 amount) external nonpayable returns (bool) -``` - - - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| token | address | undefined | -| amount | uint256 | undefined | - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | bool | undefined | - - - - diff --git a/docs/bridge/interfaces/IRewarder.md b/docs/bridge/interfaces/IRewarder.md deleted file mode 100644 index 77ae30edf..000000000 --- a/docs/bridge/interfaces/IRewarder.md +++ /dev/null @@ -1,60 +0,0 @@ -# IRewarder - - - - - - - - - -## Methods - -### onSynapseReward - -```solidity -function onSynapseReward(uint256 pid, address user, address recipient, uint256 synapseAmount, uint256 newLpAmount) external nonpayable -``` - - - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| pid | uint256 | undefined | -| user | address | undefined | -| recipient | address | undefined | -| synapseAmount | uint256 | undefined | -| newLpAmount | uint256 | undefined | - -### pendingTokens - -```solidity -function pendingTokens(uint256 pid, address user, uint256 synapseAmount) external view returns (contract IERC20[], uint256[]) -``` - - - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| pid | uint256 | undefined | -| user | address | undefined | -| synapseAmount | uint256 | undefined | - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | contract IERC20[] | undefined | -| _1 | uint256[] | undefined | - - - - diff --git a/docs/bridge/interfaces/ISwap.md b/docs/bridge/interfaces/ISwap.md deleted file mode 100644 index 46ee3b5ae..000000000 --- a/docs/bridge/interfaces/ISwap.md +++ /dev/null @@ -1,353 +0,0 @@ -# ISwap - - - - - - - - - -## Methods - -### addLiquidity - -```solidity -function addLiquidity(uint256[] amounts, uint256 minToMint, uint256 deadline) external nonpayable returns (uint256) -``` - - - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| amounts | uint256[] | undefined | -| minToMint | uint256 | undefined | -| deadline | uint256 | undefined | - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | uint256 | undefined | - -### calculateRemoveLiquidity - -```solidity -function calculateRemoveLiquidity(uint256 amount) external view returns (uint256[]) -``` - - - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| amount | uint256 | undefined | - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | uint256[] | undefined | - -### calculateRemoveLiquidityOneToken - -```solidity -function calculateRemoveLiquidityOneToken(uint256 tokenAmount, uint8 tokenIndex) external view returns (uint256 availableTokenAmount) -``` - - - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| tokenAmount | uint256 | undefined | -| tokenIndex | uint8 | undefined | - -#### Returns - -| Name | Type | Description | -|---|---|---| -| availableTokenAmount | uint256 | undefined | - -### calculateSwap - -```solidity -function calculateSwap(uint8 tokenIndexFrom, uint8 tokenIndexTo, uint256 dx) external view returns (uint256) -``` - - - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| tokenIndexFrom | uint8 | undefined | -| tokenIndexTo | uint8 | undefined | -| dx | uint256 | undefined | - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | uint256 | undefined | - -### calculateTokenAmount - -```solidity -function calculateTokenAmount(uint256[] amounts, bool deposit) external view returns (uint256) -``` - - - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| amounts | uint256[] | undefined | -| deposit | bool | undefined | - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | uint256 | undefined | - -### getA - -```solidity -function getA() external view returns (uint256) -``` - - - - - - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | uint256 | undefined | - -### getToken - -```solidity -function getToken(uint8 index) external view returns (contract IERC20) -``` - - - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| index | uint8 | undefined | - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | contract IERC20 | undefined | - -### getTokenBalance - -```solidity -function getTokenBalance(uint8 index) external view returns (uint256) -``` - - - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| index | uint8 | undefined | - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | uint256 | undefined | - -### getTokenIndex - -```solidity -function getTokenIndex(address tokenAddress) external view returns (uint8) -``` - - - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| tokenAddress | address | undefined | - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | uint8 | undefined | - -### getVirtualPrice - -```solidity -function getVirtualPrice() external view returns (uint256) -``` - - - - - - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | uint256 | undefined | - -### initialize - -```solidity -function initialize(contract IERC20[] pooledTokens, uint8[] decimals, string lpTokenName, string lpTokenSymbol, uint256 a, uint256 fee, uint256 adminFee, address lpTokenTargetAddress) external nonpayable -``` - - - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| pooledTokens | contract IERC20[] | undefined | -| decimals | uint8[] | undefined | -| lpTokenName | string | undefined | -| lpTokenSymbol | string | undefined | -| a | uint256 | undefined | -| fee | uint256 | undefined | -| adminFee | uint256 | undefined | -| lpTokenTargetAddress | address | undefined | - -### removeLiquidity - -```solidity -function removeLiquidity(uint256 amount, uint256[] minAmounts, uint256 deadline) external nonpayable returns (uint256[]) -``` - - - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| amount | uint256 | undefined | -| minAmounts | uint256[] | undefined | -| deadline | uint256 | undefined | - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | uint256[] | undefined | - -### removeLiquidityImbalance - -```solidity -function removeLiquidityImbalance(uint256[] amounts, uint256 maxBurnAmount, uint256 deadline) external nonpayable returns (uint256) -``` - - - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| amounts | uint256[] | undefined | -| maxBurnAmount | uint256 | undefined | -| deadline | uint256 | undefined | - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | uint256 | undefined | - -### removeLiquidityOneToken - -```solidity -function removeLiquidityOneToken(uint256 tokenAmount, uint8 tokenIndex, uint256 minAmount, uint256 deadline) external nonpayable returns (uint256) -``` - - - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| tokenAmount | uint256 | undefined | -| tokenIndex | uint8 | undefined | -| minAmount | uint256 | undefined | -| deadline | uint256 | undefined | - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | uint256 | undefined | - -### swap - -```solidity -function swap(uint8 tokenIndexFrom, uint8 tokenIndexTo, uint256 dx, uint256 minDy, uint256 deadline) external nonpayable returns (uint256) -``` - - - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| tokenIndexFrom | uint8 | undefined | -| tokenIndexTo | uint8 | undefined | -| dx | uint256 | undefined | -| minDy | uint256 | undefined | -| deadline | uint256 | undefined | - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | uint256 | undefined | - - - - diff --git a/docs/bridge/interfaces/ISynapseBridge.md b/docs/bridge/interfaces/ISynapseBridge.md deleted file mode 100644 index 922006dfd..000000000 --- a/docs/bridge/interfaces/ISynapseBridge.md +++ /dev/null @@ -1,140 +0,0 @@ -# ISynapseBridge - - - - - - - - - -## Methods - -### deposit - -```solidity -function deposit(address to, uint256 chainId, contract IERC20 token, uint256 amount) external nonpayable -``` - - - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| to | address | undefined | -| chainId | uint256 | undefined | -| token | contract IERC20 | undefined | -| amount | uint256 | undefined | - -### depositAndSwap - -```solidity -function depositAndSwap(address to, uint256 chainId, contract IERC20 token, uint256 amount, uint8 tokenIndexFrom, uint8 tokenIndexTo, uint256 minDy, uint256 deadline) external nonpayable -``` - - - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| to | address | undefined | -| chainId | uint256 | undefined | -| token | contract IERC20 | undefined | -| amount | uint256 | undefined | -| tokenIndexFrom | uint8 | undefined | -| tokenIndexTo | uint8 | undefined | -| minDy | uint256 | undefined | -| deadline | uint256 | undefined | - -### redeem - -```solidity -function redeem(address to, uint256 chainId, contract IERC20 token, uint256 amount) external nonpayable -``` - - - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| to | address | undefined | -| chainId | uint256 | undefined | -| token | contract IERC20 | undefined | -| amount | uint256 | undefined | - -### redeemAndRemove - -```solidity -function redeemAndRemove(address to, uint256 chainId, contract IERC20 token, uint256 amount, uint8 liqTokenIndex, uint256 liqMinAmount, uint256 liqDeadline) external nonpayable -``` - - - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| to | address | undefined | -| chainId | uint256 | undefined | -| token | contract IERC20 | undefined | -| amount | uint256 | undefined | -| liqTokenIndex | uint8 | undefined | -| liqMinAmount | uint256 | undefined | -| liqDeadline | uint256 | undefined | - -### redeemAndSwap - -```solidity -function redeemAndSwap(address to, uint256 chainId, contract IERC20 token, uint256 amount, uint8 tokenIndexFrom, uint8 tokenIndexTo, uint256 minDy, uint256 deadline) external nonpayable -``` - - - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| to | address | undefined | -| chainId | uint256 | undefined | -| token | contract IERC20 | undefined | -| amount | uint256 | undefined | -| tokenIndexFrom | uint8 | undefined | -| tokenIndexTo | uint8 | undefined | -| minDy | uint256 | undefined | -| deadline | uint256 | undefined | - -### redeemv2 - -```solidity -function redeemv2(bytes32 to, uint256 chainId, contract IERC20 token, uint256 amount) external nonpayable -``` - - - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| to | bytes32 | undefined | -| chainId | uint256 | undefined | -| token | contract IERC20 | undefined | -| amount | uint256 | undefined | - - - - diff --git a/docs/bridge/interfaces/ISynapseERC20.md b/docs/bridge/interfaces/ISynapseERC20.md deleted file mode 100644 index 2d281f8a2..000000000 --- a/docs/bridge/interfaces/ISynapseERC20.md +++ /dev/null @@ -1,51 +0,0 @@ -# ISynapseERC20 - - - - - - - - - -## Methods - -### initialize - -```solidity -function initialize(string _name, string _symbol, uint8 _decimals, address owner) external nonpayable -``` - - - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| _name | string | undefined | -| _symbol | string | undefined | -| _decimals | uint8 | undefined | -| owner | address | undefined | - -### mint - -```solidity -function mint(address to, uint256 amount) external nonpayable -``` - - - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| to | address | undefined | -| amount | uint256 | undefined | - - - - diff --git a/docs/bridge/libraries/SignedSafeMath.md b/docs/bridge/libraries/SignedSafeMath.md deleted file mode 100644 index 3a931c0b2..000000000 --- a/docs/bridge/libraries/SignedSafeMath.md +++ /dev/null @@ -1,12 +0,0 @@ -# SignedSafeMath - - - - - - - - - - - diff --git a/docs/bridge/mocks/ERC20Mock.md b/docs/bridge/mocks/ERC20Mock.md deleted file mode 100644 index 156f0bf2a..000000000 --- a/docs/bridge/mocks/ERC20Mock.md +++ /dev/null @@ -1,300 +0,0 @@ -# ERC20Mock - - - - - - - - - -## Methods - -### allowance - -```solidity -function allowance(address owner, address spender) external view returns (uint256) -``` - - - -*See {IERC20-allowance}.* - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| owner | address | undefined | -| spender | address | undefined | - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | uint256 | undefined | - -### approve - -```solidity -function approve(address spender, uint256 amount) external nonpayable returns (bool) -``` - - - -*See {IERC20-approve}. Requirements: - `spender` cannot be the zero address.* - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| spender | address | undefined | -| amount | uint256 | undefined | - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | bool | undefined | - -### balanceOf - -```solidity -function balanceOf(address account) external view returns (uint256) -``` - - - -*See {IERC20-balanceOf}.* - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| account | address | undefined | - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | uint256 | undefined | - -### decimals - -```solidity -function decimals() external view returns (uint8) -``` - - - -*Returns the number of decimals used to get its user representation. For example, if `decimals` equals `2`, a balance of `505` tokens should be displayed to a user as `5,05` (`505 / 10 ** 2`). Tokens usually opt for a value of 18, imitating the relationship between Ether and Wei. This is the value {ERC20} uses, unless {_setupDecimals} is called. NOTE: This information is only used for _display_ purposes: it in no way affects any of the arithmetic of the contract, including {IERC20-balanceOf} and {IERC20-transfer}.* - - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | uint8 | undefined | - -### decreaseAllowance - -```solidity -function decreaseAllowance(address spender, uint256 subtractedValue) external nonpayable returns (bool) -``` - - - -*Atomically decreases the allowance granted to `spender` by the caller. This is an alternative to {approve} that can be used as a mitigation for problems described in {IERC20-approve}. Emits an {Approval} event indicating the updated allowance. Requirements: - `spender` cannot be the zero address. - `spender` must have allowance for the caller of at least `subtractedValue`.* - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| spender | address | undefined | -| subtractedValue | uint256 | undefined | - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | bool | undefined | - -### increaseAllowance - -```solidity -function increaseAllowance(address spender, uint256 addedValue) external nonpayable returns (bool) -``` - - - -*Atomically increases the allowance granted to `spender` by the caller. This is an alternative to {approve} that can be used as a mitigation for problems described in {IERC20-approve}. Emits an {Approval} event indicating the updated allowance. Requirements: - `spender` cannot be the zero address.* - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| spender | address | undefined | -| addedValue | uint256 | undefined | - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | bool | undefined | - -### mint - -```solidity -function mint(address to, uint256 amount) external nonpayable -``` - - - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| to | address | undefined | -| amount | uint256 | undefined | - -### name - -```solidity -function name() external view returns (string) -``` - - - -*Returns the name of the token.* - - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | string | undefined | - -### symbol - -```solidity -function symbol() external view returns (string) -``` - - - -*Returns the symbol of the token, usually a shorter version of the name.* - - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | string | undefined | - -### totalSupply - -```solidity -function totalSupply() external view returns (uint256) -``` - - - -*See {IERC20-totalSupply}.* - - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | uint256 | undefined | - -### transfer - -```solidity -function transfer(address recipient, uint256 amount) external nonpayable returns (bool) -``` - - - -*See {IERC20-transfer}. Requirements: - `recipient` cannot be the zero address. - the caller must have a balance of at least `amount`.* - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| recipient | address | undefined | -| amount | uint256 | undefined | - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | bool | undefined | - -### transferFrom - -```solidity -function transferFrom(address sender, address recipient, uint256 amount) external nonpayable returns (bool) -``` - - - -*See {IERC20-transferFrom}. Emits an {Approval} event indicating the updated allowance. This is not required by the EIP. See the note at the beginning of {ERC20}. Requirements: - `sender` and `recipient` cannot be the zero address. - `sender` must have a balance of at least `amount`. - the caller must have allowance for ``sender``'s tokens of at least `amount`.* - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| sender | address | undefined | -| recipient | address | undefined | -| amount | uint256 | undefined | - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | bool | undefined | - - - -## Events - -### Approval - -```solidity -event Approval(address indexed owner, address indexed spender, uint256 value) -``` - - - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| owner `indexed` | address | undefined | -| spender `indexed` | address | undefined | -| value | uint256 | undefined | - -### Transfer - -```solidity -event Transfer(address indexed from, address indexed to, uint256 value) -``` - - - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| from `indexed` | address | undefined | -| to `indexed` | address | undefined | -| value | uint256 | undefined | - - - diff --git a/docs/bridge/mocks/RewarderBrokenMock.md b/docs/bridge/mocks/RewarderBrokenMock.md deleted file mode 100644 index 705bd80a8..000000000 --- a/docs/bridge/mocks/RewarderBrokenMock.md +++ /dev/null @@ -1,60 +0,0 @@ -# RewarderBrokenMock - - - - - - - - - -## Methods - -### onSynapseReward - -```solidity -function onSynapseReward(uint256, address, address, uint256, uint256) external nonpayable -``` - - - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| _0 | uint256 | undefined | -| _1 | address | undefined | -| _2 | address | undefined | -| _3 | uint256 | undefined | -| _4 | uint256 | undefined | - -### pendingTokens - -```solidity -function pendingTokens(uint256 pid, address user, uint256 synapseAmount) external view returns (contract IERC20[] rewardTokens, uint256[] rewardAmounts) -``` - - - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| pid | uint256 | undefined | -| user | address | undefined | -| synapseAmount | uint256 | undefined | - -#### Returns - -| Name | Type | Description | -|---|---|---| -| rewardTokens | contract IERC20[] | undefined | -| rewardAmounts | uint256[] | undefined | - - - - diff --git a/docs/bridge/mocks/RewarderMock.md b/docs/bridge/mocks/RewarderMock.md deleted file mode 100644 index e546bc483..000000000 --- a/docs/bridge/mocks/RewarderMock.md +++ /dev/null @@ -1,60 +0,0 @@ -# RewarderMock - - - - - - - - - -## Methods - -### onSynapseReward - -```solidity -function onSynapseReward(uint256, address user, address to, uint256 synapseAmount, uint256) external nonpayable -``` - - - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| _0 | uint256 | undefined | -| user | address | undefined | -| to | address | undefined | -| synapseAmount | uint256 | undefined | -| _4 | uint256 | undefined | - -### pendingTokens - -```solidity -function pendingTokens(uint256 pid, address user, uint256 synapseAmount) external view returns (contract IERC20[] rewardTokens, uint256[] rewardAmounts) -``` - - - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| pid | uint256 | undefined | -| user | address | undefined | -| synapseAmount | uint256 | undefined | - -#### Returns - -| Name | Type | Description | -|---|---|---| -| rewardTokens | contract IERC20[] | undefined | -| rewardAmounts | uint256[] | undefined | - - - - diff --git a/docs/bridge/testing/NodeEnv.md b/docs/bridge/testing/NodeEnv.md deleted file mode 100644 index 042d330bb..000000000 --- a/docs/bridge/testing/NodeEnv.md +++ /dev/null @@ -1,348 +0,0 @@ -# NodeEnv - -*Synapse Authors* - -> NodeEnv contract - -This contract implements a key-value store for storing variables on which synapse nodes must coordinate methods are purposely arbitrary to allow these fields to be defined in synapse improvement proposals.This token is used for configuring different tokens on the bridge and mapping them across chains.* - - - -## Methods - -### BRIDGEMANAGER_ROLE - -```solidity -function BRIDGEMANAGER_ROLE() external view returns (bytes32) -``` - - - - - - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | bytes32 | undefined | - -### DEFAULT_ADMIN_ROLE - -```solidity -function DEFAULT_ADMIN_ROLE() external view returns (bytes32) -``` - - - - - - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | bytes32 | undefined | - -### get - -```solidity -function get(string _key) external view returns (string) -``` - -gets the value associated with the key - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| _key | string | undefined | - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | string | undefined | - -### getRoleAdmin - -```solidity -function getRoleAdmin(bytes32 role) external view returns (bytes32) -``` - - - -*Returns the admin role that controls `role`. See {grantRole} and {revokeRole}. To change a role's admin, use {_setRoleAdmin}.* - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| role | bytes32 | undefined | - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | bytes32 | undefined | - -### getRoleMember - -```solidity -function getRoleMember(bytes32 role, uint256 index) external view returns (address) -``` - - - -*Returns one of the accounts that have `role`. `index` must be a value between 0 and {getRoleMemberCount}, non-inclusive. Role bearers are not sorted in any particular way, and their ordering may change at any point. WARNING: When using {getRoleMember} and {getRoleMemberCount}, make sure you perform all queries on the same block. See the following https://forum.openzeppelin.com/t/iterating-over-elements-on-enumerableset-in-openzeppelin-contracts/2296[forum post] for more information.* - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| role | bytes32 | undefined | -| index | uint256 | undefined | - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | address | undefined | - -### getRoleMemberCount - -```solidity -function getRoleMemberCount(bytes32 role) external view returns (uint256) -``` - - - -*Returns the number of accounts that have `role`. Can be used together with {getRoleMember} to enumerate all bearers of a role.* - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| role | bytes32 | undefined | - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | uint256 | undefined | - -### grantRole - -```solidity -function grantRole(bytes32 role, address account) external nonpayable -``` - - - -*Grants `role` to `account`. If `account` had not been already granted `role`, emits a {RoleGranted} event. Requirements: - the caller must have ``role``'s admin role.* - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| role | bytes32 | undefined | -| account | address | undefined | - -### hasRole - -```solidity -function hasRole(bytes32 role, address account) external view returns (bool) -``` - - - -*Returns `true` if `account` has been granted `role`.* - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| role | bytes32 | undefined | -| account | address | undefined | - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | bool | undefined | - -### keyCount - -```solidity -function keyCount() external view returns (uint256) -``` - -get the length of the config - -*this is useful for enumerating through all keys in the env* - - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | uint256 | undefined | - -### keyValueByIndex - -```solidity -function keyValueByIndex(uint256 index) external view returns (string, string) -``` - -gets the key/value pair by it's index Requirements: - `index` must be strictly less than {length}. - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| index | uint256 | undefined | - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | string | undefined | -| _1 | string | undefined | - -### renounceRole - -```solidity -function renounceRole(bytes32 role, address account) external nonpayable -``` - - - -*Revokes `role` from the calling account. Roles are often managed via {grantRole} and {revokeRole}: this function's purpose is to provide a mechanism for accounts to lose their privileges if they are compromised (such as when a trusted device is misplaced). If the calling account had been granted `role`, emits a {RoleRevoked} event. Requirements: - the caller must be `account`.* - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| role | bytes32 | undefined | -| account | address | undefined | - -### revokeRole - -```solidity -function revokeRole(bytes32 role, address account) external nonpayable -``` - - - -*Revokes `role` from `account`. If `account` had been granted `role`, emits a {RoleRevoked} event. Requirements: - the caller must have ``role``'s admin role.* - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| role | bytes32 | undefined | -| account | address | undefined | - -### set - -```solidity -function set(string _key, string _value) external nonpayable returns (bool) -``` - -sets the key - -*caller must have bridge manager role* - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| _key | string | undefined | -| _value | string | undefined | - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | bool | undefined | - - - -## Events - -### ConfigUpdate - -```solidity -event ConfigUpdate(string key) -``` - - - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| key | string | undefined | - -### RoleAdminChanged - -```solidity -event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole) -``` - - - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| role `indexed` | bytes32 | undefined | -| previousAdminRole `indexed` | bytes32 | undefined | -| newAdminRole `indexed` | bytes32 | undefined | - -### RoleGranted - -```solidity -event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender) -``` - - - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| role `indexed` | bytes32 | undefined | -| account `indexed` | address | undefined | -| sender `indexed` | address | undefined | - -### RoleRevoked - -```solidity -event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender) -``` - - - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| role `indexed` | bytes32 | undefined | -| account `indexed` | address | undefined | -| sender `indexed` | address | undefined | - - - diff --git a/docs/bridge/testing/RateLimiterTest.md b/docs/bridge/testing/RateLimiterTest.md deleted file mode 100644 index f8962ded2..000000000 --- a/docs/bridge/testing/RateLimiterTest.md +++ /dev/null @@ -1,83 +0,0 @@ -# RateLimiterTest - - - -> RateLimiterTest - - - - - -## Methods - -### NAME - -```solidity -function NAME() external view returns (string) -``` - - - - - - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | string | undefined | - -### VERSION - -```solidity -function VERSION() external view returns (string) -``` - - - - - - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | string | undefined | - -### getLastUpdateValue - -```solidity -function getLastUpdateValue() external view returns (bool) -``` - - - - - - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | bool | undefined | - -### storeCheckAndUpdateAllowance - -```solidity -function storeCheckAndUpdateAllowance(address token, uint256 amount) external nonpayable -``` - - - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| token | address | undefined | -| amount | uint256 | undefined | - - - - diff --git a/docs/bridge/testing/Synapse.md b/docs/bridge/testing/Synapse.md deleted file mode 100644 index 07af17788..000000000 --- a/docs/bridge/testing/Synapse.md +++ /dev/null @@ -1,623 +0,0 @@ -# Synapse - - - - - - - - - -## Methods - -### DEFAULT_ADMIN_ROLE - -```solidity -function DEFAULT_ADMIN_ROLE() external view returns (bytes32) -``` - - - - - - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | bytes32 | undefined | - -### DOMAIN_SEPARATOR - -```solidity -function DOMAIN_SEPARATOR() external view returns (bytes32) -``` - - - -*See {IERC20Permit-DOMAIN_SEPARATOR}.* - - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | bytes32 | undefined | - -### MINTER_ROLE - -```solidity -function MINTER_ROLE() external view returns (bytes32) -``` - - - - - - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | bytes32 | undefined | - -### allowance - -```solidity -function allowance(address owner, address spender) external view returns (uint256) -``` - - - -*See {IERC20-allowance}.* - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| owner | address | undefined | -| spender | address | undefined | - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | uint256 | undefined | - -### approve - -```solidity -function approve(address spender, uint256 amount) external nonpayable returns (bool) -``` - - - -*See {IERC20-approve}. Requirements: - `spender` cannot be the zero address.* - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| spender | address | undefined | -| amount | uint256 | undefined | - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | bool | undefined | - -### balanceOf - -```solidity -function balanceOf(address account) external view returns (uint256) -``` - - - -*See {IERC20-balanceOf}.* - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| account | address | undefined | - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | uint256 | undefined | - -### burn - -```solidity -function burn(uint256 amount) external nonpayable -``` - - - -*Destroys `amount` tokens from the caller. See {ERC20-_burn}.* - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| amount | uint256 | undefined | - -### burnFrom - -```solidity -function burnFrom(address account, uint256 amount) external nonpayable -``` - - - -*Destroys `amount` tokens from `account`, deducting from the caller's allowance. See {ERC20-_burn} and {ERC20-allowance}. Requirements: - the caller must have allowance for ``accounts``'s tokens of at least `amount`.* - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| account | address | undefined | -| amount | uint256 | undefined | - -### decimals - -```solidity -function decimals() external view returns (uint8) -``` - - - -*Returns the number of decimals used to get its user representation. For example, if `decimals` equals `2`, a balance of `505` tokens should be displayed to a user as `5,05` (`505 / 10 ** 2`). Tokens usually opt for a value of 18, imitating the relationship between Ether and Wei. This is the value {ERC20} uses, unless {_setupDecimals} is called. NOTE: This information is only used for _display_ purposes: it in no way affects any of the arithmetic of the contract, including {IERC20-balanceOf} and {IERC20-transfer}.* - - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | uint8 | undefined | - -### decreaseAllowance - -```solidity -function decreaseAllowance(address spender, uint256 subtractedValue) external nonpayable returns (bool) -``` - - - -*Atomically decreases the allowance granted to `spender` by the caller. This is an alternative to {approve} that can be used as a mitigation for problems described in {IERC20-approve}. Emits an {Approval} event indicating the updated allowance. Requirements: - `spender` cannot be the zero address. - `spender` must have allowance for the caller of at least `subtractedValue`.* - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| spender | address | undefined | -| subtractedValue | uint256 | undefined | - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | bool | undefined | - -### getRoleAdmin - -```solidity -function getRoleAdmin(bytes32 role) external view returns (bytes32) -``` - - - -*Returns the admin role that controls `role`. See {grantRole} and {revokeRole}. To change a role's admin, use {_setRoleAdmin}.* - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| role | bytes32 | undefined | - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | bytes32 | undefined | - -### getRoleMember - -```solidity -function getRoleMember(bytes32 role, uint256 index) external view returns (address) -``` - - - -*Returns one of the accounts that have `role`. `index` must be a value between 0 and {getRoleMemberCount}, non-inclusive. Role bearers are not sorted in any particular way, and their ordering may change at any point. WARNING: When using {getRoleMember} and {getRoleMemberCount}, make sure you perform all queries on the same block. See the following https://forum.openzeppelin.com/t/iterating-over-elements-on-enumerableset-in-openzeppelin-contracts/2296[forum post] for more information.* - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| role | bytes32 | undefined | -| index | uint256 | undefined | - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | address | undefined | - -### getRoleMemberCount - -```solidity -function getRoleMemberCount(bytes32 role) external view returns (uint256) -``` - - - -*Returns the number of accounts that have `role`. Can be used together with {getRoleMember} to enumerate all bearers of a role.* - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| role | bytes32 | undefined | - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | uint256 | undefined | - -### grantRole - -```solidity -function grantRole(bytes32 role, address account) external nonpayable -``` - - - -*Grants `role` to `account`. If `account` had not been already granted `role`, emits a {RoleGranted} event. Requirements: - the caller must have ``role``'s admin role.* - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| role | bytes32 | undefined | -| account | address | undefined | - -### hasRole - -```solidity -function hasRole(bytes32 role, address account) external view returns (bool) -``` - - - -*Returns `true` if `account` has been granted `role`.* - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| role | bytes32 | undefined | -| account | address | undefined | - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | bool | undefined | - -### increaseAllowance - -```solidity -function increaseAllowance(address spender, uint256 addedValue) external nonpayable returns (bool) -``` - - - -*Atomically increases the allowance granted to `spender` by the caller. This is an alternative to {approve} that can be used as a mitigation for problems described in {IERC20-approve}. Emits an {Approval} event indicating the updated allowance. Requirements: - `spender` cannot be the zero address.* - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| spender | address | undefined | -| addedValue | uint256 | undefined | - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | bool | undefined | - -### mint - -```solidity -function mint(address to, uint256 amount) external nonpayable -``` - - - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| to | address | undefined | -| amount | uint256 | undefined | - -### name - -```solidity -function name() external view returns (string) -``` - - - -*Returns the name of the token.* - - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | string | undefined | - -### nonces - -```solidity -function nonces(address owner) external view returns (uint256) -``` - - - -*See {IERC20Permit-nonces}.* - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| owner | address | undefined | - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | uint256 | undefined | - -### permit - -```solidity -function permit(address owner, address spender, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s) external nonpayable -``` - - - -*See {IERC20Permit-permit}.* - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| owner | address | undefined | -| spender | address | undefined | -| value | uint256 | undefined | -| deadline | uint256 | undefined | -| v | uint8 | undefined | -| r | bytes32 | undefined | -| s | bytes32 | undefined | - -### renounceRole - -```solidity -function renounceRole(bytes32 role, address account) external nonpayable -``` - - - -*Revokes `role` from the calling account. Roles are often managed via {grantRole} and {revokeRole}: this function's purpose is to provide a mechanism for accounts to lose their privileges if they are compromised (such as when a trusted device is misplaced). If the calling account had been granted `role`, emits a {RoleRevoked} event. Requirements: - the caller must be `account`.* - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| role | bytes32 | undefined | -| account | address | undefined | - -### revokeRole - -```solidity -function revokeRole(bytes32 role, address account) external nonpayable -``` - - - -*Revokes `role` from `account`. If `account` had been granted `role`, emits a {RoleRevoked} event. Requirements: - the caller must have ``role``'s admin role.* - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| role | bytes32 | undefined | -| account | address | undefined | - -### symbol - -```solidity -function symbol() external view returns (string) -``` - - - -*Returns the symbol of the token, usually a shorter version of the name.* - - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | string | undefined | - -### totalSupply - -```solidity -function totalSupply() external view returns (uint256) -``` - - - -*See {IERC20-totalSupply}.* - - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | uint256 | undefined | - -### transfer - -```solidity -function transfer(address recipient, uint256 amount) external nonpayable returns (bool) -``` - - - -*See {IERC20-transfer}. Requirements: - `recipient` cannot be the zero address. - the caller must have a balance of at least `amount`.* - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| recipient | address | undefined | -| amount | uint256 | undefined | - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | bool | undefined | - -### transferFrom - -```solidity -function transferFrom(address sender, address recipient, uint256 amount) external nonpayable returns (bool) -``` - - - -*See {IERC20-transferFrom}. Emits an {Approval} event indicating the updated allowance. This is not required by the EIP. See the note at the beginning of {ERC20}. Requirements: - `sender` and `recipient` cannot be the zero address. - `sender` must have a balance of at least `amount`. - the caller must have allowance for ``sender``'s tokens of at least `amount`.* - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| sender | address | undefined | -| recipient | address | undefined | -| amount | uint256 | undefined | - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | bool | undefined | - - - -## Events - -### Approval - -```solidity -event Approval(address indexed owner, address indexed spender, uint256 value) -``` - - - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| owner `indexed` | address | undefined | -| spender `indexed` | address | undefined | -| value | uint256 | undefined | - -### RoleAdminChanged - -```solidity -event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole) -``` - - - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| role `indexed` | bytes32 | undefined | -| previousAdminRole `indexed` | bytes32 | undefined | -| newAdminRole `indexed` | bytes32 | undefined | - -### RoleGranted - -```solidity -event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender) -``` - - - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| role `indexed` | bytes32 | undefined | -| account `indexed` | address | undefined | -| sender `indexed` | address | undefined | - -### RoleRevoked - -```solidity -event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender) -``` - - - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| role `indexed` | bytes32 | undefined | -| account `indexed` | address | undefined | -| sender `indexed` | address | undefined | - -### Transfer - -```solidity -event Transfer(address indexed from, address indexed to, uint256 value) -``` - - - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| from `indexed` | address | undefined | -| to `indexed` | address | undefined | -| value | uint256 | undefined | - - - diff --git a/docs/bridge/utils/AddressArrayUtils.md b/docs/bridge/utils/AddressArrayUtils.md deleted file mode 100644 index f8d882857..000000000 --- a/docs/bridge/utils/AddressArrayUtils.md +++ /dev/null @@ -1,12 +0,0 @@ -# AddressArrayUtils - - - - - - - - - - - diff --git a/docs/bridge/utils/EnumerableStringMap.md b/docs/bridge/utils/EnumerableStringMap.md deleted file mode 100644 index 66491eb26..000000000 --- a/docs/bridge/utils/EnumerableStringMap.md +++ /dev/null @@ -1,12 +0,0 @@ -# EnumerableStringMap - - - -> EnumerableStringMap - - - -*Library for managing an enumerable variant of Solidity's https://solidity.readthedocs.io/en/latest/types.html#mapping-types[`mapping`] type. Maps have the following properties: - Entries are added, removed, and checked for existence in constant time (O(1)). - Entries are enumerated in O(n). No guarantees are made on the ordering. this isn't a terribly gas efficient implementation because it emphasizes usability over gas efficiency by allowing arbitrary length string memorys. If Gettetrs/Setters are going to be used frequently in contracts consider using the OpenZeppeling Bytes32 implementation this also differs from the OpenZeppelin implementation by keccac256 hashing the string memorys so we can use enumerable bytes32 set* - - - diff --git a/docs/bridge/utils/TimelockController.md b/docs/bridge/utils/TimelockController.md deleted file mode 100644 index b2e30ea4d..000000000 --- a/docs/bridge/utils/TimelockController.md +++ /dev/null @@ -1,626 +0,0 @@ -# TimelockController - - - - - - - -*Contract module which acts as a timelocked controller. When set as the owner of an `Ownable` smart contract, it enforces a timelock on all `onlyOwner` maintenance operations. This gives time for users of the controlled contract to exit before a potentially dangerous maintenance operation is applied. By default, this contract is self administered, meaning administration tasks have to go through the timelock process. The proposer (resp executor) role is in charge of proposing (resp executing) operations. A common use case is to position this {TimelockController} as the owner of a smart contract, with a multisig or a DAO as the sole proposer. _Available since v3.3._* - -## Methods - -### DEFAULT_ADMIN_ROLE - -```solidity -function DEFAULT_ADMIN_ROLE() external view returns (bytes32) -``` - - - - - - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | bytes32 | undefined | - -### EXECUTOR_ROLE - -```solidity -function EXECUTOR_ROLE() external view returns (bytes32) -``` - - - - - - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | bytes32 | undefined | - -### PROPOSER_ROLE - -```solidity -function PROPOSER_ROLE() external view returns (bytes32) -``` - - - - - - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | bytes32 | undefined | - -### TIMELOCK_ADMIN_ROLE - -```solidity -function TIMELOCK_ADMIN_ROLE() external view returns (bytes32) -``` - - - - - - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | bytes32 | undefined | - -### cancel - -```solidity -function cancel(bytes32 id) external nonpayable -``` - - - -*Cancel an operation. Requirements: - the caller must have the 'proposer' role.* - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| id | bytes32 | undefined | - -### execute - -```solidity -function execute(address target, uint256 value, bytes data, bytes32 predecessor, bytes32 salt) external payable -``` - - - -*Execute an (ready) operation containing a single transaction. Emits a {CallExecuted} event. Requirements: - the caller must have the 'executor' role.* - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| target | address | undefined | -| value | uint256 | undefined | -| data | bytes | undefined | -| predecessor | bytes32 | undefined | -| salt | bytes32 | undefined | - -### executeBatch - -```solidity -function executeBatch(address[] targets, uint256[] values, bytes[] datas, bytes32 predecessor, bytes32 salt) external payable -``` - - - -*Execute an (ready) operation containing a batch of transactions. Emits one {CallExecuted} event per transaction in the batch. Requirements: - the caller must have the 'executor' role.* - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| targets | address[] | undefined | -| values | uint256[] | undefined | -| datas | bytes[] | undefined | -| predecessor | bytes32 | undefined | -| salt | bytes32 | undefined | - -### getMinDelay - -```solidity -function getMinDelay() external view returns (uint256 duration) -``` - - - -*Returns the minimum delay for an operation to become valid. This value can be changed by executing an operation that calls `updateDelay`.* - - -#### Returns - -| Name | Type | Description | -|---|---|---| -| duration | uint256 | undefined | - -### getRoleAdmin - -```solidity -function getRoleAdmin(bytes32 role) external view returns (bytes32) -``` - - - -*Returns the admin role that controls `role`. See {grantRole} and {revokeRole}. To change a role's admin, use {_setRoleAdmin}.* - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| role | bytes32 | undefined | - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | bytes32 | undefined | - -### getTimestamp - -```solidity -function getTimestamp(bytes32 id) external view returns (uint256 timestamp) -``` - - - -*Returns the timestamp at with an operation becomes ready (0 for unset operations, 1 for done operations).* - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| id | bytes32 | undefined | - -#### Returns - -| Name | Type | Description | -|---|---|---| -| timestamp | uint256 | undefined | - -### grantRole - -```solidity -function grantRole(bytes32 role, address account) external nonpayable -``` - - - -*Grants `role` to `account`. If `account` had not been already granted `role`, emits a {RoleGranted} event. Requirements: - the caller must have ``role``'s admin role.* - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| role | bytes32 | undefined | -| account | address | undefined | - -### hasRole - -```solidity -function hasRole(bytes32 role, address account) external view returns (bool) -``` - - - -*Returns `true` if `account` has been granted `role`.* - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| role | bytes32 | undefined | -| account | address | undefined | - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | bool | undefined | - -### hashOperation - -```solidity -function hashOperation(address target, uint256 value, bytes data, bytes32 predecessor, bytes32 salt) external pure returns (bytes32 hash) -``` - - - -*Returns the identifier of an operation containing a single transaction.* - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| target | address | undefined | -| value | uint256 | undefined | -| data | bytes | undefined | -| predecessor | bytes32 | undefined | -| salt | bytes32 | undefined | - -#### Returns - -| Name | Type | Description | -|---|---|---| -| hash | bytes32 | undefined | - -### hashOperationBatch - -```solidity -function hashOperationBatch(address[] targets, uint256[] values, bytes[] datas, bytes32 predecessor, bytes32 salt) external pure returns (bytes32 hash) -``` - - - -*Returns the identifier of an operation containing a batch of transactions.* - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| targets | address[] | undefined | -| values | uint256[] | undefined | -| datas | bytes[] | undefined | -| predecessor | bytes32 | undefined | -| salt | bytes32 | undefined | - -#### Returns - -| Name | Type | Description | -|---|---|---| -| hash | bytes32 | undefined | - -### isOperation - -```solidity -function isOperation(bytes32 id) external view returns (bool pending) -``` - - - -*Returns whether an id correspond to a registered operation. This includes both Pending, Ready and Done operations.* - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| id | bytes32 | undefined | - -#### Returns - -| Name | Type | Description | -|---|---|---| -| pending | bool | undefined | - -### isOperationDone - -```solidity -function isOperationDone(bytes32 id) external view returns (bool done) -``` - - - -*Returns whether an operation is done or not.* - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| id | bytes32 | undefined | - -#### Returns - -| Name | Type | Description | -|---|---|---| -| done | bool | undefined | - -### isOperationPending - -```solidity -function isOperationPending(bytes32 id) external view returns (bool pending) -``` - - - -*Returns whether an operation is pending or not.* - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| id | bytes32 | undefined | - -#### Returns - -| Name | Type | Description | -|---|---|---| -| pending | bool | undefined | - -### isOperationReady - -```solidity -function isOperationReady(bytes32 id) external view returns (bool ready) -``` - - - -*Returns whether an operation is ready or not.* - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| id | bytes32 | undefined | - -#### Returns - -| Name | Type | Description | -|---|---|---| -| ready | bool | undefined | - -### renounceRole - -```solidity -function renounceRole(bytes32 role, address account) external nonpayable -``` - - - -*Revokes `role` from the calling account. Roles are often managed via {grantRole} and {revokeRole}: this function's purpose is to provide a mechanism for accounts to lose their privileges if they are compromised (such as when a trusted device is misplaced). If the calling account had been revoked `role`, emits a {RoleRevoked} event. Requirements: - the caller must be `account`.* - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| role | bytes32 | undefined | -| account | address | undefined | - -### revokeRole - -```solidity -function revokeRole(bytes32 role, address account) external nonpayable -``` - - - -*Revokes `role` from `account`. If `account` had been granted `role`, emits a {RoleRevoked} event. Requirements: - the caller must have ``role``'s admin role.* - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| role | bytes32 | undefined | -| account | address | undefined | - -### schedule - -```solidity -function schedule(address target, uint256 value, bytes data, bytes32 predecessor, bytes32 salt, uint256 delay) external nonpayable -``` - - - -*Schedule an operation containing a single transaction. Emits a {CallScheduled} event. Requirements: - the caller must have the 'proposer' role.* - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| target | address | undefined | -| value | uint256 | undefined | -| data | bytes | undefined | -| predecessor | bytes32 | undefined | -| salt | bytes32 | undefined | -| delay | uint256 | undefined | - -### scheduleBatch - -```solidity -function scheduleBatch(address[] targets, uint256[] values, bytes[] datas, bytes32 predecessor, bytes32 salt, uint256 delay) external nonpayable -``` - - - -*Schedule an operation containing a batch of transactions. Emits one {CallScheduled} event per transaction in the batch. Requirements: - the caller must have the 'proposer' role.* - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| targets | address[] | undefined | -| values | uint256[] | undefined | -| datas | bytes[] | undefined | -| predecessor | bytes32 | undefined | -| salt | bytes32 | undefined | -| delay | uint256 | undefined | - -### supportsInterface - -```solidity -function supportsInterface(bytes4 interfaceId) external view returns (bool) -``` - - - -*See {IERC165-supportsInterface}.* - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| interfaceId | bytes4 | undefined | - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | bool | undefined | - -### updateDelay - -```solidity -function updateDelay(uint256 newDelay) external nonpayable -``` - - - -*Changes the minimum timelock duration for future operations. Emits a {MinDelayChange} event. Requirements: - the caller must be the timelock itself. This can only be achieved by scheduling and later executing an operation where the timelock is the target and the data is the ABI-encoded call to this function.* - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| newDelay | uint256 | undefined | - - - -## Events - -### CallExecuted - -```solidity -event CallExecuted(bytes32 indexed id, uint256 indexed index, address target, uint256 value, bytes data) -``` - - - -*Emitted when a call is performed as part of operation `id`.* - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| id `indexed` | bytes32 | undefined | -| index `indexed` | uint256 | undefined | -| target | address | undefined | -| value | uint256 | undefined | -| data | bytes | undefined | - -### CallScheduled - -```solidity -event CallScheduled(bytes32 indexed id, uint256 indexed index, address target, uint256 value, bytes data, bytes32 predecessor, uint256 delay) -``` - - - -*Emitted when a call is scheduled as part of operation `id`.* - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| id `indexed` | bytes32 | undefined | -| index `indexed` | uint256 | undefined | -| target | address | undefined | -| value | uint256 | undefined | -| data | bytes | undefined | -| predecessor | bytes32 | undefined | -| delay | uint256 | undefined | - -### Cancelled - -```solidity -event Cancelled(bytes32 indexed id) -``` - - - -*Emitted when operation `id` is cancelled.* - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| id `indexed` | bytes32 | undefined | - -### MinDelayChange - -```solidity -event MinDelayChange(uint256 oldDuration, uint256 newDuration) -``` - - - -*Emitted when the minimum delay for future operations is modified.* - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| oldDuration | uint256 | undefined | -| newDuration | uint256 | undefined | - -### RoleAdminChanged - -```solidity -event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole) -``` - - - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| role `indexed` | bytes32 | undefined | -| previousAdminRole `indexed` | bytes32 | undefined | -| newAdminRole `indexed` | bytes32 | undefined | - -### RoleGranted - -```solidity -event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender) -``` - - - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| role `indexed` | bytes32 | undefined | -| account `indexed` | address | undefined | -| sender `indexed` | address | undefined | - -### RoleRevoked - -```solidity -event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender) -``` - - - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| role `indexed` | bytes32 | undefined | -| account `indexed` | address | undefined | -| sender `indexed` | address | undefined | - - - diff --git a/docs/bridge/wrappers/GMXWrapper.md b/docs/bridge/wrappers/GMXWrapper.md deleted file mode 100644 index 7fb1f6a1a..000000000 --- a/docs/bridge/wrappers/GMXWrapper.md +++ /dev/null @@ -1,106 +0,0 @@ -# GMXWrapper - - - - - - - - - -## Methods - -### bridge - -```solidity -function bridge() external view returns (address) -``` - - - - - - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | address | undefined | - -### burnFrom - -```solidity -function burnFrom(address _addr, uint256 _amount) external nonpayable -``` - - - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| _addr | address | undefined | -| _amount | uint256 | undefined | - -### gmx - -```solidity -function gmx() external view returns (address) -``` - - - - - - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | address | undefined | - -### mint - -```solidity -function mint(address _addr, uint256 _amount) external nonpayable -``` - - - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| _addr | address | undefined | -| _amount | uint256 | undefined | - -### transfer - -```solidity -function transfer(address _recipient, uint256 _amount) external nonpayable returns (bool) -``` - - - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| _recipient | address | undefined | -| _amount | uint256 | undefined | - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | bool | undefined | - - - - diff --git a/docs/bridge/wrappers/HarmonyBridgeZap.md b/docs/bridge/wrappers/HarmonyBridgeZap.md deleted file mode 100644 index bc8aa3f4d..000000000 --- a/docs/bridge/wrappers/HarmonyBridgeZap.md +++ /dev/null @@ -1,303 +0,0 @@ -# HarmonyBridgeZap - - - - - - - - - -## Methods - -### WETH_ADDRESS - -```solidity -function WETH_ADDRESS() external view returns (address payable) -``` - - - - - - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | address payable | undefined | - -### calculateSwap - -```solidity -function calculateSwap(contract IERC20 token, uint8 tokenIndexFrom, uint8 tokenIndexTo, uint256 dx) external view returns (uint256) -``` - -Calculate amount of tokens you receive on swap - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| token | contract IERC20 | undefined | -| tokenIndexFrom | uint8 | the token the user wants to sell | -| tokenIndexTo | uint8 | the token the user wants to buy | -| dx | uint256 | the amount of tokens the user wants to sell. If the token charges a fee on transfers, use the amount that gets transferred after the fee. | - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | uint256 | amount of tokens the user will receive | - -### deposit - -```solidity -function deposit(address to, uint256 chainId, contract IERC20 token, uint256 amount) external nonpayable -``` - -wraps SynapseBridge redeem() - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| to | address | address on other chain to redeem underlying assets to | -| chainId | uint256 | which underlying chain to bridge assets onto | -| token | contract IERC20 | ERC20 compatible token to deposit into the bridge | -| amount | uint256 | Amount in native token decimals to transfer cross-chain pre-fees* | - -### redeem - -```solidity -function redeem(address to, uint256 chainId, contract IERC20 token, uint256 amount) external nonpayable -``` - -wraps SynapseBridge redeem() - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| to | address | address on other chain to redeem underlying assets to | -| chainId | uint256 | which underlying chain to bridge assets onto | -| token | contract IERC20 | ERC20 compatible token to deposit into the bridge | -| amount | uint256 | Amount in native token decimals to transfer cross-chain pre-fees* | - -### redeemAndRemove - -```solidity -function redeemAndRemove(address to, uint256 chainId, contract IERC20 token, uint256 amount, uint8 liqTokenIndex, uint256 liqMinAmount, uint256 liqDeadline) external nonpayable -``` - -Wraps redeemAndRemove on SynapseBridge Relays to nodes that (typically) a wrapped synAsset ERC20 token has been burned and the underlying needs to be redeeemed on the native chain. This function indicates to the nodes that they should attempt to redeem the LP token for the underlying assets (E.g "swap" out of the LP token) - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| to | address | address on other chain to redeem underlying assets to | -| chainId | uint256 | which underlying chain to bridge assets onto | -| token | contract IERC20 | ERC20 compatible token to deposit into the bridge | -| amount | uint256 | Amount of (typically) LP token to pass to the nodes to attempt to removeLiquidity() with to redeem for the underlying assets of the LP token | -| liqTokenIndex | uint8 | Specifies which of the underlying LP assets the nodes should attempt to redeem for | -| liqMinAmount | uint256 | Specifies the minimum amount of the underlying asset needed for the nodes to execute the redeem/swap | -| liqDeadline | uint256 | Specificies the deadline that the nodes are allowed to try to redeem/swap the LP token* | - -### redeemAndSwap - -```solidity -function redeemAndSwap(address to, uint256 chainId, contract IERC20 token, uint256 amount, uint8 tokenIndexFrom, uint8 tokenIndexTo, uint256 minDy, uint256 deadline) external nonpayable -``` - -Wraps redeemAndSwap on SynapseBridge.sol Relays to nodes that (typically) a wrapped synAsset ERC20 token has been burned and the underlying needs to be redeeemed on the native chain. This function indicates to the nodes that they should attempt to redeem the LP token for the underlying assets (E.g "swap" out of the LP token) - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| to | address | address on other chain to redeem underlying assets to | -| chainId | uint256 | which underlying chain to bridge assets onto | -| token | contract IERC20 | ERC20 compatible token to deposit into the bridge | -| amount | uint256 | Amount in native token decimals to transfer cross-chain pre-fees | -| tokenIndexFrom | uint8 | the token the user wants to swap from | -| tokenIndexTo | uint8 | the token the user wants to swap to | -| minDy | uint256 | the min amount the user would like to receive, or revert to only minting the SynERC20 token crosschain. | -| deadline | uint256 | latest timestamp to accept this transaction* | - -### redeemv2 - -```solidity -function redeemv2(bytes32 to, uint256 chainId, contract IERC20 token, uint256 amount) external nonpayable -``` - -Wraps SynapseBridge redeemv2() function - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| to | bytes32 | address on other chain to bridge assets to | -| chainId | uint256 | which chain to bridge assets onto | -| token | contract IERC20 | ERC20 compatible token to redeem into the bridge | -| amount | uint256 | Amount in native token decimals to transfer cross-chain pre-fees* | - -### swapAndRedeem - -```solidity -function swapAndRedeem(address to, uint256 chainId, contract IERC20 token, uint8 tokenIndexFrom, uint8 tokenIndexTo, uint256 dx, uint256 minDy, uint256 deadline) external nonpayable -``` - - - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| to | address | undefined | -| chainId | uint256 | undefined | -| token | contract IERC20 | undefined | -| tokenIndexFrom | uint8 | undefined | -| tokenIndexTo | uint8 | undefined | -| dx | uint256 | undefined | -| minDy | uint256 | undefined | -| deadline | uint256 | undefined | - -### swapAndRedeemAndRemove - -```solidity -function swapAndRedeemAndRemove(address to, uint256 chainId, contract IERC20 token, uint8 tokenIndexFrom, uint8 tokenIndexTo, uint256 dx, uint256 minDy, uint256 deadline, uint8 liqTokenIndex, uint256 liqMinAmount, uint256 liqDeadline) external nonpayable -``` - - - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| to | address | undefined | -| chainId | uint256 | undefined | -| token | contract IERC20 | undefined | -| tokenIndexFrom | uint8 | undefined | -| tokenIndexTo | uint8 | undefined | -| dx | uint256 | undefined | -| minDy | uint256 | undefined | -| deadline | uint256 | undefined | -| liqTokenIndex | uint8 | undefined | -| liqMinAmount | uint256 | undefined | -| liqDeadline | uint256 | undefined | - -### swapAndRedeemAndSwap - -```solidity -function swapAndRedeemAndSwap(address to, uint256 chainId, contract IERC20 token, uint8 tokenIndexFrom, uint8 tokenIndexTo, uint256 dx, uint256 minDy, uint256 deadline, uint8 swapTokenIndexFrom, uint8 swapTokenIndexTo, uint256 swapMinDy, uint256 swapDeadline) external nonpayable -``` - - - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| to | address | undefined | -| chainId | uint256 | undefined | -| token | contract IERC20 | undefined | -| tokenIndexFrom | uint8 | undefined | -| tokenIndexTo | uint8 | undefined | -| dx | uint256 | undefined | -| minDy | uint256 | undefined | -| deadline | uint256 | undefined | -| swapTokenIndexFrom | uint8 | undefined | -| swapTokenIndexTo | uint8 | undefined | -| swapMinDy | uint256 | undefined | -| swapDeadline | uint256 | undefined | - -### swapETHAndRedeem - -```solidity -function swapETHAndRedeem(address to, uint256 chainId, contract IERC20 token, uint8 tokenIndexFrom, uint8 tokenIndexTo, uint256 dx, uint256 minDy, uint256 deadline) external payable -``` - - - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| to | address | undefined | -| chainId | uint256 | undefined | -| token | contract IERC20 | undefined | -| tokenIndexFrom | uint8 | undefined | -| tokenIndexTo | uint8 | undefined | -| dx | uint256 | undefined | -| minDy | uint256 | undefined | -| deadline | uint256 | undefined | - -### swapMap - -```solidity -function swapMap(address) external view returns (address) -``` - - - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| _0 | address | undefined | - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | address | undefined | - -### swapTokensMap - -```solidity -function swapTokensMap(address, uint256) external view returns (contract IERC20) -``` - - - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| _0 | address | undefined | -| _1 | uint256 | undefined | - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | contract IERC20 | undefined | - - - - diff --git a/docs/bridge/wrappers/IFrax.md b/docs/bridge/wrappers/IFrax.md deleted file mode 100644 index 6287777f5..000000000 --- a/docs/bridge/wrappers/IFrax.md +++ /dev/null @@ -1,38 +0,0 @@ -# IFrax - - - - - - - - - -## Methods - -### exchangeCanonicalForOld - -```solidity -function exchangeCanonicalForOld(address bridge_token_address, uint256 token_amount) external nonpayable returns (uint256) -``` - - - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| bridge_token_address | address | undefined | -| token_amount | uint256 | undefined | - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | uint256 | undefined | - - - - diff --git a/docs/bridge/wrappers/IGMX.md b/docs/bridge/wrappers/IGMX.md deleted file mode 100644 index a04c32737..000000000 --- a/docs/bridge/wrappers/IGMX.md +++ /dev/null @@ -1,71 +0,0 @@ -# IGMX - - - - - - - - - -## Methods - -### balanceOf - -```solidity -function balanceOf(address account) external view returns (uint256) -``` - - - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| account | address | undefined | - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | uint256 | undefined | - -### burn - -```solidity -function burn(address _account, uint256 _amount) external nonpayable -``` - - - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| _account | address | undefined | -| _amount | uint256 | undefined | - -### mint - -```solidity -function mint(address _account, uint256 _amount) external nonpayable -``` - - - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| _account | address | undefined | -| _amount | uint256 | undefined | - - - - diff --git a/docs/bridge/wrappers/L1BridgeZap.md b/docs/bridge/wrappers/L1BridgeZap.md deleted file mode 100644 index a4066af8a..000000000 --- a/docs/bridge/wrappers/L1BridgeZap.md +++ /dev/null @@ -1,266 +0,0 @@ -# L1BridgeZap - - - -> L1BridgeZap - -This contract is responsible for handling user Zaps into the SynapseBridge contract, through the Synapse Swap contracts. It does so It does so by combining the action of addLiquidity() to the base swap pool, and then calling either deposit() or depositAndSwap() on the bridge. This is done in hopes of automating portions of the bridge user experience to users, while keeping the SynapseBridge contract logic small. - -*This contract should be deployed with a base Swap.sol address and a SynapseBridge.sol address, otherwise, it will not function.* - -## Methods - -### WETH_ADDRESS - -```solidity -function WETH_ADDRESS() external view returns (address payable) -``` - - - - - - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | address payable | undefined | - -### baseTokens - -```solidity -function baseTokens(uint256) external view returns (contract IERC20) -``` - - - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| _0 | uint256 | undefined | - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | contract IERC20 | undefined | - -### calculateRemoveLiquidityOneToken - -```solidity -function calculateRemoveLiquidityOneToken(uint256 tokenAmount, uint8 tokenIndex) external view returns (uint256 availableTokenAmount) -``` - -Calculate the amount of underlying token available to withdraw when withdrawing via only single token - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| tokenAmount | uint256 | the amount of LP token to burn | -| tokenIndex | uint8 | index of which token will be withdrawn | - -#### Returns - -| Name | Type | Description | -|---|---|---| -| availableTokenAmount | uint256 | calculated amount of underlying token available to withdraw | - -### calculateTokenAmount - -```solidity -function calculateTokenAmount(uint256[] amounts, bool deposit) external view returns (uint256) -``` - -A simple method to calculate prices from deposits or withdrawals, excluding fees but including slippage. This is helpful as an input into the various "min" parameters on calls to fight front-running - -*This shouldn't be used outside frontends for user estimates.* - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| amounts | uint256[] | an array of token amounts to deposit or withdrawal, corresponding to pooledTokens. The amount should be in each pooled token's native precision. | -| deposit | bool | whether this is a deposit or a withdrawal | - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | uint256 | token amount the user will receive | - -### deposit - -```solidity -function deposit(address to, uint256 chainId, contract IERC20 token, uint256 amount) external nonpayable -``` - -Wraps SynapseBridge deposit() function - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| to | address | address on other chain to bridge assets to | -| chainId | uint256 | which chain to bridge assets onto | -| token | contract IERC20 | ERC20 compatible token to deposit into the bridge | -| amount | uint256 | Amount in native token decimals to transfer cross-chain pre-fees* | - -### depositAndSwap - -```solidity -function depositAndSwap(address to, uint256 chainId, contract IERC20 token, uint256 amount, uint8 tokenIndexFrom, uint8 tokenIndexTo, uint256 minDy, uint256 deadline) external nonpayable -``` - -Wraps SynapseBridge depositAndSwap() function - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| to | address | address on other chain to bridge assets to | -| chainId | uint256 | which chain to bridge assets onto | -| token | contract IERC20 | ERC20 compatible token to deposit into the bridge | -| amount | uint256 | Amount in native token decimals to transfer cross-chain pre-fees | -| tokenIndexFrom | uint8 | the token the user wants to swap from | -| tokenIndexTo | uint8 | the token the user wants to swap to | -| minDy | uint256 | the min amount the user would like to receive, or revert to only minting the SynERC20 token crosschain. | -| deadline | uint256 | latest timestamp to accept this transaction* | - -### depositETH - -```solidity -function depositETH(address to, uint256 chainId, uint256 amount) external payable -``` - -Wraps SynapseBridge deposit() function to make it compatible w/ ETH -> WETH conversions - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| to | address | address on other chain to bridge assets to | -| chainId | uint256 | which chain to bridge assets onto | -| amount | uint256 | Amount in native token decimals to transfer cross-chain pre-fees* | - -### depositETHAndSwap - -```solidity -function depositETHAndSwap(address to, uint256 chainId, uint256 amount, uint8 tokenIndexFrom, uint8 tokenIndexTo, uint256 minDy, uint256 deadline) external payable -``` - -Wraps SynapseBridge depositAndSwap() function to make it compatible w/ ETH -> WETH conversions - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| to | address | address on other chain to bridge assets to | -| chainId | uint256 | which chain to bridge assets onto | -| amount | uint256 | Amount in native token decimals to transfer cross-chain pre-fees | -| tokenIndexFrom | uint8 | the token the user wants to swap from | -| tokenIndexTo | uint8 | the token the user wants to swap to | -| minDy | uint256 | the min amount the user would like to receive, or revert to only minting the SynERC20 token crosschain. | -| deadline | uint256 | latest timestamp to accept this transaction* | - -### redeem - -```solidity -function redeem(address to, uint256 chainId, contract IERC20 token, uint256 amount) external nonpayable -``` - -Wraps SynapseBridge redeem() function - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| to | address | address on other chain to bridge assets to | -| chainId | uint256 | which chain to bridge assets onto | -| token | contract IERC20 | ERC20 compatible token to redeem into the bridge | -| amount | uint256 | Amount in native token decimals to transfer cross-chain pre-fees* | - -### redeemv2 - -```solidity -function redeemv2(bytes32 to, uint256 chainId, contract IERC20 token, uint256 amount) external nonpayable -``` - -Wraps SynapseBridge redeemv2() function - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| to | bytes32 | address on other chain to bridge assets to | -| chainId | uint256 | which chain to bridge assets onto | -| token | contract IERC20 | ERC20 compatible token to redeem into the bridge | -| amount | uint256 | Amount in native token decimals to transfer cross-chain pre-fees* | - -### zapAndDeposit - -```solidity -function zapAndDeposit(address to, uint256 chainId, contract IERC20 token, uint256[] liquidityAmounts, uint256 minToMint, uint256 deadline) external nonpayable -``` - -Combines adding liquidity to the given Swap, and calls deposit() on the bridge using that LP token - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| to | address | address on other chain to bridge assets to | -| chainId | uint256 | which chain to bridge assets onto | -| token | contract IERC20 | ERC20 compatible token to deposit into the bridge | -| liquidityAmounts | uint256[] | the amounts of each token to add, in their native precision | -| minToMint | uint256 | the minimum LP tokens adding this amount of liquidity should mint, otherwise revert. Handy for front-running mitigation | -| deadline | uint256 | latest timestamp to accept this transaction* | - -### zapAndDepositAndSwap - -```solidity -function zapAndDepositAndSwap(address to, uint256 chainId, contract IERC20 token, uint256[] liquidityAmounts, uint256 minToMint, uint256 liqDeadline, uint8 tokenIndexFrom, uint8 tokenIndexTo, uint256 minDy, uint256 swapDeadline) external nonpayable -``` - -Combines adding liquidity to the given Swap, and calls depositAndSwap() on the bridge using that LP token - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| to | address | address on other chain to bridge assets to | -| chainId | uint256 | which chain to bridge assets onto | -| token | contract IERC20 | ERC20 compatible token to deposit into the bridge | -| liquidityAmounts | uint256[] | the amounts of each token to add, in their native precision | -| minToMint | uint256 | the minimum LP tokens adding this amount of liquidity should mint, otherwise revert. Handy for front-running mitigation | -| liqDeadline | uint256 | latest timestamp to accept this transaction | -| tokenIndexFrom | uint8 | the token the user wants to swap from | -| tokenIndexTo | uint8 | the token the user wants to swap to | -| minDy | uint256 | the min amount the user would like to receive, or revert to only minting the SynERC20 token crosschain. | -| swapDeadline | uint256 | latest timestamp to accept this transaction* | - - - - diff --git a/docs/bridge/wrappers/L2BridgeZap.md b/docs/bridge/wrappers/L2BridgeZap.md deleted file mode 100644 index 6df9a67de..000000000 --- a/docs/bridge/wrappers/L2BridgeZap.md +++ /dev/null @@ -1,348 +0,0 @@ -# L2BridgeZap - - - - - - - - - -## Methods - -### WETH_ADDRESS - -```solidity -function WETH_ADDRESS() external view returns (address payable) -``` - - - - - - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | address payable | undefined | - -### calculateSwap - -```solidity -function calculateSwap(contract IERC20 token, uint8 tokenIndexFrom, uint8 tokenIndexTo, uint256 dx) external view returns (uint256) -``` - -Calculate amount of tokens you receive on swap - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| token | contract IERC20 | undefined | -| tokenIndexFrom | uint8 | the token the user wants to sell | -| tokenIndexTo | uint8 | the token the user wants to buy | -| dx | uint256 | the amount of tokens the user wants to sell. If the token charges a fee on transfers, use the amount that gets transferred after the fee. | - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | uint256 | amount of tokens the user will receive | - -### deposit - -```solidity -function deposit(address to, uint256 chainId, contract IERC20 token, uint256 amount) external nonpayable -``` - -wraps SynapseBridge redeem() - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| to | address | address on other chain to redeem underlying assets to | -| chainId | uint256 | which underlying chain to bridge assets onto | -| token | contract IERC20 | ERC20 compatible token to deposit into the bridge | -| amount | uint256 | Amount in native token decimals to transfer cross-chain pre-fees* | - -### depositETH - -```solidity -function depositETH(address to, uint256 chainId, uint256 amount) external payable -``` - -Wraps SynapseBridge deposit() function to make it compatible w/ ETH -> WETH conversions - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| to | address | address on other chain to bridge assets to | -| chainId | uint256 | which chain to bridge assets onto | -| amount | uint256 | Amount in native token decimals to transfer cross-chain pre-fees* | - -### redeem - -```solidity -function redeem(address to, uint256 chainId, contract IERC20 token, uint256 amount) external nonpayable -``` - -wraps SynapseBridge redeem() - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| to | address | address on other chain to redeem underlying assets to | -| chainId | uint256 | which underlying chain to bridge assets onto | -| token | contract IERC20 | ERC20 compatible token to deposit into the bridge | -| amount | uint256 | Amount in native token decimals to transfer cross-chain pre-fees* | - -### redeemAndRemove - -```solidity -function redeemAndRemove(address to, uint256 chainId, contract IERC20 token, uint256 amount, uint8 liqTokenIndex, uint256 liqMinAmount, uint256 liqDeadline) external nonpayable -``` - -Wraps redeemAndRemove on SynapseBridge Relays to nodes that (typically) a wrapped synAsset ERC20 token has been burned and the underlying needs to be redeeemed on the native chain. This function indicates to the nodes that they should attempt to redeem the LP token for the underlying assets (E.g "swap" out of the LP token) - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| to | address | address on other chain to redeem underlying assets to | -| chainId | uint256 | which underlying chain to bridge assets onto | -| token | contract IERC20 | ERC20 compatible token to deposit into the bridge | -| amount | uint256 | Amount of (typically) LP token to pass to the nodes to attempt to removeLiquidity() with to redeem for the underlying assets of the LP token | -| liqTokenIndex | uint8 | Specifies which of the underlying LP assets the nodes should attempt to redeem for | -| liqMinAmount | uint256 | Specifies the minimum amount of the underlying asset needed for the nodes to execute the redeem/swap | -| liqDeadline | uint256 | Specificies the deadline that the nodes are allowed to try to redeem/swap the LP token* | - -### redeemAndSwap - -```solidity -function redeemAndSwap(address to, uint256 chainId, contract IERC20 token, uint256 amount, uint8 tokenIndexFrom, uint8 tokenIndexTo, uint256 minDy, uint256 deadline) external nonpayable -``` - -Wraps redeemAndSwap on SynapseBridge.sol Relays to nodes that (typically) a wrapped synAsset ERC20 token has been burned and the underlying needs to be redeeemed on the native chain. This function indicates to the nodes that they should attempt to redeem the LP token for the underlying assets (E.g "swap" out of the LP token) - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| to | address | address on other chain to redeem underlying assets to | -| chainId | uint256 | which underlying chain to bridge assets onto | -| token | contract IERC20 | ERC20 compatible token to deposit into the bridge | -| amount | uint256 | Amount in native token decimals to transfer cross-chain pre-fees | -| tokenIndexFrom | uint8 | the token the user wants to swap from | -| tokenIndexTo | uint8 | the token the user wants to swap to | -| minDy | uint256 | the min amount the user would like to receive, or revert to only minting the SynERC20 token crosschain. | -| deadline | uint256 | latest timestamp to accept this transaction* | - -### redeemv2 - -```solidity -function redeemv2(bytes32 to, uint256 chainId, contract IERC20 token, uint256 amount) external nonpayable -``` - -Wraps SynapseBridge redeemv2() function - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| to | bytes32 | address on other chain to bridge assets to | -| chainId | uint256 | which chain to bridge assets onto | -| token | contract IERC20 | ERC20 compatible token to redeem into the bridge | -| amount | uint256 | Amount in native token decimals to transfer cross-chain pre-fees* | - -### swapAndRedeem - -```solidity -function swapAndRedeem(address to, uint256 chainId, contract IERC20 token, uint8 tokenIndexFrom, uint8 tokenIndexTo, uint256 dx, uint256 minDy, uint256 deadline) external nonpayable -``` - - - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| to | address | undefined | -| chainId | uint256 | undefined | -| token | contract IERC20 | undefined | -| tokenIndexFrom | uint8 | undefined | -| tokenIndexTo | uint8 | undefined | -| dx | uint256 | undefined | -| minDy | uint256 | undefined | -| deadline | uint256 | undefined | - -### swapAndRedeemAndRemove - -```solidity -function swapAndRedeemAndRemove(address to, uint256 chainId, contract IERC20 token, uint8 tokenIndexFrom, uint8 tokenIndexTo, uint256 dx, uint256 minDy, uint256 deadline, uint8 liqTokenIndex, uint256 liqMinAmount, uint256 liqDeadline) external nonpayable -``` - - - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| to | address | undefined | -| chainId | uint256 | undefined | -| token | contract IERC20 | undefined | -| tokenIndexFrom | uint8 | undefined | -| tokenIndexTo | uint8 | undefined | -| dx | uint256 | undefined | -| minDy | uint256 | undefined | -| deadline | uint256 | undefined | -| liqTokenIndex | uint8 | undefined | -| liqMinAmount | uint256 | undefined | -| liqDeadline | uint256 | undefined | - -### swapAndRedeemAndSwap - -```solidity -function swapAndRedeemAndSwap(address to, uint256 chainId, contract IERC20 token, uint8 tokenIndexFrom, uint8 tokenIndexTo, uint256 dx, uint256 minDy, uint256 deadline, uint8 swapTokenIndexFrom, uint8 swapTokenIndexTo, uint256 swapMinDy, uint256 swapDeadline) external nonpayable -``` - - - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| to | address | undefined | -| chainId | uint256 | undefined | -| token | contract IERC20 | undefined | -| tokenIndexFrom | uint8 | undefined | -| tokenIndexTo | uint8 | undefined | -| dx | uint256 | undefined | -| minDy | uint256 | undefined | -| deadline | uint256 | undefined | -| swapTokenIndexFrom | uint8 | undefined | -| swapTokenIndexTo | uint8 | undefined | -| swapMinDy | uint256 | undefined | -| swapDeadline | uint256 | undefined | - -### swapETHAndRedeem - -```solidity -function swapETHAndRedeem(address to, uint256 chainId, contract IERC20 token, uint8 tokenIndexFrom, uint8 tokenIndexTo, uint256 dx, uint256 minDy, uint256 deadline) external payable -``` - - - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| to | address | undefined | -| chainId | uint256 | undefined | -| token | contract IERC20 | undefined | -| tokenIndexFrom | uint8 | undefined | -| tokenIndexTo | uint8 | undefined | -| dx | uint256 | undefined | -| minDy | uint256 | undefined | -| deadline | uint256 | undefined | - -### swapETHAndRedeemAndSwap - -```solidity -function swapETHAndRedeemAndSwap(address to, uint256 chainId, contract IERC20 token, uint8 tokenIndexFrom, uint8 tokenIndexTo, uint256 dx, uint256 minDy, uint256 deadline, uint8 swapTokenIndexFrom, uint8 swapTokenIndexTo, uint256 swapMinDy, uint256 swapDeadline) external payable -``` - - - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| to | address | undefined | -| chainId | uint256 | undefined | -| token | contract IERC20 | undefined | -| tokenIndexFrom | uint8 | undefined | -| tokenIndexTo | uint8 | undefined | -| dx | uint256 | undefined | -| minDy | uint256 | undefined | -| deadline | uint256 | undefined | -| swapTokenIndexFrom | uint8 | undefined | -| swapTokenIndexTo | uint8 | undefined | -| swapMinDy | uint256 | undefined | -| swapDeadline | uint256 | undefined | - -### swapMap - -```solidity -function swapMap(address) external view returns (address) -``` - - - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| _0 | address | undefined | - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | address | undefined | - -### swapTokensMap - -```solidity -function swapTokensMap(address, uint256) external view returns (contract IERC20) -``` - - - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| _0 | address | undefined | -| _1 | uint256 | undefined | - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | contract IERC20 | undefined | - - - - diff --git a/docs/bridge/wrappers/MigratorBridgeZap.md b/docs/bridge/wrappers/MigratorBridgeZap.md deleted file mode 100644 index ffd90c60d..000000000 --- a/docs/bridge/wrappers/MigratorBridgeZap.md +++ /dev/null @@ -1,49 +0,0 @@ -# MigratorBridgeZap - - - - - - - - - -## Methods - -### migrate - -```solidity -function migrate(uint256 amount) external nonpayable -``` - - - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| amount | uint256 | undefined | - -### migrateAndBridge - -```solidity -function migrateAndBridge(uint256 amount, address to, uint256 chainId) external nonpayable -``` - - - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| amount | uint256 | undefined | -| to | address | undefined | -| chainId | uint256 | undefined | - - - - diff --git a/docs/bridge/wrappers/MoonriverBridgeZap.md b/docs/bridge/wrappers/MoonriverBridgeZap.md deleted file mode 100644 index bb1707f7a..000000000 --- a/docs/bridge/wrappers/MoonriverBridgeZap.md +++ /dev/null @@ -1,321 +0,0 @@ -# MoonriverBridgeZap - - - - - - - - - -## Methods - -### WETH_ADDRESS - -```solidity -function WETH_ADDRESS() external view returns (address payable) -``` - - - - - - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | address payable | undefined | - -### calculateSwap - -```solidity -function calculateSwap(contract IERC20 token, uint8 tokenIndexFrom, uint8 tokenIndexTo, uint256 dx) external view returns (uint256) -``` - -Calculate amount of tokens you receive on swap - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| token | contract IERC20 | undefined | -| tokenIndexFrom | uint8 | the token the user wants to sell | -| tokenIndexTo | uint8 | the token the user wants to buy | -| dx | uint256 | the amount of tokens the user wants to sell. If the token charges a fee on transfers, use the amount that gets transferred after the fee. | - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | uint256 | amount of tokens the user will receive | - -### deposit - -```solidity -function deposit(address to, uint256 chainId, contract IERC20 token, uint256 amount) external nonpayable -``` - -wraps SynapseBridge redeem() - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| to | address | address on other chain to redeem underlying assets to | -| chainId | uint256 | which underlying chain to bridge assets onto | -| token | contract IERC20 | ERC20 compatible token to deposit into the bridge | -| amount | uint256 | Amount in native token decimals to transfer cross-chain pre-fees* | - -### depositETH - -```solidity -function depositETH(address to, uint256 chainId, uint256 amount) external payable -``` - -Wraps SynapseBridge deposit() function to make it compatible w/ ETH -> WETH conversions - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| to | address | address on other chain to bridge assets to | -| chainId | uint256 | which chain to bridge assets onto | -| amount | uint256 | Amount in native token decimals to transfer cross-chain pre-fees* | - -### redeem - -```solidity -function redeem(address to, uint256 chainId, contract IERC20 token, uint256 amount) external nonpayable -``` - -wraps SynapseBridge redeem() - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| to | address | address on other chain to redeem underlying assets to | -| chainId | uint256 | which underlying chain to bridge assets onto | -| token | contract IERC20 | ERC20 compatible token to deposit into the bridge | -| amount | uint256 | Amount in native token decimals to transfer cross-chain pre-fees* | - -### redeemAndRemove - -```solidity -function redeemAndRemove(address to, uint256 chainId, contract IERC20 token, uint256 amount, uint8 liqTokenIndex, uint256 liqMinAmount, uint256 liqDeadline) external nonpayable -``` - -Wraps redeemAndRemove on SynapseBridge Relays to nodes that (typically) a wrapped synAsset ERC20 token has been burned and the underlying needs to be redeeemed on the native chain. This function indicates to the nodes that they should attempt to redeem the LP token for the underlying assets (E.g "swap" out of the LP token) - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| to | address | address on other chain to redeem underlying assets to | -| chainId | uint256 | which underlying chain to bridge assets onto | -| token | contract IERC20 | ERC20 compatible token to deposit into the bridge | -| amount | uint256 | Amount of (typically) LP token to pass to the nodes to attempt to removeLiquidity() with to redeem for the underlying assets of the LP token | -| liqTokenIndex | uint8 | Specifies which of the underlying LP assets the nodes should attempt to redeem for | -| liqMinAmount | uint256 | Specifies the minimum amount of the underlying asset needed for the nodes to execute the redeem/swap | -| liqDeadline | uint256 | Specificies the deadline that the nodes are allowed to try to redeem/swap the LP token* | - -### redeemAndSwap - -```solidity -function redeemAndSwap(address to, uint256 chainId, contract IERC20 token, uint256 amount, uint8 tokenIndexFrom, uint8 tokenIndexTo, uint256 minDy, uint256 deadline) external nonpayable -``` - -Wraps redeemAndSwap on SynapseBridge.sol Relays to nodes that (typically) a wrapped synAsset ERC20 token has been burned and the underlying needs to be redeeemed on the native chain. This function indicates to the nodes that they should attempt to redeem the LP token for the underlying assets (E.g "swap" out of the LP token) - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| to | address | address on other chain to redeem underlying assets to | -| chainId | uint256 | which underlying chain to bridge assets onto | -| token | contract IERC20 | ERC20 compatible token to deposit into the bridge | -| amount | uint256 | Amount in native token decimals to transfer cross-chain pre-fees | -| tokenIndexFrom | uint8 | the token the user wants to swap from | -| tokenIndexTo | uint8 | the token the user wants to swap to | -| minDy | uint256 | the min amount the user would like to receive, or revert to only minting the SynERC20 token crosschain. | -| deadline | uint256 | latest timestamp to accept this transaction* | - -### redeemv2 - -```solidity -function redeemv2(bytes32 to, uint256 chainId, contract IERC20 token, uint256 amount) external nonpayable -``` - -Wraps SynapseBridge redeemv2() function - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| to | bytes32 | address on other chain to bridge assets to | -| chainId | uint256 | which chain to bridge assets onto | -| token | contract IERC20 | ERC20 compatible token to redeem into the bridge | -| amount | uint256 | Amount in native token decimals to transfer cross-chain pre-fees* | - -### swapAndRedeem - -```solidity -function swapAndRedeem(address to, uint256 chainId, contract IERC20 token, uint8 tokenIndexFrom, uint8 tokenIndexTo, uint256 dx, uint256 minDy, uint256 deadline) external nonpayable -``` - - - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| to | address | undefined | -| chainId | uint256 | undefined | -| token | contract IERC20 | undefined | -| tokenIndexFrom | uint8 | undefined | -| tokenIndexTo | uint8 | undefined | -| dx | uint256 | undefined | -| minDy | uint256 | undefined | -| deadline | uint256 | undefined | - -### swapAndRedeemAndRemove - -```solidity -function swapAndRedeemAndRemove(address to, uint256 chainId, contract IERC20 token, uint8 tokenIndexFrom, uint8 tokenIndexTo, uint256 dx, uint256 minDy, uint256 deadline, uint8 liqTokenIndex, uint256 liqMinAmount, uint256 liqDeadline) external nonpayable -``` - - - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| to | address | undefined | -| chainId | uint256 | undefined | -| token | contract IERC20 | undefined | -| tokenIndexFrom | uint8 | undefined | -| tokenIndexTo | uint8 | undefined | -| dx | uint256 | undefined | -| minDy | uint256 | undefined | -| deadline | uint256 | undefined | -| liqTokenIndex | uint8 | undefined | -| liqMinAmount | uint256 | undefined | -| liqDeadline | uint256 | undefined | - -### swapAndRedeemAndSwap - -```solidity -function swapAndRedeemAndSwap(address to, uint256 chainId, contract IERC20 token, uint8 tokenIndexFrom, uint8 tokenIndexTo, uint256 dx, uint256 minDy, uint256 deadline, uint8 swapTokenIndexFrom, uint8 swapTokenIndexTo, uint256 swapMinDy, uint256 swapDeadline) external nonpayable -``` - - - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| to | address | undefined | -| chainId | uint256 | undefined | -| token | contract IERC20 | undefined | -| tokenIndexFrom | uint8 | undefined | -| tokenIndexTo | uint8 | undefined | -| dx | uint256 | undefined | -| minDy | uint256 | undefined | -| deadline | uint256 | undefined | -| swapTokenIndexFrom | uint8 | undefined | -| swapTokenIndexTo | uint8 | undefined | -| swapMinDy | uint256 | undefined | -| swapDeadline | uint256 | undefined | - -### swapETHAndRedeem - -```solidity -function swapETHAndRedeem(address to, uint256 chainId, contract IERC20 token, uint8 tokenIndexFrom, uint8 tokenIndexTo, uint256 dx, uint256 minDy, uint256 deadline) external payable -``` - - - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| to | address | undefined | -| chainId | uint256 | undefined | -| token | contract IERC20 | undefined | -| tokenIndexFrom | uint8 | undefined | -| tokenIndexTo | uint8 | undefined | -| dx | uint256 | undefined | -| minDy | uint256 | undefined | -| deadline | uint256 | undefined | - -### swapMap - -```solidity -function swapMap(address) external view returns (address) -``` - - - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| _0 | address | undefined | - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | address | undefined | - -### swapTokensMap - -```solidity -function swapTokensMap(address, uint256) external view returns (contract IERC20) -``` - - - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| _0 | address | undefined | -| _1 | uint256 | undefined | - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | contract IERC20 | undefined | - - - - diff --git a/docs/console.md b/docs/console.md deleted file mode 100644 index 8bab67a46..000000000 --- a/docs/console.md +++ /dev/null @@ -1,12 +0,0 @@ -# console - - - - - - - - - - - diff --git a/docs/elin/contracts-4.3.1-upgradeable/access/AccessControlUpgradeable.md b/docs/elin/contracts-4.3.1-upgradeable/access/AccessControlUpgradeable.md deleted file mode 100644 index c52e7d992..000000000 --- a/docs/elin/contracts-4.3.1-upgradeable/access/AccessControlUpgradeable.md +++ /dev/null @@ -1,207 +0,0 @@ -# AccessControlUpgradeable - - - - - - - -*Contract module that allows children to implement role-based access control mechanisms. This is a lightweight version that doesn't allow enumerating role members except through off-chain means by accessing the contract event logs. Some applications may benefit from on-chain enumerability, for those cases see {AccessControlEnumerable}. Roles are referred to by their `bytes32` identifier. These should be exposed in the external API and be unique. The best way to achieve this is by using `public constant` hash digests: ``` bytes32 public constant MY_ROLE = keccak256("MY_ROLE"); ``` Roles can be used to represent a set of permissions. To restrict access to a function call, use {hasRole}: ``` function foo() public { require(hasRole(MY_ROLE, msg.sender)); ... } ``` Roles can be granted and revoked dynamically via the {grantRole} and {revokeRole} functions. Each role has an associated admin role, and only accounts that have a role's admin role can call {grantRole} and {revokeRole}. By default, the admin role for all roles is `DEFAULT_ADMIN_ROLE`, which means that only accounts with this role will be able to grant or revoke other roles. More complex role relationships can be created by using {_setRoleAdmin}. WARNING: The `DEFAULT_ADMIN_ROLE` is also its own admin: it has permission to grant and revoke this role. Extra precautions should be taken to secure accounts that have been granted it.* - -## Methods - -### DEFAULT_ADMIN_ROLE - -```solidity -function DEFAULT_ADMIN_ROLE() external view returns (bytes32) -``` - - - - - - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | bytes32 | undefined | - -### getRoleAdmin - -```solidity -function getRoleAdmin(bytes32 role) external view returns (bytes32) -``` - - - -*Returns the admin role that controls `role`. See {grantRole} and {revokeRole}. To change a role's admin, use {_setRoleAdmin}.* - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| role | bytes32 | undefined | - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | bytes32 | undefined | - -### grantRole - -```solidity -function grantRole(bytes32 role, address account) external nonpayable -``` - - - -*Grants `role` to `account`. If `account` had not been already granted `role`, emits a {RoleGranted} event. Requirements: - the caller must have ``role``'s admin role.* - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| role | bytes32 | undefined | -| account | address | undefined | - -### hasRole - -```solidity -function hasRole(bytes32 role, address account) external view returns (bool) -``` - - - -*Returns `true` if `account` has been granted `role`.* - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| role | bytes32 | undefined | -| account | address | undefined | - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | bool | undefined | - -### renounceRole - -```solidity -function renounceRole(bytes32 role, address account) external nonpayable -``` - - - -*Revokes `role` from the calling account. Roles are often managed via {grantRole} and {revokeRole}: this function's purpose is to provide a mechanism for accounts to lose their privileges if they are compromised (such as when a trusted device is misplaced). If the calling account had been revoked `role`, emits a {RoleRevoked} event. Requirements: - the caller must be `account`.* - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| role | bytes32 | undefined | -| account | address | undefined | - -### revokeRole - -```solidity -function revokeRole(bytes32 role, address account) external nonpayable -``` - - - -*Revokes `role` from `account`. If `account` had been granted `role`, emits a {RoleRevoked} event. Requirements: - the caller must have ``role``'s admin role.* - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| role | bytes32 | undefined | -| account | address | undefined | - -### supportsInterface - -```solidity -function supportsInterface(bytes4 interfaceId) external view returns (bool) -``` - - - -*See {IERC165-supportsInterface}.* - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| interfaceId | bytes4 | undefined | - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | bool | undefined | - - - -## Events - -### RoleAdminChanged - -```solidity -event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole) -``` - - - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| role `indexed` | bytes32 | undefined | -| previousAdminRole `indexed` | bytes32 | undefined | -| newAdminRole `indexed` | bytes32 | undefined | - -### RoleGranted - -```solidity -event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender) -``` - - - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| role `indexed` | bytes32 | undefined | -| account `indexed` | address | undefined | -| sender `indexed` | address | undefined | - -### RoleRevoked - -```solidity -event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender) -``` - - - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| role `indexed` | bytes32 | undefined | -| account `indexed` | address | undefined | -| sender `indexed` | address | undefined | - - - diff --git a/docs/elin/contracts-4.3.1-upgradeable/access/IAccessControlUpgradeable.md b/docs/elin/contracts-4.3.1-upgradeable/access/IAccessControlUpgradeable.md deleted file mode 100644 index 4ad76fe12..000000000 --- a/docs/elin/contracts-4.3.1-upgradeable/access/IAccessControlUpgradeable.md +++ /dev/null @@ -1,168 +0,0 @@ -# IAccessControlUpgradeable - - - - - - - -*External interface of AccessControl declared to support ERC165 detection.* - -## Methods - -### getRoleAdmin - -```solidity -function getRoleAdmin(bytes32 role) external view returns (bytes32) -``` - - - -*Returns the admin role that controls `role`. See {grantRole} and {revokeRole}. To change a role's admin, use {AccessControl-_setRoleAdmin}.* - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| role | bytes32 | undefined | - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | bytes32 | undefined | - -### grantRole - -```solidity -function grantRole(bytes32 role, address account) external nonpayable -``` - - - -*Grants `role` to `account`. If `account` had not been already granted `role`, emits a {RoleGranted} event. Requirements: - the caller must have ``role``'s admin role.* - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| role | bytes32 | undefined | -| account | address | undefined | - -### hasRole - -```solidity -function hasRole(bytes32 role, address account) external view returns (bool) -``` - - - -*Returns `true` if `account` has been granted `role`.* - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| role | bytes32 | undefined | -| account | address | undefined | - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | bool | undefined | - -### renounceRole - -```solidity -function renounceRole(bytes32 role, address account) external nonpayable -``` - - - -*Revokes `role` from the calling account. Roles are often managed via {grantRole} and {revokeRole}: this function's purpose is to provide a mechanism for accounts to lose their privileges if they are compromised (such as when a trusted device is misplaced). If the calling account had been granted `role`, emits a {RoleRevoked} event. Requirements: - the caller must be `account`.* - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| role | bytes32 | undefined | -| account | address | undefined | - -### revokeRole - -```solidity -function revokeRole(bytes32 role, address account) external nonpayable -``` - - - -*Revokes `role` from `account`. If `account` had been granted `role`, emits a {RoleRevoked} event. Requirements: - the caller must have ``role``'s admin role.* - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| role | bytes32 | undefined | -| account | address | undefined | - - - -## Events - -### RoleAdminChanged - -```solidity -event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole) -``` - - - -*Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole` `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite {RoleAdminChanged} not being emitted signaling this. _Available since v3.1._* - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| role `indexed` | bytes32 | undefined | -| previousAdminRole `indexed` | bytes32 | undefined | -| newAdminRole `indexed` | bytes32 | undefined | - -### RoleGranted - -```solidity -event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender) -``` - - - -*Emitted when `account` is granted `role`. `sender` is the account that originated the contract call, an admin role bearer except when using {AccessControl-_setupRole}.* - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| role `indexed` | bytes32 | undefined | -| account `indexed` | address | undefined | -| sender `indexed` | address | undefined | - -### RoleRevoked - -```solidity -event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender) -``` - - - -*Emitted when `account` is revoked `role`. `sender` is the account that originated the contract call: - if using `revokeRole`, it is the admin role bearer - if using `renounceRole`, it is the role bearer (i.e. `account`)* - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| role `indexed` | bytes32 | undefined | -| account `indexed` | address | undefined | -| sender `indexed` | address | undefined | - - - diff --git a/docs/elin/contracts-4.3.1-upgradeable/proxy/utils/Initializable.md b/docs/elin/contracts-4.3.1-upgradeable/proxy/utils/Initializable.md deleted file mode 100644 index 647d95b62..000000000 --- a/docs/elin/contracts-4.3.1-upgradeable/proxy/utils/Initializable.md +++ /dev/null @@ -1,12 +0,0 @@ -# Initializable - - - - - - - -*This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed behind a proxy. Since proxied contracts do not make use of a constructor, it's common to move constructor logic to an external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer function so it can only be called once. The {initializer} modifier provided by this contract will have this effect. TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as possible by providing the encoded function call as the `_data` argument to {ERC1967Proxy-constructor}. CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure that all initializers are idempotent. This is not verified automatically as constructors are by Solidity. [CAUTION] ==== Avoid leaving a contract uninitialized. An uninitialized contract can be taken over by an attacker. This applies to both a proxy and its implementation contract, which may impact the proxy. To initialize the implementation contract, you can either invoke the initializer manually, or you can include a constructor to automatically mark it as initialized when it is deployed: [.hljs-theme-light.nopadding] ```* - - - diff --git a/docs/elin/contracts-4.3.1-upgradeable/security/ReentrancyGuardUpgradeable.md b/docs/elin/contracts-4.3.1-upgradeable/security/ReentrancyGuardUpgradeable.md deleted file mode 100644 index 6955ca2de..000000000 --- a/docs/elin/contracts-4.3.1-upgradeable/security/ReentrancyGuardUpgradeable.md +++ /dev/null @@ -1,12 +0,0 @@ -# ReentrancyGuardUpgradeable - - - - - - - -*Contract module that helps prevent reentrant calls to a function. Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier available, which can be applied to functions to make sure there are no nested (reentrant) calls to them. Note that because there is a single `nonReentrant` guard, functions marked as `nonReentrant` may not call one another. This can be worked around by making those functions `private`, and then adding `external` `nonReentrant` entry points to them. TIP: If you would like to learn more about reentrancy and alternative ways to protect against it, check out our blog post https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul].* - - - diff --git a/docs/elin/contracts-4.3.1-upgradeable/utils/AddressUpgradeable.md b/docs/elin/contracts-4.3.1-upgradeable/utils/AddressUpgradeable.md deleted file mode 100644 index 456cdd15d..000000000 --- a/docs/elin/contracts-4.3.1-upgradeable/utils/AddressUpgradeable.md +++ /dev/null @@ -1,12 +0,0 @@ -# AddressUpgradeable - - - - - - - -*Collection of functions related to the address type* - - - diff --git a/docs/elin/contracts-4.3.1-upgradeable/utils/ContextUpgradeable.md b/docs/elin/contracts-4.3.1-upgradeable/utils/ContextUpgradeable.md deleted file mode 100644 index 18f33b80f..000000000 --- a/docs/elin/contracts-4.3.1-upgradeable/utils/ContextUpgradeable.md +++ /dev/null @@ -1,12 +0,0 @@ -# ContextUpgradeable - - - - - - - -*Provides information about the current execution context, including the sender of the transaction and its data. While these are generally available via msg.sender and msg.data, they should not be accessed in such a direct manner, since when dealing with meta-transactions the account sending and paying for execution may not be the actual sender (as far as an application is concerned). This contract is only required for intermediate, library-like contracts.* - - - diff --git a/docs/elin/contracts-4.3.1-upgradeable/utils/StringsUpgradeable.md b/docs/elin/contracts-4.3.1-upgradeable/utils/StringsUpgradeable.md deleted file mode 100644 index 84464ba83..000000000 --- a/docs/elin/contracts-4.3.1-upgradeable/utils/StringsUpgradeable.md +++ /dev/null @@ -1,12 +0,0 @@ -# StringsUpgradeable - - - - - - - -*String operations.* - - - diff --git a/docs/elin/contracts-4.3.1-upgradeable/utils/introspection/ERC165Upgradeable.md b/docs/elin/contracts-4.3.1-upgradeable/utils/introspection/ERC165Upgradeable.md deleted file mode 100644 index 914b09248..000000000 --- a/docs/elin/contracts-4.3.1-upgradeable/utils/introspection/ERC165Upgradeable.md +++ /dev/null @@ -1,37 +0,0 @@ -# ERC165Upgradeable - - - - - - - -*Implementation of the {IERC165} interface. Contracts that want to implement ERC165 should inherit from this contract and override {supportsInterface} to check for the additional interface id that will be supported. For example: ```solidity function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) { return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId); } ``` Alternatively, {ERC165Storage} provides an easier to use but more expensive implementation.* - -## Methods - -### supportsInterface - -```solidity -function supportsInterface(bytes4 interfaceId) external view returns (bool) -``` - - - -*See {IERC165-supportsInterface}.* - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| interfaceId | bytes4 | undefined | - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | bool | undefined | - - - - diff --git a/docs/elin/contracts-4.3.1-upgradeable/utils/introspection/IERC165Upgradeable.md b/docs/elin/contracts-4.3.1-upgradeable/utils/introspection/IERC165Upgradeable.md deleted file mode 100644 index 40ec0512e..000000000 --- a/docs/elin/contracts-4.3.1-upgradeable/utils/introspection/IERC165Upgradeable.md +++ /dev/null @@ -1,37 +0,0 @@ -# IERC165Upgradeable - - - - - - - -*Interface of the ERC165 standard, as defined in the https://eips.ethereum.org/EIPS/eip-165[EIP]. Implementers can declare support of contract interfaces, which can then be queried by others ({ERC165Checker}). For an implementation, see {ERC165}.* - -## Methods - -### supportsInterface - -```solidity -function supportsInterface(bytes4 interfaceId) external view returns (bool) -``` - - - -*Returns true if this contract implements the interface defined by `interfaceId`. See the corresponding https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section] to learn more about how these ids are created. This function call must use less than 30 000 gas.* - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| interfaceId | bytes4 | undefined | - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | bool | undefined | - - - - diff --git a/docs/elin/contracts-4.3.1/access/AccessControl.md b/docs/elin/contracts-4.3.1/access/AccessControl.md deleted file mode 100644 index 9fdf479dd..000000000 --- a/docs/elin/contracts-4.3.1/access/AccessControl.md +++ /dev/null @@ -1,207 +0,0 @@ -# AccessControl - - - - - - - -*Contract module that allows children to implement role-based access control mechanisms. This is a lightweight version that doesn't allow enumerating role members except through off-chain means by accessing the contract event logs. Some applications may benefit from on-chain enumerability, for those cases see {AccessControlEnumerable}. Roles are referred to by their `bytes32` identifier. These should be exposed in the external API and be unique. The best way to achieve this is by using `public constant` hash digests: ``` bytes32 public constant MY_ROLE = keccak256("MY_ROLE"); ``` Roles can be used to represent a set of permissions. To restrict access to a function call, use {hasRole}: ``` function foo() public { require(hasRole(MY_ROLE, msg.sender)); ... } ``` Roles can be granted and revoked dynamically via the {grantRole} and {revokeRole} functions. Each role has an associated admin role, and only accounts that have a role's admin role can call {grantRole} and {revokeRole}. By default, the admin role for all roles is `DEFAULT_ADMIN_ROLE`, which means that only accounts with this role will be able to grant or revoke other roles. More complex role relationships can be created by using {_setRoleAdmin}. WARNING: The `DEFAULT_ADMIN_ROLE` is also its own admin: it has permission to grant and revoke this role. Extra precautions should be taken to secure accounts that have been granted it.* - -## Methods - -### DEFAULT_ADMIN_ROLE - -```solidity -function DEFAULT_ADMIN_ROLE() external view returns (bytes32) -``` - - - - - - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | bytes32 | undefined | - -### getRoleAdmin - -```solidity -function getRoleAdmin(bytes32 role) external view returns (bytes32) -``` - - - -*Returns the admin role that controls `role`. See {grantRole} and {revokeRole}. To change a role's admin, use {_setRoleAdmin}.* - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| role | bytes32 | undefined | - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | bytes32 | undefined | - -### grantRole - -```solidity -function grantRole(bytes32 role, address account) external nonpayable -``` - - - -*Grants `role` to `account`. If `account` had not been already granted `role`, emits a {RoleGranted} event. Requirements: - the caller must have ``role``'s admin role.* - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| role | bytes32 | undefined | -| account | address | undefined | - -### hasRole - -```solidity -function hasRole(bytes32 role, address account) external view returns (bool) -``` - - - -*Returns `true` if `account` has been granted `role`.* - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| role | bytes32 | undefined | -| account | address | undefined | - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | bool | undefined | - -### renounceRole - -```solidity -function renounceRole(bytes32 role, address account) external nonpayable -``` - - - -*Revokes `role` from the calling account. Roles are often managed via {grantRole} and {revokeRole}: this function's purpose is to provide a mechanism for accounts to lose their privileges if they are compromised (such as when a trusted device is misplaced). If the calling account had been revoked `role`, emits a {RoleRevoked} event. Requirements: - the caller must be `account`.* - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| role | bytes32 | undefined | -| account | address | undefined | - -### revokeRole - -```solidity -function revokeRole(bytes32 role, address account) external nonpayable -``` - - - -*Revokes `role` from `account`. If `account` had been granted `role`, emits a {RoleRevoked} event. Requirements: - the caller must have ``role``'s admin role.* - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| role | bytes32 | undefined | -| account | address | undefined | - -### supportsInterface - -```solidity -function supportsInterface(bytes4 interfaceId) external view returns (bool) -``` - - - -*See {IERC165-supportsInterface}.* - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| interfaceId | bytes4 | undefined | - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | bool | undefined | - - - -## Events - -### RoleAdminChanged - -```solidity -event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole) -``` - - - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| role `indexed` | bytes32 | undefined | -| previousAdminRole `indexed` | bytes32 | undefined | -| newAdminRole `indexed` | bytes32 | undefined | - -### RoleGranted - -```solidity -event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender) -``` - - - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| role `indexed` | bytes32 | undefined | -| account `indexed` | address | undefined | -| sender `indexed` | address | undefined | - -### RoleRevoked - -```solidity -event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender) -``` - - - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| role `indexed` | bytes32 | undefined | -| account `indexed` | address | undefined | -| sender `indexed` | address | undefined | - - - diff --git a/docs/elin/contracts-4.3.1/access/IAccessControl.md b/docs/elin/contracts-4.3.1/access/IAccessControl.md deleted file mode 100644 index 1916d28b3..000000000 --- a/docs/elin/contracts-4.3.1/access/IAccessControl.md +++ /dev/null @@ -1,168 +0,0 @@ -# IAccessControl - - - - - - - -*External interface of AccessControl declared to support ERC165 detection.* - -## Methods - -### getRoleAdmin - -```solidity -function getRoleAdmin(bytes32 role) external view returns (bytes32) -``` - - - -*Returns the admin role that controls `role`. See {grantRole} and {revokeRole}. To change a role's admin, use {AccessControl-_setRoleAdmin}.* - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| role | bytes32 | undefined | - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | bytes32 | undefined | - -### grantRole - -```solidity -function grantRole(bytes32 role, address account) external nonpayable -``` - - - -*Grants `role` to `account`. If `account` had not been already granted `role`, emits a {RoleGranted} event. Requirements: - the caller must have ``role``'s admin role.* - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| role | bytes32 | undefined | -| account | address | undefined | - -### hasRole - -```solidity -function hasRole(bytes32 role, address account) external view returns (bool) -``` - - - -*Returns `true` if `account` has been granted `role`.* - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| role | bytes32 | undefined | -| account | address | undefined | - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | bool | undefined | - -### renounceRole - -```solidity -function renounceRole(bytes32 role, address account) external nonpayable -``` - - - -*Revokes `role` from the calling account. Roles are often managed via {grantRole} and {revokeRole}: this function's purpose is to provide a mechanism for accounts to lose their privileges if they are compromised (such as when a trusted device is misplaced). If the calling account had been granted `role`, emits a {RoleRevoked} event. Requirements: - the caller must be `account`.* - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| role | bytes32 | undefined | -| account | address | undefined | - -### revokeRole - -```solidity -function revokeRole(bytes32 role, address account) external nonpayable -``` - - - -*Revokes `role` from `account`. If `account` had been granted `role`, emits a {RoleRevoked} event. Requirements: - the caller must have ``role``'s admin role.* - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| role | bytes32 | undefined | -| account | address | undefined | - - - -## Events - -### RoleAdminChanged - -```solidity -event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole) -``` - - - -*Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole` `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite {RoleAdminChanged} not being emitted signaling this. _Available since v3.1._* - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| role `indexed` | bytes32 | undefined | -| previousAdminRole `indexed` | bytes32 | undefined | -| newAdminRole `indexed` | bytes32 | undefined | - -### RoleGranted - -```solidity -event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender) -``` - - - -*Emitted when `account` is granted `role`. `sender` is the account that originated the contract call, an admin role bearer except when using {AccessControl-_setupRole}.* - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| role `indexed` | bytes32 | undefined | -| account `indexed` | address | undefined | -| sender `indexed` | address | undefined | - -### RoleRevoked - -```solidity -event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender) -``` - - - -*Emitted when `account` is revoked `role`. `sender` is the account that originated the contract call: - if using `revokeRole`, it is the admin role bearer - if using `renounceRole`, it is the role bearer (i.e. `account`)* - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| role `indexed` | bytes32 | undefined | -| account `indexed` | address | undefined | -| sender `indexed` | address | undefined | - - - diff --git a/docs/elin/contracts-4.3.1/utils/Context.md b/docs/elin/contracts-4.3.1/utils/Context.md deleted file mode 100644 index 4ab2a3548..000000000 --- a/docs/elin/contracts-4.3.1/utils/Context.md +++ /dev/null @@ -1,12 +0,0 @@ -# Context - - - - - - - -*Provides information about the current execution context, including the sender of the transaction and its data. While these are generally available via msg.sender and msg.data, they should not be accessed in such a direct manner, since when dealing with meta-transactions the account sending and paying for execution may not be the actual sender (as far as an application is concerned). This contract is only required for intermediate, library-like contracts.* - - - diff --git a/docs/elin/contracts-4.3.1/utils/Strings.md b/docs/elin/contracts-4.3.1/utils/Strings.md deleted file mode 100644 index f85055d64..000000000 --- a/docs/elin/contracts-4.3.1/utils/Strings.md +++ /dev/null @@ -1,12 +0,0 @@ -# Strings - - - - - - - -*String operations.* - - - diff --git a/docs/elin/contracts-4.3.1/utils/introspection/ERC165.md b/docs/elin/contracts-4.3.1/utils/introspection/ERC165.md deleted file mode 100644 index df8950ab9..000000000 --- a/docs/elin/contracts-4.3.1/utils/introspection/ERC165.md +++ /dev/null @@ -1,37 +0,0 @@ -# ERC165 - - - - - - - -*Implementation of the {IERC165} interface. Contracts that want to implement ERC165 should inherit from this contract and override {supportsInterface} to check for the additional interface id that will be supported. For example: ```solidity function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) { return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId); } ``` Alternatively, {ERC165Storage} provides an easier to use but more expensive implementation.* - -## Methods - -### supportsInterface - -```solidity -function supportsInterface(bytes4 interfaceId) external view returns (bool) -``` - - - -*See {IERC165-supportsInterface}.* - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| interfaceId | bytes4 | undefined | - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | bool | undefined | - - - - diff --git a/docs/elin/contracts-4.3.1/utils/introspection/IERC165.md b/docs/elin/contracts-4.3.1/utils/introspection/IERC165.md deleted file mode 100644 index 71a9f6e6d..000000000 --- a/docs/elin/contracts-4.3.1/utils/introspection/IERC165.md +++ /dev/null @@ -1,37 +0,0 @@ -# IERC165 - - - - - - - -*Interface of the ERC165 standard, as defined in the https://eips.ethereum.org/EIPS/eip-165[EIP]. Implementers can declare support of contract interfaces, which can then be queried by others ({ERC165Checker}). For an implementation, see {ERC165}.* - -## Methods - -### supportsInterface - -```solidity -function supportsInterface(bytes4 interfaceId) external view returns (bool) -``` - - - -*Returns true if this contract implements the interface defined by `interfaceId`. See the corresponding https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section] to learn more about how these ids are created. This function call must use less than 30 000 gas.* - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| interfaceId | bytes4 | undefined | - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | bool | undefined | - - - - diff --git a/docs/elin/contracts-4.3.1/utils/math/SafeMath.md b/docs/elin/contracts-4.3.1/utils/math/SafeMath.md deleted file mode 100644 index 7bf9fd7a5..000000000 --- a/docs/elin/contracts-4.3.1/utils/math/SafeMath.md +++ /dev/null @@ -1,12 +0,0 @@ -# SafeMath - - - - - - - -*Wrappers over Solidity's arithmetic operations. NOTE: `SafeMath` is generally not needed starting with Solidity 0.8, since the compiler now has built in overflow checking.* - - - diff --git a/docs/elin/contracts-upgradeable/access/AccessControlUpgradeable.md b/docs/elin/contracts-upgradeable/access/AccessControlUpgradeable.md deleted file mode 100644 index 8173dc159..000000000 --- a/docs/elin/contracts-upgradeable/access/AccessControlUpgradeable.md +++ /dev/null @@ -1,230 +0,0 @@ -# AccessControlUpgradeable - - - - - - - -*Contract module that allows children to implement role-based access control mechanisms. Roles are referred to by their `bytes32` identifier. These should be exposed in the external API and be unique. The best way to achieve this is by using `public constant` hash digests: ``` bytes32 public constant MY_ROLE = keccak256("MY_ROLE"); ``` Roles can be used to represent a set of permissions. To restrict access to a function call, use {hasRole}: ``` function foo() public { require(hasRole(MY_ROLE, msg.sender)); ... } ``` Roles can be granted and revoked dynamically via the {grantRole} and {revokeRole} functions. Each role has an associated admin role, and only accounts that have a role's admin role can call {grantRole} and {revokeRole}. By default, the admin role for all roles is `DEFAULT_ADMIN_ROLE`, which means that only accounts with this role will be able to grant or revoke other roles. More complex role relationships can be created by using {_setRoleAdmin}. WARNING: The `DEFAULT_ADMIN_ROLE` is also its own admin: it has permission to grant and revoke this role. Extra precautions should be taken to secure accounts that have been granted it.* - -## Methods - -### DEFAULT_ADMIN_ROLE - -```solidity -function DEFAULT_ADMIN_ROLE() external view returns (bytes32) -``` - - - - - - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | bytes32 | undefined | - -### getRoleAdmin - -```solidity -function getRoleAdmin(bytes32 role) external view returns (bytes32) -``` - - - -*Returns the admin role that controls `role`. See {grantRole} and {revokeRole}. To change a role's admin, use {_setRoleAdmin}.* - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| role | bytes32 | undefined | - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | bytes32 | undefined | - -### getRoleMember - -```solidity -function getRoleMember(bytes32 role, uint256 index) external view returns (address) -``` - - - -*Returns one of the accounts that have `role`. `index` must be a value between 0 and {getRoleMemberCount}, non-inclusive. Role bearers are not sorted in any particular way, and their ordering may change at any point. WARNING: When using {getRoleMember} and {getRoleMemberCount}, make sure you perform all queries on the same block. See the following https://forum.openzeppelin.com/t/iterating-over-elements-on-enumerableset-in-openzeppelin-contracts/2296[forum post] for more information.* - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| role | bytes32 | undefined | -| index | uint256 | undefined | - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | address | undefined | - -### getRoleMemberCount - -```solidity -function getRoleMemberCount(bytes32 role) external view returns (uint256) -``` - - - -*Returns the number of accounts that have `role`. Can be used together with {getRoleMember} to enumerate all bearers of a role.* - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| role | bytes32 | undefined | - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | uint256 | undefined | - -### grantRole - -```solidity -function grantRole(bytes32 role, address account) external nonpayable -``` - - - -*Grants `role` to `account`. If `account` had not been already granted `role`, emits a {RoleGranted} event. Requirements: - the caller must have ``role``'s admin role.* - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| role | bytes32 | undefined | -| account | address | undefined | - -### hasRole - -```solidity -function hasRole(bytes32 role, address account) external view returns (bool) -``` - - - -*Returns `true` if `account` has been granted `role`.* - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| role | bytes32 | undefined | -| account | address | undefined | - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | bool | undefined | - -### renounceRole - -```solidity -function renounceRole(bytes32 role, address account) external nonpayable -``` - - - -*Revokes `role` from the calling account. Roles are often managed via {grantRole} and {revokeRole}: this function's purpose is to provide a mechanism for accounts to lose their privileges if they are compromised (such as when a trusted device is misplaced). If the calling account had been granted `role`, emits a {RoleRevoked} event. Requirements: - the caller must be `account`.* - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| role | bytes32 | undefined | -| account | address | undefined | - -### revokeRole - -```solidity -function revokeRole(bytes32 role, address account) external nonpayable -``` - - - -*Revokes `role` from `account`. If `account` had been granted `role`, emits a {RoleRevoked} event. Requirements: - the caller must have ``role``'s admin role.* - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| role | bytes32 | undefined | -| account | address | undefined | - - - -## Events - -### RoleAdminChanged - -```solidity -event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole) -``` - - - -*Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole` `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite {RoleAdminChanged} not being emitted signaling this. _Available since v3.1._* - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| role `indexed` | bytes32 | undefined | -| previousAdminRole `indexed` | bytes32 | undefined | -| newAdminRole `indexed` | bytes32 | undefined | - -### RoleGranted - -```solidity -event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender) -``` - - - -*Emitted when `account` is granted `role`. `sender` is the account that originated the contract call, an admin role bearer except when using {_setupRole}.* - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| role `indexed` | bytes32 | undefined | -| account `indexed` | address | undefined | -| sender `indexed` | address | undefined | - -### RoleRevoked - -```solidity -event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender) -``` - - - -*Emitted when `account` is revoked `role`. `sender` is the account that originated the contract call: - if using `revokeRole`, it is the admin role bearer - if using `renounceRole`, it is the role bearer (i.e. `account`)* - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| role `indexed` | bytes32 | undefined | -| account `indexed` | address | undefined | -| sender `indexed` | address | undefined | - - - diff --git a/docs/elin/contracts-upgradeable/access/OwnableUpgradeable.md b/docs/elin/contracts-upgradeable/access/OwnableUpgradeable.md deleted file mode 100644 index 923f9d6ea..000000000 --- a/docs/elin/contracts-upgradeable/access/OwnableUpgradeable.md +++ /dev/null @@ -1,79 +0,0 @@ -# OwnableUpgradeable - - - - - - - -*Contract module which provides a basic access control mechanism, where there is an account (an owner) that can be granted exclusive access to specific functions. By default, the owner account will be the one that deploys the contract. This can later be changed with {transferOwnership}. This module is used through inheritance. It will make available the modifier `onlyOwner`, which can be applied to your functions to restrict their use to the owner.* - -## Methods - -### owner - -```solidity -function owner() external view returns (address) -``` - - - -*Returns the address of the current owner.* - - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | address | undefined | - -### renounceOwnership - -```solidity -function renounceOwnership() external nonpayable -``` - - - -*Leaves the contract without owner. It will not be possible to call `onlyOwner` functions anymore. Can only be called by the current owner. NOTE: Renouncing ownership will leave the contract without an owner, thereby removing any functionality that is only available to the owner.* - - -### transferOwnership - -```solidity -function transferOwnership(address newOwner) external nonpayable -``` - - - -*Transfers ownership of the contract to a new account (`newOwner`). Can only be called by the current owner.* - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| newOwner | address | undefined | - - - -## Events - -### OwnershipTransferred - -```solidity -event OwnershipTransferred(address indexed previousOwner, address indexed newOwner) -``` - - - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| previousOwner `indexed` | address | undefined | -| newOwner `indexed` | address | undefined | - - - diff --git a/docs/elin/contracts-upgradeable/cryptography/ECDSAUpgradeable.md b/docs/elin/contracts-upgradeable/cryptography/ECDSAUpgradeable.md deleted file mode 100644 index 5035a7b74..000000000 --- a/docs/elin/contracts-upgradeable/cryptography/ECDSAUpgradeable.md +++ /dev/null @@ -1,12 +0,0 @@ -# ECDSAUpgradeable - - - - - - - -*Elliptic Curve Digital Signature Algorithm (ECDSA) operations. These functions can be used to verify that a message was signed by the holder of the private keys of a given address.* - - - diff --git a/docs/elin/contracts-upgradeable/drafts/EIP712Upgradeable.md b/docs/elin/contracts-upgradeable/drafts/EIP712Upgradeable.md deleted file mode 100644 index 5dfe58185..000000000 --- a/docs/elin/contracts-upgradeable/drafts/EIP712Upgradeable.md +++ /dev/null @@ -1,12 +0,0 @@ -# EIP712Upgradeable - - - - - - - -*https://eips.ethereum.org/EIPS/eip-712[EIP 712] is a standard for hashing and signing of typed structured data. The encoding specified in the EIP is very generic, and such a generic implementation in Solidity is not feasible, thus this contract does not implement the encoding itself. Protocols need to implement the type-specific encoding they need in their contracts using a combination of `abi.encode` and `keccak256`. This contract implements the EIP 712 domain separator ({_domainSeparatorV4}) that is used as part of the encoding scheme, and the final step of the encoding to obtain the message digest that is then signed via ECDSA ({_hashTypedDataV4}). The implementation of the domain separator was designed to be as efficient as possible while still properly updating the chain id to protect against replay attacks on an eventual fork of the chain. NOTE: This contract implements the version of the encoding known as "v4", as implemented by the JSON RPC method https://docs.metamask.io/guide/signing-data.html[`eth_signTypedDataV4` in MetaMask]. _Available since v3.4._* - - - diff --git a/docs/elin/contracts-upgradeable/drafts/ERC20PermitUpgradeable.md b/docs/elin/contracts-upgradeable/drafts/ERC20PermitUpgradeable.md deleted file mode 100644 index d37d5a342..000000000 --- a/docs/elin/contracts-upgradeable/drafts/ERC20PermitUpgradeable.md +++ /dev/null @@ -1,344 +0,0 @@ -# ERC20PermitUpgradeable - - - - - - - -*Implementation of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in https://eips.ethereum.org/EIPS/eip-2612[EIP-2612]. Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by presenting a message signed by the account. By not relying on `{IERC20-approve}`, the token holder account doesn't need to send a transaction, and thus is not required to hold Ether at all. _Available since v3.4._* - -## Methods - -### DOMAIN_SEPARATOR - -```solidity -function DOMAIN_SEPARATOR() external view returns (bytes32) -``` - - - -*See {IERC20Permit-DOMAIN_SEPARATOR}.* - - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | bytes32 | undefined | - -### allowance - -```solidity -function allowance(address owner, address spender) external view returns (uint256) -``` - - - -*See {IERC20-allowance}.* - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| owner | address | undefined | -| spender | address | undefined | - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | uint256 | undefined | - -### approve - -```solidity -function approve(address spender, uint256 amount) external nonpayable returns (bool) -``` - - - -*See {IERC20-approve}. Requirements: - `spender` cannot be the zero address.* - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| spender | address | undefined | -| amount | uint256 | undefined | - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | bool | undefined | - -### balanceOf - -```solidity -function balanceOf(address account) external view returns (uint256) -``` - - - -*See {IERC20-balanceOf}.* - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| account | address | undefined | - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | uint256 | undefined | - -### decimals - -```solidity -function decimals() external view returns (uint8) -``` - - - -*Returns the number of decimals used to get its user representation. For example, if `decimals` equals `2`, a balance of `505` tokens should be displayed to a user as `5,05` (`505 / 10 ** 2`). Tokens usually opt for a value of 18, imitating the relationship between Ether and Wei. This is the value {ERC20} uses, unless {_setupDecimals} is called. NOTE: This information is only used for _display_ purposes: it in no way affects any of the arithmetic of the contract, including {IERC20-balanceOf} and {IERC20-transfer}.* - - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | uint8 | undefined | - -### decreaseAllowance - -```solidity -function decreaseAllowance(address spender, uint256 subtractedValue) external nonpayable returns (bool) -``` - - - -*Atomically decreases the allowance granted to `spender` by the caller. This is an alternative to {approve} that can be used as a mitigation for problems described in {IERC20-approve}. Emits an {Approval} event indicating the updated allowance. Requirements: - `spender` cannot be the zero address. - `spender` must have allowance for the caller of at least `subtractedValue`.* - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| spender | address | undefined | -| subtractedValue | uint256 | undefined | - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | bool | undefined | - -### increaseAllowance - -```solidity -function increaseAllowance(address spender, uint256 addedValue) external nonpayable returns (bool) -``` - - - -*Atomically increases the allowance granted to `spender` by the caller. This is an alternative to {approve} that can be used as a mitigation for problems described in {IERC20-approve}. Emits an {Approval} event indicating the updated allowance. Requirements: - `spender` cannot be the zero address.* - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| spender | address | undefined | -| addedValue | uint256 | undefined | - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | bool | undefined | - -### name - -```solidity -function name() external view returns (string) -``` - - - -*Returns the name of the token.* - - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | string | undefined | - -### nonces - -```solidity -function nonces(address owner) external view returns (uint256) -``` - - - -*See {IERC20Permit-nonces}.* - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| owner | address | undefined | - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | uint256 | undefined | - -### permit - -```solidity -function permit(address owner, address spender, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s) external nonpayable -``` - - - -*See {IERC20Permit-permit}.* - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| owner | address | undefined | -| spender | address | undefined | -| value | uint256 | undefined | -| deadline | uint256 | undefined | -| v | uint8 | undefined | -| r | bytes32 | undefined | -| s | bytes32 | undefined | - -### symbol - -```solidity -function symbol() external view returns (string) -``` - - - -*Returns the symbol of the token, usually a shorter version of the name.* - - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | string | undefined | - -### totalSupply - -```solidity -function totalSupply() external view returns (uint256) -``` - - - -*See {IERC20-totalSupply}.* - - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | uint256 | undefined | - -### transfer - -```solidity -function transfer(address recipient, uint256 amount) external nonpayable returns (bool) -``` - - - -*See {IERC20-transfer}. Requirements: - `recipient` cannot be the zero address. - the caller must have a balance of at least `amount`.* - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| recipient | address | undefined | -| amount | uint256 | undefined | - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | bool | undefined | - -### transferFrom - -```solidity -function transferFrom(address sender, address recipient, uint256 amount) external nonpayable returns (bool) -``` - - - -*See {IERC20-transferFrom}. Emits an {Approval} event indicating the updated allowance. This is not required by the EIP. See the note at the beginning of {ERC20}. Requirements: - `sender` and `recipient` cannot be the zero address. - `sender` must have a balance of at least `amount`. - the caller must have allowance for ``sender``'s tokens of at least `amount`.* - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| sender | address | undefined | -| recipient | address | undefined | -| amount | uint256 | undefined | - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | bool | undefined | - - - -## Events - -### Approval - -```solidity -event Approval(address indexed owner, address indexed spender, uint256 value) -``` - - - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| owner `indexed` | address | undefined | -| spender `indexed` | address | undefined | -| value | uint256 | undefined | - -### Transfer - -```solidity -event Transfer(address indexed from, address indexed to, uint256 value) -``` - - - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| from `indexed` | address | undefined | -| to `indexed` | address | undefined | -| value | uint256 | undefined | - - - diff --git a/docs/elin/contracts-upgradeable/drafts/IERC20PermitUpgradeable.md b/docs/elin/contracts-upgradeable/drafts/IERC20PermitUpgradeable.md deleted file mode 100644 index 484aadf15..000000000 --- a/docs/elin/contracts-upgradeable/drafts/IERC20PermitUpgradeable.md +++ /dev/null @@ -1,76 +0,0 @@ -# IERC20PermitUpgradeable - - - - - - - -*Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in https://eips.ethereum.org/EIPS/eip-2612[EIP-2612]. Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by presenting a message signed by the account. By not relying on `{IERC20-approve}`, the token holder account doesn't need to send a transaction, and thus is not required to hold Ether at all.* - -## Methods - -### DOMAIN_SEPARATOR - -```solidity -function DOMAIN_SEPARATOR() external view returns (bytes32) -``` - - - -*Returns the domain separator used in the encoding of the signature for `permit`, as defined by {EIP712}.* - - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | bytes32 | undefined | - -### nonces - -```solidity -function nonces(address owner) external view returns (uint256) -``` - - - -*Returns the current nonce for `owner`. This value must be included whenever a signature is generated for {permit}. Every successful call to {permit} increases ``owner``'s nonce by one. This prevents a signature from being used multiple times.* - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| owner | address | undefined | - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | uint256 | undefined | - -### permit - -```solidity -function permit(address owner, address spender, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s) external nonpayable -``` - - - -*Sets `value` as the allowance of `spender` over `owner`'s tokens, given `owner`'s signed approval. IMPORTANT: The same issues {IERC20-approve} has related to transaction ordering also apply here. Emits an {Approval} event. Requirements: - `spender` cannot be the zero address. - `deadline` must be a timestamp in the future. - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner` over the EIP712-formatted function arguments. - the signature must use ``owner``'s current nonce (see {nonces}). For more information on the signature format, see the https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP section].* - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| owner | address | undefined | -| spender | address | undefined | -| value | uint256 | undefined | -| deadline | uint256 | undefined | -| v | uint8 | undefined | -| r | bytes32 | undefined | -| s | bytes32 | undefined | - - - - diff --git a/docs/elin/contracts-upgradeable/math/SafeMathUpgradeable.md b/docs/elin/contracts-upgradeable/math/SafeMathUpgradeable.md deleted file mode 100644 index 5b66c328e..000000000 --- a/docs/elin/contracts-upgradeable/math/SafeMathUpgradeable.md +++ /dev/null @@ -1,12 +0,0 @@ -# SafeMathUpgradeable - - - - - - - -*Wrappers over Solidity's arithmetic operations with added overflow checks. Arithmetic operations in Solidity wrap on overflow. This can easily result in bugs, because programmers usually assume that an overflow raises an error, which is the standard behavior in high level programming languages. `SafeMath` restores this intuition by reverting the transaction when an operation overflows. Using this library instead of the unchecked operations eliminates an entire class of bugs, so it's recommended to use it always.* - - - diff --git a/docs/elin/contracts-upgradeable/proxy/Initializable.md b/docs/elin/contracts-upgradeable/proxy/Initializable.md deleted file mode 100644 index 3621c4fc8..000000000 --- a/docs/elin/contracts-upgradeable/proxy/Initializable.md +++ /dev/null @@ -1,12 +0,0 @@ -# Initializable - - - - - - - -*This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed behind a proxy. Since a proxied contract can't have a constructor, it's common to move constructor logic to an external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer function so it can only be called once. The {initializer} modifier provided by this contract will have this effect. TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as possible by providing the encoded function call as the `_data` argument to {UpgradeableProxy-constructor}. CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure that all initializers are idempotent. This is not verified automatically as constructors are by Solidity.* - - - diff --git a/docs/elin/contracts-upgradeable/token/ERC20/ERC20BurnableUpgradeable.md b/docs/elin/contracts-upgradeable/token/ERC20/ERC20BurnableUpgradeable.md deleted file mode 100644 index b91b7eafe..000000000 --- a/docs/elin/contracts-upgradeable/token/ERC20/ERC20BurnableUpgradeable.md +++ /dev/null @@ -1,316 +0,0 @@ -# ERC20BurnableUpgradeable - - - - - - - -*Extension of {ERC20} that allows token holders to destroy both their own tokens and those that they have an allowance for, in a way that can be recognized off-chain (via event analysis).* - -## Methods - -### allowance - -```solidity -function allowance(address owner, address spender) external view returns (uint256) -``` - - - -*See {IERC20-allowance}.* - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| owner | address | undefined | -| spender | address | undefined | - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | uint256 | undefined | - -### approve - -```solidity -function approve(address spender, uint256 amount) external nonpayable returns (bool) -``` - - - -*See {IERC20-approve}. Requirements: - `spender` cannot be the zero address.* - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| spender | address | undefined | -| amount | uint256 | undefined | - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | bool | undefined | - -### balanceOf - -```solidity -function balanceOf(address account) external view returns (uint256) -``` - - - -*See {IERC20-balanceOf}.* - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| account | address | undefined | - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | uint256 | undefined | - -### burn - -```solidity -function burn(uint256 amount) external nonpayable -``` - - - -*Destroys `amount` tokens from the caller. See {ERC20-_burn}.* - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| amount | uint256 | undefined | - -### burnFrom - -```solidity -function burnFrom(address account, uint256 amount) external nonpayable -``` - - - -*Destroys `amount` tokens from `account`, deducting from the caller's allowance. See {ERC20-_burn} and {ERC20-allowance}. Requirements: - the caller must have allowance for ``accounts``'s tokens of at least `amount`.* - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| account | address | undefined | -| amount | uint256 | undefined | - -### decimals - -```solidity -function decimals() external view returns (uint8) -``` - - - -*Returns the number of decimals used to get its user representation. For example, if `decimals` equals `2`, a balance of `505` tokens should be displayed to a user as `5,05` (`505 / 10 ** 2`). Tokens usually opt for a value of 18, imitating the relationship between Ether and Wei. This is the value {ERC20} uses, unless {_setupDecimals} is called. NOTE: This information is only used for _display_ purposes: it in no way affects any of the arithmetic of the contract, including {IERC20-balanceOf} and {IERC20-transfer}.* - - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | uint8 | undefined | - -### decreaseAllowance - -```solidity -function decreaseAllowance(address spender, uint256 subtractedValue) external nonpayable returns (bool) -``` - - - -*Atomically decreases the allowance granted to `spender` by the caller. This is an alternative to {approve} that can be used as a mitigation for problems described in {IERC20-approve}. Emits an {Approval} event indicating the updated allowance. Requirements: - `spender` cannot be the zero address. - `spender` must have allowance for the caller of at least `subtractedValue`.* - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| spender | address | undefined | -| subtractedValue | uint256 | undefined | - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | bool | undefined | - -### increaseAllowance - -```solidity -function increaseAllowance(address spender, uint256 addedValue) external nonpayable returns (bool) -``` - - - -*Atomically increases the allowance granted to `spender` by the caller. This is an alternative to {approve} that can be used as a mitigation for problems described in {IERC20-approve}. Emits an {Approval} event indicating the updated allowance. Requirements: - `spender` cannot be the zero address.* - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| spender | address | undefined | -| addedValue | uint256 | undefined | - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | bool | undefined | - -### name - -```solidity -function name() external view returns (string) -``` - - - -*Returns the name of the token.* - - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | string | undefined | - -### symbol - -```solidity -function symbol() external view returns (string) -``` - - - -*Returns the symbol of the token, usually a shorter version of the name.* - - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | string | undefined | - -### totalSupply - -```solidity -function totalSupply() external view returns (uint256) -``` - - - -*See {IERC20-totalSupply}.* - - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | uint256 | undefined | - -### transfer - -```solidity -function transfer(address recipient, uint256 amount) external nonpayable returns (bool) -``` - - - -*See {IERC20-transfer}. Requirements: - `recipient` cannot be the zero address. - the caller must have a balance of at least `amount`.* - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| recipient | address | undefined | -| amount | uint256 | undefined | - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | bool | undefined | - -### transferFrom - -```solidity -function transferFrom(address sender, address recipient, uint256 amount) external nonpayable returns (bool) -``` - - - -*See {IERC20-transferFrom}. Emits an {Approval} event indicating the updated allowance. This is not required by the EIP. See the note at the beginning of {ERC20}. Requirements: - `sender` and `recipient` cannot be the zero address. - `sender` must have a balance of at least `amount`. - the caller must have allowance for ``sender``'s tokens of at least `amount`.* - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| sender | address | undefined | -| recipient | address | undefined | -| amount | uint256 | undefined | - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | bool | undefined | - - - -## Events - -### Approval - -```solidity -event Approval(address indexed owner, address indexed spender, uint256 value) -``` - - - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| owner `indexed` | address | undefined | -| spender `indexed` | address | undefined | -| value | uint256 | undefined | - -### Transfer - -```solidity -event Transfer(address indexed from, address indexed to, uint256 value) -``` - - - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| from `indexed` | address | undefined | -| to `indexed` | address | undefined | -| value | uint256 | undefined | - - - diff --git a/docs/elin/contracts-upgradeable/token/ERC20/ERC20Upgradeable.md b/docs/elin/contracts-upgradeable/token/ERC20/ERC20Upgradeable.md deleted file mode 100644 index a65f0f391..000000000 --- a/docs/elin/contracts-upgradeable/token/ERC20/ERC20Upgradeable.md +++ /dev/null @@ -1,283 +0,0 @@ -# ERC20Upgradeable - - - - - - - -*Implementation of the {IERC20} interface. This implementation is agnostic to the way tokens are created. This means that a supply mechanism has to be added in a derived contract using {_mint}. For a generic mechanism see {ERC20PresetMinterPauser}. TIP: For a detailed writeup see our guide https://forum.zeppelin.solutions/t/how-to-implement-erc20-supply-mechanisms/226[How to implement supply mechanisms]. We have followed general OpenZeppelin guidelines: functions revert instead of returning `false` on failure. This behavior is nonetheless conventional and does not conflict with the expectations of ERC20 applications. Additionally, an {Approval} event is emitted on calls to {transferFrom}. This allows applications to reconstruct the allowance for all accounts just by listening to said events. Other implementations of the EIP may not emit these events, as it isn't required by the specification. Finally, the non-standard {decreaseAllowance} and {increaseAllowance} functions have been added to mitigate the well-known issues around setting allowances. See {IERC20-approve}.* - -## Methods - -### allowance - -```solidity -function allowance(address owner, address spender) external view returns (uint256) -``` - - - -*See {IERC20-allowance}.* - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| owner | address | undefined | -| spender | address | undefined | - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | uint256 | undefined | - -### approve - -```solidity -function approve(address spender, uint256 amount) external nonpayable returns (bool) -``` - - - -*See {IERC20-approve}. Requirements: - `spender` cannot be the zero address.* - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| spender | address | undefined | -| amount | uint256 | undefined | - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | bool | undefined | - -### balanceOf - -```solidity -function balanceOf(address account) external view returns (uint256) -``` - - - -*See {IERC20-balanceOf}.* - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| account | address | undefined | - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | uint256 | undefined | - -### decimals - -```solidity -function decimals() external view returns (uint8) -``` - - - -*Returns the number of decimals used to get its user representation. For example, if `decimals` equals `2`, a balance of `505` tokens should be displayed to a user as `5,05` (`505 / 10 ** 2`). Tokens usually opt for a value of 18, imitating the relationship between Ether and Wei. This is the value {ERC20} uses, unless {_setupDecimals} is called. NOTE: This information is only used for _display_ purposes: it in no way affects any of the arithmetic of the contract, including {IERC20-balanceOf} and {IERC20-transfer}.* - - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | uint8 | undefined | - -### decreaseAllowance - -```solidity -function decreaseAllowance(address spender, uint256 subtractedValue) external nonpayable returns (bool) -``` - - - -*Atomically decreases the allowance granted to `spender` by the caller. This is an alternative to {approve} that can be used as a mitigation for problems described in {IERC20-approve}. Emits an {Approval} event indicating the updated allowance. Requirements: - `spender` cannot be the zero address. - `spender` must have allowance for the caller of at least `subtractedValue`.* - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| spender | address | undefined | -| subtractedValue | uint256 | undefined | - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | bool | undefined | - -### increaseAllowance - -```solidity -function increaseAllowance(address spender, uint256 addedValue) external nonpayable returns (bool) -``` - - - -*Atomically increases the allowance granted to `spender` by the caller. This is an alternative to {approve} that can be used as a mitigation for problems described in {IERC20-approve}. Emits an {Approval} event indicating the updated allowance. Requirements: - `spender` cannot be the zero address.* - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| spender | address | undefined | -| addedValue | uint256 | undefined | - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | bool | undefined | - -### name - -```solidity -function name() external view returns (string) -``` - - - -*Returns the name of the token.* - - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | string | undefined | - -### symbol - -```solidity -function symbol() external view returns (string) -``` - - - -*Returns the symbol of the token, usually a shorter version of the name.* - - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | string | undefined | - -### totalSupply - -```solidity -function totalSupply() external view returns (uint256) -``` - - - -*See {IERC20-totalSupply}.* - - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | uint256 | undefined | - -### transfer - -```solidity -function transfer(address recipient, uint256 amount) external nonpayable returns (bool) -``` - - - -*See {IERC20-transfer}. Requirements: - `recipient` cannot be the zero address. - the caller must have a balance of at least `amount`.* - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| recipient | address | undefined | -| amount | uint256 | undefined | - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | bool | undefined | - -### transferFrom - -```solidity -function transferFrom(address sender, address recipient, uint256 amount) external nonpayable returns (bool) -``` - - - -*See {IERC20-transferFrom}. Emits an {Approval} event indicating the updated allowance. This is not required by the EIP. See the note at the beginning of {ERC20}. Requirements: - `sender` and `recipient` cannot be the zero address. - `sender` must have a balance of at least `amount`. - the caller must have allowance for ``sender``'s tokens of at least `amount`.* - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| sender | address | undefined | -| recipient | address | undefined | -| amount | uint256 | undefined | - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | bool | undefined | - - - -## Events - -### Approval - -```solidity -event Approval(address indexed owner, address indexed spender, uint256 value) -``` - - - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| owner `indexed` | address | undefined | -| spender `indexed` | address | undefined | -| value | uint256 | undefined | - -### Transfer - -```solidity -event Transfer(address indexed from, address indexed to, uint256 value) -``` - - - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| from `indexed` | address | undefined | -| to `indexed` | address | undefined | -| value | uint256 | undefined | - - - diff --git a/docs/elin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.md b/docs/elin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.md deleted file mode 100644 index 70af4f841..000000000 --- a/docs/elin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.md +++ /dev/null @@ -1,186 +0,0 @@ -# IERC20Upgradeable - - - - - - - -*Interface of the ERC20 standard as defined in the EIP.* - -## Methods - -### allowance - -```solidity -function allowance(address owner, address spender) external view returns (uint256) -``` - - - -*Returns the remaining number of tokens that `spender` will be allowed to spend on behalf of `owner` through {transferFrom}. This is zero by default. This value changes when {approve} or {transferFrom} are called.* - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| owner | address | undefined | -| spender | address | undefined | - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | uint256 | undefined | - -### approve - -```solidity -function approve(address spender, uint256 amount) external nonpayable returns (bool) -``` - - - -*Sets `amount` as the allowance of `spender` over the caller's tokens. Returns a boolean value indicating whether the operation succeeded. IMPORTANT: Beware that changing an allowance with this method brings the risk that someone may use both the old and the new allowance by unfortunate transaction ordering. One possible solution to mitigate this race condition is to first reduce the spender's allowance to 0 and set the desired value afterwards: https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729 Emits an {Approval} event.* - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| spender | address | undefined | -| amount | uint256 | undefined | - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | bool | undefined | - -### balanceOf - -```solidity -function balanceOf(address account) external view returns (uint256) -``` - - - -*Returns the amount of tokens owned by `account`.* - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| account | address | undefined | - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | uint256 | undefined | - -### totalSupply - -```solidity -function totalSupply() external view returns (uint256) -``` - - - -*Returns the amount of tokens in existence.* - - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | uint256 | undefined | - -### transfer - -```solidity -function transfer(address recipient, uint256 amount) external nonpayable returns (bool) -``` - - - -*Moves `amount` tokens from the caller's account to `recipient`. Returns a boolean value indicating whether the operation succeeded. Emits a {Transfer} event.* - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| recipient | address | undefined | -| amount | uint256 | undefined | - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | bool | undefined | - -### transferFrom - -```solidity -function transferFrom(address sender, address recipient, uint256 amount) external nonpayable returns (bool) -``` - - - -*Moves `amount` tokens from `sender` to `recipient` using the allowance mechanism. `amount` is then deducted from the caller's allowance. Returns a boolean value indicating whether the operation succeeded. Emits a {Transfer} event.* - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| sender | address | undefined | -| recipient | address | undefined | -| amount | uint256 | undefined | - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | bool | undefined | - - - -## Events - -### Approval - -```solidity -event Approval(address indexed owner, address indexed spender, uint256 value) -``` - - - -*Emitted when the allowance of a `spender` for an `owner` is set by a call to {approve}. `value` is the new allowance.* - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| owner `indexed` | address | undefined | -| spender `indexed` | address | undefined | -| value | uint256 | undefined | - -### Transfer - -```solidity -event Transfer(address indexed from, address indexed to, uint256 value) -``` - - - -*Emitted when `value` tokens are moved from one account (`from`) to another (`to`). Note that `value` may be zero.* - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| from `indexed` | address | undefined | -| to `indexed` | address | undefined | -| value | uint256 | undefined | - - - diff --git a/docs/elin/contracts-upgradeable/utils/AddressUpgradeable.md b/docs/elin/contracts-upgradeable/utils/AddressUpgradeable.md deleted file mode 100644 index 456cdd15d..000000000 --- a/docs/elin/contracts-upgradeable/utils/AddressUpgradeable.md +++ /dev/null @@ -1,12 +0,0 @@ -# AddressUpgradeable - - - - - - - -*Collection of functions related to the address type* - - - diff --git a/docs/elin/contracts-upgradeable/utils/ContextUpgradeable.md b/docs/elin/contracts-upgradeable/utils/ContextUpgradeable.md deleted file mode 100644 index 8491abdc9..000000000 --- a/docs/elin/contracts-upgradeable/utils/ContextUpgradeable.md +++ /dev/null @@ -1,12 +0,0 @@ -# ContextUpgradeable - - - - - - - - - - - diff --git a/docs/elin/contracts-upgradeable/utils/CountersUpgradeable.md b/docs/elin/contracts-upgradeable/utils/CountersUpgradeable.md deleted file mode 100644 index 66c3ec40d..000000000 --- a/docs/elin/contracts-upgradeable/utils/CountersUpgradeable.md +++ /dev/null @@ -1,12 +0,0 @@ -# CountersUpgradeable - -*Matt Condon (@shrugs)* - -> Counters - - - -*Provides counters that can only be incremented or decremented by one. This can be used e.g. to track the number of elements in a mapping, issuing ERC721 ids, or counting request ids. Include with `using Counters for Counters.Counter;` Since it is not possible to overflow a 256 bit integer with increments of one, `increment` can skip the {SafeMath} overflow check, thereby saving gas. This does assume however correct usage, in that the underlying `_value` is never directly accessed.* - - - diff --git a/docs/elin/contracts-upgradeable/utils/EnumerableSetUpgradeable.md b/docs/elin/contracts-upgradeable/utils/EnumerableSetUpgradeable.md deleted file mode 100644 index 1a169e579..000000000 --- a/docs/elin/contracts-upgradeable/utils/EnumerableSetUpgradeable.md +++ /dev/null @@ -1,12 +0,0 @@ -# EnumerableSetUpgradeable - - - - - - - -*Library for managing https://en.wikipedia.org/wiki/Set_(abstract_data_type)[sets] of primitive types. Sets have the following properties: - Elements are added, removed, and checked for existence in constant time (O(1)). - Elements are enumerated in O(n). No guarantees are made on the ordering. ``` contract Example { // Add the library methods using EnumerableSet for EnumerableSet.AddressSet; // Declare a set state variable EnumerableSet.AddressSet private mySet; } ``` As of v3.3.0, sets of type `bytes32` (`Bytes32Set`), `address` (`AddressSet`) and `uint256` (`UintSet`) are supported.* - - - diff --git a/docs/elin/contracts-upgradeable/utils/PausableUpgradeable.md b/docs/elin/contracts-upgradeable/utils/PausableUpgradeable.md deleted file mode 100644 index 38eb921ff..000000000 --- a/docs/elin/contracts-upgradeable/utils/PausableUpgradeable.md +++ /dev/null @@ -1,67 +0,0 @@ -# PausableUpgradeable - - - - - - - -*Contract module which allows children to implement an emergency stop mechanism that can be triggered by an authorized account. This module is used through inheritance. It will make available the modifiers `whenNotPaused` and `whenPaused`, which can be applied to the functions of your contract. Note that they will not be pausable by simply including this module, only once the modifiers are put in place.* - -## Methods - -### paused - -```solidity -function paused() external view returns (bool) -``` - - - -*Returns true if the contract is paused, and false otherwise.* - - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | bool | undefined | - - - -## Events - -### Paused - -```solidity -event Paused(address account) -``` - - - -*Emitted when the pause is triggered by `account`.* - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| account | address | undefined | - -### Unpaused - -```solidity -event Unpaused(address account) -``` - - - -*Emitted when the pause is lifted by `account`.* - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| account | address | undefined | - - - diff --git a/docs/elin/contracts-upgradeable/utils/ReentrancyGuardUpgradeable.md b/docs/elin/contracts-upgradeable/utils/ReentrancyGuardUpgradeable.md deleted file mode 100644 index 6955ca2de..000000000 --- a/docs/elin/contracts-upgradeable/utils/ReentrancyGuardUpgradeable.md +++ /dev/null @@ -1,12 +0,0 @@ -# ReentrancyGuardUpgradeable - - - - - - - -*Contract module that helps prevent reentrant calls to a function. Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier available, which can be applied to functions to make sure there are no nested (reentrant) calls to them. Note that because there is a single `nonReentrant` guard, functions marked as `nonReentrant` may not call one another. This can be worked around by making those functions `private`, and then adding `external` `nonReentrant` entry points to them. TIP: If you would like to learn more about reentrancy and alternative ways to protect against it, check out our blog post https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul].* - - - diff --git a/docs/elin/contracts/access/AccessControl.md b/docs/elin/contracts/access/AccessControl.md deleted file mode 100644 index 88ca92f78..000000000 --- a/docs/elin/contracts/access/AccessControl.md +++ /dev/null @@ -1,230 +0,0 @@ -# AccessControl - - - - - - - -*Contract module that allows children to implement role-based access control mechanisms. Roles are referred to by their `bytes32` identifier. These should be exposed in the external API and be unique. The best way to achieve this is by using `public constant` hash digests: ``` bytes32 public constant MY_ROLE = keccak256("MY_ROLE"); ``` Roles can be used to represent a set of permissions. To restrict access to a function call, use {hasRole}: ``` function foo() public { require(hasRole(MY_ROLE, msg.sender)); ... } ``` Roles can be granted and revoked dynamically via the {grantRole} and {revokeRole} functions. Each role has an associated admin role, and only accounts that have a role's admin role can call {grantRole} and {revokeRole}. By default, the admin role for all roles is `DEFAULT_ADMIN_ROLE`, which means that only accounts with this role will be able to grant or revoke other roles. More complex role relationships can be created by using {_setRoleAdmin}. WARNING: The `DEFAULT_ADMIN_ROLE` is also its own admin: it has permission to grant and revoke this role. Extra precautions should be taken to secure accounts that have been granted it.* - -## Methods - -### DEFAULT_ADMIN_ROLE - -```solidity -function DEFAULT_ADMIN_ROLE() external view returns (bytes32) -``` - - - - - - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | bytes32 | undefined | - -### getRoleAdmin - -```solidity -function getRoleAdmin(bytes32 role) external view returns (bytes32) -``` - - - -*Returns the admin role that controls `role`. See {grantRole} and {revokeRole}. To change a role's admin, use {_setRoleAdmin}.* - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| role | bytes32 | undefined | - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | bytes32 | undefined | - -### getRoleMember - -```solidity -function getRoleMember(bytes32 role, uint256 index) external view returns (address) -``` - - - -*Returns one of the accounts that have `role`. `index` must be a value between 0 and {getRoleMemberCount}, non-inclusive. Role bearers are not sorted in any particular way, and their ordering may change at any point. WARNING: When using {getRoleMember} and {getRoleMemberCount}, make sure you perform all queries on the same block. See the following https://forum.openzeppelin.com/t/iterating-over-elements-on-enumerableset-in-openzeppelin-contracts/2296[forum post] for more information.* - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| role | bytes32 | undefined | -| index | uint256 | undefined | - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | address | undefined | - -### getRoleMemberCount - -```solidity -function getRoleMemberCount(bytes32 role) external view returns (uint256) -``` - - - -*Returns the number of accounts that have `role`. Can be used together with {getRoleMember} to enumerate all bearers of a role.* - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| role | bytes32 | undefined | - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | uint256 | undefined | - -### grantRole - -```solidity -function grantRole(bytes32 role, address account) external nonpayable -``` - - - -*Grants `role` to `account`. If `account` had not been already granted `role`, emits a {RoleGranted} event. Requirements: - the caller must have ``role``'s admin role.* - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| role | bytes32 | undefined | -| account | address | undefined | - -### hasRole - -```solidity -function hasRole(bytes32 role, address account) external view returns (bool) -``` - - - -*Returns `true` if `account` has been granted `role`.* - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| role | bytes32 | undefined | -| account | address | undefined | - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | bool | undefined | - -### renounceRole - -```solidity -function renounceRole(bytes32 role, address account) external nonpayable -``` - - - -*Revokes `role` from the calling account. Roles are often managed via {grantRole} and {revokeRole}: this function's purpose is to provide a mechanism for accounts to lose their privileges if they are compromised (such as when a trusted device is misplaced). If the calling account had been granted `role`, emits a {RoleRevoked} event. Requirements: - the caller must be `account`.* - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| role | bytes32 | undefined | -| account | address | undefined | - -### revokeRole - -```solidity -function revokeRole(bytes32 role, address account) external nonpayable -``` - - - -*Revokes `role` from `account`. If `account` had been granted `role`, emits a {RoleRevoked} event. Requirements: - the caller must have ``role``'s admin role.* - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| role | bytes32 | undefined | -| account | address | undefined | - - - -## Events - -### RoleAdminChanged - -```solidity -event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole) -``` - - - -*Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole` `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite {RoleAdminChanged} not being emitted signaling this. _Available since v3.1._* - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| role `indexed` | bytes32 | undefined | -| previousAdminRole `indexed` | bytes32 | undefined | -| newAdminRole `indexed` | bytes32 | undefined | - -### RoleGranted - -```solidity -event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender) -``` - - - -*Emitted when `account` is granted `role`. `sender` is the account that originated the contract call, an admin role bearer except when using {_setupRole}.* - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| role `indexed` | bytes32 | undefined | -| account `indexed` | address | undefined | -| sender `indexed` | address | undefined | - -### RoleRevoked - -```solidity -event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender) -``` - - - -*Emitted when `account` is revoked `role`. `sender` is the account that originated the contract call: - if using `revokeRole`, it is the admin role bearer - if using `renounceRole`, it is the role bearer (i.e. `account`)* - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| role `indexed` | bytes32 | undefined | -| account `indexed` | address | undefined | -| sender `indexed` | address | undefined | - - - diff --git a/docs/elin/contracts/access/Ownable.md b/docs/elin/contracts/access/Ownable.md deleted file mode 100644 index ac3973421..000000000 --- a/docs/elin/contracts/access/Ownable.md +++ /dev/null @@ -1,79 +0,0 @@ -# Ownable - - - - - - - -*Contract module which provides a basic access control mechanism, where there is an account (an owner) that can be granted exclusive access to specific functions. By default, the owner account will be the one that deploys the contract. This can later be changed with {transferOwnership}. This module is used through inheritance. It will make available the modifier `onlyOwner`, which can be applied to your functions to restrict their use to the owner.* - -## Methods - -### owner - -```solidity -function owner() external view returns (address) -``` - - - -*Returns the address of the current owner.* - - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | address | undefined | - -### renounceOwnership - -```solidity -function renounceOwnership() external nonpayable -``` - - - -*Leaves the contract without owner. It will not be possible to call `onlyOwner` functions anymore. Can only be called by the current owner. NOTE: Renouncing ownership will leave the contract without an owner, thereby removing any functionality that is only available to the owner.* - - -### transferOwnership - -```solidity -function transferOwnership(address newOwner) external nonpayable -``` - - - -*Transfers ownership of the contract to a new account (`newOwner`). Can only be called by the current owner.* - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| newOwner | address | undefined | - - - -## Events - -### OwnershipTransferred - -```solidity -event OwnershipTransferred(address indexed previousOwner, address indexed newOwner) -``` - - - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| previousOwner `indexed` | address | undefined | -| newOwner `indexed` | address | undefined | - - - diff --git a/docs/elin/contracts/cryptography/ECDSA.md b/docs/elin/contracts/cryptography/ECDSA.md deleted file mode 100644 index d4fef0408..000000000 --- a/docs/elin/contracts/cryptography/ECDSA.md +++ /dev/null @@ -1,12 +0,0 @@ -# ECDSA - - - - - - - -*Elliptic Curve Digital Signature Algorithm (ECDSA) operations. These functions can be used to verify that a message was signed by the holder of the private keys of a given address.* - - - diff --git a/docs/elin/contracts/drafts/EIP712.md b/docs/elin/contracts/drafts/EIP712.md deleted file mode 100644 index d93f4f4f4..000000000 --- a/docs/elin/contracts/drafts/EIP712.md +++ /dev/null @@ -1,12 +0,0 @@ -# EIP712 - - - - - - - -*https://eips.ethereum.org/EIPS/eip-712[EIP 712] is a standard for hashing and signing of typed structured data. The encoding specified in the EIP is very generic, and such a generic implementation in Solidity is not feasible, thus this contract does not implement the encoding itself. Protocols need to implement the type-specific encoding they need in their contracts using a combination of `abi.encode` and `keccak256`. This contract implements the EIP 712 domain separator ({_domainSeparatorV4}) that is used as part of the encoding scheme, and the final step of the encoding to obtain the message digest that is then signed via ECDSA ({_hashTypedDataV4}). The implementation of the domain separator was designed to be as efficient as possible while still properly updating the chain id to protect against replay attacks on an eventual fork of the chain. NOTE: This contract implements the version of the encoding known as "v4", as implemented by the JSON RPC method https://docs.metamask.io/guide/signing-data.html[`eth_signTypedDataV4` in MetaMask]. _Available since v3.4._* - - - diff --git a/docs/elin/contracts/drafts/ERC20Permit.md b/docs/elin/contracts/drafts/ERC20Permit.md deleted file mode 100644 index abee0d6ef..000000000 --- a/docs/elin/contracts/drafts/ERC20Permit.md +++ /dev/null @@ -1,344 +0,0 @@ -# ERC20Permit - - - - - - - -*Implementation of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in https://eips.ethereum.org/EIPS/eip-2612[EIP-2612]. Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by presenting a message signed by the account. By not relying on `{IERC20-approve}`, the token holder account doesn't need to send a transaction, and thus is not required to hold Ether at all. _Available since v3.4._* - -## Methods - -### DOMAIN_SEPARATOR - -```solidity -function DOMAIN_SEPARATOR() external view returns (bytes32) -``` - - - -*See {IERC20Permit-DOMAIN_SEPARATOR}.* - - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | bytes32 | undefined | - -### allowance - -```solidity -function allowance(address owner, address spender) external view returns (uint256) -``` - - - -*See {IERC20-allowance}.* - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| owner | address | undefined | -| spender | address | undefined | - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | uint256 | undefined | - -### approve - -```solidity -function approve(address spender, uint256 amount) external nonpayable returns (bool) -``` - - - -*See {IERC20-approve}. Requirements: - `spender` cannot be the zero address.* - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| spender | address | undefined | -| amount | uint256 | undefined | - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | bool | undefined | - -### balanceOf - -```solidity -function balanceOf(address account) external view returns (uint256) -``` - - - -*See {IERC20-balanceOf}.* - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| account | address | undefined | - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | uint256 | undefined | - -### decimals - -```solidity -function decimals() external view returns (uint8) -``` - - - -*Returns the number of decimals used to get its user representation. For example, if `decimals` equals `2`, a balance of `505` tokens should be displayed to a user as `5,05` (`505 / 10 ** 2`). Tokens usually opt for a value of 18, imitating the relationship between Ether and Wei. This is the value {ERC20} uses, unless {_setupDecimals} is called. NOTE: This information is only used for _display_ purposes: it in no way affects any of the arithmetic of the contract, including {IERC20-balanceOf} and {IERC20-transfer}.* - - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | uint8 | undefined | - -### decreaseAllowance - -```solidity -function decreaseAllowance(address spender, uint256 subtractedValue) external nonpayable returns (bool) -``` - - - -*Atomically decreases the allowance granted to `spender` by the caller. This is an alternative to {approve} that can be used as a mitigation for problems described in {IERC20-approve}. Emits an {Approval} event indicating the updated allowance. Requirements: - `spender` cannot be the zero address. - `spender` must have allowance for the caller of at least `subtractedValue`.* - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| spender | address | undefined | -| subtractedValue | uint256 | undefined | - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | bool | undefined | - -### increaseAllowance - -```solidity -function increaseAllowance(address spender, uint256 addedValue) external nonpayable returns (bool) -``` - - - -*Atomically increases the allowance granted to `spender` by the caller. This is an alternative to {approve} that can be used as a mitigation for problems described in {IERC20-approve}. Emits an {Approval} event indicating the updated allowance. Requirements: - `spender` cannot be the zero address.* - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| spender | address | undefined | -| addedValue | uint256 | undefined | - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | bool | undefined | - -### name - -```solidity -function name() external view returns (string) -``` - - - -*Returns the name of the token.* - - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | string | undefined | - -### nonces - -```solidity -function nonces(address owner) external view returns (uint256) -``` - - - -*See {IERC20Permit-nonces}.* - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| owner | address | undefined | - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | uint256 | undefined | - -### permit - -```solidity -function permit(address owner, address spender, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s) external nonpayable -``` - - - -*See {IERC20Permit-permit}.* - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| owner | address | undefined | -| spender | address | undefined | -| value | uint256 | undefined | -| deadline | uint256 | undefined | -| v | uint8 | undefined | -| r | bytes32 | undefined | -| s | bytes32 | undefined | - -### symbol - -```solidity -function symbol() external view returns (string) -``` - - - -*Returns the symbol of the token, usually a shorter version of the name.* - - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | string | undefined | - -### totalSupply - -```solidity -function totalSupply() external view returns (uint256) -``` - - - -*See {IERC20-totalSupply}.* - - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | uint256 | undefined | - -### transfer - -```solidity -function transfer(address recipient, uint256 amount) external nonpayable returns (bool) -``` - - - -*See {IERC20-transfer}. Requirements: - `recipient` cannot be the zero address. - the caller must have a balance of at least `amount`.* - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| recipient | address | undefined | -| amount | uint256 | undefined | - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | bool | undefined | - -### transferFrom - -```solidity -function transferFrom(address sender, address recipient, uint256 amount) external nonpayable returns (bool) -``` - - - -*See {IERC20-transferFrom}. Emits an {Approval} event indicating the updated allowance. This is not required by the EIP. See the note at the beginning of {ERC20}. Requirements: - `sender` and `recipient` cannot be the zero address. - `sender` must have a balance of at least `amount`. - the caller must have allowance for ``sender``'s tokens of at least `amount`.* - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| sender | address | undefined | -| recipient | address | undefined | -| amount | uint256 | undefined | - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | bool | undefined | - - - -## Events - -### Approval - -```solidity -event Approval(address indexed owner, address indexed spender, uint256 value) -``` - - - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| owner `indexed` | address | undefined | -| spender `indexed` | address | undefined | -| value | uint256 | undefined | - -### Transfer - -```solidity -event Transfer(address indexed from, address indexed to, uint256 value) -``` - - - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| from `indexed` | address | undefined | -| to `indexed` | address | undefined | -| value | uint256 | undefined | - - - diff --git a/docs/elin/contracts/drafts/IERC20Permit.md b/docs/elin/contracts/drafts/IERC20Permit.md deleted file mode 100644 index 92628dc39..000000000 --- a/docs/elin/contracts/drafts/IERC20Permit.md +++ /dev/null @@ -1,76 +0,0 @@ -# IERC20Permit - - - - - - - -*Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in https://eips.ethereum.org/EIPS/eip-2612[EIP-2612]. Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by presenting a message signed by the account. By not relying on `{IERC20-approve}`, the token holder account doesn't need to send a transaction, and thus is not required to hold Ether at all.* - -## Methods - -### DOMAIN_SEPARATOR - -```solidity -function DOMAIN_SEPARATOR() external view returns (bytes32) -``` - - - -*Returns the domain separator used in the encoding of the signature for `permit`, as defined by {EIP712}.* - - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | bytes32 | undefined | - -### nonces - -```solidity -function nonces(address owner) external view returns (uint256) -``` - - - -*Returns the current nonce for `owner`. This value must be included whenever a signature is generated for {permit}. Every successful call to {permit} increases ``owner``'s nonce by one. This prevents a signature from being used multiple times.* - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| owner | address | undefined | - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | uint256 | undefined | - -### permit - -```solidity -function permit(address owner, address spender, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s) external nonpayable -``` - - - -*Sets `value` as the allowance of `spender` over `owner`'s tokens, given `owner`'s signed approval. IMPORTANT: The same issues {IERC20-approve} has related to transaction ordering also apply here. Emits an {Approval} event. Requirements: - `spender` cannot be the zero address. - `deadline` must be a timestamp in the future. - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner` over the EIP712-formatted function arguments. - the signature must use ``owner``'s current nonce (see {nonces}). For more information on the signature format, see the https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP section].* - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| owner | address | undefined | -| spender | address | undefined | -| value | uint256 | undefined | -| deadline | uint256 | undefined | -| v | uint8 | undefined | -| r | bytes32 | undefined | -| s | bytes32 | undefined | - - - - diff --git a/docs/elin/contracts/math/SafeMath.md b/docs/elin/contracts/math/SafeMath.md deleted file mode 100644 index 7399e3033..000000000 --- a/docs/elin/contracts/math/SafeMath.md +++ /dev/null @@ -1,12 +0,0 @@ -# SafeMath - - - - - - - -*Wrappers over Solidity's arithmetic operations with added overflow checks. Arithmetic operations in Solidity wrap on overflow. This can easily result in bugs, because programmers usually assume that an overflow raises an error, which is the standard behavior in high level programming languages. `SafeMath` restores this intuition by reverting the transaction when an operation overflows. Using this library instead of the unchecked operations eliminates an entire class of bugs, so it's recommended to use it always.* - - - diff --git a/docs/elin/contracts/proxy/Clones.md b/docs/elin/contracts/proxy/Clones.md deleted file mode 100644 index 05da81c8f..000000000 --- a/docs/elin/contracts/proxy/Clones.md +++ /dev/null @@ -1,12 +0,0 @@ -# Clones - - - - - - - -*https://eips.ethereum.org/EIPS/eip-1167[EIP 1167] is a standard for deploying minimal proxy contracts, also known as "clones". > To simply and cheaply clone contract functionality in an immutable way, this standard specifies > a minimal bytecode implementation that delegates all calls to a known, fixed address. The library includes functions to deploy a proxy using either `create` (traditional deployment) or `create2` (salted deterministic deployment). It also includes functions to predict the addresses of clones deployed using the deterministic method. _Available since v3.4._* - - - diff --git a/docs/elin/contracts/token/ERC20/ERC20.md b/docs/elin/contracts/token/ERC20/ERC20.md deleted file mode 100644 index b61c7d252..000000000 --- a/docs/elin/contracts/token/ERC20/ERC20.md +++ /dev/null @@ -1,283 +0,0 @@ -# ERC20 - - - - - - - -*Implementation of the {IERC20} interface. This implementation is agnostic to the way tokens are created. This means that a supply mechanism has to be added in a derived contract using {_mint}. For a generic mechanism see {ERC20PresetMinterPauser}. TIP: For a detailed writeup see our guide https://forum.zeppelin.solutions/t/how-to-implement-erc20-supply-mechanisms/226[How to implement supply mechanisms]. We have followed general OpenZeppelin guidelines: functions revert instead of returning `false` on failure. This behavior is nonetheless conventional and does not conflict with the expectations of ERC20 applications. Additionally, an {Approval} event is emitted on calls to {transferFrom}. This allows applications to reconstruct the allowance for all accounts just by listening to said events. Other implementations of the EIP may not emit these events, as it isn't required by the specification. Finally, the non-standard {decreaseAllowance} and {increaseAllowance} functions have been added to mitigate the well-known issues around setting allowances. See {IERC20-approve}.* - -## Methods - -### allowance - -```solidity -function allowance(address owner, address spender) external view returns (uint256) -``` - - - -*See {IERC20-allowance}.* - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| owner | address | undefined | -| spender | address | undefined | - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | uint256 | undefined | - -### approve - -```solidity -function approve(address spender, uint256 amount) external nonpayable returns (bool) -``` - - - -*See {IERC20-approve}. Requirements: - `spender` cannot be the zero address.* - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| spender | address | undefined | -| amount | uint256 | undefined | - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | bool | undefined | - -### balanceOf - -```solidity -function balanceOf(address account) external view returns (uint256) -``` - - - -*See {IERC20-balanceOf}.* - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| account | address | undefined | - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | uint256 | undefined | - -### decimals - -```solidity -function decimals() external view returns (uint8) -``` - - - -*Returns the number of decimals used to get its user representation. For example, if `decimals` equals `2`, a balance of `505` tokens should be displayed to a user as `5,05` (`505 / 10 ** 2`). Tokens usually opt for a value of 18, imitating the relationship between Ether and Wei. This is the value {ERC20} uses, unless {_setupDecimals} is called. NOTE: This information is only used for _display_ purposes: it in no way affects any of the arithmetic of the contract, including {IERC20-balanceOf} and {IERC20-transfer}.* - - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | uint8 | undefined | - -### decreaseAllowance - -```solidity -function decreaseAllowance(address spender, uint256 subtractedValue) external nonpayable returns (bool) -``` - - - -*Atomically decreases the allowance granted to `spender` by the caller. This is an alternative to {approve} that can be used as a mitigation for problems described in {IERC20-approve}. Emits an {Approval} event indicating the updated allowance. Requirements: - `spender` cannot be the zero address. - `spender` must have allowance for the caller of at least `subtractedValue`.* - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| spender | address | undefined | -| subtractedValue | uint256 | undefined | - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | bool | undefined | - -### increaseAllowance - -```solidity -function increaseAllowance(address spender, uint256 addedValue) external nonpayable returns (bool) -``` - - - -*Atomically increases the allowance granted to `spender` by the caller. This is an alternative to {approve} that can be used as a mitigation for problems described in {IERC20-approve}. Emits an {Approval} event indicating the updated allowance. Requirements: - `spender` cannot be the zero address.* - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| spender | address | undefined | -| addedValue | uint256 | undefined | - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | bool | undefined | - -### name - -```solidity -function name() external view returns (string) -``` - - - -*Returns the name of the token.* - - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | string | undefined | - -### symbol - -```solidity -function symbol() external view returns (string) -``` - - - -*Returns the symbol of the token, usually a shorter version of the name.* - - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | string | undefined | - -### totalSupply - -```solidity -function totalSupply() external view returns (uint256) -``` - - - -*See {IERC20-totalSupply}.* - - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | uint256 | undefined | - -### transfer - -```solidity -function transfer(address recipient, uint256 amount) external nonpayable returns (bool) -``` - - - -*See {IERC20-transfer}. Requirements: - `recipient` cannot be the zero address. - the caller must have a balance of at least `amount`.* - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| recipient | address | undefined | -| amount | uint256 | undefined | - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | bool | undefined | - -### transferFrom - -```solidity -function transferFrom(address sender, address recipient, uint256 amount) external nonpayable returns (bool) -``` - - - -*See {IERC20-transferFrom}. Emits an {Approval} event indicating the updated allowance. This is not required by the EIP. See the note at the beginning of {ERC20}. Requirements: - `sender` and `recipient` cannot be the zero address. - `sender` must have a balance of at least `amount`. - the caller must have allowance for ``sender``'s tokens of at least `amount`.* - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| sender | address | undefined | -| recipient | address | undefined | -| amount | uint256 | undefined | - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | bool | undefined | - - - -## Events - -### Approval - -```solidity -event Approval(address indexed owner, address indexed spender, uint256 value) -``` - - - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| owner `indexed` | address | undefined | -| spender `indexed` | address | undefined | -| value | uint256 | undefined | - -### Transfer - -```solidity -event Transfer(address indexed from, address indexed to, uint256 value) -``` - - - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| from `indexed` | address | undefined | -| to `indexed` | address | undefined | -| value | uint256 | undefined | - - - diff --git a/docs/elin/contracts/token/ERC20/ERC20Burnable.md b/docs/elin/contracts/token/ERC20/ERC20Burnable.md deleted file mode 100644 index b73b5034b..000000000 --- a/docs/elin/contracts/token/ERC20/ERC20Burnable.md +++ /dev/null @@ -1,316 +0,0 @@ -# ERC20Burnable - - - - - - - -*Extension of {ERC20} that allows token holders to destroy both their own tokens and those that they have an allowance for, in a way that can be recognized off-chain (via event analysis).* - -## Methods - -### allowance - -```solidity -function allowance(address owner, address spender) external view returns (uint256) -``` - - - -*See {IERC20-allowance}.* - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| owner | address | undefined | -| spender | address | undefined | - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | uint256 | undefined | - -### approve - -```solidity -function approve(address spender, uint256 amount) external nonpayable returns (bool) -``` - - - -*See {IERC20-approve}. Requirements: - `spender` cannot be the zero address.* - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| spender | address | undefined | -| amount | uint256 | undefined | - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | bool | undefined | - -### balanceOf - -```solidity -function balanceOf(address account) external view returns (uint256) -``` - - - -*See {IERC20-balanceOf}.* - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| account | address | undefined | - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | uint256 | undefined | - -### burn - -```solidity -function burn(uint256 amount) external nonpayable -``` - - - -*Destroys `amount` tokens from the caller. See {ERC20-_burn}.* - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| amount | uint256 | undefined | - -### burnFrom - -```solidity -function burnFrom(address account, uint256 amount) external nonpayable -``` - - - -*Destroys `amount` tokens from `account`, deducting from the caller's allowance. See {ERC20-_burn} and {ERC20-allowance}. Requirements: - the caller must have allowance for ``accounts``'s tokens of at least `amount`.* - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| account | address | undefined | -| amount | uint256 | undefined | - -### decimals - -```solidity -function decimals() external view returns (uint8) -``` - - - -*Returns the number of decimals used to get its user representation. For example, if `decimals` equals `2`, a balance of `505` tokens should be displayed to a user as `5,05` (`505 / 10 ** 2`). Tokens usually opt for a value of 18, imitating the relationship between Ether and Wei. This is the value {ERC20} uses, unless {_setupDecimals} is called. NOTE: This information is only used for _display_ purposes: it in no way affects any of the arithmetic of the contract, including {IERC20-balanceOf} and {IERC20-transfer}.* - - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | uint8 | undefined | - -### decreaseAllowance - -```solidity -function decreaseAllowance(address spender, uint256 subtractedValue) external nonpayable returns (bool) -``` - - - -*Atomically decreases the allowance granted to `spender` by the caller. This is an alternative to {approve} that can be used as a mitigation for problems described in {IERC20-approve}. Emits an {Approval} event indicating the updated allowance. Requirements: - `spender` cannot be the zero address. - `spender` must have allowance for the caller of at least `subtractedValue`.* - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| spender | address | undefined | -| subtractedValue | uint256 | undefined | - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | bool | undefined | - -### increaseAllowance - -```solidity -function increaseAllowance(address spender, uint256 addedValue) external nonpayable returns (bool) -``` - - - -*Atomically increases the allowance granted to `spender` by the caller. This is an alternative to {approve} that can be used as a mitigation for problems described in {IERC20-approve}. Emits an {Approval} event indicating the updated allowance. Requirements: - `spender` cannot be the zero address.* - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| spender | address | undefined | -| addedValue | uint256 | undefined | - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | bool | undefined | - -### name - -```solidity -function name() external view returns (string) -``` - - - -*Returns the name of the token.* - - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | string | undefined | - -### symbol - -```solidity -function symbol() external view returns (string) -``` - - - -*Returns the symbol of the token, usually a shorter version of the name.* - - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | string | undefined | - -### totalSupply - -```solidity -function totalSupply() external view returns (uint256) -``` - - - -*See {IERC20-totalSupply}.* - - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | uint256 | undefined | - -### transfer - -```solidity -function transfer(address recipient, uint256 amount) external nonpayable returns (bool) -``` - - - -*See {IERC20-transfer}. Requirements: - `recipient` cannot be the zero address. - the caller must have a balance of at least `amount`.* - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| recipient | address | undefined | -| amount | uint256 | undefined | - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | bool | undefined | - -### transferFrom - -```solidity -function transferFrom(address sender, address recipient, uint256 amount) external nonpayable returns (bool) -``` - - - -*See {IERC20-transferFrom}. Emits an {Approval} event indicating the updated allowance. This is not required by the EIP. See the note at the beginning of {ERC20}. Requirements: - `sender` and `recipient` cannot be the zero address. - `sender` must have a balance of at least `amount`. - the caller must have allowance for ``sender``'s tokens of at least `amount`.* - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| sender | address | undefined | -| recipient | address | undefined | -| amount | uint256 | undefined | - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | bool | undefined | - - - -## Events - -### Approval - -```solidity -event Approval(address indexed owner, address indexed spender, uint256 value) -``` - - - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| owner `indexed` | address | undefined | -| spender `indexed` | address | undefined | -| value | uint256 | undefined | - -### Transfer - -```solidity -event Transfer(address indexed from, address indexed to, uint256 value) -``` - - - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| from `indexed` | address | undefined | -| to `indexed` | address | undefined | -| value | uint256 | undefined | - - - diff --git a/docs/elin/contracts/token/ERC20/IERC20.md b/docs/elin/contracts/token/ERC20/IERC20.md deleted file mode 100644 index b50d0dbc3..000000000 --- a/docs/elin/contracts/token/ERC20/IERC20.md +++ /dev/null @@ -1,186 +0,0 @@ -# IERC20 - - - - - - - -*Interface of the ERC20 standard as defined in the EIP.* - -## Methods - -### allowance - -```solidity -function allowance(address owner, address spender) external view returns (uint256) -``` - - - -*Returns the remaining number of tokens that `spender` will be allowed to spend on behalf of `owner` through {transferFrom}. This is zero by default. This value changes when {approve} or {transferFrom} are called.* - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| owner | address | undefined | -| spender | address | undefined | - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | uint256 | undefined | - -### approve - -```solidity -function approve(address spender, uint256 amount) external nonpayable returns (bool) -``` - - - -*Sets `amount` as the allowance of `spender` over the caller's tokens. Returns a boolean value indicating whether the operation succeeded. IMPORTANT: Beware that changing an allowance with this method brings the risk that someone may use both the old and the new allowance by unfortunate transaction ordering. One possible solution to mitigate this race condition is to first reduce the spender's allowance to 0 and set the desired value afterwards: https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729 Emits an {Approval} event.* - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| spender | address | undefined | -| amount | uint256 | undefined | - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | bool | undefined | - -### balanceOf - -```solidity -function balanceOf(address account) external view returns (uint256) -``` - - - -*Returns the amount of tokens owned by `account`.* - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| account | address | undefined | - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | uint256 | undefined | - -### totalSupply - -```solidity -function totalSupply() external view returns (uint256) -``` - - - -*Returns the amount of tokens in existence.* - - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | uint256 | undefined | - -### transfer - -```solidity -function transfer(address recipient, uint256 amount) external nonpayable returns (bool) -``` - - - -*Moves `amount` tokens from the caller's account to `recipient`. Returns a boolean value indicating whether the operation succeeded. Emits a {Transfer} event.* - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| recipient | address | undefined | -| amount | uint256 | undefined | - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | bool | undefined | - -### transferFrom - -```solidity -function transferFrom(address sender, address recipient, uint256 amount) external nonpayable returns (bool) -``` - - - -*Moves `amount` tokens from `sender` to `recipient` using the allowance mechanism. `amount` is then deducted from the caller's allowance. Returns a boolean value indicating whether the operation succeeded. Emits a {Transfer} event.* - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| sender | address | undefined | -| recipient | address | undefined | -| amount | uint256 | undefined | - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | bool | undefined | - - - -## Events - -### Approval - -```solidity -event Approval(address indexed owner, address indexed spender, uint256 value) -``` - - - -*Emitted when the allowance of a `spender` for an `owner` is set by a call to {approve}. `value` is the new allowance.* - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| owner `indexed` | address | undefined | -| spender `indexed` | address | undefined | -| value | uint256 | undefined | - -### Transfer - -```solidity -event Transfer(address indexed from, address indexed to, uint256 value) -``` - - - -*Emitted when `value` tokens are moved from one account (`from`) to another (`to`). Note that `value` may be zero.* - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| from `indexed` | address | undefined | -| to `indexed` | address | undefined | -| value | uint256 | undefined | - - - diff --git a/docs/elin/contracts/token/ERC20/SafeERC20.md b/docs/elin/contracts/token/ERC20/SafeERC20.md deleted file mode 100644 index 80367d00d..000000000 --- a/docs/elin/contracts/token/ERC20/SafeERC20.md +++ /dev/null @@ -1,12 +0,0 @@ -# SafeERC20 - - - -> SafeERC20 - - - -*Wrappers around ERC20 operations that throw on failure (when the token contract returns false). Tokens that return no value (and instead revert or throw on failure) are also supported, non-reverting calls are assumed to be successful. To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract, which allows you to call the safe operations as `token.safeTransfer(...)`, etc.* - - - diff --git a/docs/elin/contracts/utils/Address.md b/docs/elin/contracts/utils/Address.md deleted file mode 100644 index 927f4068e..000000000 --- a/docs/elin/contracts/utils/Address.md +++ /dev/null @@ -1,12 +0,0 @@ -# Address - - - - - - - -*Collection of functions related to the address type* - - - diff --git a/docs/elin/contracts/utils/Context.md b/docs/elin/contracts/utils/Context.md deleted file mode 100644 index e189a3929..000000000 --- a/docs/elin/contracts/utils/Context.md +++ /dev/null @@ -1,12 +0,0 @@ -# Context - - - - - - - - - - - diff --git a/docs/elin/contracts/utils/Counters.md b/docs/elin/contracts/utils/Counters.md deleted file mode 100644 index d5e7265f7..000000000 --- a/docs/elin/contracts/utils/Counters.md +++ /dev/null @@ -1,12 +0,0 @@ -# Counters - -*Matt Condon (@shrugs)* - -> Counters - - - -*Provides counters that can only be incremented or decremented by one. This can be used e.g. to track the number of elements in a mapping, issuing ERC721 ids, or counting request ids. Include with `using Counters for Counters.Counter;` Since it is not possible to overflow a 256 bit integer with increments of one, `increment` can skip the {SafeMath} overflow check, thereby saving gas. This does assume however correct usage, in that the underlying `_value` is never directly accessed.* - - - diff --git a/docs/elin/contracts/utils/EnumerableSet.md b/docs/elin/contracts/utils/EnumerableSet.md deleted file mode 100644 index e5b07f61a..000000000 --- a/docs/elin/contracts/utils/EnumerableSet.md +++ /dev/null @@ -1,12 +0,0 @@ -# EnumerableSet - - - - - - - -*Library for managing https://en.wikipedia.org/wiki/Set_(abstract_data_type)[sets] of primitive types. Sets have the following properties: - Elements are added, removed, and checked for existence in constant time (O(1)). - Elements are enumerated in O(n). No guarantees are made on the ordering. ``` contract Example { // Add the library methods using EnumerableSet for EnumerableSet.AddressSet; // Declare a set state variable EnumerableSet.AddressSet private mySet; } ``` As of v3.3.0, sets of type `bytes32` (`Bytes32Set`), `address` (`AddressSet`) and `uint256` (`UintSet`) are supported.* - - - diff --git a/docs/elin/contracts/utils/ReentrancyGuard.md b/docs/elin/contracts/utils/ReentrancyGuard.md deleted file mode 100644 index d15113fe5..000000000 --- a/docs/elin/contracts/utils/ReentrancyGuard.md +++ /dev/null @@ -1,12 +0,0 @@ -# ReentrancyGuard - - - - - - - -*Contract module that helps prevent reentrant calls to a function. Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier available, which can be applied to functions to make sure there are no nested (reentrant) calls to them. Note that because there is a single `nonReentrant` guard, functions marked as `nonReentrant` may not call one another. This can be worked around by making those functions `private`, and then adding `external` `nonReentrant` entry points to them. TIP: If you would like to learn more about reentrancy and alternative ways to protect against it, check out our blog post https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul].* - - - diff --git a/docs/ypto/boring-solidity/contracts/BaseBoringBatchable.md b/docs/ypto/boring-solidity/contracts/BaseBoringBatchable.md deleted file mode 100644 index c2e7e1a6f..000000000 --- a/docs/ypto/boring-solidity/contracts/BaseBoringBatchable.md +++ /dev/null @@ -1,39 +0,0 @@ -# BaseBoringBatchable - - - - - - - - - -## Methods - -### batch - -```solidity -function batch(bytes[] calls, bool revertOnFail) external payable returns (bool[] successes, bytes[] results) -``` - - - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| calls | bytes[] | undefined | -| revertOnFail | bool | undefined | - -#### Returns - -| Name | Type | Description | -|---|---|---| -| successes | bool[] | undefined | -| results | bytes[] | undefined | - - - - diff --git a/docs/ypto/boring-solidity/contracts/BoringBatchable.md b/docs/ypto/boring-solidity/contracts/BoringBatchable.md deleted file mode 100644 index 5e5ed83b8..000000000 --- a/docs/ypto/boring-solidity/contracts/BoringBatchable.md +++ /dev/null @@ -1,62 +0,0 @@ -# BoringBatchable - - - - - - - - - -## Methods - -### batch - -```solidity -function batch(bytes[] calls, bool revertOnFail) external payable returns (bool[] successes, bytes[] results) -``` - - - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| calls | bytes[] | undefined | -| revertOnFail | bool | undefined | - -#### Returns - -| Name | Type | Description | -|---|---|---| -| successes | bool[] | undefined | -| results | bytes[] | undefined | - -### permitToken - -```solidity -function permitToken(contract IERC20 token, address from, address to, uint256 amount, uint256 deadline, uint8 v, bytes32 r, bytes32 s) external nonpayable -``` - - - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| token | contract IERC20 | undefined | -| from | address | undefined | -| to | address | undefined | -| amount | uint256 | undefined | -| deadline | uint256 | undefined | -| v | uint8 | undefined | -| r | bytes32 | undefined | -| s | bytes32 | undefined | - - - - diff --git a/docs/ypto/boring-solidity/contracts/BoringOwnable.md b/docs/ypto/boring-solidity/contracts/BoringOwnable.md deleted file mode 100644 index 4f354f572..000000000 --- a/docs/ypto/boring-solidity/contracts/BoringOwnable.md +++ /dev/null @@ -1,98 +0,0 @@ -# BoringOwnable - - - - - - - - - -## Methods - -### claimOwnership - -```solidity -function claimOwnership() external nonpayable -``` - - - - - - -### owner - -```solidity -function owner() external view returns (address) -``` - - - - - - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | address | undefined | - -### pendingOwner - -```solidity -function pendingOwner() external view returns (address) -``` - - - - - - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | address | undefined | - -### transferOwnership - -```solidity -function transferOwnership(address newOwner, bool direct, bool renounce) external nonpayable -``` - - - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| newOwner | address | undefined | -| direct | bool | undefined | -| renounce | bool | undefined | - - - -## Events - -### OwnershipTransferred - -```solidity -event OwnershipTransferred(address indexed previousOwner, address indexed newOwner) -``` - - - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| previousOwner `indexed` | address | undefined | -| newOwner `indexed` | address | undefined | - - - diff --git a/docs/ypto/boring-solidity/contracts/BoringOwnableData.md b/docs/ypto/boring-solidity/contracts/BoringOwnableData.md deleted file mode 100644 index b003c89e3..000000000 --- a/docs/ypto/boring-solidity/contracts/BoringOwnableData.md +++ /dev/null @@ -1,49 +0,0 @@ -# BoringOwnableData - - - - - - - - - -## Methods - -### owner - -```solidity -function owner() external view returns (address) -``` - - - - - - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | address | undefined | - -### pendingOwner - -```solidity -function pendingOwner() external view returns (address) -``` - - - - - - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | address | undefined | - - - - diff --git a/docs/ypto/boring-solidity/contracts/interfaces/IERC20.md b/docs/ypto/boring-solidity/contracts/interfaces/IERC20.md deleted file mode 100644 index a2f26df8f..000000000 --- a/docs/ypto/boring-solidity/contracts/interfaces/IERC20.md +++ /dev/null @@ -1,161 +0,0 @@ -# IERC20 - - - - - - - - - -## Methods - -### allowance - -```solidity -function allowance(address owner, address spender) external view returns (uint256) -``` - - - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| owner | address | undefined | -| spender | address | undefined | - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | uint256 | undefined | - -### approve - -```solidity -function approve(address spender, uint256 amount) external nonpayable returns (bool) -``` - - - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| spender | address | undefined | -| amount | uint256 | undefined | - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | bool | undefined | - -### balanceOf - -```solidity -function balanceOf(address account) external view returns (uint256) -``` - - - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| account | address | undefined | - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | uint256 | undefined | - -### permit - -```solidity -function permit(address owner, address spender, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s) external nonpayable -``` - - - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| owner | address | undefined | -| spender | address | undefined | -| value | uint256 | undefined | -| deadline | uint256 | undefined | -| v | uint8 | undefined | -| r | bytes32 | undefined | -| s | bytes32 | undefined | - -### totalSupply - -```solidity -function totalSupply() external view returns (uint256) -``` - - - - - - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | uint256 | undefined | - - - -## Events - -### Approval - -```solidity -event Approval(address indexed owner, address indexed spender, uint256 value) -``` - - - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| owner `indexed` | address | undefined | -| spender `indexed` | address | undefined | -| value | uint256 | undefined | - -### Transfer - -```solidity -event Transfer(address indexed from, address indexed to, uint256 value) -``` - - - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| from `indexed` | address | undefined | -| to `indexed` | address | undefined | -| value | uint256 | undefined | - - - diff --git a/docs/ypto/boring-solidity/contracts/libraries/BoringERC20.md b/docs/ypto/boring-solidity/contracts/libraries/BoringERC20.md deleted file mode 100644 index 0ef4c24dc..000000000 --- a/docs/ypto/boring-solidity/contracts/libraries/BoringERC20.md +++ /dev/null @@ -1,12 +0,0 @@ -# BoringERC20 - - - - - - - - - - - diff --git a/docs/ypto/boring-solidity/contracts/libraries/BoringMath.md b/docs/ypto/boring-solidity/contracts/libraries/BoringMath.md deleted file mode 100644 index c03e71afd..000000000 --- a/docs/ypto/boring-solidity/contracts/libraries/BoringMath.md +++ /dev/null @@ -1,12 +0,0 @@ -# BoringMath - - - - - - - - - - - diff --git a/docs/ypto/boring-solidity/contracts/libraries/BoringMath128.md b/docs/ypto/boring-solidity/contracts/libraries/BoringMath128.md deleted file mode 100644 index 2a3cdec6a..000000000 --- a/docs/ypto/boring-solidity/contracts/libraries/BoringMath128.md +++ /dev/null @@ -1,12 +0,0 @@ -# BoringMath128 - - - - - - - - - - - diff --git a/docs/ypto/boring-solidity/contracts/libraries/BoringMath32.md b/docs/ypto/boring-solidity/contracts/libraries/BoringMath32.md deleted file mode 100644 index cc0879014..000000000 --- a/docs/ypto/boring-solidity/contracts/libraries/BoringMath32.md +++ /dev/null @@ -1,12 +0,0 @@ -# BoringMath32 - - - - - - - - - - - diff --git a/docs/ypto/boring-solidity/contracts/libraries/BoringMath64.md b/docs/ypto/boring-solidity/contracts/libraries/BoringMath64.md deleted file mode 100644 index 2094ecbda..000000000 --- a/docs/ypto/boring-solidity/contracts/libraries/BoringMath64.md +++ /dev/null @@ -1,12 +0,0 @@ -# BoringMath64 - - - - - - - - - - - diff --git a/hardhat.config.ts b/hardhat.config.ts index d96730c54..01a60bced 100644 --- a/hardhat.config.ts +++ b/hardhat.config.ts @@ -103,7 +103,7 @@ let config: HardhatUserConfig = { target: "ethers-v5", }, dodoc: { - runOnCompile: true, + runOnCompile: false, debugMode: false, // pre solidity 5 breaks docgen exclude: ["MultisigWallet", "WETH9"] diff --git a/package-lock.json b/package-lock.json index e29d89f10..a99f92421 100644 --- a/package-lock.json +++ b/package-lock.json @@ -16,6 +16,7 @@ "@openzeppelin/contracts": "3.4.1", "@openzeppelin/contracts-4.3.1": "npm:@openzeppelin/contracts@^4.3.1", "@openzeppelin/contracts-4.3.1-upgradeable": "npm:@openzeppelin/contracts-upgradeable@^4.3.1", + "@openzeppelin/contracts-4.6.0-upgradeable": "npm:@openzeppelin/contracts-upgradeable@4.6.0-rc.0", "@openzeppelin/contracts-upgradeable": "^3.4.1", "@tenderly/hardhat-tenderly": "^1.0.12", "dotenv": "^10.0.0", @@ -2812,6 +2813,12 @@ "resolved": "https://registry.npmjs.org/@openzeppelin/contracts-upgradeable/-/contracts-upgradeable-4.5.2.tgz", "integrity": "sha512-xgWZYaPlrEOQo3cBj97Ufiuv79SPd8Brh4GcFYhPgb6WvAq4ppz8dWKL6h+jLAK01rUqMRp/TS9AdXgAeNvCLA==" }, + "node_modules/@openzeppelin/contracts-4.6.0-upgradeable": { + "name": "@openzeppelin/contracts-upgradeable", + "version": "4.6.0-rc.0", + "resolved": "https://registry.npmjs.org/@openzeppelin/contracts-upgradeable/-/contracts-upgradeable-4.6.0-rc.0.tgz", + "integrity": "sha512-IQo98b6AlCGqpdgW1pxsUucqMu8x6WFJmusKMS4qoaVm3cifA/aQM/klHIAdr3pmVeZRjIM1gywQU85jzWEnAA==" + }, "node_modules/@openzeppelin/contracts-upgradeable": { "version": "3.4.1", "resolved": "https://registry.npmjs.org/@openzeppelin/contracts-upgradeable/-/contracts-upgradeable-3.4.1.tgz", @@ -34897,6 +34904,11 @@ "resolved": "https://registry.npmjs.org/@openzeppelin/contracts-upgradeable/-/contracts-upgradeable-4.5.2.tgz", "integrity": "sha512-xgWZYaPlrEOQo3cBj97Ufiuv79SPd8Brh4GcFYhPgb6WvAq4ppz8dWKL6h+jLAK01rUqMRp/TS9AdXgAeNvCLA==" }, + "@openzeppelin/contracts-4.6.0-upgradeable": { + "version": "npm:@openzeppelin/contracts-upgradeable@4.6.0-rc.0", + "resolved": "https://registry.npmjs.org/@openzeppelin/contracts-upgradeable/-/contracts-upgradeable-4.6.0-rc.0.tgz", + "integrity": "sha512-IQo98b6AlCGqpdgW1pxsUucqMu8x6WFJmusKMS4qoaVm3cifA/aQM/klHIAdr3pmVeZRjIM1gywQU85jzWEnAA==" + }, "@openzeppelin/contracts-upgradeable": { "version": "3.4.1", "resolved": "https://registry.npmjs.org/@openzeppelin/contracts-upgradeable/-/contracts-upgradeable-3.4.1.tgz", diff --git a/package.json b/package.json index 817e1812c..9a825c1a6 100644 --- a/package.json +++ b/package.json @@ -33,6 +33,7 @@ "@openzeppelin/contracts": "3.4.1", "@openzeppelin/contracts-4.3.1": "npm:@openzeppelin/contracts@^4.3.1", "@openzeppelin/contracts-4.3.1-upgradeable": "npm:@openzeppelin/contracts-upgradeable@^4.3.1", + "@openzeppelin/contracts-4.6.0-upgradeable": "npm:@openzeppelin/contracts-upgradeable@4.6.0-rc.0", "@openzeppelin/contracts-upgradeable": "^3.4.1", "@tenderly/hardhat-tenderly": "^1.0.12", "dotenv": "^10.0.0", diff --git a/test/bridge/RateLimiter.ts b/test/bridge/RateLimiter.ts index d0c1863a3..14df1c0b5 100644 --- a/test/bridge/RateLimiter.ts +++ b/test/bridge/RateLimiter.ts @@ -19,7 +19,7 @@ import epochSeconds from "@stdlib/time-now" chai.use(solidity) const { expect, assert } = chai -describe.only("Rate Limiter", () => { +describe("Rate Limiter", () => { let signers: Array let deployer: Signer let owner: Signer @@ -28,7 +28,6 @@ describe.only("Rate Limiter", () => { let rateLimiterTest: RateLimiterTest let USDC: GenericERC20 - let USDT: GenericERC20 // number of minutes in an hour let hour: number = 60 @@ -41,15 +40,13 @@ describe.only("Rate Limiter", () => { owner = signers[1] attacker = signers[10] - const rateLimiterFactory = await ethers.getContractFactory("RateLimiter") - - // deploy 2 test erc-20's const erc20Factory = await ethers.getContractFactory("GenericERC20") USDC = (await erc20Factory.deploy("USDC", "USDC", "6")) as GenericERC20 - USDT = (await erc20Factory.deploy("USDT", "USDT", "6")) as GenericERC20 // deploy and initialize the rate limiter + const rateLimiterFactory = await ethers.getContractFactory("RateLimiter") + rateLimiter = (await rateLimiterFactory.deploy()) as RateLimiter await rateLimiter.initialize() diff --git a/test/bridge/SynapseBridge.ts b/test/bridge/SynapseBridge.ts index e6417dd27..8291b09ad 100644 --- a/test/bridge/SynapseBridge.ts +++ b/test/bridge/SynapseBridge.ts @@ -1,188 +1,161 @@ -// import { BigNumber, Signer } from "ethers" -// import { -// MAX_UINT256, -// TIME, -// ZERO_ADDRESS, -// asyncForEach, -// getCurrentBlockTimestamp, -// setNextTimestamp, -// setTimestamp, -// forceAdvanceOneBlock, -// } from "./testUtils" - -// import { solidity } from "ethereum-waffle" -// import { deployments, ethers } from "hardhat" - -// import { SynapseBridge } from "../build/typechain/SynapseBridge" -// import { SynapseERC20 } from "../build/typechain/SynapseERC20" - -// import chai from "chai" - -// chai.use(solidity) -// const { expect } = chai - -// describe("SynapseBridge", async () => { -// const { get } = deployments -// let signers: Array -// let synapseBridge: SynapseBridge -// let syntestERC20: SynapseERC20 -// let testERC20: SynapseERC20 -// let owner: Signer -// let user1: Signer -// let user2: Signer -// let nodeGroup: Signer -// let ownerAddress: string -// let user1Address: string -// let user2Address: string -// let nodeGroupAddress: string - -// const setupTest = deployments.createFixture( -// async ({ deployments, ethers }) => { -// const { get } = deployments -// await deployments.fixture() // ensure you start from a fresh deployments - -// signers = await ethers.getSigners() -// owner = signers[0] -// user1 = signers[1] -// user2 = signers[2] -// nodeGroup = signers[3] -// ownerAddress = await owner.getAddress() -// user1Address = await user1.getAddress() -// user2Address = await user2.getAddress() -// nodeGroupAddress = await nodeGroup.getAddress() -// const SynapseBridgeContract = await ethers.getContractFactory("SynapseBridge") -// const synapseERC20Contract = await ethers.getContractFactory("SynapseERC20") - -// synapseBridge = await SynapseBridgeContract.deploy() -// syntestERC20 = (await synapseERC20Contract.deploy()) -// testERC20 = (await synapseERC20Contract.deploy()) - -// await synapseBridge.initialize() -// await syntestERC20.initialize( -// "Synapse Test Token", -// "SYNTEST", -// 18, -// await owner.getAddress() -// ) - -// await testERC20.initialize( -// "Test Token", -// "Test", -// 18, -// await owner.getAddress() -// ) - -// // Set approvals -// await asyncForEach([owner, user1, user2], async (signer) => { -// await syntestERC20.connect(signer).approve(synapseBridge.address, MAX_UINT256) -// await testERC20.connect(signer).approve(synapseBridge.address, MAX_UINT256) -// await testERC20.connect(signer).approve(synapseBridge.address, MAX_UINT256) -// await syntestERC20.connect(owner).grantRole(await syntestERC20.MINTER_ROLE(), await owner.getAddress()); -// await syntestERC20.connect(owner).grantRole(await syntestERC20.MINTER_ROLE(), await synapseBridge.address); -// await synapseBridge.connect(owner).grantRole(await synapseBridge.NODEGROUP_ROLE(), nodeGroupAddress); -// await testERC20.connect(owner).grantRole(await testERC20.MINTER_ROLE(), await owner.getAddress()); -// await syntestERC20.connect(owner).mint(await signer.getAddress(), BigNumber.from(10).pow(18).mul(100000)) -// await testERC20.connect(owner).mint(await signer.getAddress(), BigNumber.from(10).pow(18).mul(100000)) -// }) - -// }) - -// beforeEach(async () => { -// await setupTest() -// }) - -// describe("Bridge", () => { -// describe("ERC20", () => { -// it("Deposit - return correct balance in bridge contract", async () => { -// await synapseBridge.deposit(user1Address, 56, testERC20.address, String(1e18)) -// await expect(await testERC20.balanceOf(synapseBridge.address)).to.be.eq(String(1e18)) -// }) - -// it("Withdraw - correct balance to user and keep correct fee", async () => { -// //user deposits 1 token -// await synapseBridge.deposit(user1Address, 56, testERC20.address, String(1e18)) -// let preWithdraw = await testERC20.balanceOf(user1Address) - -// // later, redeems it on a different chain. Node group withdraws w/ a selected fee -// await synapseBridge.connect(nodeGroup).withdraw(user1Address, testERC20.address, String(9e17), String(1e17)) -// await expect((await testERC20.balanceOf(user1Address)).sub(preWithdraw)).to.be.eq(String(9e17)) -// await expect(await testERC20.balanceOf(synapseBridge.address)).to.be.eq(String(1e17)) -// await expect(await synapseBridge.getFeeBalance(testERC20.address)).to.be.eq(String(1e17)) - -// }) - -// it("Mint - correct balance to user and keep correct fee", async () => { -// // nodegroup mints after receiving TokenDeposit Event -// let preMint = await syntestERC20.balanceOf(user1Address) - -// await synapseBridge.connect(nodeGroup).mint(user1Address, syntestERC20.address, String(9e17), String(1e17)) - -// // checks for mint and fee amounts - -// await expect((await syntestERC20.balanceOf(user1Address)).sub(preMint)).to.be.eq(String(9e17)) -// await expect(await syntestERC20.balanceOf(synapseBridge.address)).to.be.eq(String(1e17)) -// await expect(await synapseBridge.getFeeBalance(syntestERC20.address)).to.be.eq(String(1e17)) - -// }) - -// it("Redeem - correct balance to user and keep correct fee", async () => { -// // user decides to redeem back to base chainId -// let preRedeem = await syntestERC20.balanceOf(user1Address) - -// await synapseBridge.redeem(user1Address, 1, syntestERC20.address, String(9e17)) -// await expect((await syntestERC20.balanceOf(user1Address)).sub(preRedeem)).to.be.eq(String(0)) -// }) - -// it("Withdraw fees", async () => { -// let preWithdrawFees = await syntestERC20.balanceOf(ownerAddress) -// let synTestFees = await synapseBridge.getFeeBalance(syntestERC20.address) -// await synapseBridge.withdrawFees(syntestERC20.address, ownerAddress) -// await expect((await syntestERC20.balanceOf(ownerAddress)).sub(preWithdrawFees)).to.be.eq(synTestFees) -// }) -// }) - -// describe("ETH", () => { -// it("Deposit ETH", async () => { -// await synapseBridge.depositETH(user1Address, 56, String(1e18), { -// value: String(1e18) -// }) -// expect(await ethers.provider.getBalance(synapseBridge.address)).to.be.eq(String(1e18)) -// }) - -// it("Withdraw ETH with correct fees", async () => { -// // someone deposits eth -// await synapseBridge.depositETH(ownerAddress, 56, String(1e18), { -// value: String(1e18) -// }) -// expect(await ethers.provider.getBalance(synapseBridge.address)).to.be.eq(String(1e18)) - -// // øn a redeem, node group withdraws eth -// let preWithdrawOwner = await ethers.provider.getBalance(ownerAddress) -// expect(await ethers.provider.getBalance(synapseBridge.address)).to.be.eq(String(1e18)) -// await synapseBridge.connect(nodeGroup).withdrawETH(ownerAddress, String(9e17), String(1e17)) -// expect(await ethers.provider.getBalance(synapseBridge.address)).to.be.eq(String(1e17)) -// let postWithdrawOwner = await ethers.provider.getBalance(ownerAddress) -// expect(postWithdrawOwner.sub(preWithdrawOwner)).to.be.eq(String(9e17)) -// }) - -// it("Withdraw ETH fees", async() => { -// // someone deposits eth -// await synapseBridge.depositETH(ownerAddress, 56, String(1e18), { -// value: String(1e18) -// }) - -// // øn a redeem, node group withdraws eth -// let preWithdrawOwner = await ethers.provider.getBalance(ownerAddress) - -// await synapseBridge.connect(nodeGroup).withdrawETH(ownerAddress, String(9e17), String(1e17)) - -// let preuser1Address = await ethers.provider.getBalance(user1Address) - -// await synapseBridge.connect(owner).withdrawETHFees(user1Address) -// expect((await ethers.provider.getBalance(user1Address)).sub(preuser1Address)).to.be.eq(String(1e17)) -// }); -// }) - -// }) - -// }); +import { BigNumber, Signer } from "ethers" +import { + MAX_UINT256, + TIME, + ZERO_ADDRESS, + asyncForEach, + getCurrentBlockTimestamp, + setNextTimestamp, + setTimestamp, + forceAdvanceOneBlock, +} from "./testUtils" +import { solidity } from "ethereum-waffle" +import { deployments, ethers } from "hardhat" + +import chai from "chai" +import { GenericERC20, RateLimiter, SynapseBridge } from "../../build/typechain" +import epochSeconds from "@stdlib/time-now" +import { keccak256 } from "ethers/lib/utils" +import { randomBytes } from "crypto" + +chai.use(solidity) +const { expect } = chai + +describe.only("SynapseBridge", async () => { + const { get } = deployments + + // signers + let signers: Array + let deployer: Signer + let owner: Signer + let limiter: Signer + let nodeGroup: Signer + let recipient: Signer + + // contracts + let bridge: SynapseBridge + let rateLimiter: RateLimiter + let USDC: GenericERC20 + + const decimals = Math.pow(10, 6) + + // deploy rateLimiter deploys the rate limiter contract, sets it to RateLimiter and + // assigns owner the limiter role + const deployRateLimiter = async () => { + const rateLimiterFactory = await ethers.getContractFactory("RateLimiter") + rateLimiter = (await rateLimiterFactory.deploy()) as RateLimiter + await rateLimiter.initialize() + + const limiterRole = await rateLimiter.LIMITER_ROLE() + await rateLimiter + .connect(deployer) + .grantRole(limiterRole, await owner.getAddress()) + + // connect the bridge config v3 with the owner. For unauthorized tests, this can be overriden + rateLimiter = rateLimiter.connect(owner) + } + + // deploys the bridge, grants role. Rate limiter *must* be deployed first + const deployBridge = async () => { + if (rateLimiter == null) { + throw "rate limiter must be deployed before bridge" + } + + // deploy and initialize the rate limiter + const synapseBridgeFactory = await ethers.getContractFactory( + "SynapseBridge", + ) + bridge = (await synapseBridgeFactory.deploy()) as SynapseBridge + await bridge.initialize() + + // grant rate limiter role on bridge to rate limiter + const rateLimiterRole = await bridge.RATE_LIMITER_ROLE() + await bridge + .connect(deployer) + .grantRole(rateLimiterRole, rateLimiter.address) + + await bridge.setRateLimiter(rateLimiter.address) + + const nodeGroupRole = await bridge.NODEGROUP_ROLE() + await bridge + .connect(deployer) + .grantRole(nodeGroupRole, await nodeGroup.getAddress()) + + bridge = await bridge.connect(nodeGroup) + + await rateLimiter + .connect(deployer) + .grantRole(await rateLimiter.BRIDGE_ROLE(), bridge.address) + } + + const setupTokens = async () => { + const erc20Factory = await ethers.getContractFactory("GenericERC20") + USDC = (await erc20Factory.deploy("USDC", "USDC", "6")) as GenericERC20 + } + + const setupTest = deployments.createFixture( + async ({ deployments, ethers }) => { + await deployments.fixture() + + signers = await ethers.getSigners() + + // assign roles + deployer = signers[0] + owner = signers[1] + limiter = signers[2] + nodeGroup = signers[3] + recipient = signers[4] + + await deployRateLimiter() + await deployBridge() + await setupTokens() + }, + ) + + beforeEach(async () => { + await setupTest() + }) + + // ammounts are multiplied by 10^6 + const setupAllowanceTest = async ( + token: GenericERC20, + allowanceAmount: number, + mintAmount: number, + intervalMin: number = 60, + ) => { + const lastReset = Math.floor(epochSeconds() / 60) + allowanceAmount = allowanceAmount * decimals + + await expect( + rateLimiter.setAllowance( + token.address, + allowanceAmount, + intervalMin, + lastReset, + ), + ).to.be.not.reverted + await expect(USDC.mint(bridge.address, mintAmount * decimals)) + } + + it("should add to retry queue if rate limit hit", async () => { + const mintAmount = 50 + await setupAllowanceTest(USDC, 100, mintAmount) + + const kappa = keccak256(randomBytes(32)) + + await expect( + bridge + .connect(nodeGroup) + .withdraw(await recipient.getAddress(), USDC.address, 101, 50, kappa), + ).to.be.not.reverted + + // make sure withdraw didn't happen + expect(await USDC.balanceOf(bridge.address)).to.be.eq( + (mintAmount * decimals).toString(), + ) + + // now retry. This should bypass the rate limiter + + await expect(rateLimiter.retryByKappa(kappa)).to.be.not.reverted + }) +}) diff --git a/test/bridge/SynapseBridge1.ts b/test/bridge/SynapseBridge1.ts new file mode 100644 index 000000000..e6417dd27 --- /dev/null +++ b/test/bridge/SynapseBridge1.ts @@ -0,0 +1,188 @@ +// import { BigNumber, Signer } from "ethers" +// import { +// MAX_UINT256, +// TIME, +// ZERO_ADDRESS, +// asyncForEach, +// getCurrentBlockTimestamp, +// setNextTimestamp, +// setTimestamp, +// forceAdvanceOneBlock, +// } from "./testUtils" + +// import { solidity } from "ethereum-waffle" +// import { deployments, ethers } from "hardhat" + +// import { SynapseBridge } from "../build/typechain/SynapseBridge" +// import { SynapseERC20 } from "../build/typechain/SynapseERC20" + +// import chai from "chai" + +// chai.use(solidity) +// const { expect } = chai + +// describe("SynapseBridge", async () => { +// const { get } = deployments +// let signers: Array +// let synapseBridge: SynapseBridge +// let syntestERC20: SynapseERC20 +// let testERC20: SynapseERC20 +// let owner: Signer +// let user1: Signer +// let user2: Signer +// let nodeGroup: Signer +// let ownerAddress: string +// let user1Address: string +// let user2Address: string +// let nodeGroupAddress: string + +// const setupTest = deployments.createFixture( +// async ({ deployments, ethers }) => { +// const { get } = deployments +// await deployments.fixture() // ensure you start from a fresh deployments + +// signers = await ethers.getSigners() +// owner = signers[0] +// user1 = signers[1] +// user2 = signers[2] +// nodeGroup = signers[3] +// ownerAddress = await owner.getAddress() +// user1Address = await user1.getAddress() +// user2Address = await user2.getAddress() +// nodeGroupAddress = await nodeGroup.getAddress() +// const SynapseBridgeContract = await ethers.getContractFactory("SynapseBridge") +// const synapseERC20Contract = await ethers.getContractFactory("SynapseERC20") + +// synapseBridge = await SynapseBridgeContract.deploy() +// syntestERC20 = (await synapseERC20Contract.deploy()) +// testERC20 = (await synapseERC20Contract.deploy()) + +// await synapseBridge.initialize() +// await syntestERC20.initialize( +// "Synapse Test Token", +// "SYNTEST", +// 18, +// await owner.getAddress() +// ) + +// await testERC20.initialize( +// "Test Token", +// "Test", +// 18, +// await owner.getAddress() +// ) + +// // Set approvals +// await asyncForEach([owner, user1, user2], async (signer) => { +// await syntestERC20.connect(signer).approve(synapseBridge.address, MAX_UINT256) +// await testERC20.connect(signer).approve(synapseBridge.address, MAX_UINT256) +// await testERC20.connect(signer).approve(synapseBridge.address, MAX_UINT256) +// await syntestERC20.connect(owner).grantRole(await syntestERC20.MINTER_ROLE(), await owner.getAddress()); +// await syntestERC20.connect(owner).grantRole(await syntestERC20.MINTER_ROLE(), await synapseBridge.address); +// await synapseBridge.connect(owner).grantRole(await synapseBridge.NODEGROUP_ROLE(), nodeGroupAddress); +// await testERC20.connect(owner).grantRole(await testERC20.MINTER_ROLE(), await owner.getAddress()); +// await syntestERC20.connect(owner).mint(await signer.getAddress(), BigNumber.from(10).pow(18).mul(100000)) +// await testERC20.connect(owner).mint(await signer.getAddress(), BigNumber.from(10).pow(18).mul(100000)) +// }) + +// }) + +// beforeEach(async () => { +// await setupTest() +// }) + +// describe("Bridge", () => { +// describe("ERC20", () => { +// it("Deposit - return correct balance in bridge contract", async () => { +// await synapseBridge.deposit(user1Address, 56, testERC20.address, String(1e18)) +// await expect(await testERC20.balanceOf(synapseBridge.address)).to.be.eq(String(1e18)) +// }) + +// it("Withdraw - correct balance to user and keep correct fee", async () => { +// //user deposits 1 token +// await synapseBridge.deposit(user1Address, 56, testERC20.address, String(1e18)) +// let preWithdraw = await testERC20.balanceOf(user1Address) + +// // later, redeems it on a different chain. Node group withdraws w/ a selected fee +// await synapseBridge.connect(nodeGroup).withdraw(user1Address, testERC20.address, String(9e17), String(1e17)) +// await expect((await testERC20.balanceOf(user1Address)).sub(preWithdraw)).to.be.eq(String(9e17)) +// await expect(await testERC20.balanceOf(synapseBridge.address)).to.be.eq(String(1e17)) +// await expect(await synapseBridge.getFeeBalance(testERC20.address)).to.be.eq(String(1e17)) + +// }) + +// it("Mint - correct balance to user and keep correct fee", async () => { +// // nodegroup mints after receiving TokenDeposit Event +// let preMint = await syntestERC20.balanceOf(user1Address) + +// await synapseBridge.connect(nodeGroup).mint(user1Address, syntestERC20.address, String(9e17), String(1e17)) + +// // checks for mint and fee amounts + +// await expect((await syntestERC20.balanceOf(user1Address)).sub(preMint)).to.be.eq(String(9e17)) +// await expect(await syntestERC20.balanceOf(synapseBridge.address)).to.be.eq(String(1e17)) +// await expect(await synapseBridge.getFeeBalance(syntestERC20.address)).to.be.eq(String(1e17)) + +// }) + +// it("Redeem - correct balance to user and keep correct fee", async () => { +// // user decides to redeem back to base chainId +// let preRedeem = await syntestERC20.balanceOf(user1Address) + +// await synapseBridge.redeem(user1Address, 1, syntestERC20.address, String(9e17)) +// await expect((await syntestERC20.balanceOf(user1Address)).sub(preRedeem)).to.be.eq(String(0)) +// }) + +// it("Withdraw fees", async () => { +// let preWithdrawFees = await syntestERC20.balanceOf(ownerAddress) +// let synTestFees = await synapseBridge.getFeeBalance(syntestERC20.address) +// await synapseBridge.withdrawFees(syntestERC20.address, ownerAddress) +// await expect((await syntestERC20.balanceOf(ownerAddress)).sub(preWithdrawFees)).to.be.eq(synTestFees) +// }) +// }) + +// describe("ETH", () => { +// it("Deposit ETH", async () => { +// await synapseBridge.depositETH(user1Address, 56, String(1e18), { +// value: String(1e18) +// }) +// expect(await ethers.provider.getBalance(synapseBridge.address)).to.be.eq(String(1e18)) +// }) + +// it("Withdraw ETH with correct fees", async () => { +// // someone deposits eth +// await synapseBridge.depositETH(ownerAddress, 56, String(1e18), { +// value: String(1e18) +// }) +// expect(await ethers.provider.getBalance(synapseBridge.address)).to.be.eq(String(1e18)) + +// // øn a redeem, node group withdraws eth +// let preWithdrawOwner = await ethers.provider.getBalance(ownerAddress) +// expect(await ethers.provider.getBalance(synapseBridge.address)).to.be.eq(String(1e18)) +// await synapseBridge.connect(nodeGroup).withdrawETH(ownerAddress, String(9e17), String(1e17)) +// expect(await ethers.provider.getBalance(synapseBridge.address)).to.be.eq(String(1e17)) +// let postWithdrawOwner = await ethers.provider.getBalance(ownerAddress) +// expect(postWithdrawOwner.sub(preWithdrawOwner)).to.be.eq(String(9e17)) +// }) + +// it("Withdraw ETH fees", async() => { +// // someone deposits eth +// await synapseBridge.depositETH(ownerAddress, 56, String(1e18), { +// value: String(1e18) +// }) + +// // øn a redeem, node group withdraws eth +// let preWithdrawOwner = await ethers.provider.getBalance(ownerAddress) + +// await synapseBridge.connect(nodeGroup).withdrawETH(ownerAddress, String(9e17), String(1e17)) + +// let preuser1Address = await ethers.provider.getBalance(user1Address) + +// await synapseBridge.connect(owner).withdrawETHFees(user1Address) +// expect((await ethers.provider.getBalance(user1Address)).sub(preuser1Address)).to.be.eq(String(1e17)) +// }); +// }) + +// }) + +// }); From 795790d78822819cca4b84124c1449f8298bde8d Mon Sep 17 00:00:00 2001 From: Trajan0x Date: Fri, 8 Apr 2022 01:59:54 -0400 Subject: [PATCH 012/135] re-add docs --- docs/amm/AaveSwap.md | 814 ++++++++++++ docs/amm/AaveSwapWrapper.md | 351 ++++++ docs/amm/AmplificationUtils.md | 88 ++ docs/amm/ILendingPool.md | 58 + docs/amm/LPToken.md | 417 +++++++ docs/amm/MathUtils.md | 12 + docs/amm/OwnerPausableUpgradeable.md | 150 +++ docs/amm/Swap.md | 787 ++++++++++++ docs/amm/SwapDeployer.md | 127 ++ docs/amm/SwapEthWrapper.md | 324 +++++ docs/amm/SwapFlashLoan.md | 894 ++++++++++++++ docs/amm/SwapUtils.md | 199 +++ docs/amm/helper/BaseSwapDeposit.md | 126 ++ docs/amm/helper/FlashLoanBorrowerExample.md | 54 + docs/amm/helper/GenericERC20.md | 361 ++++++ docs/amm/helper/Multicall2.md | 256 ++++ docs/amm/helper/test/TestMathUtils.md | 61 + docs/amm/helper/test/TestSwapReturnValues.md | 171 +++ docs/amm/interfaces/IFlashLoanReceiver.md | 35 + docs/amm/interfaces/IMetaSwap.md | 444 +++++++ docs/amm/interfaces/IMetaSwapDeposit.md | 33 + docs/amm/interfaces/ISwap.md | 353 ++++++ docs/amm/interfaces/ISwapFlashLoan.md | 372 ++++++ docs/auxiliary/DummyWeth.md | 144 +++ docs/auxiliary/DummyWethProxy.md | 155 +++ docs/bridge/BridgeConfigV3.md | 684 +++++++++++ docs/bridge/ECDSAFactory.md | 159 +++ docs/bridge/ECDSANodeManagement.md | 310 +++++ docs/bridge/ERC20Migrator.md | 65 + docs/bridge/HarmonySynapseBridge.md | 951 ++++++++++++++ docs/bridge/IERC20Mintable.md | 203 +++ docs/bridge/IFrax.md | 38 + docs/bridge/MRSynapseBridge.md | 951 ++++++++++++++ docs/bridge/MiniChefV2.md | 655 ++++++++++ docs/bridge/PoolConfig.md | 295 +++++ docs/bridge/RateLimiter.md | 580 +++++++++ docs/bridge/SynapseBridge.md | 1090 +++++++++++++++++ docs/bridge/SynapseERC20.md | 642 ++++++++++ docs/bridge/SynapseERC20Factory.md | 60 + .../bridge/interfaces/IECDSANodeManagement.md | 33 + docs/bridge/interfaces/IERC20Migrator.md | 31 + docs/bridge/interfaces/IMasterChef.md | 71 ++ docs/bridge/interfaces/IMetaSwapDeposit.md | 87 ++ docs/bridge/interfaces/IMiniChefV2.md | 166 +++ docs/bridge/interfaces/IRateLimiter.md | 55 + docs/bridge/interfaces/IRewarder.md | 60 + docs/bridge/interfaces/ISwap.md | 353 ++++++ docs/bridge/interfaces/ISynapseBridge.md | 140 +++ docs/bridge/interfaces/ISynapseERC20.md | 51 + .../libraries/EnumerableMapUpgradeable.md | 12 + docs/bridge/libraries/SignedSafeMath.md | 12 + docs/bridge/mocks/ERC20Mock.md | 300 +++++ docs/bridge/mocks/RewarderBrokenMock.md | 60 + docs/bridge/mocks/RewarderMock.md | 60 + docs/bridge/testing/NodeEnv.md | 348 ++++++ docs/bridge/testing/RateLimiterTest.md | 83 ++ docs/bridge/testing/Synapse.md | 623 ++++++++++ docs/bridge/utils/AddressArrayUtils.md | 12 + docs/bridge/utils/EnumerableStringMap.md | 12 + docs/bridge/utils/TimelockController.md | 626 ++++++++++ docs/bridge/wrappers/GMXWrapper.md | 106 ++ docs/bridge/wrappers/HarmonyBridgeZap.md | 303 +++++ docs/bridge/wrappers/IFrax.md | 38 + docs/bridge/wrappers/IGMX.md | 71 ++ docs/bridge/wrappers/L1BridgeZap.md | 266 ++++ docs/bridge/wrappers/L2BridgeZap.md | 348 ++++++ docs/bridge/wrappers/MigratorBridgeZap.md | 49 + docs/bridge/wrappers/MoonriverBridgeZap.md | 321 +++++ docs/console.md | 12 + .../access/AccessControlUpgradeable.md | 207 ++++ .../access/IAccessControlUpgradeable.md | 168 +++ .../proxy/utils/Initializable.md | 12 + .../security/ReentrancyGuardUpgradeable.md | 12 + .../utils/AddressUpgradeable.md | 12 + .../utils/ContextUpgradeable.md | 12 + .../utils/StringsUpgradeable.md | 12 + .../utils/introspection/ERC165Upgradeable.md | 37 + .../utils/introspection/IERC165Upgradeable.md | 37 + .../utils/math/MathUpgradeable.md | 12 + .../contracts-4.3.1/access/AccessControl.md | 207 ++++ .../contracts-4.3.1/access/IAccessControl.md | 168 +++ docs/elin/contracts-4.3.1/utils/Context.md | 12 + docs/elin/contracts-4.3.1/utils/Strings.md | 12 + .../utils/introspection/ERC165.md | 37 + .../utils/introspection/IERC165.md | 37 + .../contracts-4.3.1/utils/math/SafeMath.md | 12 + .../utils/structs/EnumerableMapUpgradeable.md | 12 + .../utils/structs/EnumerableSetUpgradeable.md | 12 + .../access/AccessControlUpgradeable.md | 230 ++++ .../access/OwnableUpgradeable.md | 79 ++ .../cryptography/ECDSAUpgradeable.md | 12 + .../drafts/EIP712Upgradeable.md | 12 + .../drafts/ERC20PermitUpgradeable.md | 344 ++++++ .../drafts/IERC20PermitUpgradeable.md | 76 ++ .../math/SafeMathUpgradeable.md | 12 + .../proxy/Initializable.md | 12 + .../token/ERC20/ERC20BurnableUpgradeable.md | 316 +++++ .../token/ERC20/ERC20Upgradeable.md | 283 +++++ .../token/ERC20/IERC20Upgradeable.md | 186 +++ .../utils/AddressUpgradeable.md | 12 + .../utils/ContextUpgradeable.md | 12 + .../utils/CountersUpgradeable.md | 12 + .../utils/EnumerableSetUpgradeable.md | 12 + .../utils/PausableUpgradeable.md | 67 + .../utils/ReentrancyGuardUpgradeable.md | 12 + docs/elin/contracts/access/AccessControl.md | 230 ++++ docs/elin/contracts/access/Ownable.md | 79 ++ docs/elin/contracts/cryptography/ECDSA.md | 12 + docs/elin/contracts/drafts/EIP712.md | 12 + docs/elin/contracts/drafts/ERC20Permit.md | 344 ++++++ docs/elin/contracts/drafts/IERC20Permit.md | 76 ++ docs/elin/contracts/math/SafeMath.md | 12 + docs/elin/contracts/proxy/Clones.md | 12 + docs/elin/contracts/token/ERC20/ERC20.md | 283 +++++ .../contracts/token/ERC20/ERC20Burnable.md | 316 +++++ docs/elin/contracts/token/ERC20/IERC20.md | 186 +++ docs/elin/contracts/token/ERC20/SafeERC20.md | 12 + docs/elin/contracts/utils/Address.md | 12 + docs/elin/contracts/utils/Context.md | 12 + docs/elin/contracts/utils/Counters.md | 12 + docs/elin/contracts/utils/EnumerableSet.md | 12 + docs/elin/contracts/utils/ReentrancyGuard.md | 12 + .../contracts/BaseBoringBatchable.md | 39 + .../contracts/BoringBatchable.md | 62 + .../contracts/BoringOwnable.md | 98 ++ .../contracts/BoringOwnableData.md | 49 + .../contracts/interfaces/IERC20.md | 161 +++ .../contracts/libraries/BoringERC20.md | 12 + .../contracts/libraries/BoringMath.md | 12 + .../contracts/libraries/BoringMath128.md | 12 + .../contracts/libraries/BoringMath32.md | 12 + .../contracts/libraries/BoringMath64.md | 12 + hardhat.config.ts | 2 +- 133 files changed, 23001 insertions(+), 1 deletion(-) create mode 100644 docs/amm/AaveSwap.md create mode 100644 docs/amm/AaveSwapWrapper.md create mode 100644 docs/amm/AmplificationUtils.md create mode 100644 docs/amm/ILendingPool.md create mode 100644 docs/amm/LPToken.md create mode 100644 docs/amm/MathUtils.md create mode 100644 docs/amm/OwnerPausableUpgradeable.md create mode 100644 docs/amm/Swap.md create mode 100644 docs/amm/SwapDeployer.md create mode 100644 docs/amm/SwapEthWrapper.md create mode 100644 docs/amm/SwapFlashLoan.md create mode 100644 docs/amm/SwapUtils.md create mode 100644 docs/amm/helper/BaseSwapDeposit.md create mode 100644 docs/amm/helper/FlashLoanBorrowerExample.md create mode 100644 docs/amm/helper/GenericERC20.md create mode 100644 docs/amm/helper/Multicall2.md create mode 100644 docs/amm/helper/test/TestMathUtils.md create mode 100644 docs/amm/helper/test/TestSwapReturnValues.md create mode 100644 docs/amm/interfaces/IFlashLoanReceiver.md create mode 100644 docs/amm/interfaces/IMetaSwap.md create mode 100644 docs/amm/interfaces/IMetaSwapDeposit.md create mode 100644 docs/amm/interfaces/ISwap.md create mode 100644 docs/amm/interfaces/ISwapFlashLoan.md create mode 100644 docs/auxiliary/DummyWeth.md create mode 100644 docs/auxiliary/DummyWethProxy.md create mode 100644 docs/bridge/BridgeConfigV3.md create mode 100644 docs/bridge/ECDSAFactory.md create mode 100644 docs/bridge/ECDSANodeManagement.md create mode 100644 docs/bridge/ERC20Migrator.md create mode 100644 docs/bridge/HarmonySynapseBridge.md create mode 100644 docs/bridge/IERC20Mintable.md create mode 100644 docs/bridge/IFrax.md create mode 100644 docs/bridge/MRSynapseBridge.md create mode 100644 docs/bridge/MiniChefV2.md create mode 100644 docs/bridge/PoolConfig.md create mode 100644 docs/bridge/RateLimiter.md create mode 100644 docs/bridge/SynapseBridge.md create mode 100644 docs/bridge/SynapseERC20.md create mode 100644 docs/bridge/SynapseERC20Factory.md create mode 100644 docs/bridge/interfaces/IECDSANodeManagement.md create mode 100644 docs/bridge/interfaces/IERC20Migrator.md create mode 100644 docs/bridge/interfaces/IMasterChef.md create mode 100644 docs/bridge/interfaces/IMetaSwapDeposit.md create mode 100644 docs/bridge/interfaces/IMiniChefV2.md create mode 100644 docs/bridge/interfaces/IRateLimiter.md create mode 100644 docs/bridge/interfaces/IRewarder.md create mode 100644 docs/bridge/interfaces/ISwap.md create mode 100644 docs/bridge/interfaces/ISynapseBridge.md create mode 100644 docs/bridge/interfaces/ISynapseERC20.md create mode 100644 docs/bridge/libraries/EnumerableMapUpgradeable.md create mode 100644 docs/bridge/libraries/SignedSafeMath.md create mode 100644 docs/bridge/mocks/ERC20Mock.md create mode 100644 docs/bridge/mocks/RewarderBrokenMock.md create mode 100644 docs/bridge/mocks/RewarderMock.md create mode 100644 docs/bridge/testing/NodeEnv.md create mode 100644 docs/bridge/testing/RateLimiterTest.md create mode 100644 docs/bridge/testing/Synapse.md create mode 100644 docs/bridge/utils/AddressArrayUtils.md create mode 100644 docs/bridge/utils/EnumerableStringMap.md create mode 100644 docs/bridge/utils/TimelockController.md create mode 100644 docs/bridge/wrappers/GMXWrapper.md create mode 100644 docs/bridge/wrappers/HarmonyBridgeZap.md create mode 100644 docs/bridge/wrappers/IFrax.md create mode 100644 docs/bridge/wrappers/IGMX.md create mode 100644 docs/bridge/wrappers/L1BridgeZap.md create mode 100644 docs/bridge/wrappers/L2BridgeZap.md create mode 100644 docs/bridge/wrappers/MigratorBridgeZap.md create mode 100644 docs/bridge/wrappers/MoonriverBridgeZap.md create mode 100644 docs/console.md create mode 100644 docs/elin/contracts-4.3.1-upgradeable/access/AccessControlUpgradeable.md create mode 100644 docs/elin/contracts-4.3.1-upgradeable/access/IAccessControlUpgradeable.md create mode 100644 docs/elin/contracts-4.3.1-upgradeable/proxy/utils/Initializable.md create mode 100644 docs/elin/contracts-4.3.1-upgradeable/security/ReentrancyGuardUpgradeable.md create mode 100644 docs/elin/contracts-4.3.1-upgradeable/utils/AddressUpgradeable.md create mode 100644 docs/elin/contracts-4.3.1-upgradeable/utils/ContextUpgradeable.md create mode 100644 docs/elin/contracts-4.3.1-upgradeable/utils/StringsUpgradeable.md create mode 100644 docs/elin/contracts-4.3.1-upgradeable/utils/introspection/ERC165Upgradeable.md create mode 100644 docs/elin/contracts-4.3.1-upgradeable/utils/introspection/IERC165Upgradeable.md create mode 100644 docs/elin/contracts-4.3.1-upgradeable/utils/math/MathUpgradeable.md create mode 100644 docs/elin/contracts-4.3.1/access/AccessControl.md create mode 100644 docs/elin/contracts-4.3.1/access/IAccessControl.md create mode 100644 docs/elin/contracts-4.3.1/utils/Context.md create mode 100644 docs/elin/contracts-4.3.1/utils/Strings.md create mode 100644 docs/elin/contracts-4.3.1/utils/introspection/ERC165.md create mode 100644 docs/elin/contracts-4.3.1/utils/introspection/IERC165.md create mode 100644 docs/elin/contracts-4.3.1/utils/math/SafeMath.md create mode 100644 docs/elin/contracts-4.6.0-upgradeable/utils/structs/EnumerableMapUpgradeable.md create mode 100644 docs/elin/contracts-4.6.0-upgradeable/utils/structs/EnumerableSetUpgradeable.md create mode 100644 docs/elin/contracts-upgradeable/access/AccessControlUpgradeable.md create mode 100644 docs/elin/contracts-upgradeable/access/OwnableUpgradeable.md create mode 100644 docs/elin/contracts-upgradeable/cryptography/ECDSAUpgradeable.md create mode 100644 docs/elin/contracts-upgradeable/drafts/EIP712Upgradeable.md create mode 100644 docs/elin/contracts-upgradeable/drafts/ERC20PermitUpgradeable.md create mode 100644 docs/elin/contracts-upgradeable/drafts/IERC20PermitUpgradeable.md create mode 100644 docs/elin/contracts-upgradeable/math/SafeMathUpgradeable.md create mode 100644 docs/elin/contracts-upgradeable/proxy/Initializable.md create mode 100644 docs/elin/contracts-upgradeable/token/ERC20/ERC20BurnableUpgradeable.md create mode 100644 docs/elin/contracts-upgradeable/token/ERC20/ERC20Upgradeable.md create mode 100644 docs/elin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.md create mode 100644 docs/elin/contracts-upgradeable/utils/AddressUpgradeable.md create mode 100644 docs/elin/contracts-upgradeable/utils/ContextUpgradeable.md create mode 100644 docs/elin/contracts-upgradeable/utils/CountersUpgradeable.md create mode 100644 docs/elin/contracts-upgradeable/utils/EnumerableSetUpgradeable.md create mode 100644 docs/elin/contracts-upgradeable/utils/PausableUpgradeable.md create mode 100644 docs/elin/contracts-upgradeable/utils/ReentrancyGuardUpgradeable.md create mode 100644 docs/elin/contracts/access/AccessControl.md create mode 100644 docs/elin/contracts/access/Ownable.md create mode 100644 docs/elin/contracts/cryptography/ECDSA.md create mode 100644 docs/elin/contracts/drafts/EIP712.md create mode 100644 docs/elin/contracts/drafts/ERC20Permit.md create mode 100644 docs/elin/contracts/drafts/IERC20Permit.md create mode 100644 docs/elin/contracts/math/SafeMath.md create mode 100644 docs/elin/contracts/proxy/Clones.md create mode 100644 docs/elin/contracts/token/ERC20/ERC20.md create mode 100644 docs/elin/contracts/token/ERC20/ERC20Burnable.md create mode 100644 docs/elin/contracts/token/ERC20/IERC20.md create mode 100644 docs/elin/contracts/token/ERC20/SafeERC20.md create mode 100644 docs/elin/contracts/utils/Address.md create mode 100644 docs/elin/contracts/utils/Context.md create mode 100644 docs/elin/contracts/utils/Counters.md create mode 100644 docs/elin/contracts/utils/EnumerableSet.md create mode 100644 docs/elin/contracts/utils/ReentrancyGuard.md create mode 100644 docs/ypto/boring-solidity/contracts/BaseBoringBatchable.md create mode 100644 docs/ypto/boring-solidity/contracts/BoringBatchable.md create mode 100644 docs/ypto/boring-solidity/contracts/BoringOwnable.md create mode 100644 docs/ypto/boring-solidity/contracts/BoringOwnableData.md create mode 100644 docs/ypto/boring-solidity/contracts/interfaces/IERC20.md create mode 100644 docs/ypto/boring-solidity/contracts/libraries/BoringERC20.md create mode 100644 docs/ypto/boring-solidity/contracts/libraries/BoringMath.md create mode 100644 docs/ypto/boring-solidity/contracts/libraries/BoringMath128.md create mode 100644 docs/ypto/boring-solidity/contracts/libraries/BoringMath32.md create mode 100644 docs/ypto/boring-solidity/contracts/libraries/BoringMath64.md diff --git a/docs/amm/AaveSwap.md b/docs/amm/AaveSwap.md new file mode 100644 index 000000000..0f5abfa98 --- /dev/null +++ b/docs/amm/AaveSwap.md @@ -0,0 +1,814 @@ +# AaveSwap + + + +> AaveSwap - A StableSwap implementation in solidity, integrated with Aave. + +This contract is responsible for custody of closely pegged assets (eg. group of stablecoins) and automatic market making system. Users become an LP (Liquidity Provider) by depositing their tokens in desired ratios for an exchange of the pool token that represents their share of the pool. Users can burn pool tokens and withdraw their share of token(s). Each time a swap between the pooled tokens happens, a set fee incurs which effectively gets distributed to the LPs. In case of emergencies, admin can pause additional deposits, swaps, or single-asset withdraws - which stops the ratio of the tokens in the pool from changing. Users can always withdraw their tokens via multi-asset withdraws. + +*Most of the logic is stored as a library `SwapUtils` for the sake of reducing contract's deployment size.* + +## Methods + +### addLiquidity + +```solidity +function addLiquidity(uint256[] amounts, uint256 minToMint, uint256 deadline) external nonpayable returns (uint256) +``` + +Add liquidity to the pool with the given amounts of tokens + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| amounts | uint256[] | the amounts of each token to add, in their native precision | +| minToMint | uint256 | the minimum LP tokens adding this amount of liquidity should mint, otherwise revert. Handy for front-running mitigation | +| deadline | uint256 | latest timestamp to accept this transaction | + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | uint256 | amount of LP token user minted and received | + +### calculateRemoveLiquidity + +```solidity +function calculateRemoveLiquidity(uint256 amount) external view returns (uint256[]) +``` + +A simple method to calculate amount of each underlying tokens that is returned upon burning given amount of LP tokens + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| amount | uint256 | the amount of LP tokens that would be burned on withdrawal | + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | uint256[] | array of token balances that the user will receive | + +### calculateRemoveLiquidityOneToken + +```solidity +function calculateRemoveLiquidityOneToken(uint256 tokenAmount, uint8 tokenIndex) external view returns (uint256 availableTokenAmount) +``` + +Calculate the amount of underlying token available to withdraw when withdrawing via only single token + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| tokenAmount | uint256 | the amount of LP token to burn | +| tokenIndex | uint8 | index of which token will be withdrawn | + +#### Returns + +| Name | Type | Description | +|---|---|---| +| availableTokenAmount | uint256 | calculated amount of underlying token available to withdraw | + +### calculateSwap + +```solidity +function calculateSwap(uint8 tokenIndexFrom, uint8 tokenIndexTo, uint256 dx) external view returns (uint256) +``` + +Calculate amount of tokens you receive on swap + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| tokenIndexFrom | uint8 | the token the user wants to sell | +| tokenIndexTo | uint8 | the token the user wants to buy | +| dx | uint256 | the amount of tokens the user wants to sell. If the token charges a fee on transfers, use the amount that gets transferred after the fee. | + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | uint256 | amount of tokens the user will receive | + +### calculateTokenAmount + +```solidity +function calculateTokenAmount(uint256[] amounts, bool deposit) external view returns (uint256) +``` + +A simple method to calculate prices from deposits or withdrawals, excluding fees but including slippage. This is helpful as an input into the various "min" parameters on calls to fight front-running + +*This shouldn't be used outside frontends for user estimates.* + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| amounts | uint256[] | an array of token amounts to deposit or withdrawal, corresponding to pooledTokens. The amount should be in each pooled token's native precision. If a token charges a fee on transfers, use the amount that gets transferred after the fee. | +| deposit | bool | whether this is a deposit or a withdrawal | + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | uint256 | token amount the user will receive | + +### claimAaveRewards + +```solidity +function claimAaveRewards() external nonpayable +``` + + + + + + +### getA + +```solidity +function getA() external view returns (uint256) +``` + +Return A, the amplification coefficient * n * (n - 1) + +*See the StableSwap paper for details* + + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | uint256 | A parameter | + +### getAPrecise + +```solidity +function getAPrecise() external view returns (uint256) +``` + +Return A in its raw precision form + +*See the StableSwap paper for details* + + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | uint256 | A parameter in its raw precision form | + +### getAdminBalance + +```solidity +function getAdminBalance(uint256 index) external view returns (uint256) +``` + +This function reads the accumulated amount of admin fees of the token with given index + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| index | uint256 | Index of the pooled token | + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | uint256 | admin's token balance in the token's precision | + +### getToken + +```solidity +function getToken(uint8 index) external view returns (contract IERC20) +``` + +Return address of the pooled token at given index. Reverts if tokenIndex is out of range. + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| index | uint8 | the index of the token | + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | contract IERC20 | address of the token at given index | + +### getTokenBalance + +```solidity +function getTokenBalance(uint8 index) external view returns (uint256) +``` + +Return current balance of the pooled token at given index + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| index | uint8 | the index of the token | + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | uint256 | current balance of the pooled token at given index with token's native precision | + +### getTokenIndex + +```solidity +function getTokenIndex(address tokenAddress) external view returns (uint8) +``` + +Return the index of the given token address. Reverts if no matching token is found. + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| tokenAddress | address | address of the token | + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | uint8 | the index of the given token address | + +### getVirtualPrice + +```solidity +function getVirtualPrice() external view returns (uint256) +``` + +Get the virtual price, to help calculate profit + + + + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | uint256 | the virtual price, scaled to the POOL_PRECISION_DECIMALS | + +### initialize + +```solidity +function initialize(contract IERC20[] _pooledTokens, uint8[] decimals, string lpTokenName, string lpTokenSymbol, uint256 _a, uint256 _fee, uint256 _adminFee, address lpTokenTargetAddress) external nonpayable +``` + +Initializes this Swap contract with the given parameters. This will also clone a LPToken contract that represents users' LP positions. The owner of LPToken will be this contract - which means only this contract is allowed to mint/burn tokens. + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| _pooledTokens | contract IERC20[] | an array of ERC20s this pool will accept | +| decimals | uint8[] | the decimals to use for each pooled token, eg 8 for WBTC. Cannot be larger than POOL_PRECISION_DECIMALS | +| lpTokenName | string | the long-form name of the token to be deployed | +| lpTokenSymbol | string | the short symbol for the token to be deployed | +| _a | uint256 | the amplification coefficient * n * (n - 1). See the StableSwap paper for details | +| _fee | uint256 | default swap fee to be initialized with | +| _adminFee | uint256 | default adminFee to be initialized with | +| lpTokenTargetAddress | address | the address of an existing LPToken contract to use as a target | + +### owner + +```solidity +function owner() external view returns (address) +``` + + + +*Returns the address of the current owner.* + + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | address | undefined | + +### pause + +```solidity +function pause() external nonpayable +``` + +Pause the contract. Revert if already paused. + + + + +### paused + +```solidity +function paused() external view returns (bool) +``` + + + +*Returns true if the contract is paused, and false otherwise.* + + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | bool | undefined | + +### rampA + +```solidity +function rampA(uint256 futureA, uint256 futureTime) external nonpayable +``` + +Start ramping up or down A parameter towards given futureA and futureTime Checks if the change is too rapid, and commits the new A value only when it falls under the limit range. + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| futureA | uint256 | the new A to ramp towards | +| futureTime | uint256 | timestamp when the new A should be reached | + +### removeLiquidity + +```solidity +function removeLiquidity(uint256 amount, uint256[] minAmounts, uint256 deadline) external nonpayable returns (uint256[]) +``` + +Burn LP tokens to remove liquidity from the pool. Withdraw fee that decays linearly over period of 4 weeks since last deposit will apply. + +*Liquidity can always be removed, even when the pool is paused.* + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| amount | uint256 | the amount of LP tokens to burn | +| minAmounts | uint256[] | the minimum amounts of each token in the pool acceptable for this burn. Useful as a front-running mitigation | +| deadline | uint256 | latest timestamp to accept this transaction | + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | uint256[] | amounts of tokens user received | + +### removeLiquidityImbalance + +```solidity +function removeLiquidityImbalance(uint256[] amounts, uint256 maxBurnAmount, uint256 deadline) external nonpayable returns (uint256) +``` + +Remove liquidity from the pool, weighted differently than the pool's current balances. Withdraw fee that decays linearly over period of 4 weeks since last deposit will apply. + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| amounts | uint256[] | how much of each token to withdraw | +| maxBurnAmount | uint256 | the max LP token provider is willing to pay to remove liquidity. Useful as a front-running mitigation. | +| deadline | uint256 | latest timestamp to accept this transaction | + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | uint256 | amount of LP tokens burned | + +### removeLiquidityOneToken + +```solidity +function removeLiquidityOneToken(uint256 tokenAmount, uint8 tokenIndex, uint256 minAmount, uint256 deadline) external nonpayable returns (uint256) +``` + +Remove liquidity from the pool all in one token. Withdraw fee that decays linearly over period of 4 weeks since last deposit will apply. + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| tokenAmount | uint256 | the amount of the token you want to receive | +| tokenIndex | uint8 | the index of the token you want to receive | +| minAmount | uint256 | the minimum amount to withdraw, otherwise revert | +| deadline | uint256 | latest timestamp to accept this transaction | + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | uint256 | amount of chosen token user received | + +### renounceOwnership + +```solidity +function renounceOwnership() external nonpayable +``` + + + +*Leaves the contract without owner. It will not be possible to call `onlyOwner` functions anymore. Can only be called by the current owner. NOTE: Renouncing ownership will leave the contract without an owner, thereby removing any functionality that is only available to the owner.* + + +### setAdminFee + +```solidity +function setAdminFee(uint256 newAdminFee) external nonpayable +``` + +Update the admin fee. Admin fee takes portion of the swap fee. + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| newAdminFee | uint256 | new admin fee to be applied on future transactions | + +### setRewardReceiver + +```solidity +function setRewardReceiver(address _reward_receiver) external nonpayable +``` + + + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| _reward_receiver | address | undefined | + +### setSwapFee + +```solidity +function setSwapFee(uint256 newSwapFee) external nonpayable +``` + +Update the swap fee to be applied on swaps + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| newSwapFee | uint256 | new swap fee to be applied on future transactions | + +### stopRampA + +```solidity +function stopRampA() external nonpayable +``` + +Stop ramping A immediately. Reverts if ramp A is already stopped. + + + + +### swap + +```solidity +function swap(uint8 tokenIndexFrom, uint8 tokenIndexTo, uint256 dx, uint256 minDy, uint256 deadline) external nonpayable returns (uint256) +``` + +Swap two tokens using this pool + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| tokenIndexFrom | uint8 | the token the user wants to swap from | +| tokenIndexTo | uint8 | the token the user wants to swap to | +| dx | uint256 | the amount of tokens the user wants to swap from | +| minDy | uint256 | the min amount the user would like to receive, or revert. | +| deadline | uint256 | latest timestamp to accept this transaction | + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | uint256 | undefined | + +### swapStorage + +```solidity +function swapStorage() external view returns (uint256 initialA, uint256 futureA, uint256 initialATime, uint256 futureATime, uint256 swapFee, uint256 adminFee, contract LPToken lpToken) +``` + + + + + + +#### Returns + +| Name | Type | Description | +|---|---|---| +| initialA | uint256 | undefined | +| futureA | uint256 | undefined | +| initialATime | uint256 | undefined | +| futureATime | uint256 | undefined | +| swapFee | uint256 | undefined | +| adminFee | uint256 | undefined | +| lpToken | contract LPToken | undefined | + +### transferOwnership + +```solidity +function transferOwnership(address newOwner) external nonpayable +``` + + + +*Transfers ownership of the contract to a new account (`newOwner`). Can only be called by the current owner.* + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| newOwner | address | undefined | + +### unpause + +```solidity +function unpause() external nonpayable +``` + +Unpause the contract. Revert if already unpaused. + + + + +### withdrawAdminFees + +```solidity +function withdrawAdminFees() external nonpayable +``` + +Withdraw all admin fees to the contract owner + + + + + + +## Events + +### AddLiquidity + +```solidity +event AddLiquidity(address indexed provider, uint256[] tokenAmounts, uint256[] fees, uint256 invariant, uint256 lpTokenSupply) +``` + + + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| provider `indexed` | address | undefined | +| tokenAmounts | uint256[] | undefined | +| fees | uint256[] | undefined | +| invariant | uint256 | undefined | +| lpTokenSupply | uint256 | undefined | + +### NewAdminFee + +```solidity +event NewAdminFee(uint256 newAdminFee) +``` + + + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| newAdminFee | uint256 | undefined | + +### NewSwapFee + +```solidity +event NewSwapFee(uint256 newSwapFee) +``` + + + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| newSwapFee | uint256 | undefined | + +### OwnershipTransferred + +```solidity +event OwnershipTransferred(address indexed previousOwner, address indexed newOwner) +``` + + + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| previousOwner `indexed` | address | undefined | +| newOwner `indexed` | address | undefined | + +### Paused + +```solidity +event Paused(address account) +``` + + + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| account | address | undefined | + +### RampA + +```solidity +event RampA(uint256 oldA, uint256 newA, uint256 initialTime, uint256 futureTime) +``` + + + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| oldA | uint256 | undefined | +| newA | uint256 | undefined | +| initialTime | uint256 | undefined | +| futureTime | uint256 | undefined | + +### RemoveLiquidity + +```solidity +event RemoveLiquidity(address indexed provider, uint256[] tokenAmounts, uint256 lpTokenSupply) +``` + + + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| provider `indexed` | address | undefined | +| tokenAmounts | uint256[] | undefined | +| lpTokenSupply | uint256 | undefined | + +### RemoveLiquidityImbalance + +```solidity +event RemoveLiquidityImbalance(address indexed provider, uint256[] tokenAmounts, uint256[] fees, uint256 invariant, uint256 lpTokenSupply) +``` + + + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| provider `indexed` | address | undefined | +| tokenAmounts | uint256[] | undefined | +| fees | uint256[] | undefined | +| invariant | uint256 | undefined | +| lpTokenSupply | uint256 | undefined | + +### RemoveLiquidityOne + +```solidity +event RemoveLiquidityOne(address indexed provider, uint256 lpTokenAmount, uint256 lpTokenSupply, uint256 boughtId, uint256 tokensBought) +``` + + + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| provider `indexed` | address | undefined | +| lpTokenAmount | uint256 | undefined | +| lpTokenSupply | uint256 | undefined | +| boughtId | uint256 | undefined | +| tokensBought | uint256 | undefined | + +### StopRampA + +```solidity +event StopRampA(uint256 currentA, uint256 time) +``` + + + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| currentA | uint256 | undefined | +| time | uint256 | undefined | + +### TokenSwap + +```solidity +event TokenSwap(address indexed buyer, uint256 tokensSold, uint256 tokensBought, uint128 soldId, uint128 boughtId) +``` + + + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| buyer `indexed` | address | undefined | +| tokensSold | uint256 | undefined | +| tokensBought | uint256 | undefined | +| soldId | uint128 | undefined | +| boughtId | uint128 | undefined | + +### Unpaused + +```solidity +event Unpaused(address account) +``` + + + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| account | address | undefined | + + + diff --git a/docs/amm/AaveSwapWrapper.md b/docs/amm/AaveSwapWrapper.md new file mode 100644 index 000000000..d337ac5d5 --- /dev/null +++ b/docs/amm/AaveSwapWrapper.md @@ -0,0 +1,351 @@ +# AaveSwapWrapper + + + +> AaveSwapWrapper + +A wrapper contract for interacting with aTokens + + + +## Methods + +### LENDING_POOL + +```solidity +function LENDING_POOL() external view returns (contract ILendingPool) +``` + + + + + + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | contract ILendingPool | undefined | + +### LP_TOKEN + +```solidity +function LP_TOKEN() external view returns (contract LPToken) +``` + + + + + + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | contract LPToken | undefined | + +### OWNER + +```solidity +function OWNER() external view returns (address) +``` + + + + + + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | address | undefined | + +### POOLED_TOKENS + +```solidity +function POOLED_TOKENS(uint256) external view returns (contract IERC20) +``` + + + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| _0 | uint256 | undefined | + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | contract IERC20 | undefined | + +### SWAP + +```solidity +function SWAP() external view returns (contract Swap) +``` + + + + + + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | contract Swap | undefined | + +### UNDERLYING_TOKENS + +```solidity +function UNDERLYING_TOKENS(uint256) external view returns (contract IERC20) +``` + + + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| _0 | uint256 | undefined | + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | contract IERC20 | undefined | + +### addLiquidity + +```solidity +function addLiquidity(uint256[] amounts, uint256 minToMint, uint256 deadline) external nonpayable returns (uint256) +``` + +Add liquidity to the pool with the given amounts of tokens. + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| amounts | uint256[] | the amounts of each token to add, in their native precision | +| minToMint | uint256 | the minimum LP tokens adding this amount of liquidity should mint, otherwise revert. Handy for front-running mitigation | +| deadline | uint256 | latest timestamp to accept this transaction | + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | uint256 | amount of LP token user minted and received | + +### calculateRemoveLiquidity + +```solidity +function calculateRemoveLiquidity(uint256 amount) external view returns (uint256[]) +``` + +A simple method to calculate amount of each underlying tokens that is returned upon burning given amount of LP tokens + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| amount | uint256 | the amount of LP tokens that would be burned on withdrawal | + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | uint256[] | array of token balances that the user will receive | + +### calculateRemoveLiquidityOneToken + +```solidity +function calculateRemoveLiquidityOneToken(uint256 tokenAmount, uint8 tokenIndex) external view returns (uint256 availableTokenAmount) +``` + +Calculate the amount of underlying token available to withdraw when withdrawing via only single token + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| tokenAmount | uint256 | the amount of LP token to burn | +| tokenIndex | uint8 | index of which token will be withdrawn | + +#### Returns + +| Name | Type | Description | +|---|---|---| +| availableTokenAmount | uint256 | calculated amount of underlying token available to withdraw | + +### calculateSwap + +```solidity +function calculateSwap(uint8 tokenIndexFrom, uint8 tokenIndexTo, uint256 dx) external view returns (uint256) +``` + +Calculate amount of tokens you receive on swap + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| tokenIndexFrom | uint8 | the token the user wants to sell | +| tokenIndexTo | uint8 | the token the user wants to buy | +| dx | uint256 | the amount of tokens the user wants to sell. If the token charges a fee on transfers, use the amount that gets transferred after the fee. | + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | uint256 | amount of tokens the user will receive | + +### calculateTokenAmount + +```solidity +function calculateTokenAmount(uint256[] amounts, bool deposit) external view returns (uint256) +``` + +A simple method to calculate prices from deposits or withdrawals, excluding fees but including slippage. This is helpful as an input into the various "min" parameters on calls to fight front-running + +*This shouldn't be used outside frontends for user estimates.* + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| amounts | uint256[] | an array of token amounts to deposit or withdrawal, corresponding to pooledTokens. The amount should be in each pooled token's native precision. If a token charges a fee on transfers, use the amount that gets transferred after the fee. | +| deposit | bool | whether this is a deposit or a withdrawal | + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | uint256 | token amount the user will receive | + +### getToken + +```solidity +function getToken(uint8 index) external view returns (contract IERC20) +``` + +Return address of the pooled token at given index. Reverts if tokenIndex is out of range. + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| index | uint8 | the index of the token | + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | contract IERC20 | address of the token at given index | + +### removeLiquidity + +```solidity +function removeLiquidity(uint256 amount, uint256[] minAmounts, uint256 deadline) external nonpayable returns (uint256[]) +``` + +Burn LP tokens to remove liquidity from the pool. + +*Liquidity can always be removed, even when the pool is paused. Caller will receive ETH instead of WETH9.* + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| amount | uint256 | the amount of LP tokens to burn | +| minAmounts | uint256[] | the minimum amounts of each token in the pool acceptable for this burn. Useful as a front-running mitigation | +| deadline | uint256 | latest timestamp to accept this transaction | + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | uint256[] | amounts of tokens user received | + +### removeLiquidityOneToken + +```solidity +function removeLiquidityOneToken(uint256 tokenAmount, uint8 tokenIndex, uint256 minAmount, uint256 deadline) external nonpayable returns (uint256) +``` + +Remove liquidity from the pool all in one token. + +*Caller will receive ETH instead of WETH9.* + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| tokenAmount | uint256 | the amount of the token you want to receive | +| tokenIndex | uint8 | the index of the token you want to receive | +| minAmount | uint256 | the minimum amount to withdraw, otherwise revert | +| deadline | uint256 | latest timestamp to accept this transaction | + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | uint256 | amount of chosen token user received | + +### rescue + +```solidity +function rescue() external nonpayable +``` + +Rescues any of the ETH, the pooled tokens, or the LPToken that may be stuck in this contract. Only the OWNER can call this function. + + + + +### swap + +```solidity +function swap(uint8 tokenIndexFrom, uint8 tokenIndexTo, uint256 dx, uint256 minDy, uint256 deadline) external nonpayable returns (uint256) +``` + +Swap two tokens using the underlying pool. If tokenIndexFrom represents WETH9 in the pool, the caller must set msg.value equal to dx. If the user is swapping to WETH9 in the pool, the user will receive ETH instead. + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| tokenIndexFrom | uint8 | the token the user wants to swap from | +| tokenIndexTo | uint8 | the token the user wants to swap to | +| dx | uint256 | the amount of tokens the user wants to swap from | +| minDy | uint256 | the min amount the user would like to receive, or revert. | +| deadline | uint256 | latest timestamp to accept this transaction | + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | uint256 | undefined | + + + + diff --git a/docs/amm/AmplificationUtils.md b/docs/amm/AmplificationUtils.md new file mode 100644 index 000000000..2131a526b --- /dev/null +++ b/docs/amm/AmplificationUtils.md @@ -0,0 +1,88 @@ +# AmplificationUtils + + + +> AmplificationUtils library + +A library to calculate and ramp the A parameter of a given `SwapUtils.Swap` struct. This library assumes the struct is fully validated. + + + +## Methods + +### A_PRECISION + +```solidity +function A_PRECISION() external view returns (uint256) +``` + + + + + + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | uint256 | undefined | + +### MAX_A + +```solidity +function MAX_A() external view returns (uint256) +``` + + + + + + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | uint256 | undefined | + + + +## Events + +### RampA + +```solidity +event RampA(uint256 oldA, uint256 newA, uint256 initialTime, uint256 futureTime) +``` + + + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| oldA | uint256 | undefined | +| newA | uint256 | undefined | +| initialTime | uint256 | undefined | +| futureTime | uint256 | undefined | + +### StopRampA + +```solidity +event StopRampA(uint256 currentA, uint256 time) +``` + + + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| currentA | uint256 | undefined | +| time | uint256 | undefined | + + + diff --git a/docs/amm/ILendingPool.md b/docs/amm/ILendingPool.md new file mode 100644 index 000000000..ecf05407c --- /dev/null +++ b/docs/amm/ILendingPool.md @@ -0,0 +1,58 @@ +# ILendingPool + + + + + + + + + +## Methods + +### deposit + +```solidity +function deposit(address asset, uint256 amount, address onBehalfOf, uint16 referralCode) external nonpayable +``` + + + +*Deposits an `amount` of underlying asset into the reserve, receiving in return overlying aTokens. - E.g. User deposits 100 USDC and gets in return 100 aUSDC* + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| asset | address | The address of the underlying asset to deposit | +| amount | uint256 | The amount to be deposited | +| onBehalfOf | address | The address that will receive the aTokens, same as msg.sender if the user wants to receive them on his own wallet, or a different address if the beneficiary of aTokens is a different wallet | +| referralCode | uint16 | Code used to register the integrator originating the operation, for potential rewards. 0 if the action is executed directly by the user, without any middle-man* | + +### withdraw + +```solidity +function withdraw(address asset, uint256 amount, address to) external nonpayable returns (uint256) +``` + + + +*Withdraws an `amount` of underlying asset from the reserve, burning the equivalent aTokens owned E.g. User has 100 aUSDC, calls withdraw() and receives 100 USDC, burning the 100 aUSDC* + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| asset | address | The address of the underlying asset to withdraw | +| amount | uint256 | The underlying amount to be withdrawn - Send the value type(uint256).max in order to withdraw the whole aToken balance | +| to | address | Address that will receive the underlying, same as msg.sender if the user wants to receive it on his own wallet, or a different address if the beneficiary is a different wallet | + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | uint256 | The final amount withdrawn* | + + + + diff --git a/docs/amm/LPToken.md b/docs/amm/LPToken.md new file mode 100644 index 000000000..aa526829b --- /dev/null +++ b/docs/amm/LPToken.md @@ -0,0 +1,417 @@ +# LPToken + + + +> Liquidity Provider Token + +This token is an ERC20 detailed token with added capability to be minted by the owner. It is used to represent user's shares when providing liquidity to swap contracts. + +*Only Swap contracts should initialize and own LPToken contracts.* + +## Methods + +### allowance + +```solidity +function allowance(address owner, address spender) external view returns (uint256) +``` + + + +*See {IERC20-allowance}.* + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| owner | address | undefined | +| spender | address | undefined | + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | uint256 | undefined | + +### approve + +```solidity +function approve(address spender, uint256 amount) external nonpayable returns (bool) +``` + + + +*See {IERC20-approve}. Requirements: - `spender` cannot be the zero address.* + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| spender | address | undefined | +| amount | uint256 | undefined | + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | bool | undefined | + +### balanceOf + +```solidity +function balanceOf(address account) external view returns (uint256) +``` + + + +*See {IERC20-balanceOf}.* + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| account | address | undefined | + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | uint256 | undefined | + +### burn + +```solidity +function burn(uint256 amount) external nonpayable +``` + + + +*Destroys `amount` tokens from the caller. See {ERC20-_burn}.* + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| amount | uint256 | undefined | + +### burnFrom + +```solidity +function burnFrom(address account, uint256 amount) external nonpayable +``` + + + +*Destroys `amount` tokens from `account`, deducting from the caller's allowance. See {ERC20-_burn} and {ERC20-allowance}. Requirements: - the caller must have allowance for ``accounts``'s tokens of at least `amount`.* + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| account | address | undefined | +| amount | uint256 | undefined | + +### decimals + +```solidity +function decimals() external view returns (uint8) +``` + + + +*Returns the number of decimals used to get its user representation. For example, if `decimals` equals `2`, a balance of `505` tokens should be displayed to a user as `5,05` (`505 / 10 ** 2`). Tokens usually opt for a value of 18, imitating the relationship between Ether and Wei. This is the value {ERC20} uses, unless {_setupDecimals} is called. NOTE: This information is only used for _display_ purposes: it in no way affects any of the arithmetic of the contract, including {IERC20-balanceOf} and {IERC20-transfer}.* + + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | uint8 | undefined | + +### decreaseAllowance + +```solidity +function decreaseAllowance(address spender, uint256 subtractedValue) external nonpayable returns (bool) +``` + + + +*Atomically decreases the allowance granted to `spender` by the caller. This is an alternative to {approve} that can be used as a mitigation for problems described in {IERC20-approve}. Emits an {Approval} event indicating the updated allowance. Requirements: - `spender` cannot be the zero address. - `spender` must have allowance for the caller of at least `subtractedValue`.* + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| spender | address | undefined | +| subtractedValue | uint256 | undefined | + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | bool | undefined | + +### increaseAllowance + +```solidity +function increaseAllowance(address spender, uint256 addedValue) external nonpayable returns (bool) +``` + + + +*Atomically increases the allowance granted to `spender` by the caller. This is an alternative to {approve} that can be used as a mitigation for problems described in {IERC20-approve}. Emits an {Approval} event indicating the updated allowance. Requirements: - `spender` cannot be the zero address.* + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| spender | address | undefined | +| addedValue | uint256 | undefined | + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | bool | undefined | + +### initialize + +```solidity +function initialize(string name, string symbol) external nonpayable returns (bool) +``` + +Initializes this LPToken contract with the given name and symbol + +*The caller of this function will become the owner. A Swap contract should call this in its initializer function.* + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| name | string | name of this token | +| symbol | string | symbol of this token | + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | bool | undefined | + +### mint + +```solidity +function mint(address recipient, uint256 amount) external nonpayable +``` + +Mints the given amount of LPToken to the recipient. + +*only owner can call this mint function* + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| recipient | address | address of account to receive the tokens | +| amount | uint256 | amount of tokens to mint | + +### name + +```solidity +function name() external view returns (string) +``` + + + +*Returns the name of the token.* + + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | string | undefined | + +### owner + +```solidity +function owner() external view returns (address) +``` + + + +*Returns the address of the current owner.* + + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | address | undefined | + +### renounceOwnership + +```solidity +function renounceOwnership() external nonpayable +``` + + + +*Leaves the contract without owner. It will not be possible to call `onlyOwner` functions anymore. Can only be called by the current owner. NOTE: Renouncing ownership will leave the contract without an owner, thereby removing any functionality that is only available to the owner.* + + +### symbol + +```solidity +function symbol() external view returns (string) +``` + + + +*Returns the symbol of the token, usually a shorter version of the name.* + + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | string | undefined | + +### totalSupply + +```solidity +function totalSupply() external view returns (uint256) +``` + + + +*See {IERC20-totalSupply}.* + + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | uint256 | undefined | + +### transfer + +```solidity +function transfer(address recipient, uint256 amount) external nonpayable returns (bool) +``` + + + +*See {IERC20-transfer}. Requirements: - `recipient` cannot be the zero address. - the caller must have a balance of at least `amount`.* + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| recipient | address | undefined | +| amount | uint256 | undefined | + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | bool | undefined | + +### transferFrom + +```solidity +function transferFrom(address sender, address recipient, uint256 amount) external nonpayable returns (bool) +``` + + + +*See {IERC20-transferFrom}. Emits an {Approval} event indicating the updated allowance. This is not required by the EIP. See the note at the beginning of {ERC20}. Requirements: - `sender` and `recipient` cannot be the zero address. - `sender` must have a balance of at least `amount`. - the caller must have allowance for ``sender``'s tokens of at least `amount`.* + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| sender | address | undefined | +| recipient | address | undefined | +| amount | uint256 | undefined | + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | bool | undefined | + +### transferOwnership + +```solidity +function transferOwnership(address newOwner) external nonpayable +``` + + + +*Transfers ownership of the contract to a new account (`newOwner`). Can only be called by the current owner.* + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| newOwner | address | undefined | + + + +## Events + +### Approval + +```solidity +event Approval(address indexed owner, address indexed spender, uint256 value) +``` + + + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| owner `indexed` | address | undefined | +| spender `indexed` | address | undefined | +| value | uint256 | undefined | + +### OwnershipTransferred + +```solidity +event OwnershipTransferred(address indexed previousOwner, address indexed newOwner) +``` + + + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| previousOwner `indexed` | address | undefined | +| newOwner `indexed` | address | undefined | + +### Transfer + +```solidity +event Transfer(address indexed from, address indexed to, uint256 value) +``` + + + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| from `indexed` | address | undefined | +| to `indexed` | address | undefined | +| value | uint256 | undefined | + + + diff --git a/docs/amm/MathUtils.md b/docs/amm/MathUtils.md new file mode 100644 index 000000000..707649233 --- /dev/null +++ b/docs/amm/MathUtils.md @@ -0,0 +1,12 @@ +# MathUtils + + + +> MathUtils library + +A library to be used in conjunction with SafeMath. Contains functions for calculating differences between two uint256. + + + + + diff --git a/docs/amm/OwnerPausableUpgradeable.md b/docs/amm/OwnerPausableUpgradeable.md new file mode 100644 index 000000000..3c2730f00 --- /dev/null +++ b/docs/amm/OwnerPausableUpgradeable.md @@ -0,0 +1,150 @@ +# OwnerPausableUpgradeable + + + +> OwnerPausable + +An ownable contract allows the owner to pause and unpause the contract without a delay. + +*Only methods using the provided modifiers will be paused.* + +## Methods + +### owner + +```solidity +function owner() external view returns (address) +``` + + + +*Returns the address of the current owner.* + + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | address | undefined | + +### pause + +```solidity +function pause() external nonpayable +``` + +Pause the contract. Revert if already paused. + + + + +### paused + +```solidity +function paused() external view returns (bool) +``` + + + +*Returns true if the contract is paused, and false otherwise.* + + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | bool | undefined | + +### renounceOwnership + +```solidity +function renounceOwnership() external nonpayable +``` + + + +*Leaves the contract without owner. It will not be possible to call `onlyOwner` functions anymore. Can only be called by the current owner. NOTE: Renouncing ownership will leave the contract without an owner, thereby removing any functionality that is only available to the owner.* + + +### transferOwnership + +```solidity +function transferOwnership(address newOwner) external nonpayable +``` + + + +*Transfers ownership of the contract to a new account (`newOwner`). Can only be called by the current owner.* + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| newOwner | address | undefined | + +### unpause + +```solidity +function unpause() external nonpayable +``` + +Unpause the contract. Revert if already unpaused. + + + + + + +## Events + +### OwnershipTransferred + +```solidity +event OwnershipTransferred(address indexed previousOwner, address indexed newOwner) +``` + + + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| previousOwner `indexed` | address | undefined | +| newOwner `indexed` | address | undefined | + +### Paused + +```solidity +event Paused(address account) +``` + + + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| account | address | undefined | + +### Unpaused + +```solidity +event Unpaused(address account) +``` + + + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| account | address | undefined | + + + diff --git a/docs/amm/Swap.md b/docs/amm/Swap.md new file mode 100644 index 000000000..bdb434b6f --- /dev/null +++ b/docs/amm/Swap.md @@ -0,0 +1,787 @@ +# Swap + + + +> Swap - A StableSwap implementation in solidity. + +This contract is responsible for custody of closely pegged assets (eg. group of stablecoins) and automatic market making system. Users become an LP (Liquidity Provider) by depositing their tokens in desired ratios for an exchange of the pool token that represents their share of the pool. Users can burn pool tokens and withdraw their share of token(s). Each time a swap between the pooled tokens happens, a set fee incurs which effectively gets distributed to the LPs. In case of emergencies, admin can pause additional deposits, swaps, or single-asset withdraws - which stops the ratio of the tokens in the pool from changing. Users can always withdraw their tokens via multi-asset withdraws. + +*Most of the logic is stored as a library `SwapUtils` for the sake of reducing contract's deployment size.* + +## Methods + +### addLiquidity + +```solidity +function addLiquidity(uint256[] amounts, uint256 minToMint, uint256 deadline) external nonpayable returns (uint256) +``` + +Add liquidity to the pool with the given amounts of tokens + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| amounts | uint256[] | the amounts of each token to add, in their native precision | +| minToMint | uint256 | the minimum LP tokens adding this amount of liquidity should mint, otherwise revert. Handy for front-running mitigation | +| deadline | uint256 | latest timestamp to accept this transaction | + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | uint256 | amount of LP token user minted and received | + +### calculateRemoveLiquidity + +```solidity +function calculateRemoveLiquidity(uint256 amount) external view returns (uint256[]) +``` + +A simple method to calculate amount of each underlying tokens that is returned upon burning given amount of LP tokens + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| amount | uint256 | the amount of LP tokens that would be burned on withdrawal | + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | uint256[] | array of token balances that the user will receive | + +### calculateRemoveLiquidityOneToken + +```solidity +function calculateRemoveLiquidityOneToken(uint256 tokenAmount, uint8 tokenIndex) external view returns (uint256 availableTokenAmount) +``` + +Calculate the amount of underlying token available to withdraw when withdrawing via only single token + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| tokenAmount | uint256 | the amount of LP token to burn | +| tokenIndex | uint8 | index of which token will be withdrawn | + +#### Returns + +| Name | Type | Description | +|---|---|---| +| availableTokenAmount | uint256 | calculated amount of underlying token available to withdraw | + +### calculateSwap + +```solidity +function calculateSwap(uint8 tokenIndexFrom, uint8 tokenIndexTo, uint256 dx) external view returns (uint256) +``` + +Calculate amount of tokens you receive on swap + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| tokenIndexFrom | uint8 | the token the user wants to sell | +| tokenIndexTo | uint8 | the token the user wants to buy | +| dx | uint256 | the amount of tokens the user wants to sell. If the token charges a fee on transfers, use the amount that gets transferred after the fee. | + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | uint256 | amount of tokens the user will receive | + +### calculateTokenAmount + +```solidity +function calculateTokenAmount(uint256[] amounts, bool deposit) external view returns (uint256) +``` + +A simple method to calculate prices from deposits or withdrawals, excluding fees but including slippage. This is helpful as an input into the various "min" parameters on calls to fight front-running + +*This shouldn't be used outside frontends for user estimates.* + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| amounts | uint256[] | an array of token amounts to deposit or withdrawal, corresponding to pooledTokens. The amount should be in each pooled token's native precision. If a token charges a fee on transfers, use the amount that gets transferred after the fee. | +| deposit | bool | whether this is a deposit or a withdrawal | + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | uint256 | token amount the user will receive | + +### getA + +```solidity +function getA() external view returns (uint256) +``` + +Return A, the amplification coefficient * n * (n - 1) + +*See the StableSwap paper for details* + + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | uint256 | A parameter | + +### getAPrecise + +```solidity +function getAPrecise() external view returns (uint256) +``` + +Return A in its raw precision form + +*See the StableSwap paper for details* + + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | uint256 | A parameter in its raw precision form | + +### getAdminBalance + +```solidity +function getAdminBalance(uint256 index) external view returns (uint256) +``` + +This function reads the accumulated amount of admin fees of the token with given index + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| index | uint256 | Index of the pooled token | + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | uint256 | admin's token balance in the token's precision | + +### getToken + +```solidity +function getToken(uint8 index) external view returns (contract IERC20) +``` + +Return address of the pooled token at given index. Reverts if tokenIndex is out of range. + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| index | uint8 | the index of the token | + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | contract IERC20 | address of the token at given index | + +### getTokenBalance + +```solidity +function getTokenBalance(uint8 index) external view returns (uint256) +``` + +Return current balance of the pooled token at given index + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| index | uint8 | the index of the token | + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | uint256 | current balance of the pooled token at given index with token's native precision | + +### getTokenIndex + +```solidity +function getTokenIndex(address tokenAddress) external view returns (uint8) +``` + +Return the index of the given token address. Reverts if no matching token is found. + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| tokenAddress | address | address of the token | + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | uint8 | the index of the given token address | + +### getVirtualPrice + +```solidity +function getVirtualPrice() external view returns (uint256) +``` + +Get the virtual price, to help calculate profit + + + + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | uint256 | the virtual price, scaled to the POOL_PRECISION_DECIMALS | + +### initialize + +```solidity +function initialize(contract IERC20[] _pooledTokens, uint8[] decimals, string lpTokenName, string lpTokenSymbol, uint256 _a, uint256 _fee, uint256 _adminFee, address lpTokenTargetAddress) external nonpayable +``` + +Initializes this Swap contract with the given parameters. This will also clone a LPToken contract that represents users' LP positions. The owner of LPToken will be this contract - which means only this contract is allowed to mint/burn tokens. + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| _pooledTokens | contract IERC20[] | an array of ERC20s this pool will accept | +| decimals | uint8[] | the decimals to use for each pooled token, eg 8 for WBTC. Cannot be larger than POOL_PRECISION_DECIMALS | +| lpTokenName | string | the long-form name of the token to be deployed | +| lpTokenSymbol | string | the short symbol for the token to be deployed | +| _a | uint256 | the amplification coefficient * n * (n - 1). See the StableSwap paper for details | +| _fee | uint256 | default swap fee to be initialized with | +| _adminFee | uint256 | default adminFee to be initialized with | +| lpTokenTargetAddress | address | the address of an existing LPToken contract to use as a target | + +### owner + +```solidity +function owner() external view returns (address) +``` + + + +*Returns the address of the current owner.* + + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | address | undefined | + +### pause + +```solidity +function pause() external nonpayable +``` + +Pause the contract. Revert if already paused. + + + + +### paused + +```solidity +function paused() external view returns (bool) +``` + + + +*Returns true if the contract is paused, and false otherwise.* + + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | bool | undefined | + +### rampA + +```solidity +function rampA(uint256 futureA, uint256 futureTime) external nonpayable +``` + +Start ramping up or down A parameter towards given futureA and futureTime Checks if the change is too rapid, and commits the new A value only when it falls under the limit range. + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| futureA | uint256 | the new A to ramp towards | +| futureTime | uint256 | timestamp when the new A should be reached | + +### removeLiquidity + +```solidity +function removeLiquidity(uint256 amount, uint256[] minAmounts, uint256 deadline) external nonpayable returns (uint256[]) +``` + +Burn LP tokens to remove liquidity from the pool. Withdraw fee that decays linearly over period of 4 weeks since last deposit will apply. + +*Liquidity can always be removed, even when the pool is paused.* + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| amount | uint256 | the amount of LP tokens to burn | +| minAmounts | uint256[] | the minimum amounts of each token in the pool acceptable for this burn. Useful as a front-running mitigation | +| deadline | uint256 | latest timestamp to accept this transaction | + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | uint256[] | amounts of tokens user received | + +### removeLiquidityImbalance + +```solidity +function removeLiquidityImbalance(uint256[] amounts, uint256 maxBurnAmount, uint256 deadline) external nonpayable returns (uint256) +``` + +Remove liquidity from the pool, weighted differently than the pool's current balances. Withdraw fee that decays linearly over period of 4 weeks since last deposit will apply. + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| amounts | uint256[] | how much of each token to withdraw | +| maxBurnAmount | uint256 | the max LP token provider is willing to pay to remove liquidity. Useful as a front-running mitigation. | +| deadline | uint256 | latest timestamp to accept this transaction | + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | uint256 | amount of LP tokens burned | + +### removeLiquidityOneToken + +```solidity +function removeLiquidityOneToken(uint256 tokenAmount, uint8 tokenIndex, uint256 minAmount, uint256 deadline) external nonpayable returns (uint256) +``` + +Remove liquidity from the pool all in one token. Withdraw fee that decays linearly over period of 4 weeks since last deposit will apply. + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| tokenAmount | uint256 | the amount of the token you want to receive | +| tokenIndex | uint8 | the index of the token you want to receive | +| minAmount | uint256 | the minimum amount to withdraw, otherwise revert | +| deadline | uint256 | latest timestamp to accept this transaction | + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | uint256 | amount of chosen token user received | + +### renounceOwnership + +```solidity +function renounceOwnership() external nonpayable +``` + + + +*Leaves the contract without owner. It will not be possible to call `onlyOwner` functions anymore. Can only be called by the current owner. NOTE: Renouncing ownership will leave the contract without an owner, thereby removing any functionality that is only available to the owner.* + + +### setAdminFee + +```solidity +function setAdminFee(uint256 newAdminFee) external nonpayable +``` + +Update the admin fee. Admin fee takes portion of the swap fee. + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| newAdminFee | uint256 | new admin fee to be applied on future transactions | + +### setSwapFee + +```solidity +function setSwapFee(uint256 newSwapFee) external nonpayable +``` + +Update the swap fee to be applied on swaps + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| newSwapFee | uint256 | new swap fee to be applied on future transactions | + +### stopRampA + +```solidity +function stopRampA() external nonpayable +``` + +Stop ramping A immediately. Reverts if ramp A is already stopped. + + + + +### swap + +```solidity +function swap(uint8 tokenIndexFrom, uint8 tokenIndexTo, uint256 dx, uint256 minDy, uint256 deadline) external nonpayable returns (uint256) +``` + +Swap two tokens using this pool + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| tokenIndexFrom | uint8 | the token the user wants to swap from | +| tokenIndexTo | uint8 | the token the user wants to swap to | +| dx | uint256 | the amount of tokens the user wants to swap from | +| minDy | uint256 | the min amount the user would like to receive, or revert. | +| deadline | uint256 | latest timestamp to accept this transaction | + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | uint256 | undefined | + +### swapStorage + +```solidity +function swapStorage() external view returns (uint256 initialA, uint256 futureA, uint256 initialATime, uint256 futureATime, uint256 swapFee, uint256 adminFee, contract LPToken lpToken) +``` + + + + + + +#### Returns + +| Name | Type | Description | +|---|---|---| +| initialA | uint256 | undefined | +| futureA | uint256 | undefined | +| initialATime | uint256 | undefined | +| futureATime | uint256 | undefined | +| swapFee | uint256 | undefined | +| adminFee | uint256 | undefined | +| lpToken | contract LPToken | undefined | + +### transferOwnership + +```solidity +function transferOwnership(address newOwner) external nonpayable +``` + + + +*Transfers ownership of the contract to a new account (`newOwner`). Can only be called by the current owner.* + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| newOwner | address | undefined | + +### unpause + +```solidity +function unpause() external nonpayable +``` + +Unpause the contract. Revert if already unpaused. + + + + +### withdrawAdminFees + +```solidity +function withdrawAdminFees() external nonpayable +``` + +Withdraw all admin fees to the contract owner + + + + + + +## Events + +### AddLiquidity + +```solidity +event AddLiquidity(address indexed provider, uint256[] tokenAmounts, uint256[] fees, uint256 invariant, uint256 lpTokenSupply) +``` + + + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| provider `indexed` | address | undefined | +| tokenAmounts | uint256[] | undefined | +| fees | uint256[] | undefined | +| invariant | uint256 | undefined | +| lpTokenSupply | uint256 | undefined | + +### NewAdminFee + +```solidity +event NewAdminFee(uint256 newAdminFee) +``` + + + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| newAdminFee | uint256 | undefined | + +### NewSwapFee + +```solidity +event NewSwapFee(uint256 newSwapFee) +``` + + + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| newSwapFee | uint256 | undefined | + +### OwnershipTransferred + +```solidity +event OwnershipTransferred(address indexed previousOwner, address indexed newOwner) +``` + + + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| previousOwner `indexed` | address | undefined | +| newOwner `indexed` | address | undefined | + +### Paused + +```solidity +event Paused(address account) +``` + + + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| account | address | undefined | + +### RampA + +```solidity +event RampA(uint256 oldA, uint256 newA, uint256 initialTime, uint256 futureTime) +``` + + + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| oldA | uint256 | undefined | +| newA | uint256 | undefined | +| initialTime | uint256 | undefined | +| futureTime | uint256 | undefined | + +### RemoveLiquidity + +```solidity +event RemoveLiquidity(address indexed provider, uint256[] tokenAmounts, uint256 lpTokenSupply) +``` + + + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| provider `indexed` | address | undefined | +| tokenAmounts | uint256[] | undefined | +| lpTokenSupply | uint256 | undefined | + +### RemoveLiquidityImbalance + +```solidity +event RemoveLiquidityImbalance(address indexed provider, uint256[] tokenAmounts, uint256[] fees, uint256 invariant, uint256 lpTokenSupply) +``` + + + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| provider `indexed` | address | undefined | +| tokenAmounts | uint256[] | undefined | +| fees | uint256[] | undefined | +| invariant | uint256 | undefined | +| lpTokenSupply | uint256 | undefined | + +### RemoveLiquidityOne + +```solidity +event RemoveLiquidityOne(address indexed provider, uint256 lpTokenAmount, uint256 lpTokenSupply, uint256 boughtId, uint256 tokensBought) +``` + + + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| provider `indexed` | address | undefined | +| lpTokenAmount | uint256 | undefined | +| lpTokenSupply | uint256 | undefined | +| boughtId | uint256 | undefined | +| tokensBought | uint256 | undefined | + +### StopRampA + +```solidity +event StopRampA(uint256 currentA, uint256 time) +``` + + + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| currentA | uint256 | undefined | +| time | uint256 | undefined | + +### TokenSwap + +```solidity +event TokenSwap(address indexed buyer, uint256 tokensSold, uint256 tokensBought, uint128 soldId, uint128 boughtId) +``` + + + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| buyer `indexed` | address | undefined | +| tokensSold | uint256 | undefined | +| tokensBought | uint256 | undefined | +| soldId | uint128 | undefined | +| boughtId | uint128 | undefined | + +### Unpaused + +```solidity +event Unpaused(address account) +``` + + + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| account | address | undefined | + + + diff --git a/docs/amm/SwapDeployer.md b/docs/amm/SwapDeployer.md new file mode 100644 index 000000000..5f0d5deb7 --- /dev/null +++ b/docs/amm/SwapDeployer.md @@ -0,0 +1,127 @@ +# SwapDeployer + + + + + + + + + +## Methods + +### deploy + +```solidity +function deploy(address swapAddress, contract IERC20[] _pooledTokens, uint8[] decimals, string lpTokenName, string lpTokenSymbol, uint256 _a, uint256 _fee, uint256 _adminFee, address lpTokenTargetAddress) external nonpayable returns (address) +``` + + + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| swapAddress | address | undefined | +| _pooledTokens | contract IERC20[] | undefined | +| decimals | uint8[] | undefined | +| lpTokenName | string | undefined | +| lpTokenSymbol | string | undefined | +| _a | uint256 | undefined | +| _fee | uint256 | undefined | +| _adminFee | uint256 | undefined | +| lpTokenTargetAddress | address | undefined | + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | address | undefined | + +### owner + +```solidity +function owner() external view returns (address) +``` + + + +*Returns the address of the current owner.* + + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | address | undefined | + +### renounceOwnership + +```solidity +function renounceOwnership() external nonpayable +``` + + + +*Leaves the contract without owner. It will not be possible to call `onlyOwner` functions anymore. Can only be called by the current owner. NOTE: Renouncing ownership will leave the contract without an owner, thereby removing any functionality that is only available to the owner.* + + +### transferOwnership + +```solidity +function transferOwnership(address newOwner) external nonpayable +``` + + + +*Transfers ownership of the contract to a new account (`newOwner`). Can only be called by the current owner.* + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| newOwner | address | undefined | + + + +## Events + +### NewSwapPool + +```solidity +event NewSwapPool(address indexed deployer, address swapAddress, contract IERC20[] pooledTokens) +``` + + + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| deployer `indexed` | address | undefined | +| swapAddress | address | undefined | +| pooledTokens | contract IERC20[] | undefined | + +### OwnershipTransferred + +```solidity +event OwnershipTransferred(address indexed previousOwner, address indexed newOwner) +``` + + + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| previousOwner `indexed` | address | undefined | +| newOwner `indexed` | address | undefined | + + + diff --git a/docs/amm/SwapEthWrapper.md b/docs/amm/SwapEthWrapper.md new file mode 100644 index 000000000..682ebadfc --- /dev/null +++ b/docs/amm/SwapEthWrapper.md @@ -0,0 +1,324 @@ +# SwapEthWrapper + +*Jongseung Lim (@weeb_mcgee)* + +> SwapEthWrapper + +A wrapper contract for Swap contracts that have WETH as one of the pooled tokens. + + + +## Methods + +### LP_TOKEN + +```solidity +function LP_TOKEN() external view returns (contract LPToken) +``` + + + + + + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | contract LPToken | undefined | + +### OWNER + +```solidity +function OWNER() external view returns (address) +``` + + + + + + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | address | undefined | + +### SWAP + +```solidity +function SWAP() external view returns (contract Swap) +``` + + + + + + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | contract Swap | undefined | + +### WETH_ADDRESS + +```solidity +function WETH_ADDRESS() external view returns (address payable) +``` + + + + + + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | address payable | undefined | + +### WETH_INDEX + +```solidity +function WETH_INDEX() external view returns (uint8) +``` + + + + + + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | uint8 | undefined | + +### addLiquidity + +```solidity +function addLiquidity(uint256[] amounts, uint256 minToMint, uint256 deadline) external payable returns (uint256) +``` + +Add liquidity to the pool with the given amounts of tokens. + +*The msg.value of this call should match the value in amounts array in position of WETH9.* + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| amounts | uint256[] | the amounts of each token to add, in their native precision | +| minToMint | uint256 | the minimum LP tokens adding this amount of liquidity should mint, otherwise revert. Handy for front-running mitigation | +| deadline | uint256 | latest timestamp to accept this transaction | + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | uint256 | amount of LP token user minted and received | + +### calculateRemoveLiquidity + +```solidity +function calculateRemoveLiquidity(uint256 amount) external view returns (uint256[]) +``` + +A simple method to calculate amount of each underlying tokens that is returned upon burning given amount of LP tokens + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| amount | uint256 | the amount of LP tokens that would be burned on withdrawal | + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | uint256[] | array of token balances that the user will receive | + +### calculateRemoveLiquidityOneToken + +```solidity +function calculateRemoveLiquidityOneToken(uint256 tokenAmount, uint8 tokenIndex) external view returns (uint256 availableTokenAmount) +``` + +Calculate the amount of underlying token available to withdraw when withdrawing via only single token + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| tokenAmount | uint256 | the amount of LP token to burn | +| tokenIndex | uint8 | index of which token will be withdrawn | + +#### Returns + +| Name | Type | Description | +|---|---|---| +| availableTokenAmount | uint256 | calculated amount of underlying token available to withdraw | + +### calculateTokenAmount + +```solidity +function calculateTokenAmount(uint256[] amounts, bool deposit) external view returns (uint256) +``` + +A simple method to calculate prices from deposits or withdrawals, excluding fees but including slippage. This is helpful as an input into the various "min" parameters on calls to fight front-running + +*This shouldn't be used outside frontends for user estimates.* + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| amounts | uint256[] | an array of token amounts to deposit or withdrawal, corresponding to pooledTokens. The amount should be in each pooled token's native precision. If a token charges a fee on transfers, use the amount that gets transferred after the fee. | +| deposit | bool | whether this is a deposit or a withdrawal | + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | uint256 | token amount the user will receive | + +### pooledTokens + +```solidity +function pooledTokens(uint256) external view returns (contract IERC20) +``` + + + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| _0 | uint256 | undefined | + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | contract IERC20 | undefined | + +### removeLiquidity + +```solidity +function removeLiquidity(uint256 amount, uint256[] minAmounts, uint256 deadline) external nonpayable returns (uint256[]) +``` + +Burn LP tokens to remove liquidity from the pool. + +*Liquidity can always be removed, even when the pool is paused. Caller will receive ETH instead of WETH9.* + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| amount | uint256 | the amount of LP tokens to burn | +| minAmounts | uint256[] | the minimum amounts of each token in the pool acceptable for this burn. Useful as a front-running mitigation | +| deadline | uint256 | latest timestamp to accept this transaction | + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | uint256[] | amounts of tokens user received | + +### removeLiquidityImbalance + +```solidity +function removeLiquidityImbalance(uint256[] amounts, uint256 maxBurnAmount, uint256 deadline) external nonpayable returns (uint256) +``` + +Remove liquidity from the pool, weighted differently than the pool's current balances. + +*Caller will receive ETH instead of WETH9.* + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| amounts | uint256[] | how much of each token to withdraw | +| maxBurnAmount | uint256 | the max LP token provider is willing to pay to remove liquidity. Useful as a front-running mitigation. | +| deadline | uint256 | latest timestamp to accept this transaction | + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | uint256 | amount of LP tokens burned | + +### removeLiquidityOneToken + +```solidity +function removeLiquidityOneToken(uint256 tokenAmount, uint8 tokenIndex, uint256 minAmount, uint256 deadline) external nonpayable returns (uint256) +``` + +Remove liquidity from the pool all in one token. + +*Caller will receive ETH instead of WETH9.* + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| tokenAmount | uint256 | the amount of the token you want to receive | +| tokenIndex | uint8 | the index of the token you want to receive | +| minAmount | uint256 | the minimum amount to withdraw, otherwise revert | +| deadline | uint256 | latest timestamp to accept this transaction | + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | uint256 | amount of chosen token user received | + +### rescue + +```solidity +function rescue() external nonpayable +``` + +Rescues any of the ETH, the pooled tokens, or the LPToken that may be stuck in this contract. Only the OWNER can call this function. + + + + +### swap + +```solidity +function swap(uint8 tokenIndexFrom, uint8 tokenIndexTo, uint256 dx, uint256 minDy, uint256 deadline) external payable returns (uint256) +``` + +Swap two tokens using the underlying pool. If tokenIndexFrom represents WETH9 in the pool, the caller must set msg.value equal to dx. If the user is swapping to WETH9 in the pool, the user will receive ETH instead. + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| tokenIndexFrom | uint8 | the token the user wants to swap from | +| tokenIndexTo | uint8 | the token the user wants to swap to | +| dx | uint256 | the amount of tokens the user wants to swap from | +| minDy | uint256 | the min amount the user would like to receive, or revert. | +| deadline | uint256 | latest timestamp to accept this transaction | + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | uint256 | undefined | + + + + diff --git a/docs/amm/SwapFlashLoan.md b/docs/amm/SwapFlashLoan.md new file mode 100644 index 000000000..0edf8bcfa --- /dev/null +++ b/docs/amm/SwapFlashLoan.md @@ -0,0 +1,894 @@ +# SwapFlashLoan + + + +> Swap - A StableSwap implementation in solidity. + +This contract is responsible for custody of closely pegged assets (eg. group of stablecoins) and automatic market making system. Users become an LP (Liquidity Provider) by depositing their tokens in desired ratios for an exchange of the pool token that represents their share of the pool. Users can burn pool tokens and withdraw their share of token(s). Each time a swap between the pooled tokens happens, a set fee incurs which effectively gets distributed to the LPs. In case of emergencies, admin can pause additional deposits, swaps, or single-asset withdraws - which stops the ratio of the tokens in the pool from changing. Users can always withdraw their tokens via multi-asset withdraws. + +*Most of the logic is stored as a library `SwapUtils` for the sake of reducing contract's deployment size.* + +## Methods + +### MAX_BPS + +```solidity +function MAX_BPS() external view returns (uint256) +``` + + + + + + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | uint256 | undefined | + +### addLiquidity + +```solidity +function addLiquidity(uint256[] amounts, uint256 minToMint, uint256 deadline) external nonpayable returns (uint256) +``` + +Add liquidity to the pool with the given amounts of tokens + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| amounts | uint256[] | the amounts of each token to add, in their native precision | +| minToMint | uint256 | the minimum LP tokens adding this amount of liquidity should mint, otherwise revert. Handy for front-running mitigation | +| deadline | uint256 | latest timestamp to accept this transaction | + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | uint256 | amount of LP token user minted and received | + +### calculateRemoveLiquidity + +```solidity +function calculateRemoveLiquidity(uint256 amount) external view returns (uint256[]) +``` + +A simple method to calculate amount of each underlying tokens that is returned upon burning given amount of LP tokens + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| amount | uint256 | the amount of LP tokens that would be burned on withdrawal | + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | uint256[] | array of token balances that the user will receive | + +### calculateRemoveLiquidityOneToken + +```solidity +function calculateRemoveLiquidityOneToken(uint256 tokenAmount, uint8 tokenIndex) external view returns (uint256 availableTokenAmount) +``` + +Calculate the amount of underlying token available to withdraw when withdrawing via only single token + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| tokenAmount | uint256 | the amount of LP token to burn | +| tokenIndex | uint8 | index of which token will be withdrawn | + +#### Returns + +| Name | Type | Description | +|---|---|---| +| availableTokenAmount | uint256 | calculated amount of underlying token available to withdraw | + +### calculateSwap + +```solidity +function calculateSwap(uint8 tokenIndexFrom, uint8 tokenIndexTo, uint256 dx) external view returns (uint256) +``` + +Calculate amount of tokens you receive on swap + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| tokenIndexFrom | uint8 | the token the user wants to sell | +| tokenIndexTo | uint8 | the token the user wants to buy | +| dx | uint256 | the amount of tokens the user wants to sell. If the token charges a fee on transfers, use the amount that gets transferred after the fee. | + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | uint256 | amount of tokens the user will receive | + +### calculateTokenAmount + +```solidity +function calculateTokenAmount(uint256[] amounts, bool deposit) external view returns (uint256) +``` + +A simple method to calculate prices from deposits or withdrawals, excluding fees but including slippage. This is helpful as an input into the various "min" parameters on calls to fight front-running + +*This shouldn't be used outside frontends for user estimates.* + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| amounts | uint256[] | an array of token amounts to deposit or withdrawal, corresponding to pooledTokens. The amount should be in each pooled token's native precision. If a token charges a fee on transfers, use the amount that gets transferred after the fee. | +| deposit | bool | whether this is a deposit or a withdrawal | + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | uint256 | token amount the user will receive | + +### flashLoan + +```solidity +function flashLoan(address receiver, contract IERC20 token, uint256 amount, bytes params) external nonpayable +``` + +Borrow the specified token from this pool for this transaction only. This function will call `IFlashLoanReceiver(receiver).executeOperation` and the `receiver` must return the full amount of the token and the associated fee by the end of the callback transaction. If the conditions are not met, this call is reverted. + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| receiver | address | the address of the receiver of the token. This address must implement the IFlashLoanReceiver interface and the callback function `executeOperation`. | +| token | contract IERC20 | the protocol fee in bps to be applied on the total flash loan fee | +| amount | uint256 | the total amount to borrow in this transaction | +| params | bytes | optional data to pass along to the callback function | + +### flashLoanFeeBPS + +```solidity +function flashLoanFeeBPS() external view returns (uint256) +``` + + + + + + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | uint256 | undefined | + +### getA + +```solidity +function getA() external view returns (uint256) +``` + +Return A, the amplification coefficient * n * (n - 1) + +*See the StableSwap paper for details* + + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | uint256 | A parameter | + +### getAPrecise + +```solidity +function getAPrecise() external view returns (uint256) +``` + +Return A in its raw precision form + +*See the StableSwap paper for details* + + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | uint256 | A parameter in its raw precision form | + +### getAdminBalance + +```solidity +function getAdminBalance(uint256 index) external view returns (uint256) +``` + +This function reads the accumulated amount of admin fees of the token with given index + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| index | uint256 | Index of the pooled token | + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | uint256 | admin's token balance in the token's precision | + +### getToken + +```solidity +function getToken(uint8 index) external view returns (contract IERC20) +``` + +Return address of the pooled token at given index. Reverts if tokenIndex is out of range. + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| index | uint8 | the index of the token | + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | contract IERC20 | address of the token at given index | + +### getTokenBalance + +```solidity +function getTokenBalance(uint8 index) external view returns (uint256) +``` + +Return current balance of the pooled token at given index + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| index | uint8 | the index of the token | + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | uint256 | current balance of the pooled token at given index with token's native precision | + +### getTokenIndex + +```solidity +function getTokenIndex(address tokenAddress) external view returns (uint8) +``` + +Return the index of the given token address. Reverts if no matching token is found. + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| tokenAddress | address | address of the token | + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | uint8 | the index of the given token address | + +### getVirtualPrice + +```solidity +function getVirtualPrice() external view returns (uint256) +``` + +Get the virtual price, to help calculate profit + + + + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | uint256 | the virtual price, scaled to the POOL_PRECISION_DECIMALS | + +### initialize + +```solidity +function initialize(contract IERC20[] _pooledTokens, uint8[] decimals, string lpTokenName, string lpTokenSymbol, uint256 _a, uint256 _fee, uint256 _adminFee, address lpTokenTargetAddress) external nonpayable +``` + +Initializes this Swap contract with the given parameters. This will also clone a LPToken contract that represents users' LP positions. The owner of LPToken will be this contract - which means only this contract is allowed to mint/burn tokens. + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| _pooledTokens | contract IERC20[] | an array of ERC20s this pool will accept | +| decimals | uint8[] | the decimals to use for each pooled token, eg 8 for WBTC. Cannot be larger than POOL_PRECISION_DECIMALS | +| lpTokenName | string | the long-form name of the token to be deployed | +| lpTokenSymbol | string | the short symbol for the token to be deployed | +| _a | uint256 | the amplification coefficient * n * (n - 1). See the StableSwap paper for details | +| _fee | uint256 | default swap fee to be initialized with | +| _adminFee | uint256 | default adminFee to be initialized with | +| lpTokenTargetAddress | address | the address of an existing LPToken contract to use as a target | + +### owner + +```solidity +function owner() external view returns (address) +``` + + + +*Returns the address of the current owner.* + + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | address | undefined | + +### pause + +```solidity +function pause() external nonpayable +``` + +Pause the contract. Revert if already paused. + + + + +### paused + +```solidity +function paused() external view returns (bool) +``` + + + +*Returns true if the contract is paused, and false otherwise.* + + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | bool | undefined | + +### protocolFeeShareBPS + +```solidity +function protocolFeeShareBPS() external view returns (uint256) +``` + + + + + + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | uint256 | undefined | + +### rampA + +```solidity +function rampA(uint256 futureA, uint256 futureTime) external nonpayable +``` + +Start ramping up or down A parameter towards given futureA and futureTime Checks if the change is too rapid, and commits the new A value only when it falls under the limit range. + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| futureA | uint256 | the new A to ramp towards | +| futureTime | uint256 | timestamp when the new A should be reached | + +### removeLiquidity + +```solidity +function removeLiquidity(uint256 amount, uint256[] minAmounts, uint256 deadline) external nonpayable returns (uint256[]) +``` + +Burn LP tokens to remove liquidity from the pool. Withdraw fee that decays linearly over period of 4 weeks since last deposit will apply. + +*Liquidity can always be removed, even when the pool is paused.* + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| amount | uint256 | the amount of LP tokens to burn | +| minAmounts | uint256[] | the minimum amounts of each token in the pool acceptable for this burn. Useful as a front-running mitigation | +| deadline | uint256 | latest timestamp to accept this transaction | + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | uint256[] | amounts of tokens user received | + +### removeLiquidityImbalance + +```solidity +function removeLiquidityImbalance(uint256[] amounts, uint256 maxBurnAmount, uint256 deadline) external nonpayable returns (uint256) +``` + +Remove liquidity from the pool, weighted differently than the pool's current balances. Withdraw fee that decays linearly over period of 4 weeks since last deposit will apply. + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| amounts | uint256[] | how much of each token to withdraw | +| maxBurnAmount | uint256 | the max LP token provider is willing to pay to remove liquidity. Useful as a front-running mitigation. | +| deadline | uint256 | latest timestamp to accept this transaction | + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | uint256 | amount of LP tokens burned | + +### removeLiquidityOneToken + +```solidity +function removeLiquidityOneToken(uint256 tokenAmount, uint8 tokenIndex, uint256 minAmount, uint256 deadline) external nonpayable returns (uint256) +``` + +Remove liquidity from the pool all in one token. Withdraw fee that decays linearly over period of 4 weeks since last deposit will apply. + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| tokenAmount | uint256 | the amount of the token you want to receive | +| tokenIndex | uint8 | the index of the token you want to receive | +| minAmount | uint256 | the minimum amount to withdraw, otherwise revert | +| deadline | uint256 | latest timestamp to accept this transaction | + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | uint256 | amount of chosen token user received | + +### renounceOwnership + +```solidity +function renounceOwnership() external nonpayable +``` + + + +*Leaves the contract without owner. It will not be possible to call `onlyOwner` functions anymore. Can only be called by the current owner. NOTE: Renouncing ownership will leave the contract without an owner, thereby removing any functionality that is only available to the owner.* + + +### setAdminFee + +```solidity +function setAdminFee(uint256 newAdminFee) external nonpayable +``` + +Update the admin fee. Admin fee takes portion of the swap fee. + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| newAdminFee | uint256 | new admin fee to be applied on future transactions | + +### setFlashLoanFees + +```solidity +function setFlashLoanFees(uint256 newFlashLoanFeeBPS, uint256 newProtocolFeeShareBPS) external nonpayable +``` + +Updates the flash loan fee parameters. This function can only be called by the owner. + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| newFlashLoanFeeBPS | uint256 | the total fee in bps to be applied on future flash loans | +| newProtocolFeeShareBPS | uint256 | the protocol fee in bps to be applied on the total flash loan fee | + +### setSwapFee + +```solidity +function setSwapFee(uint256 newSwapFee) external nonpayable +``` + +Update the swap fee to be applied on swaps + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| newSwapFee | uint256 | new swap fee to be applied on future transactions | + +### stopRampA + +```solidity +function stopRampA() external nonpayable +``` + +Stop ramping A immediately. Reverts if ramp A is already stopped. + + + + +### swap + +```solidity +function swap(uint8 tokenIndexFrom, uint8 tokenIndexTo, uint256 dx, uint256 minDy, uint256 deadline) external nonpayable returns (uint256) +``` + +Swap two tokens using this pool + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| tokenIndexFrom | uint8 | the token the user wants to swap from | +| tokenIndexTo | uint8 | the token the user wants to swap to | +| dx | uint256 | the amount of tokens the user wants to swap from | +| minDy | uint256 | the min amount the user would like to receive, or revert. | +| deadline | uint256 | latest timestamp to accept this transaction | + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | uint256 | undefined | + +### swapStorage + +```solidity +function swapStorage() external view returns (uint256 initialA, uint256 futureA, uint256 initialATime, uint256 futureATime, uint256 swapFee, uint256 adminFee, contract LPToken lpToken) +``` + + + + + + +#### Returns + +| Name | Type | Description | +|---|---|---| +| initialA | uint256 | undefined | +| futureA | uint256 | undefined | +| initialATime | uint256 | undefined | +| futureATime | uint256 | undefined | +| swapFee | uint256 | undefined | +| adminFee | uint256 | undefined | +| lpToken | contract LPToken | undefined | + +### transferOwnership + +```solidity +function transferOwnership(address newOwner) external nonpayable +``` + + + +*Transfers ownership of the contract to a new account (`newOwner`). Can only be called by the current owner.* + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| newOwner | address | undefined | + +### unpause + +```solidity +function unpause() external nonpayable +``` + +Unpause the contract. Revert if already unpaused. + + + + +### withdrawAdminFees + +```solidity +function withdrawAdminFees() external nonpayable +``` + +Withdraw all admin fees to the contract owner + + + + + + +## Events + +### AddLiquidity + +```solidity +event AddLiquidity(address indexed provider, uint256[] tokenAmounts, uint256[] fees, uint256 invariant, uint256 lpTokenSupply) +``` + + + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| provider `indexed` | address | undefined | +| tokenAmounts | uint256[] | undefined | +| fees | uint256[] | undefined | +| invariant | uint256 | undefined | +| lpTokenSupply | uint256 | undefined | + +### FlashLoan + +```solidity +event FlashLoan(address indexed receiver, uint8 tokenIndex, uint256 amount, uint256 amountFee, uint256 protocolFee) +``` + + + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| receiver `indexed` | address | undefined | +| tokenIndex | uint8 | undefined | +| amount | uint256 | undefined | +| amountFee | uint256 | undefined | +| protocolFee | uint256 | undefined | + +### NewAdminFee + +```solidity +event NewAdminFee(uint256 newAdminFee) +``` + + + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| newAdminFee | uint256 | undefined | + +### NewSwapFee + +```solidity +event NewSwapFee(uint256 newSwapFee) +``` + + + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| newSwapFee | uint256 | undefined | + +### OwnershipTransferred + +```solidity +event OwnershipTransferred(address indexed previousOwner, address indexed newOwner) +``` + + + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| previousOwner `indexed` | address | undefined | +| newOwner `indexed` | address | undefined | + +### Paused + +```solidity +event Paused(address account) +``` + + + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| account | address | undefined | + +### RampA + +```solidity +event RampA(uint256 oldA, uint256 newA, uint256 initialTime, uint256 futureTime) +``` + + + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| oldA | uint256 | undefined | +| newA | uint256 | undefined | +| initialTime | uint256 | undefined | +| futureTime | uint256 | undefined | + +### RemoveLiquidity + +```solidity +event RemoveLiquidity(address indexed provider, uint256[] tokenAmounts, uint256 lpTokenSupply) +``` + + + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| provider `indexed` | address | undefined | +| tokenAmounts | uint256[] | undefined | +| lpTokenSupply | uint256 | undefined | + +### RemoveLiquidityImbalance + +```solidity +event RemoveLiquidityImbalance(address indexed provider, uint256[] tokenAmounts, uint256[] fees, uint256 invariant, uint256 lpTokenSupply) +``` + + + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| provider `indexed` | address | undefined | +| tokenAmounts | uint256[] | undefined | +| fees | uint256[] | undefined | +| invariant | uint256 | undefined | +| lpTokenSupply | uint256 | undefined | + +### RemoveLiquidityOne + +```solidity +event RemoveLiquidityOne(address indexed provider, uint256 lpTokenAmount, uint256 lpTokenSupply, uint256 boughtId, uint256 tokensBought) +``` + + + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| provider `indexed` | address | undefined | +| lpTokenAmount | uint256 | undefined | +| lpTokenSupply | uint256 | undefined | +| boughtId | uint256 | undefined | +| tokensBought | uint256 | undefined | + +### StopRampA + +```solidity +event StopRampA(uint256 currentA, uint256 time) +``` + + + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| currentA | uint256 | undefined | +| time | uint256 | undefined | + +### TokenSwap + +```solidity +event TokenSwap(address indexed buyer, uint256 tokensSold, uint256 tokensBought, uint128 soldId, uint128 boughtId) +``` + + + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| buyer `indexed` | address | undefined | +| tokensSold | uint256 | undefined | +| tokensBought | uint256 | undefined | +| soldId | uint128 | undefined | +| boughtId | uint128 | undefined | + +### Unpaused + +```solidity +event Unpaused(address account) +``` + + + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| account | address | undefined | + + + diff --git a/docs/amm/SwapUtils.md b/docs/amm/SwapUtils.md new file mode 100644 index 000000000..f8238b186 --- /dev/null +++ b/docs/amm/SwapUtils.md @@ -0,0 +1,199 @@ +# SwapUtils + + + +> SwapUtils library + +A library to be used within Swap.sol. Contains functions responsible for custody and AMM functionalities. + +*Contracts relying on this library must initialize SwapUtils.Swap struct then use this library for SwapUtils.Swap struct. Note that this library contains both functions called by users and admins. Admin functions should be protected within contracts using this library.* + +## Methods + +### MAX_ADMIN_FEE + +```solidity +function MAX_ADMIN_FEE() external view returns (uint256) +``` + + + + + + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | uint256 | undefined | + +### MAX_SWAP_FEE + +```solidity +function MAX_SWAP_FEE() external view returns (uint256) +``` + + + + + + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | uint256 | undefined | + +### POOL_PRECISION_DECIMALS + +```solidity +function POOL_PRECISION_DECIMALS() external view returns (uint8) +``` + + + + + + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | uint8 | undefined | + + + +## Events + +### AddLiquidity + +```solidity +event AddLiquidity(address indexed provider, uint256[] tokenAmounts, uint256[] fees, uint256 invariant, uint256 lpTokenSupply) +``` + + + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| provider `indexed` | address | undefined | +| tokenAmounts | uint256[] | undefined | +| fees | uint256[] | undefined | +| invariant | uint256 | undefined | +| lpTokenSupply | uint256 | undefined | + +### NewAdminFee + +```solidity +event NewAdminFee(uint256 newAdminFee) +``` + + + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| newAdminFee | uint256 | undefined | + +### NewSwapFee + +```solidity +event NewSwapFee(uint256 newSwapFee) +``` + + + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| newSwapFee | uint256 | undefined | + +### RemoveLiquidity + +```solidity +event RemoveLiquidity(address indexed provider, uint256[] tokenAmounts, uint256 lpTokenSupply) +``` + + + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| provider `indexed` | address | undefined | +| tokenAmounts | uint256[] | undefined | +| lpTokenSupply | uint256 | undefined | + +### RemoveLiquidityImbalance + +```solidity +event RemoveLiquidityImbalance(address indexed provider, uint256[] tokenAmounts, uint256[] fees, uint256 invariant, uint256 lpTokenSupply) +``` + + + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| provider `indexed` | address | undefined | +| tokenAmounts | uint256[] | undefined | +| fees | uint256[] | undefined | +| invariant | uint256 | undefined | +| lpTokenSupply | uint256 | undefined | + +### RemoveLiquidityOne + +```solidity +event RemoveLiquidityOne(address indexed provider, uint256 lpTokenAmount, uint256 lpTokenSupply, uint256 boughtId, uint256 tokensBought) +``` + + + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| provider `indexed` | address | undefined | +| lpTokenAmount | uint256 | undefined | +| lpTokenSupply | uint256 | undefined | +| boughtId | uint256 | undefined | +| tokensBought | uint256 | undefined | + +### TokenSwap + +```solidity +event TokenSwap(address indexed buyer, uint256 tokensSold, uint256 tokensBought, uint128 soldId, uint128 boughtId) +``` + + + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| buyer `indexed` | address | undefined | +| tokensSold | uint256 | undefined | +| tokensBought | uint256 | undefined | +| soldId | uint128 | undefined | +| boughtId | uint128 | undefined | + + + diff --git a/docs/amm/helper/BaseSwapDeposit.md b/docs/amm/helper/BaseSwapDeposit.md new file mode 100644 index 000000000..fd0d66dd8 --- /dev/null +++ b/docs/amm/helper/BaseSwapDeposit.md @@ -0,0 +1,126 @@ +# BaseSwapDeposit + + + + + + + + + +## Methods + +### baseSwap + +```solidity +function baseSwap() external view returns (contract ISwap) +``` + + + + + + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | contract ISwap | undefined | + +### baseTokens + +```solidity +function baseTokens(uint256) external view returns (contract IERC20) +``` + + + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| _0 | uint256 | undefined | + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | contract IERC20 | undefined | + +### calculateSwap + +```solidity +function calculateSwap(uint8 tokenIndexFrom, uint8 tokenIndexTo, uint256 dx) external view returns (uint256) +``` + +Calculate amount of tokens you receive on swap + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| tokenIndexFrom | uint8 | the token the user wants to sell | +| tokenIndexTo | uint8 | the token the user wants to buy | +| dx | uint256 | the amount of tokens the user wants to sell. If the token charges a fee on transfers, use the amount that gets transferred after the fee. | + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | uint256 | amount of tokens the user will receive | + +### getToken + +```solidity +function getToken(uint256 index) external view returns (contract IERC20) +``` + +Returns the address of the pooled token at given index. Reverts if tokenIndex is out of range. + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| index | uint256 | the index of the token | + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | contract IERC20 | address of the token at given index | + +### swap + +```solidity +function swap(uint8 tokenIndexFrom, uint8 tokenIndexTo, uint256 dx, uint256 minDy, uint256 deadline) external nonpayable returns (uint256) +``` + +Swap two underlying tokens using the meta pool and the base pool + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| tokenIndexFrom | uint8 | the token the user wants to swap from | +| tokenIndexTo | uint8 | the token the user wants to swap to | +| dx | uint256 | the amount of tokens the user wants to swap from | +| minDy | uint256 | the min amount the user would like to receive, or revert. | +| deadline | uint256 | latest timestamp to accept this transaction | + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | uint256 | undefined | + + + + diff --git a/docs/amm/helper/FlashLoanBorrowerExample.md b/docs/amm/helper/FlashLoanBorrowerExample.md new file mode 100644 index 000000000..a35b08e9c --- /dev/null +++ b/docs/amm/helper/FlashLoanBorrowerExample.md @@ -0,0 +1,54 @@ +# FlashLoanBorrowerExample + + + + + + + + + +## Methods + +### executeOperation + +```solidity +function executeOperation(address pool, address token, uint256 amount, uint256 fee, bytes params) external nonpayable +``` + + + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| pool | address | undefined | +| token | address | undefined | +| amount | uint256 | undefined | +| fee | uint256 | undefined | +| params | bytes | undefined | + +### flashLoan + +```solidity +function flashLoan(contract ISwapFlashLoan swap, contract IERC20 token, uint256 amount, bytes params) external nonpayable +``` + + + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| swap | contract ISwapFlashLoan | undefined | +| token | contract IERC20 | undefined | +| amount | uint256 | undefined | +| params | bytes | undefined | + + + + diff --git a/docs/amm/helper/GenericERC20.md b/docs/amm/helper/GenericERC20.md new file mode 100644 index 000000000..1497bbb5b --- /dev/null +++ b/docs/amm/helper/GenericERC20.md @@ -0,0 +1,361 @@ +# GenericERC20 + + + +> Generic ERC20 token + +This contract simulates a generic ERC20 token that is mintable and burnable. + + + +## Methods + +### allowance + +```solidity +function allowance(address owner, address spender) external view returns (uint256) +``` + + + +*See {IERC20-allowance}.* + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| owner | address | undefined | +| spender | address | undefined | + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | uint256 | undefined | + +### approve + +```solidity +function approve(address spender, uint256 amount) external nonpayable returns (bool) +``` + + + +*See {IERC20-approve}. Requirements: - `spender` cannot be the zero address.* + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| spender | address | undefined | +| amount | uint256 | undefined | + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | bool | undefined | + +### balanceOf + +```solidity +function balanceOf(address account) external view returns (uint256) +``` + + + +*See {IERC20-balanceOf}.* + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| account | address | undefined | + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | uint256 | undefined | + +### decimals + +```solidity +function decimals() external view returns (uint8) +``` + + + +*Returns the number of decimals used to get its user representation. For example, if `decimals` equals `2`, a balance of `505` tokens should be displayed to a user as `5,05` (`505 / 10 ** 2`). Tokens usually opt for a value of 18, imitating the relationship between Ether and Wei. This is the value {ERC20} uses, unless {_setupDecimals} is called. NOTE: This information is only used for _display_ purposes: it in no way affects any of the arithmetic of the contract, including {IERC20-balanceOf} and {IERC20-transfer}.* + + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | uint8 | undefined | + +### decreaseAllowance + +```solidity +function decreaseAllowance(address spender, uint256 subtractedValue) external nonpayable returns (bool) +``` + + + +*Atomically decreases the allowance granted to `spender` by the caller. This is an alternative to {approve} that can be used as a mitigation for problems described in {IERC20-approve}. Emits an {Approval} event indicating the updated allowance. Requirements: - `spender` cannot be the zero address. - `spender` must have allowance for the caller of at least `subtractedValue`.* + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| spender | address | undefined | +| subtractedValue | uint256 | undefined | + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | bool | undefined | + +### increaseAllowance + +```solidity +function increaseAllowance(address spender, uint256 addedValue) external nonpayable returns (bool) +``` + + + +*Atomically increases the allowance granted to `spender` by the caller. This is an alternative to {approve} that can be used as a mitigation for problems described in {IERC20-approve}. Emits an {Approval} event indicating the updated allowance. Requirements: - `spender` cannot be the zero address.* + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| spender | address | undefined | +| addedValue | uint256 | undefined | + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | bool | undefined | + +### mint + +```solidity +function mint(address recipient, uint256 amount) external nonpayable +``` + +Mints given amount of tokens to recipient + +*only owner can call this mint function* + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| recipient | address | address of account to receive the tokens | +| amount | uint256 | amount of tokens to mint | + +### name + +```solidity +function name() external view returns (string) +``` + + + +*Returns the name of the token.* + + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | string | undefined | + +### owner + +```solidity +function owner() external view returns (address) +``` + + + +*Returns the address of the current owner.* + + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | address | undefined | + +### renounceOwnership + +```solidity +function renounceOwnership() external nonpayable +``` + + + +*Leaves the contract without owner. It will not be possible to call `onlyOwner` functions anymore. Can only be called by the current owner. NOTE: Renouncing ownership will leave the contract without an owner, thereby removing any functionality that is only available to the owner.* + + +### symbol + +```solidity +function symbol() external view returns (string) +``` + + + +*Returns the symbol of the token, usually a shorter version of the name.* + + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | string | undefined | + +### totalSupply + +```solidity +function totalSupply() external view returns (uint256) +``` + + + +*See {IERC20-totalSupply}.* + + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | uint256 | undefined | + +### transfer + +```solidity +function transfer(address recipient, uint256 amount) external nonpayable returns (bool) +``` + + + +*See {IERC20-transfer}. Requirements: - `recipient` cannot be the zero address. - the caller must have a balance of at least `amount`.* + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| recipient | address | undefined | +| amount | uint256 | undefined | + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | bool | undefined | + +### transferFrom + +```solidity +function transferFrom(address sender, address recipient, uint256 amount) external nonpayable returns (bool) +``` + + + +*See {IERC20-transferFrom}. Emits an {Approval} event indicating the updated allowance. This is not required by the EIP. See the note at the beginning of {ERC20}. Requirements: - `sender` and `recipient` cannot be the zero address. - `sender` must have a balance of at least `amount`. - the caller must have allowance for ``sender``'s tokens of at least `amount`.* + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| sender | address | undefined | +| recipient | address | undefined | +| amount | uint256 | undefined | + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | bool | undefined | + +### transferOwnership + +```solidity +function transferOwnership(address newOwner) external nonpayable +``` + + + +*Transfers ownership of the contract to a new account (`newOwner`). Can only be called by the current owner.* + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| newOwner | address | undefined | + + + +## Events + +### Approval + +```solidity +event Approval(address indexed owner, address indexed spender, uint256 value) +``` + + + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| owner `indexed` | address | undefined | +| spender `indexed` | address | undefined | +| value | uint256 | undefined | + +### OwnershipTransferred + +```solidity +event OwnershipTransferred(address indexed previousOwner, address indexed newOwner) +``` + + + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| previousOwner `indexed` | address | undefined | +| newOwner `indexed` | address | undefined | + +### Transfer + +```solidity +event Transfer(address indexed from, address indexed to, uint256 value) +``` + + + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| from `indexed` | address | undefined | +| to `indexed` | address | undefined | +| value | uint256 | undefined | + + + diff --git a/docs/amm/helper/Multicall2.md b/docs/amm/helper/Multicall2.md new file mode 100644 index 000000000..e0c6b7d51 --- /dev/null +++ b/docs/amm/helper/Multicall2.md @@ -0,0 +1,256 @@ +# Multicall2 + +*Michael Elliot <mike@makerdao.com>Joshua Levine <joshua@makerdao.com>Nick Johnson <arachnid@notdot.net>* + +> Multicall2 - Aggregate results from multiple read-only function calls + + + + + +## Methods + +### aggregate + +```solidity +function aggregate(Multicall2.Call[] calls) external nonpayable returns (uint256 blockNumber, bytes[] returnData) +``` + + + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| calls | Multicall2.Call[] | undefined | + +#### Returns + +| Name | Type | Description | +|---|---|---| +| blockNumber | uint256 | undefined | +| returnData | bytes[] | undefined | + +### blockAndAggregate + +```solidity +function blockAndAggregate(Multicall2.Call[] calls) external nonpayable returns (uint256 blockNumber, bytes32 blockHash, struct Multicall2.Result[] returnData) +``` + + + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| calls | Multicall2.Call[] | undefined | + +#### Returns + +| Name | Type | Description | +|---|---|---| +| blockNumber | uint256 | undefined | +| blockHash | bytes32 | undefined | +| returnData | Multicall2.Result[] | undefined | + +### getBlockHash + +```solidity +function getBlockHash(uint256 blockNumber) external view returns (bytes32 blockHash) +``` + + + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| blockNumber | uint256 | undefined | + +#### Returns + +| Name | Type | Description | +|---|---|---| +| blockHash | bytes32 | undefined | + +### getBlockNumber + +```solidity +function getBlockNumber() external view returns (uint256 blockNumber) +``` + + + + + + +#### Returns + +| Name | Type | Description | +|---|---|---| +| blockNumber | uint256 | undefined | + +### getCurrentBlockCoinbase + +```solidity +function getCurrentBlockCoinbase() external view returns (address coinbase) +``` + + + + + + +#### Returns + +| Name | Type | Description | +|---|---|---| +| coinbase | address | undefined | + +### getCurrentBlockDifficulty + +```solidity +function getCurrentBlockDifficulty() external view returns (uint256 difficulty) +``` + + + + + + +#### Returns + +| Name | Type | Description | +|---|---|---| +| difficulty | uint256 | undefined | + +### getCurrentBlockGasLimit + +```solidity +function getCurrentBlockGasLimit() external view returns (uint256 gaslimit) +``` + + + + + + +#### Returns + +| Name | Type | Description | +|---|---|---| +| gaslimit | uint256 | undefined | + +### getCurrentBlockTimestamp + +```solidity +function getCurrentBlockTimestamp() external view returns (uint256 timestamp) +``` + + + + + + +#### Returns + +| Name | Type | Description | +|---|---|---| +| timestamp | uint256 | undefined | + +### getEthBalance + +```solidity +function getEthBalance(address addr) external view returns (uint256 balance) +``` + + + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| addr | address | undefined | + +#### Returns + +| Name | Type | Description | +|---|---|---| +| balance | uint256 | undefined | + +### getLastBlockHash + +```solidity +function getLastBlockHash() external view returns (bytes32 blockHash) +``` + + + + + + +#### Returns + +| Name | Type | Description | +|---|---|---| +| blockHash | bytes32 | undefined | + +### tryAggregate + +```solidity +function tryAggregate(bool requireSuccess, Multicall2.Call[] calls) external nonpayable returns (struct Multicall2.Result[] returnData) +``` + + + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| requireSuccess | bool | undefined | +| calls | Multicall2.Call[] | undefined | + +#### Returns + +| Name | Type | Description | +|---|---|---| +| returnData | Multicall2.Result[] | undefined | + +### tryBlockAndAggregate + +```solidity +function tryBlockAndAggregate(bool requireSuccess, Multicall2.Call[] calls) external nonpayable returns (uint256 blockNumber, bytes32 blockHash, struct Multicall2.Result[] returnData) +``` + + + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| requireSuccess | bool | undefined | +| calls | Multicall2.Call[] | undefined | + +#### Returns + +| Name | Type | Description | +|---|---|---| +| blockNumber | uint256 | undefined | +| blockHash | bytes32 | undefined | +| returnData | Multicall2.Result[] | undefined | + + + + diff --git a/docs/amm/helper/test/TestMathUtils.md b/docs/amm/helper/test/TestMathUtils.md new file mode 100644 index 000000000..f169929ae --- /dev/null +++ b/docs/amm/helper/test/TestMathUtils.md @@ -0,0 +1,61 @@ +# TestMathUtils + + + + + + + + + +## Methods + +### difference + +```solidity +function difference(uint256 a, uint256 b) external pure returns (uint256) +``` + + + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| a | uint256 | undefined | +| b | uint256 | undefined | + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | uint256 | undefined | + +### within1 + +```solidity +function within1(uint256 a, uint256 b) external pure returns (bool) +``` + + + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| a | uint256 | undefined | +| b | uint256 | undefined | + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | bool | undefined | + + + + diff --git a/docs/amm/helper/test/TestSwapReturnValues.md b/docs/amm/helper/test/TestSwapReturnValues.md new file mode 100644 index 000000000..ba29e5f51 --- /dev/null +++ b/docs/amm/helper/test/TestSwapReturnValues.md @@ -0,0 +1,171 @@ +# TestSwapReturnValues + + + + + + + + + +## Methods + +### MAX_INT + +```solidity +function MAX_INT() external view returns (uint256) +``` + + + + + + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | uint256 | undefined | + +### lpToken + +```solidity +function lpToken() external view returns (contract IERC20) +``` + + + + + + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | contract IERC20 | undefined | + +### n + +```solidity +function n() external view returns (uint8) +``` + + + + + + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | uint8 | undefined | + +### swap + +```solidity +function swap() external view returns (contract ISwap) +``` + + + + + + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | contract ISwap | undefined | + +### test_addLiquidity + +```solidity +function test_addLiquidity(uint256[] amounts, uint256 minToMint) external nonpayable +``` + + + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| amounts | uint256[] | undefined | +| minToMint | uint256 | undefined | + +### test_removeLiquidity + +```solidity +function test_removeLiquidity(uint256 amount, uint256[] minAmounts) external nonpayable +``` + + + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| amount | uint256 | undefined | +| minAmounts | uint256[] | undefined | + +### test_removeLiquidityImbalance + +```solidity +function test_removeLiquidityImbalance(uint256[] amounts, uint256 maxBurnAmount) external nonpayable +``` + + + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| amounts | uint256[] | undefined | +| maxBurnAmount | uint256 | undefined | + +### test_removeLiquidityOneToken + +```solidity +function test_removeLiquidityOneToken(uint256 tokenAmount, uint8 tokenIndex, uint256 minAmount) external nonpayable +``` + + + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| tokenAmount | uint256 | undefined | +| tokenIndex | uint8 | undefined | +| minAmount | uint256 | undefined | + +### test_swap + +```solidity +function test_swap(uint8 tokenIndexFrom, uint8 tokenIndexTo, uint256 dx, uint256 minDy) external nonpayable +``` + + + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| tokenIndexFrom | uint8 | undefined | +| tokenIndexTo | uint8 | undefined | +| dx | uint256 | undefined | +| minDy | uint256 | undefined | + + + + diff --git a/docs/amm/interfaces/IFlashLoanReceiver.md b/docs/amm/interfaces/IFlashLoanReceiver.md new file mode 100644 index 000000000..970e718d6 --- /dev/null +++ b/docs/amm/interfaces/IFlashLoanReceiver.md @@ -0,0 +1,35 @@ +# IFlashLoanReceiver + +*Aave* + +> IFlashLoanReceiver interface + +Interface for the Nerve fee IFlashLoanReceiver. Modified from Aave's IFlashLoanReceiver interface. https://github.com/aave/aave-protocol/blob/4b4545fb583fd4f400507b10f3c3114f45b8a037/contracts/flashloan/interfaces/IFlashLoanReceiver.sol + +*implement this interface to develop a flashloan-compatible flashLoanReceiver contract** + +## Methods + +### executeOperation + +```solidity +function executeOperation(address pool, address token, uint256 amount, uint256 fee, bytes params) external nonpayable +``` + + + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| pool | address | undefined | +| token | address | undefined | +| amount | uint256 | undefined | +| fee | uint256 | undefined | +| params | bytes | undefined | + + + + diff --git a/docs/amm/interfaces/IMetaSwap.md b/docs/amm/interfaces/IMetaSwap.md new file mode 100644 index 000000000..bd6562220 --- /dev/null +++ b/docs/amm/interfaces/IMetaSwap.md @@ -0,0 +1,444 @@ +# IMetaSwap + + + + + + + + + +## Methods + +### addLiquidity + +```solidity +function addLiquidity(uint256[] amounts, uint256 minToMint, uint256 deadline) external nonpayable returns (uint256) +``` + + + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| amounts | uint256[] | undefined | +| minToMint | uint256 | undefined | +| deadline | uint256 | undefined | + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | uint256 | undefined | + +### calculateRemoveLiquidity + +```solidity +function calculateRemoveLiquidity(uint256 amount) external view returns (uint256[]) +``` + + + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| amount | uint256 | undefined | + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | uint256[] | undefined | + +### calculateRemoveLiquidityOneToken + +```solidity +function calculateRemoveLiquidityOneToken(uint256 tokenAmount, uint8 tokenIndex) external view returns (uint256 availableTokenAmount) +``` + + + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| tokenAmount | uint256 | undefined | +| tokenIndex | uint8 | undefined | + +#### Returns + +| Name | Type | Description | +|---|---|---| +| availableTokenAmount | uint256 | undefined | + +### calculateSwap + +```solidity +function calculateSwap(uint8 tokenIndexFrom, uint8 tokenIndexTo, uint256 dx) external view returns (uint256) +``` + + + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| tokenIndexFrom | uint8 | undefined | +| tokenIndexTo | uint8 | undefined | +| dx | uint256 | undefined | + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | uint256 | undefined | + +### calculateSwapUnderlying + +```solidity +function calculateSwapUnderlying(uint8 tokenIndexFrom, uint8 tokenIndexTo, uint256 dx) external view returns (uint256) +``` + + + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| tokenIndexFrom | uint8 | undefined | +| tokenIndexTo | uint8 | undefined | +| dx | uint256 | undefined | + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | uint256 | undefined | + +### calculateTokenAmount + +```solidity +function calculateTokenAmount(uint256[] amounts, bool deposit) external view returns (uint256) +``` + + + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| amounts | uint256[] | undefined | +| deposit | bool | undefined | + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | uint256 | undefined | + +### getA + +```solidity +function getA() external view returns (uint256) +``` + + + + + + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | uint256 | undefined | + +### getToken + +```solidity +function getToken(uint8 index) external view returns (contract IERC20) +``` + + + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| index | uint8 | undefined | + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | contract IERC20 | undefined | + +### getTokenBalance + +```solidity +function getTokenBalance(uint8 index) external view returns (uint256) +``` + + + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| index | uint8 | undefined | + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | uint256 | undefined | + +### getTokenIndex + +```solidity +function getTokenIndex(address tokenAddress) external view returns (uint8) +``` + + + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| tokenAddress | address | undefined | + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | uint8 | undefined | + +### getVirtualPrice + +```solidity +function getVirtualPrice() external view returns (uint256) +``` + + + + + + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | uint256 | undefined | + +### initializeMetaSwap + +```solidity +function initializeMetaSwap(contract IERC20[] pooledTokens, uint8[] decimals, string lpTokenName, string lpTokenSymbol, uint256 a, uint256 fee, uint256 adminFee, address lpTokenTargetAddress, address baseSwap) external nonpayable +``` + + + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| pooledTokens | contract IERC20[] | undefined | +| decimals | uint8[] | undefined | +| lpTokenName | string | undefined | +| lpTokenSymbol | string | undefined | +| a | uint256 | undefined | +| fee | uint256 | undefined | +| adminFee | uint256 | undefined | +| lpTokenTargetAddress | address | undefined | +| baseSwap | address | undefined | + +### isGuarded + +```solidity +function isGuarded() external view returns (bool) +``` + + + + + + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | bool | undefined | + +### removeLiquidity + +```solidity +function removeLiquidity(uint256 amount, uint256[] minAmounts, uint256 deadline) external nonpayable returns (uint256[]) +``` + + + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| amount | uint256 | undefined | +| minAmounts | uint256[] | undefined | +| deadline | uint256 | undefined | + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | uint256[] | undefined | + +### removeLiquidityImbalance + +```solidity +function removeLiquidityImbalance(uint256[] amounts, uint256 maxBurnAmount, uint256 deadline) external nonpayable returns (uint256) +``` + + + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| amounts | uint256[] | undefined | +| maxBurnAmount | uint256 | undefined | +| deadline | uint256 | undefined | + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | uint256 | undefined | + +### removeLiquidityOneToken + +```solidity +function removeLiquidityOneToken(uint256 tokenAmount, uint8 tokenIndex, uint256 minAmount, uint256 deadline) external nonpayable returns (uint256) +``` + + + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| tokenAmount | uint256 | undefined | +| tokenIndex | uint8 | undefined | +| minAmount | uint256 | undefined | +| deadline | uint256 | undefined | + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | uint256 | undefined | + +### swap + +```solidity +function swap(uint8 tokenIndexFrom, uint8 tokenIndexTo, uint256 dx, uint256 minDy, uint256 deadline) external nonpayable returns (uint256) +``` + + + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| tokenIndexFrom | uint8 | undefined | +| tokenIndexTo | uint8 | undefined | +| dx | uint256 | undefined | +| minDy | uint256 | undefined | +| deadline | uint256 | undefined | + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | uint256 | undefined | + +### swapStorage + +```solidity +function swapStorage() external view returns (uint256 initialA, uint256 futureA, uint256 initialATime, uint256 futureATime, uint256 swapFee, uint256 adminFee, address lpToken) +``` + + + + + + +#### Returns + +| Name | Type | Description | +|---|---|---| +| initialA | uint256 | undefined | +| futureA | uint256 | undefined | +| initialATime | uint256 | undefined | +| futureATime | uint256 | undefined | +| swapFee | uint256 | undefined | +| adminFee | uint256 | undefined | +| lpToken | address | undefined | + +### swapUnderlying + +```solidity +function swapUnderlying(uint8 tokenIndexFrom, uint8 tokenIndexTo, uint256 dx, uint256 minDy, uint256 deadline) external nonpayable returns (uint256) +``` + + + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| tokenIndexFrom | uint8 | undefined | +| tokenIndexTo | uint8 | undefined | +| dx | uint256 | undefined | +| minDy | uint256 | undefined | +| deadline | uint256 | undefined | + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | uint256 | undefined | + + + + diff --git a/docs/amm/interfaces/IMetaSwapDeposit.md b/docs/amm/interfaces/IMetaSwapDeposit.md new file mode 100644 index 000000000..9ebe4f6b2 --- /dev/null +++ b/docs/amm/interfaces/IMetaSwapDeposit.md @@ -0,0 +1,33 @@ +# IMetaSwapDeposit + + + + + + + + + +## Methods + +### initialize + +```solidity +function initialize(contract ISwap baseSwap_, contract IMetaSwap metaSwap_, contract IERC20 metaLPToken_) external nonpayable +``` + + + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| baseSwap_ | contract ISwap | undefined | +| metaSwap_ | contract IMetaSwap | undefined | +| metaLPToken_ | contract IERC20 | undefined | + + + + diff --git a/docs/amm/interfaces/ISwap.md b/docs/amm/interfaces/ISwap.md new file mode 100644 index 000000000..46ee3b5ae --- /dev/null +++ b/docs/amm/interfaces/ISwap.md @@ -0,0 +1,353 @@ +# ISwap + + + + + + + + + +## Methods + +### addLiquidity + +```solidity +function addLiquidity(uint256[] amounts, uint256 minToMint, uint256 deadline) external nonpayable returns (uint256) +``` + + + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| amounts | uint256[] | undefined | +| minToMint | uint256 | undefined | +| deadline | uint256 | undefined | + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | uint256 | undefined | + +### calculateRemoveLiquidity + +```solidity +function calculateRemoveLiquidity(uint256 amount) external view returns (uint256[]) +``` + + + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| amount | uint256 | undefined | + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | uint256[] | undefined | + +### calculateRemoveLiquidityOneToken + +```solidity +function calculateRemoveLiquidityOneToken(uint256 tokenAmount, uint8 tokenIndex) external view returns (uint256 availableTokenAmount) +``` + + + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| tokenAmount | uint256 | undefined | +| tokenIndex | uint8 | undefined | + +#### Returns + +| Name | Type | Description | +|---|---|---| +| availableTokenAmount | uint256 | undefined | + +### calculateSwap + +```solidity +function calculateSwap(uint8 tokenIndexFrom, uint8 tokenIndexTo, uint256 dx) external view returns (uint256) +``` + + + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| tokenIndexFrom | uint8 | undefined | +| tokenIndexTo | uint8 | undefined | +| dx | uint256 | undefined | + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | uint256 | undefined | + +### calculateTokenAmount + +```solidity +function calculateTokenAmount(uint256[] amounts, bool deposit) external view returns (uint256) +``` + + + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| amounts | uint256[] | undefined | +| deposit | bool | undefined | + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | uint256 | undefined | + +### getA + +```solidity +function getA() external view returns (uint256) +``` + + + + + + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | uint256 | undefined | + +### getToken + +```solidity +function getToken(uint8 index) external view returns (contract IERC20) +``` + + + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| index | uint8 | undefined | + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | contract IERC20 | undefined | + +### getTokenBalance + +```solidity +function getTokenBalance(uint8 index) external view returns (uint256) +``` + + + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| index | uint8 | undefined | + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | uint256 | undefined | + +### getTokenIndex + +```solidity +function getTokenIndex(address tokenAddress) external view returns (uint8) +``` + + + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| tokenAddress | address | undefined | + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | uint8 | undefined | + +### getVirtualPrice + +```solidity +function getVirtualPrice() external view returns (uint256) +``` + + + + + + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | uint256 | undefined | + +### initialize + +```solidity +function initialize(contract IERC20[] pooledTokens, uint8[] decimals, string lpTokenName, string lpTokenSymbol, uint256 a, uint256 fee, uint256 adminFee, address lpTokenTargetAddress) external nonpayable +``` + + + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| pooledTokens | contract IERC20[] | undefined | +| decimals | uint8[] | undefined | +| lpTokenName | string | undefined | +| lpTokenSymbol | string | undefined | +| a | uint256 | undefined | +| fee | uint256 | undefined | +| adminFee | uint256 | undefined | +| lpTokenTargetAddress | address | undefined | + +### removeLiquidity + +```solidity +function removeLiquidity(uint256 amount, uint256[] minAmounts, uint256 deadline) external nonpayable returns (uint256[]) +``` + + + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| amount | uint256 | undefined | +| minAmounts | uint256[] | undefined | +| deadline | uint256 | undefined | + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | uint256[] | undefined | + +### removeLiquidityImbalance + +```solidity +function removeLiquidityImbalance(uint256[] amounts, uint256 maxBurnAmount, uint256 deadline) external nonpayable returns (uint256) +``` + + + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| amounts | uint256[] | undefined | +| maxBurnAmount | uint256 | undefined | +| deadline | uint256 | undefined | + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | uint256 | undefined | + +### removeLiquidityOneToken + +```solidity +function removeLiquidityOneToken(uint256 tokenAmount, uint8 tokenIndex, uint256 minAmount, uint256 deadline) external nonpayable returns (uint256) +``` + + + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| tokenAmount | uint256 | undefined | +| tokenIndex | uint8 | undefined | +| minAmount | uint256 | undefined | +| deadline | uint256 | undefined | + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | uint256 | undefined | + +### swap + +```solidity +function swap(uint8 tokenIndexFrom, uint8 tokenIndexTo, uint256 dx, uint256 minDy, uint256 deadline) external nonpayable returns (uint256) +``` + + + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| tokenIndexFrom | uint8 | undefined | +| tokenIndexTo | uint8 | undefined | +| dx | uint256 | undefined | +| minDy | uint256 | undefined | +| deadline | uint256 | undefined | + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | uint256 | undefined | + + + + diff --git a/docs/amm/interfaces/ISwapFlashLoan.md b/docs/amm/interfaces/ISwapFlashLoan.md new file mode 100644 index 000000000..13f72049c --- /dev/null +++ b/docs/amm/interfaces/ISwapFlashLoan.md @@ -0,0 +1,372 @@ +# ISwapFlashLoan + + + + + + + + + +## Methods + +### addLiquidity + +```solidity +function addLiquidity(uint256[] amounts, uint256 minToMint, uint256 deadline) external nonpayable returns (uint256) +``` + + + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| amounts | uint256[] | undefined | +| minToMint | uint256 | undefined | +| deadline | uint256 | undefined | + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | uint256 | undefined | + +### calculateRemoveLiquidity + +```solidity +function calculateRemoveLiquidity(uint256 amount) external view returns (uint256[]) +``` + + + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| amount | uint256 | undefined | + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | uint256[] | undefined | + +### calculateRemoveLiquidityOneToken + +```solidity +function calculateRemoveLiquidityOneToken(uint256 tokenAmount, uint8 tokenIndex) external view returns (uint256 availableTokenAmount) +``` + + + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| tokenAmount | uint256 | undefined | +| tokenIndex | uint8 | undefined | + +#### Returns + +| Name | Type | Description | +|---|---|---| +| availableTokenAmount | uint256 | undefined | + +### calculateSwap + +```solidity +function calculateSwap(uint8 tokenIndexFrom, uint8 tokenIndexTo, uint256 dx) external view returns (uint256) +``` + + + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| tokenIndexFrom | uint8 | undefined | +| tokenIndexTo | uint8 | undefined | +| dx | uint256 | undefined | + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | uint256 | undefined | + +### calculateTokenAmount + +```solidity +function calculateTokenAmount(uint256[] amounts, bool deposit) external view returns (uint256) +``` + + + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| amounts | uint256[] | undefined | +| deposit | bool | undefined | + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | uint256 | undefined | + +### flashLoan + +```solidity +function flashLoan(address receiver, contract IERC20 token, uint256 amount, bytes params) external nonpayable +``` + + + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| receiver | address | undefined | +| token | contract IERC20 | undefined | +| amount | uint256 | undefined | +| params | bytes | undefined | + +### getA + +```solidity +function getA() external view returns (uint256) +``` + + + + + + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | uint256 | undefined | + +### getToken + +```solidity +function getToken(uint8 index) external view returns (contract IERC20) +``` + + + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| index | uint8 | undefined | + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | contract IERC20 | undefined | + +### getTokenBalance + +```solidity +function getTokenBalance(uint8 index) external view returns (uint256) +``` + + + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| index | uint8 | undefined | + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | uint256 | undefined | + +### getTokenIndex + +```solidity +function getTokenIndex(address tokenAddress) external view returns (uint8) +``` + + + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| tokenAddress | address | undefined | + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | uint8 | undefined | + +### getVirtualPrice + +```solidity +function getVirtualPrice() external view returns (uint256) +``` + + + + + + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | uint256 | undefined | + +### initialize + +```solidity +function initialize(contract IERC20[] pooledTokens, uint8[] decimals, string lpTokenName, string lpTokenSymbol, uint256 a, uint256 fee, uint256 adminFee, address lpTokenTargetAddress) external nonpayable +``` + + + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| pooledTokens | contract IERC20[] | undefined | +| decimals | uint8[] | undefined | +| lpTokenName | string | undefined | +| lpTokenSymbol | string | undefined | +| a | uint256 | undefined | +| fee | uint256 | undefined | +| adminFee | uint256 | undefined | +| lpTokenTargetAddress | address | undefined | + +### removeLiquidity + +```solidity +function removeLiquidity(uint256 amount, uint256[] minAmounts, uint256 deadline) external nonpayable returns (uint256[]) +``` + + + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| amount | uint256 | undefined | +| minAmounts | uint256[] | undefined | +| deadline | uint256 | undefined | + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | uint256[] | undefined | + +### removeLiquidityImbalance + +```solidity +function removeLiquidityImbalance(uint256[] amounts, uint256 maxBurnAmount, uint256 deadline) external nonpayable returns (uint256) +``` + + + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| amounts | uint256[] | undefined | +| maxBurnAmount | uint256 | undefined | +| deadline | uint256 | undefined | + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | uint256 | undefined | + +### removeLiquidityOneToken + +```solidity +function removeLiquidityOneToken(uint256 tokenAmount, uint8 tokenIndex, uint256 minAmount, uint256 deadline) external nonpayable returns (uint256) +``` + + + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| tokenAmount | uint256 | undefined | +| tokenIndex | uint8 | undefined | +| minAmount | uint256 | undefined | +| deadline | uint256 | undefined | + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | uint256 | undefined | + +### swap + +```solidity +function swap(uint8 tokenIndexFrom, uint8 tokenIndexTo, uint256 dx, uint256 minDy, uint256 deadline) external nonpayable returns (uint256) +``` + + + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| tokenIndexFrom | uint8 | undefined | +| tokenIndexTo | uint8 | undefined | +| dx | uint256 | undefined | +| minDy | uint256 | undefined | +| deadline | uint256 | undefined | + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | uint256 | undefined | + + + + diff --git a/docs/auxiliary/DummyWeth.md b/docs/auxiliary/DummyWeth.md new file mode 100644 index 000000000..edda2f2f0 --- /dev/null +++ b/docs/auxiliary/DummyWeth.md @@ -0,0 +1,144 @@ +# DummyWeth + + + + + + + + + +## Methods + +### WETH + +```solidity +function WETH() external view returns (contract IWETH9) +``` + + + + + + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | contract IWETH9 | undefined | + +### owner + +```solidity +function owner() external view returns (address) +``` + + + +*Returns the address of the current owner.* + + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | address | undefined | + +### renounceOwnership + +```solidity +function renounceOwnership() external nonpayable +``` + + + +*Leaves the contract without owner. It will not be possible to call `onlyOwner` functions anymore. Can only be called by the current owner. NOTE: Renouncing ownership will leave the contract without an owner, thereby removing any functionality that is only available to the owner.* + + +### rescue + +```solidity +function rescue(uint256 amount) external nonpayable +``` + + + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| amount | uint256 | undefined | + +### setWETHAddress + +```solidity +function setWETHAddress(address payable _weth) external nonpayable +``` + + + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| _weth | address payable | undefined | + +### transferOwnership + +```solidity +function transferOwnership(address newOwner) external nonpayable +``` + + + +*Transfers ownership of the contract to a new account (`newOwner`). Can only be called by the current owner.* + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| newOwner | address | undefined | + +### withdrawToSelf + +```solidity +function withdrawToSelf(uint256 amount) external nonpayable +``` + + + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| amount | uint256 | undefined | + + + +## Events + +### OwnershipTransferred + +```solidity +event OwnershipTransferred(address indexed previousOwner, address indexed newOwner) +``` + + + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| previousOwner `indexed` | address | undefined | +| newOwner `indexed` | address | undefined | + + + diff --git a/docs/auxiliary/DummyWethProxy.md b/docs/auxiliary/DummyWethProxy.md new file mode 100644 index 000000000..de7577ca2 --- /dev/null +++ b/docs/auxiliary/DummyWethProxy.md @@ -0,0 +1,155 @@ +# DummyWethProxy + + + + + + + + + +## Methods + +### WETH + +```solidity +function WETH() external view returns (contract IWETH9) +``` + + + + + + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | contract IWETH9 | undefined | + +### initialize + +```solidity +function initialize() external nonpayable +``` + + + + + + +### owner + +```solidity +function owner() external view returns (address) +``` + + + +*Returns the address of the current owner.* + + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | address | undefined | + +### renounceOwnership + +```solidity +function renounceOwnership() external nonpayable +``` + + + +*Leaves the contract without owner. It will not be possible to call `onlyOwner` functions anymore. Can only be called by the current owner. NOTE: Renouncing ownership will leave the contract without an owner, thereby removing any functionality that is only available to the owner.* + + +### rescue + +```solidity +function rescue(uint256 amount) external nonpayable +``` + + + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| amount | uint256 | undefined | + +### setWETHAddress + +```solidity +function setWETHAddress(address payable _weth) external nonpayable +``` + + + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| _weth | address payable | undefined | + +### transferOwnership + +```solidity +function transferOwnership(address newOwner) external nonpayable +``` + + + +*Transfers ownership of the contract to a new account (`newOwner`). Can only be called by the current owner.* + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| newOwner | address | undefined | + +### withdrawToSelf + +```solidity +function withdrawToSelf(uint256 amount) external nonpayable +``` + + + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| amount | uint256 | undefined | + + + +## Events + +### OwnershipTransferred + +```solidity +event OwnershipTransferred(address indexed previousOwner, address indexed newOwner) +``` + + + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| previousOwner `indexed` | address | undefined | +| newOwner `indexed` | address | undefined | + + + diff --git a/docs/bridge/BridgeConfigV3.md b/docs/bridge/BridgeConfigV3.md new file mode 100644 index 000000000..96f1328c7 --- /dev/null +++ b/docs/bridge/BridgeConfigV3.md @@ -0,0 +1,684 @@ +# BridgeConfigV3 + + + +> BridgeConfig contract + +This token is used for configuring different tokens on the bridge and mapping them across chains.* + + + +## Methods + +### BRIDGEMANAGER_ROLE + +```solidity +function BRIDGEMANAGER_ROLE() external view returns (bytes32) +``` + + + + + + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | bytes32 | undefined | + +### DEFAULT_ADMIN_ROLE + +```solidity +function DEFAULT_ADMIN_ROLE() external view returns (bytes32) +``` + + + + + + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | bytes32 | undefined | + +### bridgeConfigVersion + +```solidity +function bridgeConfigVersion() external view returns (uint256) +``` + + + + + + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | uint256 | undefined | + +### calculateSwapFee + +```solidity +function calculateSwapFee(string tokenAddress, uint256 chainID, uint256 amount) external view returns (uint256) +``` + +Calculates bridge swap fee based on the destination chain's token transfer. + +*This means the fee should be calculated based on the chain that the nodes emit a tx on* + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| tokenAddress | string | address of the destination token to query token config for | +| chainID | uint256 | destination chain ID to query the token config for | +| amount | uint256 | in native token decimals | + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | uint256 | Fee calculated in token decimals | + +### calculateSwapFee + +```solidity +function calculateSwapFee(address tokenAddress, uint256 chainID, uint256 amount) external view returns (uint256) +``` + +Calculates bridge swap fee based on the destination chain's token transfer. + +*This means the fee should be calculated based on the chain that the nodes emit a tx on* + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| tokenAddress | address | address of the destination token to query token config for | +| chainID | uint256 | destination chain ID to query the token config for | +| amount | uint256 | in native token decimals | + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | uint256 | Fee calculated in token decimals | + +### getAllTokenIDs + +```solidity +function getAllTokenIDs() external view returns (string[] result) +``` + +Returns a list of all existing token IDs converted to strings + + + + +#### Returns + +| Name | Type | Description | +|---|---|---| +| result | string[] | undefined | + +### getMaxGasPrice + +```solidity +function getMaxGasPrice(uint256 chainID) external view returns (uint256) +``` + +gets the max gas price for a chain + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| chainID | uint256 | undefined | + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | uint256 | undefined | + +### getPoolConfig + +```solidity +function getPoolConfig(address tokenAddress, uint256 chainID) external view returns (struct BridgeConfigV3.Pool) +``` + + + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| tokenAddress | address | undefined | +| chainID | uint256 | undefined | + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | BridgeConfigV3.Pool | undefined | + +### getRoleAdmin + +```solidity +function getRoleAdmin(bytes32 role) external view returns (bytes32) +``` + + + +*Returns the admin role that controls `role`. See {grantRole} and {revokeRole}. To change a role's admin, use {_setRoleAdmin}.* + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| role | bytes32 | undefined | + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | bytes32 | undefined | + +### getRoleMember + +```solidity +function getRoleMember(bytes32 role, uint256 index) external view returns (address) +``` + + + +*Returns one of the accounts that have `role`. `index` must be a value between 0 and {getRoleMemberCount}, non-inclusive. Role bearers are not sorted in any particular way, and their ordering may change at any point. WARNING: When using {getRoleMember} and {getRoleMemberCount}, make sure you perform all queries on the same block. See the following https://forum.openzeppelin.com/t/iterating-over-elements-on-enumerableset-in-openzeppelin-contracts/2296[forum post] for more information.* + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| role | bytes32 | undefined | +| index | uint256 | undefined | + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | address | undefined | + +### getRoleMemberCount + +```solidity +function getRoleMemberCount(bytes32 role) external view returns (uint256) +``` + + + +*Returns the number of accounts that have `role`. Can be used together with {getRoleMember} to enumerate all bearers of a role.* + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| role | bytes32 | undefined | + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | uint256 | undefined | + +### getToken + +```solidity +function getToken(string tokenID, uint256 chainID) external view returns (struct BridgeConfigV3.Token token) +``` + +Returns the full token config struct + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| tokenID | string | String input of the token ID for the token | +| chainID | uint256 | Chain ID of which token address + config to get | + +#### Returns + +| Name | Type | Description | +|---|---|---| +| token | BridgeConfigV3.Token | undefined | + +### getTokenByAddress + +```solidity +function getTokenByAddress(string tokenAddress, uint256 chainID) external view returns (struct BridgeConfigV3.Token token) +``` + +Returns token config struct, given an address and chainID + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| tokenAddress | string | Matches the token ID by using a combo of address + chain ID | +| chainID | uint256 | Chain ID of which token to get config for | + +#### Returns + +| Name | Type | Description | +|---|---|---| +| token | BridgeConfigV3.Token | undefined | + +### getTokenByEVMAddress + +```solidity +function getTokenByEVMAddress(address tokenAddress, uint256 chainID) external view returns (struct BridgeConfigV3.Token token) +``` + + + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| tokenAddress | address | undefined | +| chainID | uint256 | undefined | + +#### Returns + +| Name | Type | Description | +|---|---|---| +| token | BridgeConfigV3.Token | undefined | + +### getTokenByID + +```solidity +function getTokenByID(string tokenID, uint256 chainID) external view returns (struct BridgeConfigV3.Token token) +``` + +Returns the full token config struct + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| tokenID | string | String input of the token ID for the token | +| chainID | uint256 | Chain ID of which token address + config to get | + +#### Returns + +| Name | Type | Description | +|---|---|---| +| token | BridgeConfigV3.Token | undefined | + +### getTokenID + +```solidity +function getTokenID(address tokenAddress, uint256 chainID) external view returns (string) +``` + +Returns the token ID (string) of the cross-chain token inputted + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| tokenAddress | address | address of token to get ID for | +| chainID | uint256 | chainID of which to get token ID for | + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | string | undefined | + +### getTokenID + +```solidity +function getTokenID(string tokenAddress, uint256 chainID) external view returns (string) +``` + + + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| tokenAddress | string | undefined | +| chainID | uint256 | undefined | + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | string | undefined | + +### getUnderlyingToken + +```solidity +function getUnderlyingToken(string tokenID) external view returns (struct BridgeConfigV3.Token token) +``` + +Returns which token is the underlying token to withdraw + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| tokenID | string | string token ID | + +#### Returns + +| Name | Type | Description | +|---|---|---| +| token | BridgeConfigV3.Token | undefined | + +### grantRole + +```solidity +function grantRole(bytes32 role, address account) external nonpayable +``` + + + +*Grants `role` to `account`. If `account` had not been already granted `role`, emits a {RoleGranted} event. Requirements: - the caller must have ``role``'s admin role.* + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| role | bytes32 | undefined | +| account | address | undefined | + +### hasRole + +```solidity +function hasRole(bytes32 role, address account) external view returns (bool) +``` + + + +*Returns `true` if `account` has been granted `role`.* + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| role | bytes32 | undefined | +| account | address | undefined | + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | bool | undefined | + +### hasUnderlyingToken + +```solidity +function hasUnderlyingToken(string tokenID) external view returns (bool) +``` + +Returns true if the token has an underlying token -- meaning the token is deposited into the bridge + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| tokenID | string | String to check if it is a withdraw/underlying token | + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | bool | undefined | + +### isTokenIDExist + +```solidity +function isTokenIDExist(string tokenID) external view returns (bool) +``` + +Public function returning if token ID exists given a string + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| tokenID | string | undefined | + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | bool | undefined | + +### renounceRole + +```solidity +function renounceRole(bytes32 role, address account) external nonpayable +``` + + + +*Revokes `role` from the calling account. Roles are often managed via {grantRole} and {revokeRole}: this function's purpose is to provide a mechanism for accounts to lose their privileges if they are compromised (such as when a trusted device is misplaced). If the calling account had been granted `role`, emits a {RoleRevoked} event. Requirements: - the caller must be `account`.* + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| role | bytes32 | undefined | +| account | address | undefined | + +### revokeRole + +```solidity +function revokeRole(bytes32 role, address account) external nonpayable +``` + + + +*Revokes `role` from `account`. If `account` had been granted `role`, emits a {RoleRevoked} event. Requirements: - the caller must have ``role``'s admin role.* + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| role | bytes32 | undefined | +| account | address | undefined | + +### setMaxGasPrice + +```solidity +function setMaxGasPrice(uint256 chainID, uint256 maxPrice) external nonpayable +``` + +sets the max gas price for a chain + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| chainID | uint256 | undefined | +| maxPrice | uint256 | undefined | + +### setPoolConfig + +```solidity +function setPoolConfig(address tokenAddress, uint256 chainID, address poolAddress, bool metaswap) external nonpayable returns (struct BridgeConfigV3.Pool) +``` + + + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| tokenAddress | address | undefined | +| chainID | uint256 | undefined | +| poolAddress | address | undefined | +| metaswap | bool | undefined | + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | BridgeConfigV3.Pool | undefined | + +### setTokenConfig + +```solidity +function setTokenConfig(string tokenID, uint256 chainID, address tokenAddress, uint8 tokenDecimals, uint256 maxSwap, uint256 minSwap, uint256 swapFee, uint256 maxSwapFee, uint256 minSwapFee, bool hasUnderlying, bool isUnderlying) external nonpayable returns (bool) +``` + +Main write function of this contract - Handles creating the struct and passing it to the internal logic function + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| tokenID | string | string ID to set the token config object form | +| chainID | uint256 | chain ID to use for the token config object | +| tokenAddress | address | token address of the token on the given chain | +| tokenDecimals | uint8 | decimals of token | +| maxSwap | uint256 | maximum amount of token allowed to be transferred at once - in native token decimals | +| minSwap | uint256 | minimum amount of token needed to be transferred at once - in native token decimals | +| swapFee | uint256 | percent based swap fee -- 10e6 == 10bps | +| maxSwapFee | uint256 | max swap fee to be charged - in native token decimals | +| minSwapFee | uint256 | min swap fee to be charged - in native token decimals - especially useful for mainnet ETH | +| hasUnderlying | bool | bool which represents whether this is a global mint token or one to withdraw() | +| isUnderlying | bool | bool which represents if this token is the one to withdraw on the given chain | + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | bool | undefined | + +### setTokenConfig + +```solidity +function setTokenConfig(string tokenID, uint256 chainID, string tokenAddress, uint8 tokenDecimals, uint256 maxSwap, uint256 minSwap, uint256 swapFee, uint256 maxSwapFee, uint256 minSwapFee, bool hasUnderlying, bool isUnderlying) external nonpayable returns (bool) +``` + +Main write function of this contract - Handles creating the struct and passing it to the internal logic function + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| tokenID | string | string ID to set the token config object form | +| chainID | uint256 | chain ID to use for the token config object | +| tokenAddress | string | token address of the token on the given chain | +| tokenDecimals | uint8 | decimals of token | +| maxSwap | uint256 | maximum amount of token allowed to be transferred at once - in native token decimals | +| minSwap | uint256 | minimum amount of token needed to be transferred at once - in native token decimals | +| swapFee | uint256 | percent based swap fee -- 10e6 == 10bps | +| maxSwapFee | uint256 | max swap fee to be charged - in native token decimals | +| minSwapFee | uint256 | min swap fee to be charged - in native token decimals - especially useful for mainnet ETH | +| hasUnderlying | bool | bool which represents whether this is a global mint token or one to withdraw() | +| isUnderlying | bool | bool which represents if this token is the one to withdraw on the given chain | + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | bool | undefined | + + + +## Events + +### RoleAdminChanged + +```solidity +event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole) +``` + + + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| role `indexed` | bytes32 | undefined | +| previousAdminRole `indexed` | bytes32 | undefined | +| newAdminRole `indexed` | bytes32 | undefined | + +### RoleGranted + +```solidity +event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender) +``` + + + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| role `indexed` | bytes32 | undefined | +| account `indexed` | address | undefined | +| sender `indexed` | address | undefined | + +### RoleRevoked + +```solidity +event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender) +``` + + + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| role `indexed` | bytes32 | undefined | +| account `indexed` | address | undefined | +| sender `indexed` | address | undefined | + + + diff --git a/docs/bridge/ECDSAFactory.md b/docs/bridge/ECDSAFactory.md new file mode 100644 index 000000000..061769e51 --- /dev/null +++ b/docs/bridge/ECDSAFactory.md @@ -0,0 +1,159 @@ +# ECDSAFactory + + + + + + + + + +## Methods + +### deploy + +```solidity +function deploy(address nodeMgmtAddress, address owner, address[] members, uint256 honestThreshold) external nonpayable returns (address) +``` + +Deploys a new node + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| nodeMgmtAddress | address | address of the ECDSANodeManagement contract to initialize with | +| owner | address | Owner of the ECDSANodeManagement contract who can determine if the node group is closed or active | +| members | address[] | Array of node group members addresses | +| honestThreshold | uint256 | Number of signers to process a transaction | + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | address | Address of the newest node management contract created* | + +### getMembers + +```solidity +function getMembers() external view returns (address[]) +``` + +Returns members of the keep. + + + + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | address[] | List of the keep members' addresses. | + +### latestNodeGroup + +```solidity +function latestNodeGroup() external view returns (address keepAddress, address owner, uint256 honestThreshold) +``` + + + + + + +#### Returns + +| Name | Type | Description | +|---|---|---| +| keepAddress | address | undefined | +| owner | address | undefined | +| honestThreshold | uint256 | undefined | + +### owner + +```solidity +function owner() external view returns (address) +``` + + + +*Returns the address of the current owner.* + + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | address | undefined | + +### renounceOwnership + +```solidity +function renounceOwnership() external nonpayable +``` + + + +*Leaves the contract without owner. It will not be possible to call `onlyOwner` functions anymore. Can only be called by the current owner. NOTE: Renouncing ownership will leave the contract without an owner, thereby removing any functionality that is only available to the owner.* + + +### transferOwnership + +```solidity +function transferOwnership(address newOwner) external nonpayable +``` + + + +*Transfers ownership of the contract to a new account (`newOwner`). Can only be called by the current owner.* + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| newOwner | address | undefined | + + + +## Events + +### ECDSANodeGroupCreated + +```solidity +event ECDSANodeGroupCreated(address indexed keepAddress, address[] members, address indexed owner, uint256 honestThreshold) +``` + + + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| keepAddress `indexed` | address | undefined | +| members | address[] | undefined | +| owner `indexed` | address | undefined | +| honestThreshold | uint256 | undefined | + +### OwnershipTransferred + +```solidity +event OwnershipTransferred(address indexed previousOwner, address indexed newOwner) +``` + + + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| previousOwner `indexed` | address | undefined | +| newOwner `indexed` | address | undefined | + + + diff --git a/docs/bridge/ECDSANodeManagement.md b/docs/bridge/ECDSANodeManagement.md new file mode 100644 index 000000000..f7657bb41 --- /dev/null +++ b/docs/bridge/ECDSANodeManagement.md @@ -0,0 +1,310 @@ +# ECDSANodeManagement + + + + + + + + + +## Methods + +### closeKeep + +```solidity +function closeKeep() external nonpayable +``` + +Closes keep when owner decides that they no longer need it. Releases bonds to the keep members. + +*The function can be called only by the owner of the keep and only if the keep has not been already closed.* + + +### getMembers + +```solidity +function getMembers() external view returns (address[]) +``` + +Returns members of the keep. + + + + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | address[] | List of the keep members' addresses. | + +### getOpenedTimestamp + +```solidity +function getOpenedTimestamp() external view returns (uint256) +``` + +Gets the timestamp the keep was opened at. + + + + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | uint256 | Timestamp the keep was opened at. | + +### getOwner + +```solidity +function getOwner() external view returns (address) +``` + +Gets the owner of the keep. + + + + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | address | Address of the keep owner. | + +### getPublicKey + +```solidity +function getPublicKey() external view returns (bytes) +``` + +Returns keep's ECDSA public key. + + + + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | bytes | Keep's ECDSA public key. | + +### honestThreshold + +```solidity +function honestThreshold() external view returns (uint256) +``` + + + + + + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | uint256 | undefined | + +### initialize + +```solidity +function initialize(address _owner, address[] _members, uint256 _honestThreshold) external nonpayable +``` + +Initialization function. + +*We use clone factory to create new keep. That is why this contract doesn't have a constructor. We provide keep parameters for each instance function after cloning instances from the master contract. Initialization must happen in the same transaction in which the clone is created.* + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| _owner | address | Address of the keep owner. | +| _members | address[] | Addresses of the keep members. | +| _honestThreshold | uint256 | Minimum number of honest keep members. | + +### isActive + +```solidity +function isActive() external view returns (bool) +``` + +Returns true if the keep is active. + + + + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | bool | true if the keep is active, false otherwise. | + +### isClosed + +```solidity +function isClosed() external view returns (bool) +``` + +Returns true if the keep is closed and members no longer support this keep. + + + + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | bool | true if the keep is closed, false otherwise. | + +### isTerminated + +```solidity +function isTerminated() external view returns (bool) +``` + +Returns true if the keep has been terminated. Keep is terminated when bonds are seized and members no longer support this keep. + + + + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | bool | true if the keep has been terminated, false otherwise. | + +### members + +```solidity +function members(uint256) external view returns (address) +``` + + + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| _0 | uint256 | undefined | + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | address | undefined | + +### owner + +```solidity +function owner() external view returns (address) +``` + + + + + + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | address | undefined | + +### publicKey + +```solidity +function publicKey() external view returns (bytes) +``` + + + + + + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | bytes | undefined | + +### submitPublicKey + +```solidity +function submitPublicKey(bytes _publicKey) external nonpayable +``` + +Submits a public key to the keep. + +*Public key is published successfully if all members submit the same value. In case of conflicts with others members submissions it will emit `ConflictingPublicKeySubmitted` event. When all submitted keys match it will store the key as keep's public key and emit a `PublicKeyPublished` event.* + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| _publicKey | bytes | Signer's public key. | + + + +## Events + +### ConflictingPublicKeySubmitted + +```solidity +event ConflictingPublicKeySubmitted(address indexed submittingMember, bytes conflictingPublicKey) +``` + + + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| submittingMember `indexed` | address | undefined | +| conflictingPublicKey | bytes | undefined | + +### KeepClosed + +```solidity +event KeepClosed() +``` + + + + + + +### KeepTerminated + +```solidity +event KeepTerminated() +``` + + + + + + +### PublicKeyPublished + +```solidity +event PublicKeyPublished(bytes publicKey) +``` + + + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| publicKey | bytes | undefined | + + + diff --git a/docs/bridge/ERC20Migrator.md b/docs/bridge/ERC20Migrator.md new file mode 100644 index 000000000..6d46f3e53 --- /dev/null +++ b/docs/bridge/ERC20Migrator.md @@ -0,0 +1,65 @@ +# ERC20Migrator + + + + + + + + + +## Methods + +### legacyToken + +```solidity +function legacyToken() external view returns (contract IERC20) +``` + + + +*Returns the legacy token that is being migrated.* + + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | contract IERC20 | undefined | + +### migrate + +```solidity +function migrate(uint256 amount) external nonpayable +``` + + + +*Transfers part of an account's balance in the old token to this contract, and mints the same amount of new tokens for that account.* + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| amount | uint256 | amount of tokens to be migrated | + +### newToken + +```solidity +function newToken() external view returns (contract IERC20) +``` + + + +*Returns the new token to which we are migrating.* + + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | contract IERC20 | undefined | + + + + diff --git a/docs/bridge/HarmonySynapseBridge.md b/docs/bridge/HarmonySynapseBridge.md new file mode 100644 index 000000000..65dbd8413 --- /dev/null +++ b/docs/bridge/HarmonySynapseBridge.md @@ -0,0 +1,951 @@ +# HarmonySynapseBridge + + + + + + + + + +## Methods + +### DEFAULT_ADMIN_ROLE + +```solidity +function DEFAULT_ADMIN_ROLE() external view returns (bytes32) +``` + + + + + + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | bytes32 | undefined | + +### GOVERNANCE_ROLE + +```solidity +function GOVERNANCE_ROLE() external view returns (bytes32) +``` + + + + + + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | bytes32 | undefined | + +### NODEGROUP_ROLE + +```solidity +function NODEGROUP_ROLE() external view returns (bytes32) +``` + + + + + + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | bytes32 | undefined | + +### WETH_ADDRESS + +```solidity +function WETH_ADDRESS() external view returns (address payable) +``` + + + + + + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | address payable | undefined | + +### addKappas + +```solidity +function addKappas(bytes32[] kappas) external nonpayable +``` + + + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| kappas | bytes32[] | undefined | + +### bridgeVersion + +```solidity +function bridgeVersion() external view returns (uint256) +``` + + + + + + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | uint256 | undefined | + +### chainGasAmount + +```solidity +function chainGasAmount() external view returns (uint256) +``` + + + + + + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | uint256 | undefined | + +### deposit + +```solidity +function deposit(address to, uint256 chainId, contract IERC20 token, uint256 amount) external nonpayable +``` + +Relays to nodes to transfers an ERC20 token cross-chain + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| to | address | address on other chain to bridge assets to | +| chainId | uint256 | which chain to bridge assets onto | +| token | contract IERC20 | ERC20 compatible token to deposit into the bridge | +| amount | uint256 | Amount in native token decimals to transfer cross-chain pre-fees* | + +### depositAndSwap + +```solidity +function depositAndSwap(address to, uint256 chainId, contract IERC20 token, uint256 amount, uint8 tokenIndexFrom, uint8 tokenIndexTo, uint256 minDy, uint256 deadline) external nonpayable +``` + +Relays to nodes to both transfer an ERC20 token cross-chain, and then have the nodes execute a swap through a liquidity pool on behalf of the user. + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| to | address | address on other chain to bridge assets to | +| chainId | uint256 | which chain to bridge assets onto | +| token | contract IERC20 | ERC20 compatible token to deposit into the bridge | +| amount | uint256 | Amount in native token decimals to transfer cross-chain pre-fees | +| tokenIndexFrom | uint8 | the token the user wants to swap from | +| tokenIndexTo | uint8 | the token the user wants to swap to | +| minDy | uint256 | the min amount the user would like to receive, or revert to only minting the SynERC20 token crosschain. | +| deadline | uint256 | latest timestamp to accept this transaction* | + +### getFeeBalance + +```solidity +function getFeeBalance(address tokenAddress) external view returns (uint256) +``` + + + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| tokenAddress | address | undefined | + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | uint256 | undefined | + +### getRoleAdmin + +```solidity +function getRoleAdmin(bytes32 role) external view returns (bytes32) +``` + + + +*Returns the admin role that controls `role`. See {grantRole} and {revokeRole}. To change a role's admin, use {_setRoleAdmin}.* + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| role | bytes32 | undefined | + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | bytes32 | undefined | + +### getRoleMember + +```solidity +function getRoleMember(bytes32 role, uint256 index) external view returns (address) +``` + + + +*Returns one of the accounts that have `role`. `index` must be a value between 0 and {getRoleMemberCount}, non-inclusive. Role bearers are not sorted in any particular way, and their ordering may change at any point. WARNING: When using {getRoleMember} and {getRoleMemberCount}, make sure you perform all queries on the same block. See the following https://forum.openzeppelin.com/t/iterating-over-elements-on-enumerableset-in-openzeppelin-contracts/2296[forum post] for more information.* + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| role | bytes32 | undefined | +| index | uint256 | undefined | + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | address | undefined | + +### getRoleMemberCount + +```solidity +function getRoleMemberCount(bytes32 role) external view returns (uint256) +``` + + + +*Returns the number of accounts that have `role`. Can be used together with {getRoleMember} to enumerate all bearers of a role.* + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| role | bytes32 | undefined | + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | uint256 | undefined | + +### grantRole + +```solidity +function grantRole(bytes32 role, address account) external nonpayable +``` + + + +*Grants `role` to `account`. If `account` had not been already granted `role`, emits a {RoleGranted} event. Requirements: - the caller must have ``role``'s admin role.* + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| role | bytes32 | undefined | +| account | address | undefined | + +### hasRole + +```solidity +function hasRole(bytes32 role, address account) external view returns (bool) +``` + + + +*Returns `true` if `account` has been granted `role`.* + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| role | bytes32 | undefined | +| account | address | undefined | + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | bool | undefined | + +### initialize + +```solidity +function initialize() external nonpayable +``` + + + + + + +### kappaExists + +```solidity +function kappaExists(bytes32 kappa) external view returns (bool) +``` + + + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| kappa | bytes32 | undefined | + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | bool | undefined | + +### mint + +```solidity +function mint(address payable to, contract IERC20Mintable token, uint256 amount, uint256 fee, bytes32 kappa) external nonpayable +``` + +Nodes call this function to mint a SynERC20 (or any asset that the bridge is given minter access to). This is called by the nodes after a TokenDeposit event is emitted. + +*This means the SynapseBridge.sol contract must have minter access to the token attempting to be minted* + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| to | address payable | address on other chain to redeem underlying assets to | +| token | contract IERC20Mintable | ERC20 compatible token to deposit into the bridge | +| amount | uint256 | Amount in native token decimals to transfer cross-chain post-fees | +| fee | uint256 | Amount in native token decimals to save to the contract as fees | +| kappa | bytes32 | kappa* | + +### mintAndSwap + +```solidity +function mintAndSwap(address payable to, contract IERC20Mintable token, uint256 amount, uint256 fee, contract ISwap pool, uint8 tokenIndexFrom, uint8 tokenIndexTo, uint256 minDy, uint256 deadline, bytes32 kappa) external nonpayable +``` + +Nodes call this function to mint a SynERC20 (or any asset that the bridge is given minter access to), and then attempt to swap the SynERC20 into the desired destination asset. This is called by the nodes after a TokenDepositAndSwap event is emitted. + +*This means the BridgeDeposit.sol contract must have minter access to the token attempting to be minted* + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| to | address payable | address on other chain to redeem underlying assets to | +| token | contract IERC20Mintable | ERC20 compatible token to deposit into the bridge | +| amount | uint256 | Amount in native token decimals to transfer cross-chain post-fees | +| fee | uint256 | Amount in native token decimals to save to the contract as fees | +| pool | contract ISwap | Destination chain's pool to use to swap SynERC20 -> Asset. The nodes determine this by using PoolConfig.sol. | +| tokenIndexFrom | uint8 | Index of the SynERC20 asset in the pool | +| tokenIndexTo | uint8 | Index of the desired final asset | +| minDy | uint256 | Minumum amount (in final asset decimals) that must be swapped for, otherwise the user will receive the SynERC20. | +| deadline | uint256 | Epoch time of the deadline that the swap is allowed to be executed. | +| kappa | bytes32 | kappa* | + +### pause + +```solidity +function pause() external nonpayable +``` + + + + + + +### paused + +```solidity +function paused() external view returns (bool) +``` + + + +*Returns true if the contract is paused, and false otherwise.* + + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | bool | undefined | + +### redeem + +```solidity +function redeem(address to, uint256 chainId, contract ERC20Burnable token, uint256 amount) external nonpayable +``` + +Relays to nodes that (typically) a wrapped synAsset ERC20 token has been burned and the underlying needs to be redeeemed on the native chain + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| to | address | address on other chain to redeem underlying assets to | +| chainId | uint256 | which underlying chain to bridge assets onto | +| token | contract ERC20Burnable | ERC20 compatible token to deposit into the bridge | +| amount | uint256 | Amount in native token decimals to transfer cross-chain pre-fees* | + +### redeemAndRemove + +```solidity +function redeemAndRemove(address to, uint256 chainId, contract ERC20Burnable token, uint256 amount, uint8 swapTokenIndex, uint256 swapMinAmount, uint256 swapDeadline) external nonpayable +``` + +Relays to nodes that (typically) a wrapped synAsset ERC20 token has been burned and the underlying needs to be redeeemed on the native chain. This function indicates to the nodes that they should attempt to redeem the LP token for the underlying assets (E.g "swap" out of the LP token) + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| to | address | address on other chain to redeem underlying assets to | +| chainId | uint256 | which underlying chain to bridge assets onto | +| token | contract ERC20Burnable | ERC20 compatible token to deposit into the bridge | +| amount | uint256 | Amount in native token decimals to transfer cross-chain pre-fees | +| swapTokenIndex | uint8 | Specifies which of the underlying LP assets the nodes should attempt to redeem for | +| swapMinAmount | uint256 | Specifies the minimum amount of the underlying asset needed for the nodes to execute the redeem/swap | +| swapDeadline | uint256 | Specificies the deadline that the nodes are allowed to try to redeem/swap the LP token* | + +### redeemAndSwap + +```solidity +function redeemAndSwap(address to, uint256 chainId, contract ERC20Burnable token, uint256 amount, uint8 tokenIndexFrom, uint8 tokenIndexTo, uint256 minDy, uint256 deadline) external nonpayable +``` + +Relays to nodes that (typically) a wrapped synAsset ERC20 token has been burned and the underlying needs to be redeeemed on the native chain. This function indicates to the nodes that they should attempt to redeem the LP token for the underlying assets (E.g "swap" out of the LP token) + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| to | address | address on other chain to redeem underlying assets to | +| chainId | uint256 | which underlying chain to bridge assets onto | +| token | contract ERC20Burnable | ERC20 compatible token to deposit into the bridge | +| amount | uint256 | Amount in native token decimals to transfer cross-chain pre-fees | +| tokenIndexFrom | uint8 | the token the user wants to swap from | +| tokenIndexTo | uint8 | the token the user wants to swap to | +| minDy | uint256 | the min amount the user would like to receive, or revert to only minting the SynERC20 token crosschain. | +| deadline | uint256 | latest timestamp to accept this transaction* | + +### redeemV2 + +```solidity +function redeemV2(bytes32 to, uint256 chainId, contract ERC20Burnable token, uint256 amount) external nonpayable +``` + +Relays to nodes that (typically) a wrapped synAsset ERC20 token has been burned and the underlying needs to be redeeemed on the native chain + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| to | bytes32 | address on other chain to redeem underlying assets to | +| chainId | uint256 | which underlying chain to bridge assets onto | +| token | contract ERC20Burnable | ERC20 compatible token to deposit into the bridge | +| amount | uint256 | Amount in native token decimals to transfer cross-chain pre-fees* | + +### renounceRole + +```solidity +function renounceRole(bytes32 role, address account) external nonpayable +``` + + + +*Revokes `role` from the calling account. Roles are often managed via {grantRole} and {revokeRole}: this function's purpose is to provide a mechanism for accounts to lose their privileges if they are compromised (such as when a trusted device is misplaced). If the calling account had been granted `role`, emits a {RoleRevoked} event. Requirements: - the caller must be `account`.* + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| role | bytes32 | undefined | +| account | address | undefined | + +### revokeRole + +```solidity +function revokeRole(bytes32 role, address account) external nonpayable +``` + + + +*Revokes `role` from `account`. If `account` had been granted `role`, emits a {RoleRevoked} event. Requirements: - the caller must have ``role``'s admin role.* + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| role | bytes32 | undefined | +| account | address | undefined | + +### setChainGasAmount + +```solidity +function setChainGasAmount(uint256 amount) external nonpayable +``` + + + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| amount | uint256 | undefined | + +### setWethAddress + +```solidity +function setWethAddress(address payable _wethAddress) external nonpayable +``` + + + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| _wethAddress | address payable | undefined | + +### startBlockNumber + +```solidity +function startBlockNumber() external view returns (uint256) +``` + + + + + + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | uint256 | undefined | + +### unpause + +```solidity +function unpause() external nonpayable +``` + + + + + + +### withdraw + +```solidity +function withdraw(address to, contract IERC20 token, uint256 amount, uint256 fee, bytes32 kappa) external nonpayable +``` + +Function to be called by the node group to withdraw the underlying assets from the contract + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| to | address | address on chain to send underlying assets to | +| token | contract IERC20 | ERC20 compatible token to withdraw from the bridge | +| amount | uint256 | Amount in native token decimals to withdraw | +| fee | uint256 | Amount in native token decimals to save to the contract as fees | +| kappa | bytes32 | kappa* | + +### withdrawAndRemove + +```solidity +function withdrawAndRemove(address to, contract IERC20 token, uint256 amount, uint256 fee, contract ISwap pool, uint8 swapTokenIndex, uint256 swapMinAmount, uint256 swapDeadline, bytes32 kappa) external nonpayable +``` + +Function to be called by the node group to withdraw the underlying assets from the contract + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| to | address | address on chain to send underlying assets to | +| token | contract IERC20 | ERC20 compatible token to withdraw from the bridge | +| amount | uint256 | Amount in native token decimals to withdraw | +| fee | uint256 | Amount in native token decimals to save to the contract as fees | +| pool | contract ISwap | Destination chain's pool to use to swap SynERC20 -> Asset. The nodes determine this by using PoolConfig.sol. | +| swapTokenIndex | uint8 | Specifies which of the underlying LP assets the nodes should attempt to redeem for | +| swapMinAmount | uint256 | Specifies the minimum amount of the underlying asset needed for the nodes to execute the redeem/swap | +| swapDeadline | uint256 | Specificies the deadline that the nodes are allowed to try to redeem/swap the LP token | +| kappa | bytes32 | kappa* | + +### withdrawFees + +```solidity +function withdrawFees(contract IERC20 token, address to) external nonpayable +``` + +withdraw specified ERC20 token fees to a given address + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| token | contract IERC20 | ERC20 token in which fees acccumulated to transfer | +| to | address | Address to send the fees to | + + + +## Events + +### Paused + +```solidity +event Paused(address account) +``` + + + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| account | address | undefined | + +### RoleAdminChanged + +```solidity +event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole) +``` + + + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| role `indexed` | bytes32 | undefined | +| previousAdminRole `indexed` | bytes32 | undefined | +| newAdminRole `indexed` | bytes32 | undefined | + +### RoleGranted + +```solidity +event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender) +``` + + + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| role `indexed` | bytes32 | undefined | +| account `indexed` | address | undefined | +| sender `indexed` | address | undefined | + +### RoleRevoked + +```solidity +event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender) +``` + + + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| role `indexed` | bytes32 | undefined | +| account `indexed` | address | undefined | +| sender `indexed` | address | undefined | + +### TokenDeposit + +```solidity +event TokenDeposit(address indexed to, uint256 chainId, contract IERC20 token, uint256 amount) +``` + + + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| to `indexed` | address | undefined | +| chainId | uint256 | undefined | +| token | contract IERC20 | undefined | +| amount | uint256 | undefined | + +### TokenDepositAndSwap + +```solidity +event TokenDepositAndSwap(address indexed to, uint256 chainId, contract IERC20 token, uint256 amount, uint8 tokenIndexFrom, uint8 tokenIndexTo, uint256 minDy, uint256 deadline) +``` + + + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| to `indexed` | address | undefined | +| chainId | uint256 | undefined | +| token | contract IERC20 | undefined | +| amount | uint256 | undefined | +| tokenIndexFrom | uint8 | undefined | +| tokenIndexTo | uint8 | undefined | +| minDy | uint256 | undefined | +| deadline | uint256 | undefined | + +### TokenMint + +```solidity +event TokenMint(address indexed to, contract IERC20Mintable token, uint256 amount, uint256 fee, bytes32 indexed kappa) +``` + + + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| to `indexed` | address | undefined | +| token | contract IERC20Mintable | undefined | +| amount | uint256 | undefined | +| fee | uint256 | undefined | +| kappa `indexed` | bytes32 | undefined | + +### TokenMintAndSwap + +```solidity +event TokenMintAndSwap(address indexed to, contract IERC20Mintable token, uint256 amount, uint256 fee, uint8 tokenIndexFrom, uint8 tokenIndexTo, uint256 minDy, uint256 deadline, bool swapSuccess, bytes32 indexed kappa) +``` + + + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| to `indexed` | address | undefined | +| token | contract IERC20Mintable | undefined | +| amount | uint256 | undefined | +| fee | uint256 | undefined | +| tokenIndexFrom | uint8 | undefined | +| tokenIndexTo | uint8 | undefined | +| minDy | uint256 | undefined | +| deadline | uint256 | undefined | +| swapSuccess | bool | undefined | +| kappa `indexed` | bytes32 | undefined | + +### TokenRedeem + +```solidity +event TokenRedeem(address indexed to, uint256 chainId, contract IERC20 token, uint256 amount) +``` + + + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| to `indexed` | address | undefined | +| chainId | uint256 | undefined | +| token | contract IERC20 | undefined | +| amount | uint256 | undefined | + +### TokenRedeemAndRemove + +```solidity +event TokenRedeemAndRemove(address indexed to, uint256 chainId, contract IERC20 token, uint256 amount, uint8 swapTokenIndex, uint256 swapMinAmount, uint256 swapDeadline) +``` + + + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| to `indexed` | address | undefined | +| chainId | uint256 | undefined | +| token | contract IERC20 | undefined | +| amount | uint256 | undefined | +| swapTokenIndex | uint8 | undefined | +| swapMinAmount | uint256 | undefined | +| swapDeadline | uint256 | undefined | + +### TokenRedeemAndSwap + +```solidity +event TokenRedeemAndSwap(address indexed to, uint256 chainId, contract IERC20 token, uint256 amount, uint8 tokenIndexFrom, uint8 tokenIndexTo, uint256 minDy, uint256 deadline) +``` + + + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| to `indexed` | address | undefined | +| chainId | uint256 | undefined | +| token | contract IERC20 | undefined | +| amount | uint256 | undefined | +| tokenIndexFrom | uint8 | undefined | +| tokenIndexTo | uint8 | undefined | +| minDy | uint256 | undefined | +| deadline | uint256 | undefined | + +### TokenRedeemV2 + +```solidity +event TokenRedeemV2(bytes32 indexed to, uint256 chainId, contract IERC20 token, uint256 amount) +``` + + + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| to `indexed` | bytes32 | undefined | +| chainId | uint256 | undefined | +| token | contract IERC20 | undefined | +| amount | uint256 | undefined | + +### TokenWithdraw + +```solidity +event TokenWithdraw(address indexed to, contract IERC20 token, uint256 amount, uint256 fee, bytes32 indexed kappa) +``` + + + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| to `indexed` | address | undefined | +| token | contract IERC20 | undefined | +| amount | uint256 | undefined | +| fee | uint256 | undefined | +| kappa `indexed` | bytes32 | undefined | + +### TokenWithdrawAndRemove + +```solidity +event TokenWithdrawAndRemove(address indexed to, contract IERC20 token, uint256 amount, uint256 fee, uint8 swapTokenIndex, uint256 swapMinAmount, uint256 swapDeadline, bool swapSuccess, bytes32 indexed kappa) +``` + + + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| to `indexed` | address | undefined | +| token | contract IERC20 | undefined | +| amount | uint256 | undefined | +| fee | uint256 | undefined | +| swapTokenIndex | uint8 | undefined | +| swapMinAmount | uint256 | undefined | +| swapDeadline | uint256 | undefined | +| swapSuccess | bool | undefined | +| kappa `indexed` | bytes32 | undefined | + +### Unpaused + +```solidity +event Unpaused(address account) +``` + + + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| account | address | undefined | + + + diff --git a/docs/bridge/IERC20Mintable.md b/docs/bridge/IERC20Mintable.md new file mode 100644 index 000000000..40e9fa272 --- /dev/null +++ b/docs/bridge/IERC20Mintable.md @@ -0,0 +1,203 @@ +# IERC20Mintable + + + + + + + + + +## Methods + +### allowance + +```solidity +function allowance(address owner, address spender) external view returns (uint256) +``` + + + +*Returns the remaining number of tokens that `spender` will be allowed to spend on behalf of `owner` through {transferFrom}. This is zero by default. This value changes when {approve} or {transferFrom} are called.* + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| owner | address | undefined | +| spender | address | undefined | + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | uint256 | undefined | + +### approve + +```solidity +function approve(address spender, uint256 amount) external nonpayable returns (bool) +``` + + + +*Sets `amount` as the allowance of `spender` over the caller's tokens. Returns a boolean value indicating whether the operation succeeded. IMPORTANT: Beware that changing an allowance with this method brings the risk that someone may use both the old and the new allowance by unfortunate transaction ordering. One possible solution to mitigate this race condition is to first reduce the spender's allowance to 0 and set the desired value afterwards: https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729 Emits an {Approval} event.* + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| spender | address | undefined | +| amount | uint256 | undefined | + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | bool | undefined | + +### balanceOf + +```solidity +function balanceOf(address account) external view returns (uint256) +``` + + + +*Returns the amount of tokens owned by `account`.* + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| account | address | undefined | + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | uint256 | undefined | + +### mint + +```solidity +function mint(address to, uint256 amount) external nonpayable +``` + + + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| to | address | undefined | +| amount | uint256 | undefined | + +### totalSupply + +```solidity +function totalSupply() external view returns (uint256) +``` + + + +*Returns the amount of tokens in existence.* + + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | uint256 | undefined | + +### transfer + +```solidity +function transfer(address recipient, uint256 amount) external nonpayable returns (bool) +``` + + + +*Moves `amount` tokens from the caller's account to `recipient`. Returns a boolean value indicating whether the operation succeeded. Emits a {Transfer} event.* + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| recipient | address | undefined | +| amount | uint256 | undefined | + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | bool | undefined | + +### transferFrom + +```solidity +function transferFrom(address sender, address recipient, uint256 amount) external nonpayable returns (bool) +``` + + + +*Moves `amount` tokens from `sender` to `recipient` using the allowance mechanism. `amount` is then deducted from the caller's allowance. Returns a boolean value indicating whether the operation succeeded. Emits a {Transfer} event.* + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| sender | address | undefined | +| recipient | address | undefined | +| amount | uint256 | undefined | + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | bool | undefined | + + + +## Events + +### Approval + +```solidity +event Approval(address indexed owner, address indexed spender, uint256 value) +``` + + + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| owner `indexed` | address | undefined | +| spender `indexed` | address | undefined | +| value | uint256 | undefined | + +### Transfer + +```solidity +event Transfer(address indexed from, address indexed to, uint256 value) +``` + + + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| from `indexed` | address | undefined | +| to `indexed` | address | undefined | +| value | uint256 | undefined | + + + diff --git a/docs/bridge/IFrax.md b/docs/bridge/IFrax.md new file mode 100644 index 000000000..8ff094150 --- /dev/null +++ b/docs/bridge/IFrax.md @@ -0,0 +1,38 @@ +# IFrax + + + + + + + + + +## Methods + +### exchangeOldForCanonical + +```solidity +function exchangeOldForCanonical(address bridge_token_address, uint256 token_amount) external nonpayable returns (uint256) +``` + + + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| bridge_token_address | address | undefined | +| token_amount | uint256 | undefined | + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | uint256 | undefined | + + + + diff --git a/docs/bridge/MRSynapseBridge.md b/docs/bridge/MRSynapseBridge.md new file mode 100644 index 000000000..5ac560ea7 --- /dev/null +++ b/docs/bridge/MRSynapseBridge.md @@ -0,0 +1,951 @@ +# MRSynapseBridge + + + + + + + + + +## Methods + +### DEFAULT_ADMIN_ROLE + +```solidity +function DEFAULT_ADMIN_ROLE() external view returns (bytes32) +``` + + + + + + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | bytes32 | undefined | + +### GOVERNANCE_ROLE + +```solidity +function GOVERNANCE_ROLE() external view returns (bytes32) +``` + + + + + + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | bytes32 | undefined | + +### NODEGROUP_ROLE + +```solidity +function NODEGROUP_ROLE() external view returns (bytes32) +``` + + + + + + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | bytes32 | undefined | + +### WETH_ADDRESS + +```solidity +function WETH_ADDRESS() external view returns (address payable) +``` + + + + + + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | address payable | undefined | + +### addKappas + +```solidity +function addKappas(bytes32[] kappas) external nonpayable +``` + + + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| kappas | bytes32[] | undefined | + +### bridgeVersion + +```solidity +function bridgeVersion() external view returns (uint256) +``` + + + + + + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | uint256 | undefined | + +### chainGasAmount + +```solidity +function chainGasAmount() external view returns (uint256) +``` + + + + + + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | uint256 | undefined | + +### deposit + +```solidity +function deposit(address to, uint256 chainId, contract IERC20 token, uint256 amount) external nonpayable +``` + +Relays to nodes to transfers an ERC20 token cross-chain + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| to | address | address on other chain to bridge assets to | +| chainId | uint256 | which chain to bridge assets onto | +| token | contract IERC20 | ERC20 compatible token to deposit into the bridge | +| amount | uint256 | Amount in native token decimals to transfer cross-chain pre-fees* | + +### depositAndSwap + +```solidity +function depositAndSwap(address to, uint256 chainId, contract IERC20 token, uint256 amount, uint8 tokenIndexFrom, uint8 tokenIndexTo, uint256 minDy, uint256 deadline) external nonpayable +``` + +Relays to nodes to both transfer an ERC20 token cross-chain, and then have the nodes execute a swap through a liquidity pool on behalf of the user. + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| to | address | address on other chain to bridge assets to | +| chainId | uint256 | which chain to bridge assets onto | +| token | contract IERC20 | ERC20 compatible token to deposit into the bridge | +| amount | uint256 | Amount in native token decimals to transfer cross-chain pre-fees | +| tokenIndexFrom | uint8 | the token the user wants to swap from | +| tokenIndexTo | uint8 | the token the user wants to swap to | +| minDy | uint256 | the min amount the user would like to receive, or revert to only minting the SynERC20 token crosschain. | +| deadline | uint256 | latest timestamp to accept this transaction* | + +### getFeeBalance + +```solidity +function getFeeBalance(address tokenAddress) external view returns (uint256) +``` + + + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| tokenAddress | address | undefined | + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | uint256 | undefined | + +### getRoleAdmin + +```solidity +function getRoleAdmin(bytes32 role) external view returns (bytes32) +``` + + + +*Returns the admin role that controls `role`. See {grantRole} and {revokeRole}. To change a role's admin, use {_setRoleAdmin}.* + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| role | bytes32 | undefined | + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | bytes32 | undefined | + +### getRoleMember + +```solidity +function getRoleMember(bytes32 role, uint256 index) external view returns (address) +``` + + + +*Returns one of the accounts that have `role`. `index` must be a value between 0 and {getRoleMemberCount}, non-inclusive. Role bearers are not sorted in any particular way, and their ordering may change at any point. WARNING: When using {getRoleMember} and {getRoleMemberCount}, make sure you perform all queries on the same block. See the following https://forum.openzeppelin.com/t/iterating-over-elements-on-enumerableset-in-openzeppelin-contracts/2296[forum post] for more information.* + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| role | bytes32 | undefined | +| index | uint256 | undefined | + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | address | undefined | + +### getRoleMemberCount + +```solidity +function getRoleMemberCount(bytes32 role) external view returns (uint256) +``` + + + +*Returns the number of accounts that have `role`. Can be used together with {getRoleMember} to enumerate all bearers of a role.* + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| role | bytes32 | undefined | + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | uint256 | undefined | + +### grantRole + +```solidity +function grantRole(bytes32 role, address account) external nonpayable +``` + + + +*Grants `role` to `account`. If `account` had not been already granted `role`, emits a {RoleGranted} event. Requirements: - the caller must have ``role``'s admin role.* + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| role | bytes32 | undefined | +| account | address | undefined | + +### hasRole + +```solidity +function hasRole(bytes32 role, address account) external view returns (bool) +``` + + + +*Returns `true` if `account` has been granted `role`.* + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| role | bytes32 | undefined | +| account | address | undefined | + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | bool | undefined | + +### initialize + +```solidity +function initialize() external nonpayable +``` + + + + + + +### kappaExists + +```solidity +function kappaExists(bytes32 kappa) external view returns (bool) +``` + + + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| kappa | bytes32 | undefined | + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | bool | undefined | + +### mint + +```solidity +function mint(address payable to, contract IERC20Mintable token, uint256 amount, uint256 fee, bytes32 kappa) external nonpayable +``` + +Nodes call this function to mint a SynERC20 (or any asset that the bridge is given minter access to). This is called by the nodes after a TokenDeposit event is emitted. + +*This means the SynapseBridge.sol contract must have minter access to the token attempting to be minted* + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| to | address payable | address on other chain to redeem underlying assets to | +| token | contract IERC20Mintable | ERC20 compatible token to deposit into the bridge | +| amount | uint256 | Amount in native token decimals to transfer cross-chain post-fees | +| fee | uint256 | Amount in native token decimals to save to the contract as fees | +| kappa | bytes32 | kappa* | + +### mintAndSwap + +```solidity +function mintAndSwap(address payable to, contract IERC20Mintable token, uint256 amount, uint256 fee, contract ISwap pool, uint8 tokenIndexFrom, uint8 tokenIndexTo, uint256 minDy, uint256 deadline, bytes32 kappa) external nonpayable +``` + +Nodes call this function to mint a SynERC20 (or any asset that the bridge is given minter access to), and then attempt to swap the SynERC20 into the desired destination asset. This is called by the nodes after a TokenDepositAndSwap event is emitted. + +*This means the BridgeDeposit.sol contract must have minter access to the token attempting to be minted* + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| to | address payable | address on other chain to redeem underlying assets to | +| token | contract IERC20Mintable | ERC20 compatible token to deposit into the bridge | +| amount | uint256 | Amount in native token decimals to transfer cross-chain post-fees | +| fee | uint256 | Amount in native token decimals to save to the contract as fees | +| pool | contract ISwap | Destination chain's pool to use to swap SynERC20 -> Asset. The nodes determine this by using PoolConfig.sol. | +| tokenIndexFrom | uint8 | Index of the SynERC20 asset in the pool | +| tokenIndexTo | uint8 | Index of the desired final asset | +| minDy | uint256 | Minumum amount (in final asset decimals) that must be swapped for, otherwise the user will receive the SynERC20. | +| deadline | uint256 | Epoch time of the deadline that the swap is allowed to be executed. | +| kappa | bytes32 | kappa* | + +### pause + +```solidity +function pause() external nonpayable +``` + + + + + + +### paused + +```solidity +function paused() external view returns (bool) +``` + + + +*Returns true if the contract is paused, and false otherwise.* + + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | bool | undefined | + +### redeem + +```solidity +function redeem(address to, uint256 chainId, contract ERC20Burnable token, uint256 amount) external nonpayable +``` + +Relays to nodes that (typically) a wrapped synAsset ERC20 token has been burned and the underlying needs to be redeeemed on the native chain + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| to | address | address on other chain to redeem underlying assets to | +| chainId | uint256 | which underlying chain to bridge assets onto | +| token | contract ERC20Burnable | ERC20 compatible token to deposit into the bridge | +| amount | uint256 | Amount in native token decimals to transfer cross-chain pre-fees* | + +### redeemAndRemove + +```solidity +function redeemAndRemove(address to, uint256 chainId, contract ERC20Burnable token, uint256 amount, uint8 swapTokenIndex, uint256 swapMinAmount, uint256 swapDeadline) external nonpayable +``` + +Relays to nodes that (typically) a wrapped synAsset ERC20 token has been burned and the underlying needs to be redeeemed on the native chain. This function indicates to the nodes that they should attempt to redeem the LP token for the underlying assets (E.g "swap" out of the LP token) + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| to | address | address on other chain to redeem underlying assets to | +| chainId | uint256 | which underlying chain to bridge assets onto | +| token | contract ERC20Burnable | ERC20 compatible token to deposit into the bridge | +| amount | uint256 | Amount in native token decimals to transfer cross-chain pre-fees | +| swapTokenIndex | uint8 | Specifies which of the underlying LP assets the nodes should attempt to redeem for | +| swapMinAmount | uint256 | Specifies the minimum amount of the underlying asset needed for the nodes to execute the redeem/swap | +| swapDeadline | uint256 | Specificies the deadline that the nodes are allowed to try to redeem/swap the LP token* | + +### redeemAndSwap + +```solidity +function redeemAndSwap(address to, uint256 chainId, contract ERC20Burnable token, uint256 amount, uint8 tokenIndexFrom, uint8 tokenIndexTo, uint256 minDy, uint256 deadline) external nonpayable +``` + +Relays to nodes that (typically) a wrapped synAsset ERC20 token has been burned and the underlying needs to be redeeemed on the native chain. This function indicates to the nodes that they should attempt to redeem the LP token for the underlying assets (E.g "swap" out of the LP token) + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| to | address | address on other chain to redeem underlying assets to | +| chainId | uint256 | which underlying chain to bridge assets onto | +| token | contract ERC20Burnable | ERC20 compatible token to deposit into the bridge | +| amount | uint256 | Amount in native token decimals to transfer cross-chain pre-fees | +| tokenIndexFrom | uint8 | the token the user wants to swap from | +| tokenIndexTo | uint8 | the token the user wants to swap to | +| minDy | uint256 | the min amount the user would like to receive, or revert to only minting the SynERC20 token crosschain. | +| deadline | uint256 | latest timestamp to accept this transaction* | + +### redeemV2 + +```solidity +function redeemV2(bytes32 to, uint256 chainId, contract ERC20Burnable token, uint256 amount) external nonpayable +``` + +Relays to nodes that (typically) a wrapped synAsset ERC20 token has been burned and the underlying needs to be redeeemed on the native chain + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| to | bytes32 | address on other chain to redeem underlying assets to | +| chainId | uint256 | which underlying chain to bridge assets onto | +| token | contract ERC20Burnable | ERC20 compatible token to deposit into the bridge | +| amount | uint256 | Amount in native token decimals to transfer cross-chain pre-fees* | + +### renounceRole + +```solidity +function renounceRole(bytes32 role, address account) external nonpayable +``` + + + +*Revokes `role` from the calling account. Roles are often managed via {grantRole} and {revokeRole}: this function's purpose is to provide a mechanism for accounts to lose their privileges if they are compromised (such as when a trusted device is misplaced). If the calling account had been granted `role`, emits a {RoleRevoked} event. Requirements: - the caller must be `account`.* + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| role | bytes32 | undefined | +| account | address | undefined | + +### revokeRole + +```solidity +function revokeRole(bytes32 role, address account) external nonpayable +``` + + + +*Revokes `role` from `account`. If `account` had been granted `role`, emits a {RoleRevoked} event. Requirements: - the caller must have ``role``'s admin role.* + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| role | bytes32 | undefined | +| account | address | undefined | + +### setChainGasAmount + +```solidity +function setChainGasAmount(uint256 amount) external nonpayable +``` + + + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| amount | uint256 | undefined | + +### setWethAddress + +```solidity +function setWethAddress(address payable _wethAddress) external nonpayable +``` + + + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| _wethAddress | address payable | undefined | + +### startBlockNumber + +```solidity +function startBlockNumber() external view returns (uint256) +``` + + + + + + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | uint256 | undefined | + +### unpause + +```solidity +function unpause() external nonpayable +``` + + + + + + +### withdraw + +```solidity +function withdraw(address to, contract IERC20 token, uint256 amount, uint256 fee, bytes32 kappa) external nonpayable +``` + +Function to be called by the node group to withdraw the underlying assets from the contract + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| to | address | address on chain to send underlying assets to | +| token | contract IERC20 | ERC20 compatible token to withdraw from the bridge | +| amount | uint256 | Amount in native token decimals to withdraw | +| fee | uint256 | Amount in native token decimals to save to the contract as fees | +| kappa | bytes32 | kappa* | + +### withdrawAndRemove + +```solidity +function withdrawAndRemove(address to, contract IERC20 token, uint256 amount, uint256 fee, contract ISwap pool, uint8 swapTokenIndex, uint256 swapMinAmount, uint256 swapDeadline, bytes32 kappa) external nonpayable +``` + +Function to be called by the node group to withdraw the underlying assets from the contract + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| to | address | address on chain to send underlying assets to | +| token | contract IERC20 | ERC20 compatible token to withdraw from the bridge | +| amount | uint256 | Amount in native token decimals to withdraw | +| fee | uint256 | Amount in native token decimals to save to the contract as fees | +| pool | contract ISwap | Destination chain's pool to use to swap SynERC20 -> Asset. The nodes determine this by using PoolConfig.sol. | +| swapTokenIndex | uint8 | Specifies which of the underlying LP assets the nodes should attempt to redeem for | +| swapMinAmount | uint256 | Specifies the minimum amount of the underlying asset needed for the nodes to execute the redeem/swap | +| swapDeadline | uint256 | Specificies the deadline that the nodes are allowed to try to redeem/swap the LP token | +| kappa | bytes32 | kappa* | + +### withdrawFees + +```solidity +function withdrawFees(contract IERC20 token, address to) external nonpayable +``` + +withdraw specified ERC20 token fees to a given address + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| token | contract IERC20 | ERC20 token in which fees acccumulated to transfer | +| to | address | Address to send the fees to | + + + +## Events + +### Paused + +```solidity +event Paused(address account) +``` + + + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| account | address | undefined | + +### RoleAdminChanged + +```solidity +event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole) +``` + + + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| role `indexed` | bytes32 | undefined | +| previousAdminRole `indexed` | bytes32 | undefined | +| newAdminRole `indexed` | bytes32 | undefined | + +### RoleGranted + +```solidity +event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender) +``` + + + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| role `indexed` | bytes32 | undefined | +| account `indexed` | address | undefined | +| sender `indexed` | address | undefined | + +### RoleRevoked + +```solidity +event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender) +``` + + + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| role `indexed` | bytes32 | undefined | +| account `indexed` | address | undefined | +| sender `indexed` | address | undefined | + +### TokenDeposit + +```solidity +event TokenDeposit(address indexed to, uint256 chainId, contract IERC20 token, uint256 amount) +``` + + + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| to `indexed` | address | undefined | +| chainId | uint256 | undefined | +| token | contract IERC20 | undefined | +| amount | uint256 | undefined | + +### TokenDepositAndSwap + +```solidity +event TokenDepositAndSwap(address indexed to, uint256 chainId, contract IERC20 token, uint256 amount, uint8 tokenIndexFrom, uint8 tokenIndexTo, uint256 minDy, uint256 deadline) +``` + + + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| to `indexed` | address | undefined | +| chainId | uint256 | undefined | +| token | contract IERC20 | undefined | +| amount | uint256 | undefined | +| tokenIndexFrom | uint8 | undefined | +| tokenIndexTo | uint8 | undefined | +| minDy | uint256 | undefined | +| deadline | uint256 | undefined | + +### TokenMint + +```solidity +event TokenMint(address indexed to, contract IERC20Mintable token, uint256 amount, uint256 fee, bytes32 indexed kappa) +``` + + + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| to `indexed` | address | undefined | +| token | contract IERC20Mintable | undefined | +| amount | uint256 | undefined | +| fee | uint256 | undefined | +| kappa `indexed` | bytes32 | undefined | + +### TokenMintAndSwap + +```solidity +event TokenMintAndSwap(address indexed to, contract IERC20Mintable token, uint256 amount, uint256 fee, uint8 tokenIndexFrom, uint8 tokenIndexTo, uint256 minDy, uint256 deadline, bool swapSuccess, bytes32 indexed kappa) +``` + + + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| to `indexed` | address | undefined | +| token | contract IERC20Mintable | undefined | +| amount | uint256 | undefined | +| fee | uint256 | undefined | +| tokenIndexFrom | uint8 | undefined | +| tokenIndexTo | uint8 | undefined | +| minDy | uint256 | undefined | +| deadline | uint256 | undefined | +| swapSuccess | bool | undefined | +| kappa `indexed` | bytes32 | undefined | + +### TokenRedeem + +```solidity +event TokenRedeem(address indexed to, uint256 chainId, contract IERC20 token, uint256 amount) +``` + + + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| to `indexed` | address | undefined | +| chainId | uint256 | undefined | +| token | contract IERC20 | undefined | +| amount | uint256 | undefined | + +### TokenRedeemAndRemove + +```solidity +event TokenRedeemAndRemove(address indexed to, uint256 chainId, contract IERC20 token, uint256 amount, uint8 swapTokenIndex, uint256 swapMinAmount, uint256 swapDeadline) +``` + + + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| to `indexed` | address | undefined | +| chainId | uint256 | undefined | +| token | contract IERC20 | undefined | +| amount | uint256 | undefined | +| swapTokenIndex | uint8 | undefined | +| swapMinAmount | uint256 | undefined | +| swapDeadline | uint256 | undefined | + +### TokenRedeemAndSwap + +```solidity +event TokenRedeemAndSwap(address indexed to, uint256 chainId, contract IERC20 token, uint256 amount, uint8 tokenIndexFrom, uint8 tokenIndexTo, uint256 minDy, uint256 deadline) +``` + + + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| to `indexed` | address | undefined | +| chainId | uint256 | undefined | +| token | contract IERC20 | undefined | +| amount | uint256 | undefined | +| tokenIndexFrom | uint8 | undefined | +| tokenIndexTo | uint8 | undefined | +| minDy | uint256 | undefined | +| deadline | uint256 | undefined | + +### TokenRedeemV2 + +```solidity +event TokenRedeemV2(bytes32 indexed to, uint256 chainId, contract IERC20 token, uint256 amount) +``` + + + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| to `indexed` | bytes32 | undefined | +| chainId | uint256 | undefined | +| token | contract IERC20 | undefined | +| amount | uint256 | undefined | + +### TokenWithdraw + +```solidity +event TokenWithdraw(address indexed to, contract IERC20 token, uint256 amount, uint256 fee, bytes32 indexed kappa) +``` + + + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| to `indexed` | address | undefined | +| token | contract IERC20 | undefined | +| amount | uint256 | undefined | +| fee | uint256 | undefined | +| kappa `indexed` | bytes32 | undefined | + +### TokenWithdrawAndRemove + +```solidity +event TokenWithdrawAndRemove(address indexed to, contract IERC20 token, uint256 amount, uint256 fee, uint8 swapTokenIndex, uint256 swapMinAmount, uint256 swapDeadline, bool swapSuccess, bytes32 indexed kappa) +``` + + + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| to `indexed` | address | undefined | +| token | contract IERC20 | undefined | +| amount | uint256 | undefined | +| fee | uint256 | undefined | +| swapTokenIndex | uint8 | undefined | +| swapMinAmount | uint256 | undefined | +| swapDeadline | uint256 | undefined | +| swapSuccess | bool | undefined | +| kappa `indexed` | bytes32 | undefined | + +### Unpaused + +```solidity +event Unpaused(address account) +``` + + + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| account | address | undefined | + + + diff --git a/docs/bridge/MiniChefV2.md b/docs/bridge/MiniChefV2.md new file mode 100644 index 000000000..1d3f54156 --- /dev/null +++ b/docs/bridge/MiniChefV2.md @@ -0,0 +1,655 @@ +# MiniChefV2 + + + + + +The (older) MasterChef contract gives out a constant number of SYNAPSE tokens per block. It is the only address with minting rights for SYNAPSE. The idea for this MasterChef V2 (MCV2) contract is therefore to be the owner of a dummy token that is deposited into the MasterChef V1 (MCV1) contract. The allocation point for this pool on MCV1 is the total allocation point for all pools that receive double incentives. + + + +## Methods + +### SYNAPSE + +```solidity +function SYNAPSE() external view returns (contract IERC20) +``` + +Address of SYNAPSE contract. + + + + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | contract IERC20 | undefined | + +### add + +```solidity +function add(uint256 allocPoint, contract IERC20 _lpToken, contract IRewarder _rewarder) external nonpayable +``` + +Add a new LP to the pool. Can only be called by the owner. DO NOT add the same LP token more than once. Rewards will be messed up if you do. + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| allocPoint | uint256 | AP of the new pool. | +| _lpToken | contract IERC20 | Address of the LP ERC-20 token. | +| _rewarder | contract IRewarder | Address of the rewarder delegate. | + +### batch + +```solidity +function batch(bytes[] calls, bool revertOnFail) external payable returns (bool[] successes, bytes[] results) +``` + + + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| calls | bytes[] | undefined | +| revertOnFail | bool | undefined | + +#### Returns + +| Name | Type | Description | +|---|---|---| +| successes | bool[] | undefined | +| results | bytes[] | undefined | + +### claimOwnership + +```solidity +function claimOwnership() external nonpayable +``` + + + + + + +### deposit + +```solidity +function deposit(uint256 pid, uint256 amount, address to) external nonpayable +``` + +Deposit LP tokens to MCV2 for SYNAPSE allocation. + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| pid | uint256 | The index of the pool. See `poolInfo`. | +| amount | uint256 | LP token amount to deposit. | +| to | address | The receiver of `amount` deposit benefit. | + +### emergencyWithdraw + +```solidity +function emergencyWithdraw(uint256 pid, address to) external nonpayable +``` + +Withdraw without caring about rewards. EMERGENCY ONLY. + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| pid | uint256 | The index of the pool. See `poolInfo`. | +| to | address | Receiver of the LP tokens. | + +### harvest + +```solidity +function harvest(uint256 pid, address to) external nonpayable +``` + +Harvest proceeds for transaction sender to `to`. + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| pid | uint256 | The index of the pool. See `poolInfo`. | +| to | address | Receiver of SYNAPSE rewards. | + +### lpToken + +```solidity +function lpToken(uint256) external view returns (contract IERC20) +``` + +Address of the LP token for each MCV2 pool. + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| _0 | uint256 | undefined | + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | contract IERC20 | undefined | + +### massUpdatePools + +```solidity +function massUpdatePools(uint256[] pids) external nonpayable +``` + +Update reward variables for all pools. Be careful of gas spending! + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| pids | uint256[] | Pool IDs of all to be updated. Make sure to update all active pools. | + +### owner + +```solidity +function owner() external view returns (address) +``` + + + + + + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | address | undefined | + +### pendingOwner + +```solidity +function pendingOwner() external view returns (address) +``` + + + + + + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | address | undefined | + +### pendingSynapse + +```solidity +function pendingSynapse(uint256 _pid, address _user) external view returns (uint256 pending) +``` + +View function to see pending SYNAPSE on frontend. + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| _pid | uint256 | The index of the pool. See `poolInfo`. | +| _user | address | Address of user. | + +#### Returns + +| Name | Type | Description | +|---|---|---| +| pending | uint256 | SYNAPSE reward for a given user. | + +### permitToken + +```solidity +function permitToken(contract IERC20 token, address from, address to, uint256 amount, uint256 deadline, uint8 v, bytes32 r, bytes32 s) external nonpayable +``` + + + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| token | contract IERC20 | undefined | +| from | address | undefined | +| to | address | undefined | +| amount | uint256 | undefined | +| deadline | uint256 | undefined | +| v | uint8 | undefined | +| r | bytes32 | undefined | +| s | bytes32 | undefined | + +### poolInfo + +```solidity +function poolInfo(uint256) external view returns (uint128 accSynapsePerShare, uint64 lastRewardTime, uint64 allocPoint) +``` + +Info of each MCV2 pool. + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| _0 | uint256 | undefined | + +#### Returns + +| Name | Type | Description | +|---|---|---| +| accSynapsePerShare | uint128 | undefined | +| lastRewardTime | uint64 | undefined | +| allocPoint | uint64 | undefined | + +### poolLength + +```solidity +function poolLength() external view returns (uint256 pools) +``` + +Returns the number of MCV2 pools. + + + + +#### Returns + +| Name | Type | Description | +|---|---|---| +| pools | uint256 | undefined | + +### rewarder + +```solidity +function rewarder(uint256) external view returns (contract IRewarder) +``` + +Address of each `IRewarder` contract in MCV2. + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| _0 | uint256 | undefined | + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | contract IRewarder | undefined | + +### set + +```solidity +function set(uint256 _pid, uint256 _allocPoint, contract IRewarder _rewarder, bool overwrite) external nonpayable +``` + +Update the given pool's SYNAPSE allocation point and `IRewarder` contract. Can only be called by the owner. + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| _pid | uint256 | The index of the pool. See `poolInfo`. | +| _allocPoint | uint256 | New AP of the pool. | +| _rewarder | contract IRewarder | Address of the rewarder delegate. | +| overwrite | bool | True if _rewarder should be `set`. Otherwise `_rewarder` is ignored. | + +### setSynapsePerSecond + +```solidity +function setSynapsePerSecond(uint256 _synapsePerSecond) external nonpayable +``` + +Sets the synapse per second to be distributed. Can only be called by the owner. + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| _synapsePerSecond | uint256 | The amount of Synapse to be distributed per second. | + +### synapsePerSecond + +```solidity +function synapsePerSecond() external view returns (uint256) +``` + + + + + + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | uint256 | undefined | + +### totalAllocPoint + +```solidity +function totalAllocPoint() external view returns (uint256) +``` + + + +*Total allocation points. Must be the sum of all allocation points in all pools.* + + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | uint256 | undefined | + +### transferOwnership + +```solidity +function transferOwnership(address newOwner, bool direct, bool renounce) external nonpayable +``` + + + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| newOwner | address | undefined | +| direct | bool | undefined | +| renounce | bool | undefined | + +### updatePool + +```solidity +function updatePool(uint256 pid) external nonpayable returns (struct MiniChefV2.PoolInfo pool) +``` + +Update reward variables of the given pool. + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| pid | uint256 | The index of the pool. See `poolInfo`. | + +#### Returns + +| Name | Type | Description | +|---|---|---| +| pool | MiniChefV2.PoolInfo | Returns the pool that was updated. | + +### userInfo + +```solidity +function userInfo(uint256, address) external view returns (uint256 amount, int256 rewardDebt) +``` + +Info of each user that stakes LP tokens. + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| _0 | uint256 | undefined | +| _1 | address | undefined | + +#### Returns + +| Name | Type | Description | +|---|---|---| +| amount | uint256 | undefined | +| rewardDebt | int256 | undefined | + +### withdraw + +```solidity +function withdraw(uint256 pid, uint256 amount, address to) external nonpayable +``` + +Withdraw LP tokens from MCV2. + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| pid | uint256 | The index of the pool. See `poolInfo`. | +| amount | uint256 | LP token amount to withdraw. | +| to | address | Receiver of the LP tokens. | + +### withdrawAndHarvest + +```solidity +function withdrawAndHarvest(uint256 pid, uint256 amount, address to) external nonpayable +``` + +Withdraw LP tokens from MCV2 and harvest proceeds for transaction sender to `to`. + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| pid | uint256 | The index of the pool. See `poolInfo`. | +| amount | uint256 | LP token amount to withdraw. | +| to | address | Receiver of the LP tokens and SYNAPSE rewards. | + + + +## Events + +### Deposit + +```solidity +event Deposit(address indexed user, uint256 indexed pid, uint256 amount, address indexed to) +``` + + + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| user `indexed` | address | undefined | +| pid `indexed` | uint256 | undefined | +| amount | uint256 | undefined | +| to `indexed` | address | undefined | + +### EmergencyWithdraw + +```solidity +event EmergencyWithdraw(address indexed user, uint256 indexed pid, uint256 amount, address indexed to) +``` + + + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| user `indexed` | address | undefined | +| pid `indexed` | uint256 | undefined | +| amount | uint256 | undefined | +| to `indexed` | address | undefined | + +### Harvest + +```solidity +event Harvest(address indexed user, uint256 indexed pid, uint256 amount) +``` + + + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| user `indexed` | address | undefined | +| pid `indexed` | uint256 | undefined | +| amount | uint256 | undefined | + +### LogPoolAddition + +```solidity +event LogPoolAddition(uint256 indexed pid, uint256 allocPoint, contract IERC20 indexed lpToken, contract IRewarder indexed rewarder) +``` + + + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| pid `indexed` | uint256 | undefined | +| allocPoint | uint256 | undefined | +| lpToken `indexed` | contract IERC20 | undefined | +| rewarder `indexed` | contract IRewarder | undefined | + +### LogSetPool + +```solidity +event LogSetPool(uint256 indexed pid, uint256 allocPoint, contract IRewarder indexed rewarder, bool overwrite) +``` + + + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| pid `indexed` | uint256 | undefined | +| allocPoint | uint256 | undefined | +| rewarder `indexed` | contract IRewarder | undefined | +| overwrite | bool | undefined | + +### LogSynapsePerSecond + +```solidity +event LogSynapsePerSecond(uint256 synapsePerSecond) +``` + + + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| synapsePerSecond | uint256 | undefined | + +### LogUpdatePool + +```solidity +event LogUpdatePool(uint256 indexed pid, uint64 lastRewardTime, uint256 lpSupply, uint256 accSynapsePerShare) +``` + + + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| pid `indexed` | uint256 | undefined | +| lastRewardTime | uint64 | undefined | +| lpSupply | uint256 | undefined | +| accSynapsePerShare | uint256 | undefined | + +### OwnershipTransferred + +```solidity +event OwnershipTransferred(address indexed previousOwner, address indexed newOwner) +``` + + + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| previousOwner `indexed` | address | undefined | +| newOwner `indexed` | address | undefined | + +### Withdraw + +```solidity +event Withdraw(address indexed user, uint256 indexed pid, uint256 amount, address indexed to) +``` + + + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| user `indexed` | address | undefined | +| pid `indexed` | uint256 | undefined | +| amount | uint256 | undefined | +| to `indexed` | address | undefined | + + + diff --git a/docs/bridge/PoolConfig.md b/docs/bridge/PoolConfig.md new file mode 100644 index 000000000..1908e0007 --- /dev/null +++ b/docs/bridge/PoolConfig.md @@ -0,0 +1,295 @@ +# PoolConfig + + + + + + + + + +## Methods + +### BRIDGEMANAGER_ROLE + +```solidity +function BRIDGEMANAGER_ROLE() external view returns (bytes32) +``` + + + + + + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | bytes32 | undefined | + +### DEFAULT_ADMIN_ROLE + +```solidity +function DEFAULT_ADMIN_ROLE() external view returns (bytes32) +``` + + + + + + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | bytes32 | undefined | + +### getPoolConfig + +```solidity +function getPoolConfig(address tokenAddress, uint256 chainID) external view returns (struct PoolConfig.Pool) +``` + + + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| tokenAddress | address | undefined | +| chainID | uint256 | undefined | + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | PoolConfig.Pool | undefined | + +### getRoleAdmin + +```solidity +function getRoleAdmin(bytes32 role) external view returns (bytes32) +``` + + + +*Returns the admin role that controls `role`. See {grantRole} and {revokeRole}. To change a role's admin, use {_setRoleAdmin}.* + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| role | bytes32 | undefined | + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | bytes32 | undefined | + +### getRoleMember + +```solidity +function getRoleMember(bytes32 role, uint256 index) external view returns (address) +``` + + + +*Returns one of the accounts that have `role`. `index` must be a value between 0 and {getRoleMemberCount}, non-inclusive. Role bearers are not sorted in any particular way, and their ordering may change at any point. WARNING: When using {getRoleMember} and {getRoleMemberCount}, make sure you perform all queries on the same block. See the following https://forum.openzeppelin.com/t/iterating-over-elements-on-enumerableset-in-openzeppelin-contracts/2296[forum post] for more information.* + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| role | bytes32 | undefined | +| index | uint256 | undefined | + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | address | undefined | + +### getRoleMemberCount + +```solidity +function getRoleMemberCount(bytes32 role) external view returns (uint256) +``` + + + +*Returns the number of accounts that have `role`. Can be used together with {getRoleMember} to enumerate all bearers of a role.* + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| role | bytes32 | undefined | + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | uint256 | undefined | + +### grantRole + +```solidity +function grantRole(bytes32 role, address account) external nonpayable +``` + + + +*Grants `role` to `account`. If `account` had not been already granted `role`, emits a {RoleGranted} event. Requirements: - the caller must have ``role``'s admin role.* + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| role | bytes32 | undefined | +| account | address | undefined | + +### hasRole + +```solidity +function hasRole(bytes32 role, address account) external view returns (bool) +``` + + + +*Returns `true` if `account` has been granted `role`.* + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| role | bytes32 | undefined | +| account | address | undefined | + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | bool | undefined | + +### renounceRole + +```solidity +function renounceRole(bytes32 role, address account) external nonpayable +``` + + + +*Revokes `role` from the calling account. Roles are often managed via {grantRole} and {revokeRole}: this function's purpose is to provide a mechanism for accounts to lose their privileges if they are compromised (such as when a trusted device is misplaced). If the calling account had been granted `role`, emits a {RoleRevoked} event. Requirements: - the caller must be `account`.* + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| role | bytes32 | undefined | +| account | address | undefined | + +### revokeRole + +```solidity +function revokeRole(bytes32 role, address account) external nonpayable +``` + + + +*Revokes `role` from `account`. If `account` had been granted `role`, emits a {RoleRevoked} event. Requirements: - the caller must have ``role``'s admin role.* + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| role | bytes32 | undefined | +| account | address | undefined | + +### setPoolConfig + +```solidity +function setPoolConfig(address tokenAddress, uint256 chainID, address poolAddress, bool metaswap) external nonpayable returns (struct PoolConfig.Pool) +``` + + + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| tokenAddress | address | undefined | +| chainID | uint256 | undefined | +| poolAddress | address | undefined | +| metaswap | bool | undefined | + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | PoolConfig.Pool | undefined | + + + +## Events + +### RoleAdminChanged + +```solidity +event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole) +``` + + + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| role `indexed` | bytes32 | undefined | +| previousAdminRole `indexed` | bytes32 | undefined | +| newAdminRole `indexed` | bytes32 | undefined | + +### RoleGranted + +```solidity +event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender) +``` + + + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| role `indexed` | bytes32 | undefined | +| account `indexed` | address | undefined | +| sender `indexed` | address | undefined | + +### RoleRevoked + +```solidity +event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender) +``` + + + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| role `indexed` | bytes32 | undefined | +| account `indexed` | address | undefined | +| sender `indexed` | address | undefined | + + + diff --git a/docs/bridge/RateLimiter.md b/docs/bridge/RateLimiter.md new file mode 100644 index 000000000..6cd07a1e1 --- /dev/null +++ b/docs/bridge/RateLimiter.md @@ -0,0 +1,580 @@ +# RateLimiter + + + + + + + + + +## Methods + +### BRIDGE_ADDRESS + +```solidity +function BRIDGE_ADDRESS() external view returns (address) +``` + + + + + + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | address | undefined | + +### BRIDGE_ROLE + +```solidity +function BRIDGE_ROLE() external view returns (bytes32) +``` + + + + + + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | bytes32 | undefined | + +### DEFAULT_ADMIN_ROLE + +```solidity +function DEFAULT_ADMIN_ROLE() external view returns (bytes32) +``` + + + + + + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | bytes32 | undefined | + +### GOVERNANCE_ROLE + +```solidity +function GOVERNANCE_ROLE() external view returns (bytes32) +``` + + + + + + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | bytes32 | undefined | + +### LIMITER_ROLE + +```solidity +function LIMITER_ROLE() external view returns (bytes32) +``` + + + + + + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | bytes32 | undefined | + +### NAME + +```solidity +function NAME() external view returns (string) +``` + + + + + + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | string | undefined | + +### VERSION + +```solidity +function VERSION() external view returns (string) +``` + + + + + + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | string | undefined | + +### addToRetryQueue + +```solidity +function addToRetryQueue(bytes32 kappa, bytes rateLimited) external nonpayable +``` + + + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| kappa | bytes32 | undefined | +| rateLimited | bytes | undefined | + +### allowances + +```solidity +function allowances(address) external view returns (uint96 amount, uint96 spent, uint16 resetTimeMin, uint32 lastResetMin, bool initialized) +``` + + + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| _0 | address | undefined | + +#### Returns + +| Name | Type | Description | +|---|---|---| +| amount | uint96 | undefined | +| spent | uint96 | undefined | +| resetTimeMin | uint16 | undefined | +| lastResetMin | uint32 | undefined | +| initialized | bool | undefined | + +### checkAndUpdateAllowance + +```solidity +function checkAndUpdateAllowance(address token, uint256 amount) external nonpayable returns (bool) +``` + +Checks the allowance for a given token. If the new amount exceeds the allowance, it is not updated and false is returned otherwise true is returned and the transaction can proceed + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| token | address | undefined | +| amount | uint256 | to transfer* | + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | bool | undefined | + +### deleteByKappa + +```solidity +function deleteByKappa(bytes32 kappa) external nonpayable +``` + + + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| kappa | bytes32 | undefined | + +### getRoleAdmin + +```solidity +function getRoleAdmin(bytes32 role) external view returns (bytes32) +``` + + + +*Returns the admin role that controls `role`. See {grantRole} and {revokeRole}. To change a role's admin, use {_setRoleAdmin}.* + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| role | bytes32 | undefined | + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | bytes32 | undefined | + +### getTokenAllowance + +```solidity +function getTokenAllowance(address token) external view returns (uint256[4]) +``` + + + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| token | address | undefined | + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | uint256[4] | undefined | + +### getTokens + +```solidity +function getTokens() external view returns (address[]) +``` + +Gets a list of tokens with allowances* + + + + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | address[] | undefined | + +### grantRole + +```solidity +function grantRole(bytes32 role, address account) external nonpayable +``` + + + +*Grants `role` to `account`. If `account` had not been already granted `role`, emits a {RoleGranted} event. Requirements: - the caller must have ``role``'s admin role.* + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| role | bytes32 | undefined | +| account | address | undefined | + +### hasRole + +```solidity +function hasRole(bytes32 role, address account) external view returns (bool) +``` + + + +*Returns `true` if `account` has been granted `role`.* + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| role | bytes32 | undefined | +| account | address | undefined | + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | bool | undefined | + +### initialize + +```solidity +function initialize() external nonpayable +``` + + + + + + +### renounceRole + +```solidity +function renounceRole(bytes32 role, address account) external nonpayable +``` + + + +*Revokes `role` from the calling account. Roles are often managed via {grantRole} and {revokeRole}: this function's purpose is to provide a mechanism for accounts to lose their privileges if they are compromised (such as when a trusted device is misplaced). If the calling account had been revoked `role`, emits a {RoleRevoked} event. Requirements: - the caller must be `account`.* + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| role | bytes32 | undefined | +| account | address | undefined | + +### resetAllowance + +```solidity +function resetAllowance(address token) external nonpayable +``` + + + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| token | address | undefined | + +### retryByKappa + +```solidity +function retryByKappa(bytes32 kappa) external nonpayable +``` + + + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| kappa | bytes32 | undefined | + +### retryCount + +```solidity +function retryCount(uint8 count) external nonpayable +``` + + + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| count | uint8 | undefined | + +### revokeRole + +```solidity +function revokeRole(bytes32 role, address account) external nonpayable +``` + + + +*Revokes `role` from `account`. If `account` had been granted `role`, emits a {RoleRevoked} event. Requirements: - the caller must have ``role``'s admin role.* + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| role | bytes32 | undefined | +| account | address | undefined | + +### setAllowance + +```solidity +function setAllowance(address token, uint96 allowanceAmount, uint16 resetTimeMin, uint32 resetBaseMin) external nonpayable +``` + +Updates the allowance for a given token + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| token | address | to update the allowance for | +| allowanceAmount | uint96 | for the token | +| resetTimeMin | uint16 | minimum reset time (amount goes to 0 after this) | +| resetBaseMin | uint32 | amount Amount in native token decimals to transfer cross-chain pre-fees* | + +### setBridgeAddress + +```solidity +function setBridgeAddress(address bridge) external nonpayable +``` + + + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| bridge | address | undefined | + +### supportsInterface + +```solidity +function supportsInterface(bytes4 interfaceId) external view returns (bool) +``` + + + +*See {IERC165-supportsInterface}.* + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| interfaceId | bytes4 | undefined | + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | bool | undefined | + +### tokens + +```solidity +function tokens(uint256) external view returns (address) +``` + + + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| _0 | uint256 | undefined | + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | address | undefined | + + + +## Events + +### ResetAllowance + +```solidity +event ResetAllowance(address indexed token) +``` + + + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| token `indexed` | address | undefined | + +### RoleAdminChanged + +```solidity +event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole) +``` + + + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| role `indexed` | bytes32 | undefined | +| previousAdminRole `indexed` | bytes32 | undefined | +| newAdminRole `indexed` | bytes32 | undefined | + +### RoleGranted + +```solidity +event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender) +``` + + + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| role `indexed` | bytes32 | undefined | +| account `indexed` | address | undefined | +| sender `indexed` | address | undefined | + +### RoleRevoked + +```solidity +event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender) +``` + + + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| role `indexed` | bytes32 | undefined | +| account `indexed` | address | undefined | +| sender `indexed` | address | undefined | + +### SetAllowance + +```solidity +event SetAllowance(address indexed token, uint96 allowanceAmount, uint16 resetTime) +``` + + + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| token `indexed` | address | undefined | +| allowanceAmount | uint96 | undefined | +| resetTime | uint16 | undefined | + + + diff --git a/docs/bridge/SynapseBridge.md b/docs/bridge/SynapseBridge.md new file mode 100644 index 000000000..d5a38c518 --- /dev/null +++ b/docs/bridge/SynapseBridge.md @@ -0,0 +1,1090 @@ +# SynapseBridge + + + + + + + + + +## Methods + +### DEFAULT_ADMIN_ROLE + +```solidity +function DEFAULT_ADMIN_ROLE() external view returns (bytes32) +``` + + + + + + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | bytes32 | undefined | + +### GOVERNANCE_ROLE + +```solidity +function GOVERNANCE_ROLE() external view returns (bytes32) +``` + + + + + + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | bytes32 | undefined | + +### NODEGROUP_ROLE + +```solidity +function NODEGROUP_ROLE() external view returns (bytes32) +``` + + + + + + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | bytes32 | undefined | + +### RATE_LIMITER_ROLE + +```solidity +function RATE_LIMITER_ROLE() external view returns (bytes32) +``` + + + + + + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | bytes32 | undefined | + +### WETH_ADDRESS + +```solidity +function WETH_ADDRESS() external view returns (address payable) +``` + + + + + + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | address payable | undefined | + +### addKappas + +```solidity +function addKappas(bytes32[] kappas) external nonpayable +``` + + + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| kappas | bytes32[] | undefined | + +### bridgeVersion + +```solidity +function bridgeVersion() external view returns (uint256) +``` + + + + + + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | uint256 | undefined | + +### chainGasAmount + +```solidity +function chainGasAmount() external view returns (uint256) +``` + + + + + + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | uint256 | undefined | + +### deposit + +```solidity +function deposit(address to, uint256 chainId, contract IERC20 token, uint256 amount) external nonpayable +``` + +Relays to nodes to transfers an ERC20 token cross-chain + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| to | address | address on other chain to bridge assets to | +| chainId | uint256 | which chain to bridge assets onto | +| token | contract IERC20 | ERC20 compatible token to deposit into the bridge | +| amount | uint256 | Amount in native token decimals to transfer cross-chain pre-fees* | + +### depositAndSwap + +```solidity +function depositAndSwap(address to, uint256 chainId, contract IERC20 token, uint256 amount, uint8 tokenIndexFrom, uint8 tokenIndexTo, uint256 minDy, uint256 deadline) external nonpayable +``` + +Relays to nodes to both transfer an ERC20 token cross-chain, and then have the nodes execute a swap through a liquidity pool on behalf of the user. + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| to | address | address on other chain to bridge assets to | +| chainId | uint256 | which chain to bridge assets onto | +| token | contract IERC20 | ERC20 compatible token to deposit into the bridge | +| amount | uint256 | Amount in native token decimals to transfer cross-chain pre-fees | +| tokenIndexFrom | uint8 | the token the user wants to swap from | +| tokenIndexTo | uint8 | the token the user wants to swap to | +| minDy | uint256 | the min amount the user would like to receive, or revert to only minting the SynERC20 token crosschain. | +| deadline | uint256 | latest timestamp to accept this transaction* | + +### getFeeBalance + +```solidity +function getFeeBalance(address tokenAddress) external view returns (uint256) +``` + + + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| tokenAddress | address | undefined | + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | uint256 | undefined | + +### getRoleAdmin + +```solidity +function getRoleAdmin(bytes32 role) external view returns (bytes32) +``` + + + +*Returns the admin role that controls `role`. See {grantRole} and {revokeRole}. To change a role's admin, use {_setRoleAdmin}.* + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| role | bytes32 | undefined | + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | bytes32 | undefined | + +### getRoleMember + +```solidity +function getRoleMember(bytes32 role, uint256 index) external view returns (address) +``` + + + +*Returns one of the accounts that have `role`. `index` must be a value between 0 and {getRoleMemberCount}, non-inclusive. Role bearers are not sorted in any particular way, and their ordering may change at any point. WARNING: When using {getRoleMember} and {getRoleMemberCount}, make sure you perform all queries on the same block. See the following https://forum.openzeppelin.com/t/iterating-over-elements-on-enumerableset-in-openzeppelin-contracts/2296[forum post] for more information.* + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| role | bytes32 | undefined | +| index | uint256 | undefined | + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | address | undefined | + +### getRoleMemberCount + +```solidity +function getRoleMemberCount(bytes32 role) external view returns (uint256) +``` + + + +*Returns the number of accounts that have `role`. Can be used together with {getRoleMember} to enumerate all bearers of a role.* + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| role | bytes32 | undefined | + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | uint256 | undefined | + +### grantRole + +```solidity +function grantRole(bytes32 role, address account) external nonpayable +``` + + + +*Grants `role` to `account`. If `account` had not been already granted `role`, emits a {RoleGranted} event. Requirements: - the caller must have ``role``'s admin role.* + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| role | bytes32 | undefined | +| account | address | undefined | + +### hasRole + +```solidity +function hasRole(bytes32 role, address account) external view returns (bool) +``` + + + +*Returns `true` if `account` has been granted `role`.* + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| role | bytes32 | undefined | +| account | address | undefined | + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | bool | undefined | + +### initialize + +```solidity +function initialize() external nonpayable +``` + + + + + + +### kappaExists + +```solidity +function kappaExists(bytes32 kappa) external view returns (bool) +``` + + + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| kappa | bytes32 | undefined | + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | bool | undefined | + +### mint + +```solidity +function mint(address payable to, contract IERC20Mintable token, uint256 amount, uint256 fee, bytes32 kappa) external nonpayable +``` + +Nodes call this function to mint a SynERC20 (or any asset that the bridge is given minter access to). This is called by the nodes after a TokenDeposit event is emitted. + +*This means the SynapseBridge.sol contract must have minter access to the token attempting to be minted* + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| to | address payable | address on other chain to redeem underlying assets to | +| token | contract IERC20Mintable | ERC20 compatible token to deposit into the bridge | +| amount | uint256 | Amount in native token decimals to transfer cross-chain post-fees | +| fee | uint256 | Amount in native token decimals to save to the contract as fees | +| kappa | bytes32 | kappa* | + +### mintAndSwap + +```solidity +function mintAndSwap(address payable to, contract IERC20Mintable token, uint256 amount, uint256 fee, contract ISwap pool, uint8 tokenIndexFrom, uint8 tokenIndexTo, uint256 minDy, uint256 deadline, bytes32 kappa) external nonpayable +``` + +Nodes call this function to mint a SynERC20 (or any asset that the bridge is given minter access to), and then attempt to swap the SynERC20 into the desired destination asset. This is called by the nodes after a TokenDepositAndSwap event is emitted. + +*This means the BridgeDeposit.sol contract must have minter access to the token attempting to be minted* + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| to | address payable | address on other chain to redeem underlying assets to | +| token | contract IERC20Mintable | ERC20 compatible token to deposit into the bridge | +| amount | uint256 | Amount in native token decimals to transfer cross-chain post-fees | +| fee | uint256 | Amount in native token decimals to save to the contract as fees | +| pool | contract ISwap | Destination chain's pool to use to swap SynERC20 -> Asset. The nodes determine this by using PoolConfig.sol. | +| tokenIndexFrom | uint8 | Index of the SynERC20 asset in the pool | +| tokenIndexTo | uint8 | Index of the desired final asset | +| minDy | uint256 | Minumum amount (in final asset decimals) that must be swapped for, otherwise the user will receive the SynERC20. | +| deadline | uint256 | Epoch time of the deadline that the swap is allowed to be executed. | +| kappa | bytes32 | kappa* | + +### pause + +```solidity +function pause() external nonpayable +``` + + + + + + +### paused + +```solidity +function paused() external view returns (bool) +``` + + + +*Returns true if the contract is paused, and false otherwise.* + + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | bool | undefined | + +### rateLimiter + +```solidity +function rateLimiter() external view returns (contract IRateLimiter) +``` + + + + + + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | contract IRateLimiter | undefined | + +### redeem + +```solidity +function redeem(address to, uint256 chainId, contract ERC20Burnable token, uint256 amount) external nonpayable +``` + +Relays to nodes that (typically) a wrapped synAsset ERC20 token has been burned and the underlying needs to be redeeemed on the native chain + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| to | address | address on other chain to redeem underlying assets to | +| chainId | uint256 | which underlying chain to bridge assets onto | +| token | contract ERC20Burnable | ERC20 compatible token to deposit into the bridge | +| amount | uint256 | Amount in native token decimals to transfer cross-chain pre-fees* | + +### redeemAndRemove + +```solidity +function redeemAndRemove(address to, uint256 chainId, contract ERC20Burnable token, uint256 amount, uint8 swapTokenIndex, uint256 swapMinAmount, uint256 swapDeadline) external nonpayable +``` + +Relays to nodes that (typically) a wrapped synAsset ERC20 token has been burned and the underlying needs to be redeeemed on the native chain. This function indicates to the nodes that they should attempt to redeem the LP token for the underlying assets (E.g "swap" out of the LP token) + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| to | address | address on other chain to redeem underlying assets to | +| chainId | uint256 | which underlying chain to bridge assets onto | +| token | contract ERC20Burnable | ERC20 compatible token to deposit into the bridge | +| amount | uint256 | Amount in native token decimals to transfer cross-chain pre-fees | +| swapTokenIndex | uint8 | Specifies which of the underlying LP assets the nodes should attempt to redeem for | +| swapMinAmount | uint256 | Specifies the minimum amount of the underlying asset needed for the nodes to execute the redeem/swap | +| swapDeadline | uint256 | Specificies the deadline that the nodes are allowed to try to redeem/swap the LP token* | + +### redeemAndSwap + +```solidity +function redeemAndSwap(address to, uint256 chainId, contract ERC20Burnable token, uint256 amount, uint8 tokenIndexFrom, uint8 tokenIndexTo, uint256 minDy, uint256 deadline) external nonpayable +``` + +Relays to nodes that (typically) a wrapped synAsset ERC20 token has been burned and the underlying needs to be redeeemed on the native chain. This function indicates to the nodes that they should attempt to redeem the LP token for the underlying assets (E.g "swap" out of the LP token) + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| to | address | address on other chain to redeem underlying assets to | +| chainId | uint256 | which underlying chain to bridge assets onto | +| token | contract ERC20Burnable | ERC20 compatible token to deposit into the bridge | +| amount | uint256 | Amount in native token decimals to transfer cross-chain pre-fees | +| tokenIndexFrom | uint8 | the token the user wants to swap from | +| tokenIndexTo | uint8 | the token the user wants to swap to | +| minDy | uint256 | the min amount the user would like to receive, or revert to only minting the SynERC20 token crosschain. | +| deadline | uint256 | latest timestamp to accept this transaction* | + +### redeemV2 + +```solidity +function redeemV2(bytes32 to, uint256 chainId, contract ERC20Burnable token, uint256 amount) external nonpayable +``` + +Relays to nodes that (typically) a wrapped synAsset ERC20 token has been burned and the underlying needs to be redeeemed on the native chain + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| to | bytes32 | address on other chain to redeem underlying assets to | +| chainId | uint256 | which underlying chain to bridge assets onto | +| token | contract ERC20Burnable | ERC20 compatible token to deposit into the bridge | +| amount | uint256 | Amount in native token decimals to transfer cross-chain pre-fees* | + +### renounceRole + +```solidity +function renounceRole(bytes32 role, address account) external nonpayable +``` + + + +*Revokes `role` from the calling account. Roles are often managed via {grantRole} and {revokeRole}: this function's purpose is to provide a mechanism for accounts to lose their privileges if they are compromised (such as when a trusted device is misplaced). If the calling account had been granted `role`, emits a {RoleRevoked} event. Requirements: - the caller must be `account`.* + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| role | bytes32 | undefined | +| account | address | undefined | + +### retryMint + +```solidity +function retryMint(address payable to, contract IERC20Mintable token, uint256 amount, uint256 fee, bytes32 kappa) external nonpayable +``` + +Rate Limiter call this function to retry a mint of a SynERC20 (or any asset that the bridge is given minter access to). This is called by the nodes after a TokenDeposit event is emitted. + +*This means the SynapseBridge.sol contract must have minter access to the token attempting to be minted* + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| to | address payable | address on other chain to redeem underlying assets to | +| token | contract IERC20Mintable | ERC20 compatible token to deposit into the bridge | +| amount | uint256 | Amount in native token decimals to transfer cross-chain post-fees | +| fee | uint256 | Amount in native token decimals to save to the contract as fees | +| kappa | bytes32 | kappa* | + +### retryMintAndSwap + +```solidity +function retryMintAndSwap(address payable to, contract IERC20Mintable token, uint256 amount, uint256 fee, contract ISwap pool, uint8 tokenIndexFrom, uint8 tokenIndexTo, uint256 minDy, uint256 deadline, bytes32 kappa) external nonpayable +``` + +RateLimiter call this function to retry a mint of a SynERC20 (or any asset that the bridge is given minter access to), and then attempt to swap the SynERC20 into the desired destination asset. This is called by the nodes after a TokenDepositAndSwap event is emitted. + +*This means the BridgeDeposit.sol contract must have minter access to the token attempting to be minted* + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| to | address payable | address on other chain to redeem underlying assets to | +| token | contract IERC20Mintable | ERC20 compatible token to deposit into the bridge | +| amount | uint256 | Amount in native token decimals to transfer cross-chain post-fees | +| fee | uint256 | Amount in native token decimals to save to the contract as fees | +| pool | contract ISwap | Destination chain's pool to use to swap SynERC20 -> Asset. The nodes determine this by using PoolConfig.sol. | +| tokenIndexFrom | uint8 | Index of the SynERC20 asset in the pool | +| tokenIndexTo | uint8 | Index of the desired final asset | +| minDy | uint256 | Minumum amount (in final asset decimals) that must be swapped for, otherwise the user will receive the SynERC20. | +| deadline | uint256 | Epoch time of the deadline that the swap is allowed to be executed. | +| kappa | bytes32 | kappa* | + +### retryWithdraw + +```solidity +function retryWithdraw(address to, contract IERC20 token, uint256 amount, uint256 fee, bytes32 kappa) external nonpayable +``` + +Function to be called by the rate limiter to retry a withdraw bypassing the rate limiter + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| to | address | address on chain to send underlying assets to | +| token | contract IERC20 | ERC20 compatible token to withdraw from the bridge | +| amount | uint256 | Amount in native token decimals to withdraw | +| fee | uint256 | Amount in native token decimals to save to the contract as fees | +| kappa | bytes32 | kappa* | + +### retryWithdrawAndRemove + +```solidity +function retryWithdrawAndRemove(address to, contract IERC20 token, uint256 amount, uint256 fee, contract ISwap pool, uint8 swapTokenIndex, uint256 swapMinAmount, uint256 swapDeadline, bytes32 kappa) external nonpayable +``` + +Function to be called by the rate limiter to retry a withdraw of the underlying assets from the contract + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| to | address | address on chain to send underlying assets to | +| token | contract IERC20 | ERC20 compatible token to withdraw from the bridge | +| amount | uint256 | Amount in native token decimals to withdraw | +| fee | uint256 | Amount in native token decimals to save to the contract as fees | +| pool | contract ISwap | Destination chain's pool to use to swap SynERC20 -> Asset. The nodes determine this by using PoolConfig.sol. | +| swapTokenIndex | uint8 | Specifies which of the underlying LP assets the nodes should attempt to redeem for | +| swapMinAmount | uint256 | Specifies the minimum amount of the underlying asset needed for the nodes to execute the redeem/swap | +| swapDeadline | uint256 | Specificies the deadline that the nodes are allowed to try to redeem/swap the LP token | +| kappa | bytes32 | kappa* | + +### revokeRole + +```solidity +function revokeRole(bytes32 role, address account) external nonpayable +``` + + + +*Revokes `role` from `account`. If `account` had been granted `role`, emits a {RoleRevoked} event. Requirements: - the caller must have ``role``'s admin role.* + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| role | bytes32 | undefined | +| account | address | undefined | + +### setChainGasAmount + +```solidity +function setChainGasAmount(uint256 amount) external nonpayable +``` + + + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| amount | uint256 | undefined | + +### setRateLimiter + +```solidity +function setRateLimiter(contract IRateLimiter _rateLimiter) external nonpayable +``` + + + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| _rateLimiter | contract IRateLimiter | undefined | + +### setWethAddress + +```solidity +function setWethAddress(address payable _wethAddress) external nonpayable +``` + + + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| _wethAddress | address payable | undefined | + +### startBlockNumber + +```solidity +function startBlockNumber() external view returns (uint256) +``` + + + + + + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | uint256 | undefined | + +### unpause + +```solidity +function unpause() external nonpayable +``` + + + + + + +### withdraw + +```solidity +function withdraw(address to, contract IERC20 token, uint256 amount, uint256 fee, bytes32 kappa) external nonpayable +``` + +Function to be called by the node group to withdraw the underlying assets from the contract + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| to | address | address on chain to send underlying assets to | +| token | contract IERC20 | ERC20 compatible token to withdraw from the bridge | +| amount | uint256 | Amount in native token decimals to withdraw | +| fee | uint256 | Amount in native token decimals to save to the contract as fees | +| kappa | bytes32 | kappa* | + +### withdrawAndRemove + +```solidity +function withdrawAndRemove(address to, contract IERC20 token, uint256 amount, uint256 fee, contract ISwap pool, uint8 swapTokenIndex, uint256 swapMinAmount, uint256 swapDeadline, bytes32 kappa) external nonpayable +``` + +Function to be called by the node group to withdraw the underlying assets from the contract + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| to | address | address on chain to send underlying assets to | +| token | contract IERC20 | ERC20 compatible token to withdraw from the bridge | +| amount | uint256 | Amount in native token decimals to withdraw | +| fee | uint256 | Amount in native token decimals to save to the contract as fees | +| pool | contract ISwap | Destination chain's pool to use to swap SynERC20 -> Asset. The nodes determine this by using PoolConfig.sol. | +| swapTokenIndex | uint8 | Specifies which of the underlying LP assets the nodes should attempt to redeem for | +| swapMinAmount | uint256 | Specifies the minimum amount of the underlying asset needed for the nodes to execute the redeem/swap | +| swapDeadline | uint256 | Specificies the deadline that the nodes are allowed to try to redeem/swap the LP token | +| kappa | bytes32 | kappa* | + +### withdrawFees + +```solidity +function withdrawFees(contract IERC20 token, address to) external nonpayable +``` + +withdraw specified ERC20 token fees to a given address + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| token | contract IERC20 | ERC20 token in which fees acccumulated to transfer | +| to | address | Address to send the fees to | + + + +## Events + +### Paused + +```solidity +event Paused(address account) +``` + + + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| account | address | undefined | + +### RoleAdminChanged + +```solidity +event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole) +``` + + + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| role `indexed` | bytes32 | undefined | +| previousAdminRole `indexed` | bytes32 | undefined | +| newAdminRole `indexed` | bytes32 | undefined | + +### RoleGranted + +```solidity +event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender) +``` + + + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| role `indexed` | bytes32 | undefined | +| account `indexed` | address | undefined | +| sender `indexed` | address | undefined | + +### RoleRevoked + +```solidity +event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender) +``` + + + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| role `indexed` | bytes32 | undefined | +| account `indexed` | address | undefined | +| sender `indexed` | address | undefined | + +### TokenDeposit + +```solidity +event TokenDeposit(address indexed to, uint256 chainId, contract IERC20 token, uint256 amount) +``` + + + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| to `indexed` | address | undefined | +| chainId | uint256 | undefined | +| token | contract IERC20 | undefined | +| amount | uint256 | undefined | + +### TokenDepositAndSwap + +```solidity +event TokenDepositAndSwap(address indexed to, uint256 chainId, contract IERC20 token, uint256 amount, uint8 tokenIndexFrom, uint8 tokenIndexTo, uint256 minDy, uint256 deadline) +``` + + + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| to `indexed` | address | undefined | +| chainId | uint256 | undefined | +| token | contract IERC20 | undefined | +| amount | uint256 | undefined | +| tokenIndexFrom | uint8 | undefined | +| tokenIndexTo | uint8 | undefined | +| minDy | uint256 | undefined | +| deadline | uint256 | undefined | + +### TokenMint + +```solidity +event TokenMint(address indexed to, contract IERC20Mintable token, uint256 amount, uint256 fee, bytes32 indexed kappa) +``` + + + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| to `indexed` | address | undefined | +| token | contract IERC20Mintable | undefined | +| amount | uint256 | undefined | +| fee | uint256 | undefined | +| kappa `indexed` | bytes32 | undefined | + +### TokenMintAndSwap + +```solidity +event TokenMintAndSwap(address indexed to, contract IERC20Mintable token, uint256 amount, uint256 fee, uint8 tokenIndexFrom, uint8 tokenIndexTo, uint256 minDy, uint256 deadline, bool swapSuccess, bytes32 indexed kappa) +``` + + + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| to `indexed` | address | undefined | +| token | contract IERC20Mintable | undefined | +| amount | uint256 | undefined | +| fee | uint256 | undefined | +| tokenIndexFrom | uint8 | undefined | +| tokenIndexTo | uint8 | undefined | +| minDy | uint256 | undefined | +| deadline | uint256 | undefined | +| swapSuccess | bool | undefined | +| kappa `indexed` | bytes32 | undefined | + +### TokenRedeem + +```solidity +event TokenRedeem(address indexed to, uint256 chainId, contract IERC20 token, uint256 amount) +``` + + + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| to `indexed` | address | undefined | +| chainId | uint256 | undefined | +| token | contract IERC20 | undefined | +| amount | uint256 | undefined | + +### TokenRedeemAndRemove + +```solidity +event TokenRedeemAndRemove(address indexed to, uint256 chainId, contract IERC20 token, uint256 amount, uint8 swapTokenIndex, uint256 swapMinAmount, uint256 swapDeadline) +``` + + + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| to `indexed` | address | undefined | +| chainId | uint256 | undefined | +| token | contract IERC20 | undefined | +| amount | uint256 | undefined | +| swapTokenIndex | uint8 | undefined | +| swapMinAmount | uint256 | undefined | +| swapDeadline | uint256 | undefined | + +### TokenRedeemAndSwap + +```solidity +event TokenRedeemAndSwap(address indexed to, uint256 chainId, contract IERC20 token, uint256 amount, uint8 tokenIndexFrom, uint8 tokenIndexTo, uint256 minDy, uint256 deadline) +``` + + + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| to `indexed` | address | undefined | +| chainId | uint256 | undefined | +| token | contract IERC20 | undefined | +| amount | uint256 | undefined | +| tokenIndexFrom | uint8 | undefined | +| tokenIndexTo | uint8 | undefined | +| minDy | uint256 | undefined | +| deadline | uint256 | undefined | + +### TokenRedeemV2 + +```solidity +event TokenRedeemV2(bytes32 indexed to, uint256 chainId, contract IERC20 token, uint256 amount) +``` + + + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| to `indexed` | bytes32 | undefined | +| chainId | uint256 | undefined | +| token | contract IERC20 | undefined | +| amount | uint256 | undefined | + +### TokenWithdraw + +```solidity +event TokenWithdraw(address indexed to, contract IERC20 token, uint256 amount, uint256 fee, bytes32 indexed kappa) +``` + + + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| to `indexed` | address | undefined | +| token | contract IERC20 | undefined | +| amount | uint256 | undefined | +| fee | uint256 | undefined | +| kappa `indexed` | bytes32 | undefined | + +### TokenWithdrawAndRemove + +```solidity +event TokenWithdrawAndRemove(address indexed to, contract IERC20 token, uint256 amount, uint256 fee, uint8 swapTokenIndex, uint256 swapMinAmount, uint256 swapDeadline, bool swapSuccess, bytes32 indexed kappa) +``` + + + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| to `indexed` | address | undefined | +| token | contract IERC20 | undefined | +| amount | uint256 | undefined | +| fee | uint256 | undefined | +| swapTokenIndex | uint8 | undefined | +| swapMinAmount | uint256 | undefined | +| swapDeadline | uint256 | undefined | +| swapSuccess | bool | undefined | +| kappa `indexed` | bytes32 | undefined | + +### Unpaused + +```solidity +event Unpaused(address account) +``` + + + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| account | address | undefined | + + + diff --git a/docs/bridge/SynapseERC20.md b/docs/bridge/SynapseERC20.md new file mode 100644 index 000000000..9dcacc92d --- /dev/null +++ b/docs/bridge/SynapseERC20.md @@ -0,0 +1,642 @@ +# SynapseERC20 + + + + + + + + + +## Methods + +### DEFAULT_ADMIN_ROLE + +```solidity +function DEFAULT_ADMIN_ROLE() external view returns (bytes32) +``` + + + + + + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | bytes32 | undefined | + +### DOMAIN_SEPARATOR + +```solidity +function DOMAIN_SEPARATOR() external view returns (bytes32) +``` + + + +*See {IERC20Permit-DOMAIN_SEPARATOR}.* + + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | bytes32 | undefined | + +### MINTER_ROLE + +```solidity +function MINTER_ROLE() external view returns (bytes32) +``` + + + + + + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | bytes32 | undefined | + +### allowance + +```solidity +function allowance(address owner, address spender) external view returns (uint256) +``` + + + +*See {IERC20-allowance}.* + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| owner | address | undefined | +| spender | address | undefined | + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | uint256 | undefined | + +### approve + +```solidity +function approve(address spender, uint256 amount) external nonpayable returns (bool) +``` + + + +*See {IERC20-approve}. Requirements: - `spender` cannot be the zero address.* + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| spender | address | undefined | +| amount | uint256 | undefined | + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | bool | undefined | + +### balanceOf + +```solidity +function balanceOf(address account) external view returns (uint256) +``` + + + +*See {IERC20-balanceOf}.* + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| account | address | undefined | + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | uint256 | undefined | + +### burn + +```solidity +function burn(uint256 amount) external nonpayable +``` + + + +*Destroys `amount` tokens from the caller. See {ERC20-_burn}.* + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| amount | uint256 | undefined | + +### burnFrom + +```solidity +function burnFrom(address account, uint256 amount) external nonpayable +``` + + + +*Destroys `amount` tokens from `account`, deducting from the caller's allowance. See {ERC20-_burn} and {ERC20-allowance}. Requirements: - the caller must have allowance for ``accounts``'s tokens of at least `amount`.* + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| account | address | undefined | +| amount | uint256 | undefined | + +### decimals + +```solidity +function decimals() external view returns (uint8) +``` + + + +*Returns the number of decimals used to get its user representation. For example, if `decimals` equals `2`, a balance of `505` tokens should be displayed to a user as `5,05` (`505 / 10 ** 2`). Tokens usually opt for a value of 18, imitating the relationship between Ether and Wei. This is the value {ERC20} uses, unless {_setupDecimals} is called. NOTE: This information is only used for _display_ purposes: it in no way affects any of the arithmetic of the contract, including {IERC20-balanceOf} and {IERC20-transfer}.* + + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | uint8 | undefined | + +### decreaseAllowance + +```solidity +function decreaseAllowance(address spender, uint256 subtractedValue) external nonpayable returns (bool) +``` + + + +*Atomically decreases the allowance granted to `spender` by the caller. This is an alternative to {approve} that can be used as a mitigation for problems described in {IERC20-approve}. Emits an {Approval} event indicating the updated allowance. Requirements: - `spender` cannot be the zero address. - `spender` must have allowance for the caller of at least `subtractedValue`.* + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| spender | address | undefined | +| subtractedValue | uint256 | undefined | + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | bool | undefined | + +### getRoleAdmin + +```solidity +function getRoleAdmin(bytes32 role) external view returns (bytes32) +``` + + + +*Returns the admin role that controls `role`. See {grantRole} and {revokeRole}. To change a role's admin, use {_setRoleAdmin}.* + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| role | bytes32 | undefined | + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | bytes32 | undefined | + +### getRoleMember + +```solidity +function getRoleMember(bytes32 role, uint256 index) external view returns (address) +``` + + + +*Returns one of the accounts that have `role`. `index` must be a value between 0 and {getRoleMemberCount}, non-inclusive. Role bearers are not sorted in any particular way, and their ordering may change at any point. WARNING: When using {getRoleMember} and {getRoleMemberCount}, make sure you perform all queries on the same block. See the following https://forum.openzeppelin.com/t/iterating-over-elements-on-enumerableset-in-openzeppelin-contracts/2296[forum post] for more information.* + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| role | bytes32 | undefined | +| index | uint256 | undefined | + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | address | undefined | + +### getRoleMemberCount + +```solidity +function getRoleMemberCount(bytes32 role) external view returns (uint256) +``` + + + +*Returns the number of accounts that have `role`. Can be used together with {getRoleMember} to enumerate all bearers of a role.* + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| role | bytes32 | undefined | + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | uint256 | undefined | + +### grantRole + +```solidity +function grantRole(bytes32 role, address account) external nonpayable +``` + + + +*Grants `role` to `account`. If `account` had not been already granted `role`, emits a {RoleGranted} event. Requirements: - the caller must have ``role``'s admin role.* + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| role | bytes32 | undefined | +| account | address | undefined | + +### hasRole + +```solidity +function hasRole(bytes32 role, address account) external view returns (bool) +``` + + + +*Returns `true` if `account` has been granted `role`.* + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| role | bytes32 | undefined | +| account | address | undefined | + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | bool | undefined | + +### increaseAllowance + +```solidity +function increaseAllowance(address spender, uint256 addedValue) external nonpayable returns (bool) +``` + + + +*Atomically increases the allowance granted to `spender` by the caller. This is an alternative to {approve} that can be used as a mitigation for problems described in {IERC20-approve}. Emits an {Approval} event indicating the updated allowance. Requirements: - `spender` cannot be the zero address.* + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| spender | address | undefined | +| addedValue | uint256 | undefined | + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | bool | undefined | + +### initialize + +```solidity +function initialize(string name, string symbol, uint8 decimals, address owner) external nonpayable +``` + +Initializes this ERC20 contract with the given parameters. + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| name | string | Token name | +| symbol | string | Token symbol | +| decimals | uint8 | Token name | +| owner | address | admin address to be initialized with | + +### mint + +```solidity +function mint(address to, uint256 amount) external nonpayable +``` + + + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| to | address | undefined | +| amount | uint256 | undefined | + +### name + +```solidity +function name() external view returns (string) +``` + + + +*Returns the name of the token.* + + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | string | undefined | + +### nonces + +```solidity +function nonces(address owner) external view returns (uint256) +``` + + + +*See {IERC20Permit-nonces}.* + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| owner | address | undefined | + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | uint256 | undefined | + +### permit + +```solidity +function permit(address owner, address spender, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s) external nonpayable +``` + + + +*See {IERC20Permit-permit}.* + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| owner | address | undefined | +| spender | address | undefined | +| value | uint256 | undefined | +| deadline | uint256 | undefined | +| v | uint8 | undefined | +| r | bytes32 | undefined | +| s | bytes32 | undefined | + +### renounceRole + +```solidity +function renounceRole(bytes32 role, address account) external nonpayable +``` + + + +*Revokes `role` from the calling account. Roles are often managed via {grantRole} and {revokeRole}: this function's purpose is to provide a mechanism for accounts to lose their privileges if they are compromised (such as when a trusted device is misplaced). If the calling account had been granted `role`, emits a {RoleRevoked} event. Requirements: - the caller must be `account`.* + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| role | bytes32 | undefined | +| account | address | undefined | + +### revokeRole + +```solidity +function revokeRole(bytes32 role, address account) external nonpayable +``` + + + +*Revokes `role` from `account`. If `account` had been granted `role`, emits a {RoleRevoked} event. Requirements: - the caller must have ``role``'s admin role.* + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| role | bytes32 | undefined | +| account | address | undefined | + +### symbol + +```solidity +function symbol() external view returns (string) +``` + + + +*Returns the symbol of the token, usually a shorter version of the name.* + + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | string | undefined | + +### totalSupply + +```solidity +function totalSupply() external view returns (uint256) +``` + + + +*See {IERC20-totalSupply}.* + + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | uint256 | undefined | + +### transfer + +```solidity +function transfer(address recipient, uint256 amount) external nonpayable returns (bool) +``` + + + +*See {IERC20-transfer}. Requirements: - `recipient` cannot be the zero address. - the caller must have a balance of at least `amount`.* + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| recipient | address | undefined | +| amount | uint256 | undefined | + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | bool | undefined | + +### transferFrom + +```solidity +function transferFrom(address sender, address recipient, uint256 amount) external nonpayable returns (bool) +``` + + + +*See {IERC20-transferFrom}. Emits an {Approval} event indicating the updated allowance. This is not required by the EIP. See the note at the beginning of {ERC20}. Requirements: - `sender` and `recipient` cannot be the zero address. - `sender` must have a balance of at least `amount`. - the caller must have allowance for ``sender``'s tokens of at least `amount`.* + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| sender | address | undefined | +| recipient | address | undefined | +| amount | uint256 | undefined | + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | bool | undefined | + + + +## Events + +### Approval + +```solidity +event Approval(address indexed owner, address indexed spender, uint256 value) +``` + + + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| owner `indexed` | address | undefined | +| spender `indexed` | address | undefined | +| value | uint256 | undefined | + +### RoleAdminChanged + +```solidity +event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole) +``` + + + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| role `indexed` | bytes32 | undefined | +| previousAdminRole `indexed` | bytes32 | undefined | +| newAdminRole `indexed` | bytes32 | undefined | + +### RoleGranted + +```solidity +event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender) +``` + + + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| role `indexed` | bytes32 | undefined | +| account `indexed` | address | undefined | +| sender `indexed` | address | undefined | + +### RoleRevoked + +```solidity +event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender) +``` + + + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| role `indexed` | bytes32 | undefined | +| account `indexed` | address | undefined | +| sender `indexed` | address | undefined | + +### Transfer + +```solidity +event Transfer(address indexed from, address indexed to, uint256 value) +``` + + + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| from `indexed` | address | undefined | +| to `indexed` | address | undefined | +| value | uint256 | undefined | + + + diff --git a/docs/bridge/SynapseERC20Factory.md b/docs/bridge/SynapseERC20Factory.md new file mode 100644 index 000000000..ce8675072 --- /dev/null +++ b/docs/bridge/SynapseERC20Factory.md @@ -0,0 +1,60 @@ +# SynapseERC20Factory + + + + + + + + + +## Methods + +### deploy + +```solidity +function deploy(address synapseERC20Address, string name, string symbol, uint8 decimals, address owner) external nonpayable returns (address) +``` + +Deploys a new node + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| synapseERC20Address | address | address of the synapseERC20Address contract to initialize with | +| name | string | Token name | +| symbol | string | Token symbol | +| decimals | uint8 | Token name | +| owner | address | admin address to be initialized with | + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | address | Address of the newest node management contract created* | + + + +## Events + +### SynapseERC20Created + +```solidity +event SynapseERC20Created(address contractAddress) +``` + + + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| contractAddress | address | undefined | + + + diff --git a/docs/bridge/interfaces/IECDSANodeManagement.md b/docs/bridge/interfaces/IECDSANodeManagement.md new file mode 100644 index 000000000..40881554b --- /dev/null +++ b/docs/bridge/interfaces/IECDSANodeManagement.md @@ -0,0 +1,33 @@ +# IECDSANodeManagement + + + +> IECDSANodeManagement interface + +Interface for the ECDSA node management interface. + +*implement this interface to develop a a factory-patterned ECDSA node management contract** + +## Methods + +### initialize + +```solidity +function initialize(address _owner, address[] _members, uint256 _honestThreshold) external nonpayable +``` + + + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| _owner | address | undefined | +| _members | address[] | undefined | +| _honestThreshold | uint256 | undefined | + + + + diff --git a/docs/bridge/interfaces/IERC20Migrator.md b/docs/bridge/interfaces/IERC20Migrator.md new file mode 100644 index 000000000..f9f4823d7 --- /dev/null +++ b/docs/bridge/interfaces/IERC20Migrator.md @@ -0,0 +1,31 @@ +# IERC20Migrator + + + + + + + + + +## Methods + +### migrate + +```solidity +function migrate(uint256 amount) external nonpayable +``` + + + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| amount | uint256 | undefined | + + + + diff --git a/docs/bridge/interfaces/IMasterChef.md b/docs/bridge/interfaces/IMasterChef.md new file mode 100644 index 000000000..e4729ac41 --- /dev/null +++ b/docs/bridge/interfaces/IMasterChef.md @@ -0,0 +1,71 @@ +# IMasterChef + + + + + + + + + +## Methods + +### deposit + +```solidity +function deposit(uint256 _pid, uint256 _amount) external nonpayable +``` + + + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| _pid | uint256 | undefined | +| _amount | uint256 | undefined | + +### poolInfo + +```solidity +function poolInfo(uint256 pid) external view returns (struct IMasterChef.PoolInfo) +``` + + + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| pid | uint256 | undefined | + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | IMasterChef.PoolInfo | undefined | + +### totalAllocPoint + +```solidity +function totalAllocPoint() external view returns (uint256) +``` + + + + + + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | uint256 | undefined | + + + + diff --git a/docs/bridge/interfaces/IMetaSwapDeposit.md b/docs/bridge/interfaces/IMetaSwapDeposit.md new file mode 100644 index 000000000..e2c7fe126 --- /dev/null +++ b/docs/bridge/interfaces/IMetaSwapDeposit.md @@ -0,0 +1,87 @@ +# IMetaSwapDeposit + + + +> IMetaSwapDeposit interface + +Interface for the meta swap contract. + +*implement this interface to develop a a factory-patterned ECDSA node management contract** + +## Methods + +### calculateSwap + +```solidity +function calculateSwap(uint8 tokenIndexFrom, uint8 tokenIndexTo, uint256 dx) external view returns (uint256) +``` + + + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| tokenIndexFrom | uint8 | undefined | +| tokenIndexTo | uint8 | undefined | +| dx | uint256 | undefined | + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | uint256 | undefined | + +### getToken + +```solidity +function getToken(uint256 index) external view returns (contract IERC20) +``` + + + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| index | uint256 | undefined | + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | contract IERC20 | undefined | + +### swap + +```solidity +function swap(uint8 tokenIndexFrom, uint8 tokenIndexTo, uint256 dx, uint256 minDy, uint256 deadline) external nonpayable returns (uint256) +``` + + + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| tokenIndexFrom | uint8 | undefined | +| tokenIndexTo | uint8 | undefined | +| dx | uint256 | undefined | +| minDy | uint256 | undefined | +| deadline | uint256 | undefined | + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | uint256 | undefined | + + + + diff --git a/docs/bridge/interfaces/IMiniChefV2.md b/docs/bridge/interfaces/IMiniChefV2.md new file mode 100644 index 000000000..5e5649f64 --- /dev/null +++ b/docs/bridge/interfaces/IMiniChefV2.md @@ -0,0 +1,166 @@ +# IMiniChefV2 + + + + + + + + + +## Methods + +### deposit + +```solidity +function deposit(uint256 pid, uint256 amount, address to) external nonpayable +``` + + + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| pid | uint256 | undefined | +| amount | uint256 | undefined | +| to | address | undefined | + +### emergencyWithdraw + +```solidity +function emergencyWithdraw(uint256 pid, address to) external nonpayable +``` + + + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| pid | uint256 | undefined | +| to | address | undefined | + +### harvest + +```solidity +function harvest(uint256 pid, address to) external nonpayable +``` + + + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| pid | uint256 | undefined | +| to | address | undefined | + +### poolLength + +```solidity +function poolLength() external view returns (uint256) +``` + + + + + + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | uint256 | undefined | + +### updatePool + +```solidity +function updatePool(uint256 pid) external nonpayable returns (struct IMiniChefV2.PoolInfo) +``` + + + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| pid | uint256 | undefined | + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | IMiniChefV2.PoolInfo | undefined | + +### userInfo + +```solidity +function userInfo(uint256 _pid, address _user) external view returns (uint256, uint256) +``` + + + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| _pid | uint256 | undefined | +| _user | address | undefined | + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | uint256 | undefined | +| _1 | uint256 | undefined | + +### withdraw + +```solidity +function withdraw(uint256 pid, uint256 amount, address to) external nonpayable +``` + + + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| pid | uint256 | undefined | +| amount | uint256 | undefined | +| to | address | undefined | + +### withdrawAndHarvest + +```solidity +function withdrawAndHarvest(uint256 pid, uint256 amount, address to) external nonpayable +``` + + + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| pid | uint256 | undefined | +| amount | uint256 | undefined | +| to | address | undefined | + + + + diff --git a/docs/bridge/interfaces/IRateLimiter.md b/docs/bridge/interfaces/IRateLimiter.md new file mode 100644 index 000000000..af17d1249 --- /dev/null +++ b/docs/bridge/interfaces/IRateLimiter.md @@ -0,0 +1,55 @@ +# IRateLimiter + + + + + + + + + +## Methods + +### addToRetryQueue + +```solidity +function addToRetryQueue(bytes32 kappa, bytes rateLimited) external nonpayable +``` + + + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| kappa | bytes32 | undefined | +| rateLimited | bytes | undefined | + +### checkAndUpdateAllowance + +```solidity +function checkAndUpdateAllowance(address token, uint256 amount) external nonpayable returns (bool) +``` + + + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| token | address | undefined | +| amount | uint256 | undefined | + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | bool | undefined | + + + + diff --git a/docs/bridge/interfaces/IRewarder.md b/docs/bridge/interfaces/IRewarder.md new file mode 100644 index 000000000..77ae30edf --- /dev/null +++ b/docs/bridge/interfaces/IRewarder.md @@ -0,0 +1,60 @@ +# IRewarder + + + + + + + + + +## Methods + +### onSynapseReward + +```solidity +function onSynapseReward(uint256 pid, address user, address recipient, uint256 synapseAmount, uint256 newLpAmount) external nonpayable +``` + + + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| pid | uint256 | undefined | +| user | address | undefined | +| recipient | address | undefined | +| synapseAmount | uint256 | undefined | +| newLpAmount | uint256 | undefined | + +### pendingTokens + +```solidity +function pendingTokens(uint256 pid, address user, uint256 synapseAmount) external view returns (contract IERC20[], uint256[]) +``` + + + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| pid | uint256 | undefined | +| user | address | undefined | +| synapseAmount | uint256 | undefined | + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | contract IERC20[] | undefined | +| _1 | uint256[] | undefined | + + + + diff --git a/docs/bridge/interfaces/ISwap.md b/docs/bridge/interfaces/ISwap.md new file mode 100644 index 000000000..46ee3b5ae --- /dev/null +++ b/docs/bridge/interfaces/ISwap.md @@ -0,0 +1,353 @@ +# ISwap + + + + + + + + + +## Methods + +### addLiquidity + +```solidity +function addLiquidity(uint256[] amounts, uint256 minToMint, uint256 deadline) external nonpayable returns (uint256) +``` + + + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| amounts | uint256[] | undefined | +| minToMint | uint256 | undefined | +| deadline | uint256 | undefined | + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | uint256 | undefined | + +### calculateRemoveLiquidity + +```solidity +function calculateRemoveLiquidity(uint256 amount) external view returns (uint256[]) +``` + + + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| amount | uint256 | undefined | + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | uint256[] | undefined | + +### calculateRemoveLiquidityOneToken + +```solidity +function calculateRemoveLiquidityOneToken(uint256 tokenAmount, uint8 tokenIndex) external view returns (uint256 availableTokenAmount) +``` + + + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| tokenAmount | uint256 | undefined | +| tokenIndex | uint8 | undefined | + +#### Returns + +| Name | Type | Description | +|---|---|---| +| availableTokenAmount | uint256 | undefined | + +### calculateSwap + +```solidity +function calculateSwap(uint8 tokenIndexFrom, uint8 tokenIndexTo, uint256 dx) external view returns (uint256) +``` + + + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| tokenIndexFrom | uint8 | undefined | +| tokenIndexTo | uint8 | undefined | +| dx | uint256 | undefined | + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | uint256 | undefined | + +### calculateTokenAmount + +```solidity +function calculateTokenAmount(uint256[] amounts, bool deposit) external view returns (uint256) +``` + + + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| amounts | uint256[] | undefined | +| deposit | bool | undefined | + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | uint256 | undefined | + +### getA + +```solidity +function getA() external view returns (uint256) +``` + + + + + + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | uint256 | undefined | + +### getToken + +```solidity +function getToken(uint8 index) external view returns (contract IERC20) +``` + + + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| index | uint8 | undefined | + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | contract IERC20 | undefined | + +### getTokenBalance + +```solidity +function getTokenBalance(uint8 index) external view returns (uint256) +``` + + + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| index | uint8 | undefined | + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | uint256 | undefined | + +### getTokenIndex + +```solidity +function getTokenIndex(address tokenAddress) external view returns (uint8) +``` + + + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| tokenAddress | address | undefined | + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | uint8 | undefined | + +### getVirtualPrice + +```solidity +function getVirtualPrice() external view returns (uint256) +``` + + + + + + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | uint256 | undefined | + +### initialize + +```solidity +function initialize(contract IERC20[] pooledTokens, uint8[] decimals, string lpTokenName, string lpTokenSymbol, uint256 a, uint256 fee, uint256 adminFee, address lpTokenTargetAddress) external nonpayable +``` + + + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| pooledTokens | contract IERC20[] | undefined | +| decimals | uint8[] | undefined | +| lpTokenName | string | undefined | +| lpTokenSymbol | string | undefined | +| a | uint256 | undefined | +| fee | uint256 | undefined | +| adminFee | uint256 | undefined | +| lpTokenTargetAddress | address | undefined | + +### removeLiquidity + +```solidity +function removeLiquidity(uint256 amount, uint256[] minAmounts, uint256 deadline) external nonpayable returns (uint256[]) +``` + + + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| amount | uint256 | undefined | +| minAmounts | uint256[] | undefined | +| deadline | uint256 | undefined | + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | uint256[] | undefined | + +### removeLiquidityImbalance + +```solidity +function removeLiquidityImbalance(uint256[] amounts, uint256 maxBurnAmount, uint256 deadline) external nonpayable returns (uint256) +``` + + + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| amounts | uint256[] | undefined | +| maxBurnAmount | uint256 | undefined | +| deadline | uint256 | undefined | + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | uint256 | undefined | + +### removeLiquidityOneToken + +```solidity +function removeLiquidityOneToken(uint256 tokenAmount, uint8 tokenIndex, uint256 minAmount, uint256 deadline) external nonpayable returns (uint256) +``` + + + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| tokenAmount | uint256 | undefined | +| tokenIndex | uint8 | undefined | +| minAmount | uint256 | undefined | +| deadline | uint256 | undefined | + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | uint256 | undefined | + +### swap + +```solidity +function swap(uint8 tokenIndexFrom, uint8 tokenIndexTo, uint256 dx, uint256 minDy, uint256 deadline) external nonpayable returns (uint256) +``` + + + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| tokenIndexFrom | uint8 | undefined | +| tokenIndexTo | uint8 | undefined | +| dx | uint256 | undefined | +| minDy | uint256 | undefined | +| deadline | uint256 | undefined | + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | uint256 | undefined | + + + + diff --git a/docs/bridge/interfaces/ISynapseBridge.md b/docs/bridge/interfaces/ISynapseBridge.md new file mode 100644 index 000000000..922006dfd --- /dev/null +++ b/docs/bridge/interfaces/ISynapseBridge.md @@ -0,0 +1,140 @@ +# ISynapseBridge + + + + + + + + + +## Methods + +### deposit + +```solidity +function deposit(address to, uint256 chainId, contract IERC20 token, uint256 amount) external nonpayable +``` + + + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| to | address | undefined | +| chainId | uint256 | undefined | +| token | contract IERC20 | undefined | +| amount | uint256 | undefined | + +### depositAndSwap + +```solidity +function depositAndSwap(address to, uint256 chainId, contract IERC20 token, uint256 amount, uint8 tokenIndexFrom, uint8 tokenIndexTo, uint256 minDy, uint256 deadline) external nonpayable +``` + + + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| to | address | undefined | +| chainId | uint256 | undefined | +| token | contract IERC20 | undefined | +| amount | uint256 | undefined | +| tokenIndexFrom | uint8 | undefined | +| tokenIndexTo | uint8 | undefined | +| minDy | uint256 | undefined | +| deadline | uint256 | undefined | + +### redeem + +```solidity +function redeem(address to, uint256 chainId, contract IERC20 token, uint256 amount) external nonpayable +``` + + + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| to | address | undefined | +| chainId | uint256 | undefined | +| token | contract IERC20 | undefined | +| amount | uint256 | undefined | + +### redeemAndRemove + +```solidity +function redeemAndRemove(address to, uint256 chainId, contract IERC20 token, uint256 amount, uint8 liqTokenIndex, uint256 liqMinAmount, uint256 liqDeadline) external nonpayable +``` + + + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| to | address | undefined | +| chainId | uint256 | undefined | +| token | contract IERC20 | undefined | +| amount | uint256 | undefined | +| liqTokenIndex | uint8 | undefined | +| liqMinAmount | uint256 | undefined | +| liqDeadline | uint256 | undefined | + +### redeemAndSwap + +```solidity +function redeemAndSwap(address to, uint256 chainId, contract IERC20 token, uint256 amount, uint8 tokenIndexFrom, uint8 tokenIndexTo, uint256 minDy, uint256 deadline) external nonpayable +``` + + + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| to | address | undefined | +| chainId | uint256 | undefined | +| token | contract IERC20 | undefined | +| amount | uint256 | undefined | +| tokenIndexFrom | uint8 | undefined | +| tokenIndexTo | uint8 | undefined | +| minDy | uint256 | undefined | +| deadline | uint256 | undefined | + +### redeemv2 + +```solidity +function redeemv2(bytes32 to, uint256 chainId, contract IERC20 token, uint256 amount) external nonpayable +``` + + + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| to | bytes32 | undefined | +| chainId | uint256 | undefined | +| token | contract IERC20 | undefined | +| amount | uint256 | undefined | + + + + diff --git a/docs/bridge/interfaces/ISynapseERC20.md b/docs/bridge/interfaces/ISynapseERC20.md new file mode 100644 index 000000000..2d281f8a2 --- /dev/null +++ b/docs/bridge/interfaces/ISynapseERC20.md @@ -0,0 +1,51 @@ +# ISynapseERC20 + + + + + + + + + +## Methods + +### initialize + +```solidity +function initialize(string _name, string _symbol, uint8 _decimals, address owner) external nonpayable +``` + + + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| _name | string | undefined | +| _symbol | string | undefined | +| _decimals | uint8 | undefined | +| owner | address | undefined | + +### mint + +```solidity +function mint(address to, uint256 amount) external nonpayable +``` + + + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| to | address | undefined | +| amount | uint256 | undefined | + + + + diff --git a/docs/bridge/libraries/EnumerableMapUpgradeable.md b/docs/bridge/libraries/EnumerableMapUpgradeable.md new file mode 100644 index 000000000..d0c1593f7 --- /dev/null +++ b/docs/bridge/libraries/EnumerableMapUpgradeable.md @@ -0,0 +1,12 @@ +# EnumerableMapUpgradeable + + + + + + + +*Library for managing an enumerable variant of Solidity's this extends https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v4.6.0-rc.0/contracts/utils/structs/EnumerableMap.sol wth a bytes32 to bytes map* + + + diff --git a/docs/bridge/libraries/SignedSafeMath.md b/docs/bridge/libraries/SignedSafeMath.md new file mode 100644 index 000000000..3a931c0b2 --- /dev/null +++ b/docs/bridge/libraries/SignedSafeMath.md @@ -0,0 +1,12 @@ +# SignedSafeMath + + + + + + + + + + + diff --git a/docs/bridge/mocks/ERC20Mock.md b/docs/bridge/mocks/ERC20Mock.md new file mode 100644 index 000000000..156f0bf2a --- /dev/null +++ b/docs/bridge/mocks/ERC20Mock.md @@ -0,0 +1,300 @@ +# ERC20Mock + + + + + + + + + +## Methods + +### allowance + +```solidity +function allowance(address owner, address spender) external view returns (uint256) +``` + + + +*See {IERC20-allowance}.* + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| owner | address | undefined | +| spender | address | undefined | + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | uint256 | undefined | + +### approve + +```solidity +function approve(address spender, uint256 amount) external nonpayable returns (bool) +``` + + + +*See {IERC20-approve}. Requirements: - `spender` cannot be the zero address.* + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| spender | address | undefined | +| amount | uint256 | undefined | + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | bool | undefined | + +### balanceOf + +```solidity +function balanceOf(address account) external view returns (uint256) +``` + + + +*See {IERC20-balanceOf}.* + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| account | address | undefined | + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | uint256 | undefined | + +### decimals + +```solidity +function decimals() external view returns (uint8) +``` + + + +*Returns the number of decimals used to get its user representation. For example, if `decimals` equals `2`, a balance of `505` tokens should be displayed to a user as `5,05` (`505 / 10 ** 2`). Tokens usually opt for a value of 18, imitating the relationship between Ether and Wei. This is the value {ERC20} uses, unless {_setupDecimals} is called. NOTE: This information is only used for _display_ purposes: it in no way affects any of the arithmetic of the contract, including {IERC20-balanceOf} and {IERC20-transfer}.* + + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | uint8 | undefined | + +### decreaseAllowance + +```solidity +function decreaseAllowance(address spender, uint256 subtractedValue) external nonpayable returns (bool) +``` + + + +*Atomically decreases the allowance granted to `spender` by the caller. This is an alternative to {approve} that can be used as a mitigation for problems described in {IERC20-approve}. Emits an {Approval} event indicating the updated allowance. Requirements: - `spender` cannot be the zero address. - `spender` must have allowance for the caller of at least `subtractedValue`.* + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| spender | address | undefined | +| subtractedValue | uint256 | undefined | + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | bool | undefined | + +### increaseAllowance + +```solidity +function increaseAllowance(address spender, uint256 addedValue) external nonpayable returns (bool) +``` + + + +*Atomically increases the allowance granted to `spender` by the caller. This is an alternative to {approve} that can be used as a mitigation for problems described in {IERC20-approve}. Emits an {Approval} event indicating the updated allowance. Requirements: - `spender` cannot be the zero address.* + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| spender | address | undefined | +| addedValue | uint256 | undefined | + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | bool | undefined | + +### mint + +```solidity +function mint(address to, uint256 amount) external nonpayable +``` + + + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| to | address | undefined | +| amount | uint256 | undefined | + +### name + +```solidity +function name() external view returns (string) +``` + + + +*Returns the name of the token.* + + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | string | undefined | + +### symbol + +```solidity +function symbol() external view returns (string) +``` + + + +*Returns the symbol of the token, usually a shorter version of the name.* + + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | string | undefined | + +### totalSupply + +```solidity +function totalSupply() external view returns (uint256) +``` + + + +*See {IERC20-totalSupply}.* + + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | uint256 | undefined | + +### transfer + +```solidity +function transfer(address recipient, uint256 amount) external nonpayable returns (bool) +``` + + + +*See {IERC20-transfer}. Requirements: - `recipient` cannot be the zero address. - the caller must have a balance of at least `amount`.* + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| recipient | address | undefined | +| amount | uint256 | undefined | + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | bool | undefined | + +### transferFrom + +```solidity +function transferFrom(address sender, address recipient, uint256 amount) external nonpayable returns (bool) +``` + + + +*See {IERC20-transferFrom}. Emits an {Approval} event indicating the updated allowance. This is not required by the EIP. See the note at the beginning of {ERC20}. Requirements: - `sender` and `recipient` cannot be the zero address. - `sender` must have a balance of at least `amount`. - the caller must have allowance for ``sender``'s tokens of at least `amount`.* + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| sender | address | undefined | +| recipient | address | undefined | +| amount | uint256 | undefined | + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | bool | undefined | + + + +## Events + +### Approval + +```solidity +event Approval(address indexed owner, address indexed spender, uint256 value) +``` + + + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| owner `indexed` | address | undefined | +| spender `indexed` | address | undefined | +| value | uint256 | undefined | + +### Transfer + +```solidity +event Transfer(address indexed from, address indexed to, uint256 value) +``` + + + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| from `indexed` | address | undefined | +| to `indexed` | address | undefined | +| value | uint256 | undefined | + + + diff --git a/docs/bridge/mocks/RewarderBrokenMock.md b/docs/bridge/mocks/RewarderBrokenMock.md new file mode 100644 index 000000000..705bd80a8 --- /dev/null +++ b/docs/bridge/mocks/RewarderBrokenMock.md @@ -0,0 +1,60 @@ +# RewarderBrokenMock + + + + + + + + + +## Methods + +### onSynapseReward + +```solidity +function onSynapseReward(uint256, address, address, uint256, uint256) external nonpayable +``` + + + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| _0 | uint256 | undefined | +| _1 | address | undefined | +| _2 | address | undefined | +| _3 | uint256 | undefined | +| _4 | uint256 | undefined | + +### pendingTokens + +```solidity +function pendingTokens(uint256 pid, address user, uint256 synapseAmount) external view returns (contract IERC20[] rewardTokens, uint256[] rewardAmounts) +``` + + + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| pid | uint256 | undefined | +| user | address | undefined | +| synapseAmount | uint256 | undefined | + +#### Returns + +| Name | Type | Description | +|---|---|---| +| rewardTokens | contract IERC20[] | undefined | +| rewardAmounts | uint256[] | undefined | + + + + diff --git a/docs/bridge/mocks/RewarderMock.md b/docs/bridge/mocks/RewarderMock.md new file mode 100644 index 000000000..e546bc483 --- /dev/null +++ b/docs/bridge/mocks/RewarderMock.md @@ -0,0 +1,60 @@ +# RewarderMock + + + + + + + + + +## Methods + +### onSynapseReward + +```solidity +function onSynapseReward(uint256, address user, address to, uint256 synapseAmount, uint256) external nonpayable +``` + + + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| _0 | uint256 | undefined | +| user | address | undefined | +| to | address | undefined | +| synapseAmount | uint256 | undefined | +| _4 | uint256 | undefined | + +### pendingTokens + +```solidity +function pendingTokens(uint256 pid, address user, uint256 synapseAmount) external view returns (contract IERC20[] rewardTokens, uint256[] rewardAmounts) +``` + + + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| pid | uint256 | undefined | +| user | address | undefined | +| synapseAmount | uint256 | undefined | + +#### Returns + +| Name | Type | Description | +|---|---|---| +| rewardTokens | contract IERC20[] | undefined | +| rewardAmounts | uint256[] | undefined | + + + + diff --git a/docs/bridge/testing/NodeEnv.md b/docs/bridge/testing/NodeEnv.md new file mode 100644 index 000000000..042d330bb --- /dev/null +++ b/docs/bridge/testing/NodeEnv.md @@ -0,0 +1,348 @@ +# NodeEnv + +*Synapse Authors* + +> NodeEnv contract + +This contract implements a key-value store for storing variables on which synapse nodes must coordinate methods are purposely arbitrary to allow these fields to be defined in synapse improvement proposals.This token is used for configuring different tokens on the bridge and mapping them across chains.* + + + +## Methods + +### BRIDGEMANAGER_ROLE + +```solidity +function BRIDGEMANAGER_ROLE() external view returns (bytes32) +``` + + + + + + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | bytes32 | undefined | + +### DEFAULT_ADMIN_ROLE + +```solidity +function DEFAULT_ADMIN_ROLE() external view returns (bytes32) +``` + + + + + + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | bytes32 | undefined | + +### get + +```solidity +function get(string _key) external view returns (string) +``` + +gets the value associated with the key + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| _key | string | undefined | + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | string | undefined | + +### getRoleAdmin + +```solidity +function getRoleAdmin(bytes32 role) external view returns (bytes32) +``` + + + +*Returns the admin role that controls `role`. See {grantRole} and {revokeRole}. To change a role's admin, use {_setRoleAdmin}.* + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| role | bytes32 | undefined | + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | bytes32 | undefined | + +### getRoleMember + +```solidity +function getRoleMember(bytes32 role, uint256 index) external view returns (address) +``` + + + +*Returns one of the accounts that have `role`. `index` must be a value between 0 and {getRoleMemberCount}, non-inclusive. Role bearers are not sorted in any particular way, and their ordering may change at any point. WARNING: When using {getRoleMember} and {getRoleMemberCount}, make sure you perform all queries on the same block. See the following https://forum.openzeppelin.com/t/iterating-over-elements-on-enumerableset-in-openzeppelin-contracts/2296[forum post] for more information.* + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| role | bytes32 | undefined | +| index | uint256 | undefined | + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | address | undefined | + +### getRoleMemberCount + +```solidity +function getRoleMemberCount(bytes32 role) external view returns (uint256) +``` + + + +*Returns the number of accounts that have `role`. Can be used together with {getRoleMember} to enumerate all bearers of a role.* + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| role | bytes32 | undefined | + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | uint256 | undefined | + +### grantRole + +```solidity +function grantRole(bytes32 role, address account) external nonpayable +``` + + + +*Grants `role` to `account`. If `account` had not been already granted `role`, emits a {RoleGranted} event. Requirements: - the caller must have ``role``'s admin role.* + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| role | bytes32 | undefined | +| account | address | undefined | + +### hasRole + +```solidity +function hasRole(bytes32 role, address account) external view returns (bool) +``` + + + +*Returns `true` if `account` has been granted `role`.* + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| role | bytes32 | undefined | +| account | address | undefined | + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | bool | undefined | + +### keyCount + +```solidity +function keyCount() external view returns (uint256) +``` + +get the length of the config + +*this is useful for enumerating through all keys in the env* + + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | uint256 | undefined | + +### keyValueByIndex + +```solidity +function keyValueByIndex(uint256 index) external view returns (string, string) +``` + +gets the key/value pair by it's index Requirements: - `index` must be strictly less than {length}. + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| index | uint256 | undefined | + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | string | undefined | +| _1 | string | undefined | + +### renounceRole + +```solidity +function renounceRole(bytes32 role, address account) external nonpayable +``` + + + +*Revokes `role` from the calling account. Roles are often managed via {grantRole} and {revokeRole}: this function's purpose is to provide a mechanism for accounts to lose their privileges if they are compromised (such as when a trusted device is misplaced). If the calling account had been granted `role`, emits a {RoleRevoked} event. Requirements: - the caller must be `account`.* + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| role | bytes32 | undefined | +| account | address | undefined | + +### revokeRole + +```solidity +function revokeRole(bytes32 role, address account) external nonpayable +``` + + + +*Revokes `role` from `account`. If `account` had been granted `role`, emits a {RoleRevoked} event. Requirements: - the caller must have ``role``'s admin role.* + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| role | bytes32 | undefined | +| account | address | undefined | + +### set + +```solidity +function set(string _key, string _value) external nonpayable returns (bool) +``` + +sets the key + +*caller must have bridge manager role* + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| _key | string | undefined | +| _value | string | undefined | + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | bool | undefined | + + + +## Events + +### ConfigUpdate + +```solidity +event ConfigUpdate(string key) +``` + + + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| key | string | undefined | + +### RoleAdminChanged + +```solidity +event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole) +``` + + + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| role `indexed` | bytes32 | undefined | +| previousAdminRole `indexed` | bytes32 | undefined | +| newAdminRole `indexed` | bytes32 | undefined | + +### RoleGranted + +```solidity +event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender) +``` + + + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| role `indexed` | bytes32 | undefined | +| account `indexed` | address | undefined | +| sender `indexed` | address | undefined | + +### RoleRevoked + +```solidity +event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender) +``` + + + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| role `indexed` | bytes32 | undefined | +| account `indexed` | address | undefined | +| sender `indexed` | address | undefined | + + + diff --git a/docs/bridge/testing/RateLimiterTest.md b/docs/bridge/testing/RateLimiterTest.md new file mode 100644 index 000000000..f8962ded2 --- /dev/null +++ b/docs/bridge/testing/RateLimiterTest.md @@ -0,0 +1,83 @@ +# RateLimiterTest + + + +> RateLimiterTest + + + + + +## Methods + +### NAME + +```solidity +function NAME() external view returns (string) +``` + + + + + + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | string | undefined | + +### VERSION + +```solidity +function VERSION() external view returns (string) +``` + + + + + + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | string | undefined | + +### getLastUpdateValue + +```solidity +function getLastUpdateValue() external view returns (bool) +``` + + + + + + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | bool | undefined | + +### storeCheckAndUpdateAllowance + +```solidity +function storeCheckAndUpdateAllowance(address token, uint256 amount) external nonpayable +``` + + + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| token | address | undefined | +| amount | uint256 | undefined | + + + + diff --git a/docs/bridge/testing/Synapse.md b/docs/bridge/testing/Synapse.md new file mode 100644 index 000000000..07af17788 --- /dev/null +++ b/docs/bridge/testing/Synapse.md @@ -0,0 +1,623 @@ +# Synapse + + + + + + + + + +## Methods + +### DEFAULT_ADMIN_ROLE + +```solidity +function DEFAULT_ADMIN_ROLE() external view returns (bytes32) +``` + + + + + + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | bytes32 | undefined | + +### DOMAIN_SEPARATOR + +```solidity +function DOMAIN_SEPARATOR() external view returns (bytes32) +``` + + + +*See {IERC20Permit-DOMAIN_SEPARATOR}.* + + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | bytes32 | undefined | + +### MINTER_ROLE + +```solidity +function MINTER_ROLE() external view returns (bytes32) +``` + + + + + + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | bytes32 | undefined | + +### allowance + +```solidity +function allowance(address owner, address spender) external view returns (uint256) +``` + + + +*See {IERC20-allowance}.* + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| owner | address | undefined | +| spender | address | undefined | + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | uint256 | undefined | + +### approve + +```solidity +function approve(address spender, uint256 amount) external nonpayable returns (bool) +``` + + + +*See {IERC20-approve}. Requirements: - `spender` cannot be the zero address.* + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| spender | address | undefined | +| amount | uint256 | undefined | + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | bool | undefined | + +### balanceOf + +```solidity +function balanceOf(address account) external view returns (uint256) +``` + + + +*See {IERC20-balanceOf}.* + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| account | address | undefined | + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | uint256 | undefined | + +### burn + +```solidity +function burn(uint256 amount) external nonpayable +``` + + + +*Destroys `amount` tokens from the caller. See {ERC20-_burn}.* + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| amount | uint256 | undefined | + +### burnFrom + +```solidity +function burnFrom(address account, uint256 amount) external nonpayable +``` + + + +*Destroys `amount` tokens from `account`, deducting from the caller's allowance. See {ERC20-_burn} and {ERC20-allowance}. Requirements: - the caller must have allowance for ``accounts``'s tokens of at least `amount`.* + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| account | address | undefined | +| amount | uint256 | undefined | + +### decimals + +```solidity +function decimals() external view returns (uint8) +``` + + + +*Returns the number of decimals used to get its user representation. For example, if `decimals` equals `2`, a balance of `505` tokens should be displayed to a user as `5,05` (`505 / 10 ** 2`). Tokens usually opt for a value of 18, imitating the relationship between Ether and Wei. This is the value {ERC20} uses, unless {_setupDecimals} is called. NOTE: This information is only used for _display_ purposes: it in no way affects any of the arithmetic of the contract, including {IERC20-balanceOf} and {IERC20-transfer}.* + + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | uint8 | undefined | + +### decreaseAllowance + +```solidity +function decreaseAllowance(address spender, uint256 subtractedValue) external nonpayable returns (bool) +``` + + + +*Atomically decreases the allowance granted to `spender` by the caller. This is an alternative to {approve} that can be used as a mitigation for problems described in {IERC20-approve}. Emits an {Approval} event indicating the updated allowance. Requirements: - `spender` cannot be the zero address. - `spender` must have allowance for the caller of at least `subtractedValue`.* + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| spender | address | undefined | +| subtractedValue | uint256 | undefined | + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | bool | undefined | + +### getRoleAdmin + +```solidity +function getRoleAdmin(bytes32 role) external view returns (bytes32) +``` + + + +*Returns the admin role that controls `role`. See {grantRole} and {revokeRole}. To change a role's admin, use {_setRoleAdmin}.* + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| role | bytes32 | undefined | + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | bytes32 | undefined | + +### getRoleMember + +```solidity +function getRoleMember(bytes32 role, uint256 index) external view returns (address) +``` + + + +*Returns one of the accounts that have `role`. `index` must be a value between 0 and {getRoleMemberCount}, non-inclusive. Role bearers are not sorted in any particular way, and their ordering may change at any point. WARNING: When using {getRoleMember} and {getRoleMemberCount}, make sure you perform all queries on the same block. See the following https://forum.openzeppelin.com/t/iterating-over-elements-on-enumerableset-in-openzeppelin-contracts/2296[forum post] for more information.* + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| role | bytes32 | undefined | +| index | uint256 | undefined | + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | address | undefined | + +### getRoleMemberCount + +```solidity +function getRoleMemberCount(bytes32 role) external view returns (uint256) +``` + + + +*Returns the number of accounts that have `role`. Can be used together with {getRoleMember} to enumerate all bearers of a role.* + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| role | bytes32 | undefined | + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | uint256 | undefined | + +### grantRole + +```solidity +function grantRole(bytes32 role, address account) external nonpayable +``` + + + +*Grants `role` to `account`. If `account` had not been already granted `role`, emits a {RoleGranted} event. Requirements: - the caller must have ``role``'s admin role.* + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| role | bytes32 | undefined | +| account | address | undefined | + +### hasRole + +```solidity +function hasRole(bytes32 role, address account) external view returns (bool) +``` + + + +*Returns `true` if `account` has been granted `role`.* + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| role | bytes32 | undefined | +| account | address | undefined | + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | bool | undefined | + +### increaseAllowance + +```solidity +function increaseAllowance(address spender, uint256 addedValue) external nonpayable returns (bool) +``` + + + +*Atomically increases the allowance granted to `spender` by the caller. This is an alternative to {approve} that can be used as a mitigation for problems described in {IERC20-approve}. Emits an {Approval} event indicating the updated allowance. Requirements: - `spender` cannot be the zero address.* + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| spender | address | undefined | +| addedValue | uint256 | undefined | + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | bool | undefined | + +### mint + +```solidity +function mint(address to, uint256 amount) external nonpayable +``` + + + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| to | address | undefined | +| amount | uint256 | undefined | + +### name + +```solidity +function name() external view returns (string) +``` + + + +*Returns the name of the token.* + + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | string | undefined | + +### nonces + +```solidity +function nonces(address owner) external view returns (uint256) +``` + + + +*See {IERC20Permit-nonces}.* + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| owner | address | undefined | + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | uint256 | undefined | + +### permit + +```solidity +function permit(address owner, address spender, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s) external nonpayable +``` + + + +*See {IERC20Permit-permit}.* + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| owner | address | undefined | +| spender | address | undefined | +| value | uint256 | undefined | +| deadline | uint256 | undefined | +| v | uint8 | undefined | +| r | bytes32 | undefined | +| s | bytes32 | undefined | + +### renounceRole + +```solidity +function renounceRole(bytes32 role, address account) external nonpayable +``` + + + +*Revokes `role` from the calling account. Roles are often managed via {grantRole} and {revokeRole}: this function's purpose is to provide a mechanism for accounts to lose their privileges if they are compromised (such as when a trusted device is misplaced). If the calling account had been granted `role`, emits a {RoleRevoked} event. Requirements: - the caller must be `account`.* + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| role | bytes32 | undefined | +| account | address | undefined | + +### revokeRole + +```solidity +function revokeRole(bytes32 role, address account) external nonpayable +``` + + + +*Revokes `role` from `account`. If `account` had been granted `role`, emits a {RoleRevoked} event. Requirements: - the caller must have ``role``'s admin role.* + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| role | bytes32 | undefined | +| account | address | undefined | + +### symbol + +```solidity +function symbol() external view returns (string) +``` + + + +*Returns the symbol of the token, usually a shorter version of the name.* + + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | string | undefined | + +### totalSupply + +```solidity +function totalSupply() external view returns (uint256) +``` + + + +*See {IERC20-totalSupply}.* + + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | uint256 | undefined | + +### transfer + +```solidity +function transfer(address recipient, uint256 amount) external nonpayable returns (bool) +``` + + + +*See {IERC20-transfer}. Requirements: - `recipient` cannot be the zero address. - the caller must have a balance of at least `amount`.* + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| recipient | address | undefined | +| amount | uint256 | undefined | + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | bool | undefined | + +### transferFrom + +```solidity +function transferFrom(address sender, address recipient, uint256 amount) external nonpayable returns (bool) +``` + + + +*See {IERC20-transferFrom}. Emits an {Approval} event indicating the updated allowance. This is not required by the EIP. See the note at the beginning of {ERC20}. Requirements: - `sender` and `recipient` cannot be the zero address. - `sender` must have a balance of at least `amount`. - the caller must have allowance for ``sender``'s tokens of at least `amount`.* + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| sender | address | undefined | +| recipient | address | undefined | +| amount | uint256 | undefined | + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | bool | undefined | + + + +## Events + +### Approval + +```solidity +event Approval(address indexed owner, address indexed spender, uint256 value) +``` + + + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| owner `indexed` | address | undefined | +| spender `indexed` | address | undefined | +| value | uint256 | undefined | + +### RoleAdminChanged + +```solidity +event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole) +``` + + + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| role `indexed` | bytes32 | undefined | +| previousAdminRole `indexed` | bytes32 | undefined | +| newAdminRole `indexed` | bytes32 | undefined | + +### RoleGranted + +```solidity +event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender) +``` + + + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| role `indexed` | bytes32 | undefined | +| account `indexed` | address | undefined | +| sender `indexed` | address | undefined | + +### RoleRevoked + +```solidity +event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender) +``` + + + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| role `indexed` | bytes32 | undefined | +| account `indexed` | address | undefined | +| sender `indexed` | address | undefined | + +### Transfer + +```solidity +event Transfer(address indexed from, address indexed to, uint256 value) +``` + + + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| from `indexed` | address | undefined | +| to `indexed` | address | undefined | +| value | uint256 | undefined | + + + diff --git a/docs/bridge/utils/AddressArrayUtils.md b/docs/bridge/utils/AddressArrayUtils.md new file mode 100644 index 000000000..f8d882857 --- /dev/null +++ b/docs/bridge/utils/AddressArrayUtils.md @@ -0,0 +1,12 @@ +# AddressArrayUtils + + + + + + + + + + + diff --git a/docs/bridge/utils/EnumerableStringMap.md b/docs/bridge/utils/EnumerableStringMap.md new file mode 100644 index 000000000..66491eb26 --- /dev/null +++ b/docs/bridge/utils/EnumerableStringMap.md @@ -0,0 +1,12 @@ +# EnumerableStringMap + + + +> EnumerableStringMap + + + +*Library for managing an enumerable variant of Solidity's https://solidity.readthedocs.io/en/latest/types.html#mapping-types[`mapping`] type. Maps have the following properties: - Entries are added, removed, and checked for existence in constant time (O(1)). - Entries are enumerated in O(n). No guarantees are made on the ordering. this isn't a terribly gas efficient implementation because it emphasizes usability over gas efficiency by allowing arbitrary length string memorys. If Gettetrs/Setters are going to be used frequently in contracts consider using the OpenZeppeling Bytes32 implementation this also differs from the OpenZeppelin implementation by keccac256 hashing the string memorys so we can use enumerable bytes32 set* + + + diff --git a/docs/bridge/utils/TimelockController.md b/docs/bridge/utils/TimelockController.md new file mode 100644 index 000000000..b2e30ea4d --- /dev/null +++ b/docs/bridge/utils/TimelockController.md @@ -0,0 +1,626 @@ +# TimelockController + + + + + + + +*Contract module which acts as a timelocked controller. When set as the owner of an `Ownable` smart contract, it enforces a timelock on all `onlyOwner` maintenance operations. This gives time for users of the controlled contract to exit before a potentially dangerous maintenance operation is applied. By default, this contract is self administered, meaning administration tasks have to go through the timelock process. The proposer (resp executor) role is in charge of proposing (resp executing) operations. A common use case is to position this {TimelockController} as the owner of a smart contract, with a multisig or a DAO as the sole proposer. _Available since v3.3._* + +## Methods + +### DEFAULT_ADMIN_ROLE + +```solidity +function DEFAULT_ADMIN_ROLE() external view returns (bytes32) +``` + + + + + + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | bytes32 | undefined | + +### EXECUTOR_ROLE + +```solidity +function EXECUTOR_ROLE() external view returns (bytes32) +``` + + + + + + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | bytes32 | undefined | + +### PROPOSER_ROLE + +```solidity +function PROPOSER_ROLE() external view returns (bytes32) +``` + + + + + + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | bytes32 | undefined | + +### TIMELOCK_ADMIN_ROLE + +```solidity +function TIMELOCK_ADMIN_ROLE() external view returns (bytes32) +``` + + + + + + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | bytes32 | undefined | + +### cancel + +```solidity +function cancel(bytes32 id) external nonpayable +``` + + + +*Cancel an operation. Requirements: - the caller must have the 'proposer' role.* + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| id | bytes32 | undefined | + +### execute + +```solidity +function execute(address target, uint256 value, bytes data, bytes32 predecessor, bytes32 salt) external payable +``` + + + +*Execute an (ready) operation containing a single transaction. Emits a {CallExecuted} event. Requirements: - the caller must have the 'executor' role.* + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| target | address | undefined | +| value | uint256 | undefined | +| data | bytes | undefined | +| predecessor | bytes32 | undefined | +| salt | bytes32 | undefined | + +### executeBatch + +```solidity +function executeBatch(address[] targets, uint256[] values, bytes[] datas, bytes32 predecessor, bytes32 salt) external payable +``` + + + +*Execute an (ready) operation containing a batch of transactions. Emits one {CallExecuted} event per transaction in the batch. Requirements: - the caller must have the 'executor' role.* + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| targets | address[] | undefined | +| values | uint256[] | undefined | +| datas | bytes[] | undefined | +| predecessor | bytes32 | undefined | +| salt | bytes32 | undefined | + +### getMinDelay + +```solidity +function getMinDelay() external view returns (uint256 duration) +``` + + + +*Returns the minimum delay for an operation to become valid. This value can be changed by executing an operation that calls `updateDelay`.* + + +#### Returns + +| Name | Type | Description | +|---|---|---| +| duration | uint256 | undefined | + +### getRoleAdmin + +```solidity +function getRoleAdmin(bytes32 role) external view returns (bytes32) +``` + + + +*Returns the admin role that controls `role`. See {grantRole} and {revokeRole}. To change a role's admin, use {_setRoleAdmin}.* + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| role | bytes32 | undefined | + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | bytes32 | undefined | + +### getTimestamp + +```solidity +function getTimestamp(bytes32 id) external view returns (uint256 timestamp) +``` + + + +*Returns the timestamp at with an operation becomes ready (0 for unset operations, 1 for done operations).* + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| id | bytes32 | undefined | + +#### Returns + +| Name | Type | Description | +|---|---|---| +| timestamp | uint256 | undefined | + +### grantRole + +```solidity +function grantRole(bytes32 role, address account) external nonpayable +``` + + + +*Grants `role` to `account`. If `account` had not been already granted `role`, emits a {RoleGranted} event. Requirements: - the caller must have ``role``'s admin role.* + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| role | bytes32 | undefined | +| account | address | undefined | + +### hasRole + +```solidity +function hasRole(bytes32 role, address account) external view returns (bool) +``` + + + +*Returns `true` if `account` has been granted `role`.* + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| role | bytes32 | undefined | +| account | address | undefined | + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | bool | undefined | + +### hashOperation + +```solidity +function hashOperation(address target, uint256 value, bytes data, bytes32 predecessor, bytes32 salt) external pure returns (bytes32 hash) +``` + + + +*Returns the identifier of an operation containing a single transaction.* + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| target | address | undefined | +| value | uint256 | undefined | +| data | bytes | undefined | +| predecessor | bytes32 | undefined | +| salt | bytes32 | undefined | + +#### Returns + +| Name | Type | Description | +|---|---|---| +| hash | bytes32 | undefined | + +### hashOperationBatch + +```solidity +function hashOperationBatch(address[] targets, uint256[] values, bytes[] datas, bytes32 predecessor, bytes32 salt) external pure returns (bytes32 hash) +``` + + + +*Returns the identifier of an operation containing a batch of transactions.* + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| targets | address[] | undefined | +| values | uint256[] | undefined | +| datas | bytes[] | undefined | +| predecessor | bytes32 | undefined | +| salt | bytes32 | undefined | + +#### Returns + +| Name | Type | Description | +|---|---|---| +| hash | bytes32 | undefined | + +### isOperation + +```solidity +function isOperation(bytes32 id) external view returns (bool pending) +``` + + + +*Returns whether an id correspond to a registered operation. This includes both Pending, Ready and Done operations.* + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| id | bytes32 | undefined | + +#### Returns + +| Name | Type | Description | +|---|---|---| +| pending | bool | undefined | + +### isOperationDone + +```solidity +function isOperationDone(bytes32 id) external view returns (bool done) +``` + + + +*Returns whether an operation is done or not.* + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| id | bytes32 | undefined | + +#### Returns + +| Name | Type | Description | +|---|---|---| +| done | bool | undefined | + +### isOperationPending + +```solidity +function isOperationPending(bytes32 id) external view returns (bool pending) +``` + + + +*Returns whether an operation is pending or not.* + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| id | bytes32 | undefined | + +#### Returns + +| Name | Type | Description | +|---|---|---| +| pending | bool | undefined | + +### isOperationReady + +```solidity +function isOperationReady(bytes32 id) external view returns (bool ready) +``` + + + +*Returns whether an operation is ready or not.* + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| id | bytes32 | undefined | + +#### Returns + +| Name | Type | Description | +|---|---|---| +| ready | bool | undefined | + +### renounceRole + +```solidity +function renounceRole(bytes32 role, address account) external nonpayable +``` + + + +*Revokes `role` from the calling account. Roles are often managed via {grantRole} and {revokeRole}: this function's purpose is to provide a mechanism for accounts to lose their privileges if they are compromised (such as when a trusted device is misplaced). If the calling account had been revoked `role`, emits a {RoleRevoked} event. Requirements: - the caller must be `account`.* + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| role | bytes32 | undefined | +| account | address | undefined | + +### revokeRole + +```solidity +function revokeRole(bytes32 role, address account) external nonpayable +``` + + + +*Revokes `role` from `account`. If `account` had been granted `role`, emits a {RoleRevoked} event. Requirements: - the caller must have ``role``'s admin role.* + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| role | bytes32 | undefined | +| account | address | undefined | + +### schedule + +```solidity +function schedule(address target, uint256 value, bytes data, bytes32 predecessor, bytes32 salt, uint256 delay) external nonpayable +``` + + + +*Schedule an operation containing a single transaction. Emits a {CallScheduled} event. Requirements: - the caller must have the 'proposer' role.* + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| target | address | undefined | +| value | uint256 | undefined | +| data | bytes | undefined | +| predecessor | bytes32 | undefined | +| salt | bytes32 | undefined | +| delay | uint256 | undefined | + +### scheduleBatch + +```solidity +function scheduleBatch(address[] targets, uint256[] values, bytes[] datas, bytes32 predecessor, bytes32 salt, uint256 delay) external nonpayable +``` + + + +*Schedule an operation containing a batch of transactions. Emits one {CallScheduled} event per transaction in the batch. Requirements: - the caller must have the 'proposer' role.* + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| targets | address[] | undefined | +| values | uint256[] | undefined | +| datas | bytes[] | undefined | +| predecessor | bytes32 | undefined | +| salt | bytes32 | undefined | +| delay | uint256 | undefined | + +### supportsInterface + +```solidity +function supportsInterface(bytes4 interfaceId) external view returns (bool) +``` + + + +*See {IERC165-supportsInterface}.* + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| interfaceId | bytes4 | undefined | + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | bool | undefined | + +### updateDelay + +```solidity +function updateDelay(uint256 newDelay) external nonpayable +``` + + + +*Changes the minimum timelock duration for future operations. Emits a {MinDelayChange} event. Requirements: - the caller must be the timelock itself. This can only be achieved by scheduling and later executing an operation where the timelock is the target and the data is the ABI-encoded call to this function.* + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| newDelay | uint256 | undefined | + + + +## Events + +### CallExecuted + +```solidity +event CallExecuted(bytes32 indexed id, uint256 indexed index, address target, uint256 value, bytes data) +``` + + + +*Emitted when a call is performed as part of operation `id`.* + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| id `indexed` | bytes32 | undefined | +| index `indexed` | uint256 | undefined | +| target | address | undefined | +| value | uint256 | undefined | +| data | bytes | undefined | + +### CallScheduled + +```solidity +event CallScheduled(bytes32 indexed id, uint256 indexed index, address target, uint256 value, bytes data, bytes32 predecessor, uint256 delay) +``` + + + +*Emitted when a call is scheduled as part of operation `id`.* + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| id `indexed` | bytes32 | undefined | +| index `indexed` | uint256 | undefined | +| target | address | undefined | +| value | uint256 | undefined | +| data | bytes | undefined | +| predecessor | bytes32 | undefined | +| delay | uint256 | undefined | + +### Cancelled + +```solidity +event Cancelled(bytes32 indexed id) +``` + + + +*Emitted when operation `id` is cancelled.* + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| id `indexed` | bytes32 | undefined | + +### MinDelayChange + +```solidity +event MinDelayChange(uint256 oldDuration, uint256 newDuration) +``` + + + +*Emitted when the minimum delay for future operations is modified.* + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| oldDuration | uint256 | undefined | +| newDuration | uint256 | undefined | + +### RoleAdminChanged + +```solidity +event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole) +``` + + + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| role `indexed` | bytes32 | undefined | +| previousAdminRole `indexed` | bytes32 | undefined | +| newAdminRole `indexed` | bytes32 | undefined | + +### RoleGranted + +```solidity +event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender) +``` + + + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| role `indexed` | bytes32 | undefined | +| account `indexed` | address | undefined | +| sender `indexed` | address | undefined | + +### RoleRevoked + +```solidity +event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender) +``` + + + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| role `indexed` | bytes32 | undefined | +| account `indexed` | address | undefined | +| sender `indexed` | address | undefined | + + + diff --git a/docs/bridge/wrappers/GMXWrapper.md b/docs/bridge/wrappers/GMXWrapper.md new file mode 100644 index 000000000..7fb1f6a1a --- /dev/null +++ b/docs/bridge/wrappers/GMXWrapper.md @@ -0,0 +1,106 @@ +# GMXWrapper + + + + + + + + + +## Methods + +### bridge + +```solidity +function bridge() external view returns (address) +``` + + + + + + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | address | undefined | + +### burnFrom + +```solidity +function burnFrom(address _addr, uint256 _amount) external nonpayable +``` + + + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| _addr | address | undefined | +| _amount | uint256 | undefined | + +### gmx + +```solidity +function gmx() external view returns (address) +``` + + + + + + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | address | undefined | + +### mint + +```solidity +function mint(address _addr, uint256 _amount) external nonpayable +``` + + + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| _addr | address | undefined | +| _amount | uint256 | undefined | + +### transfer + +```solidity +function transfer(address _recipient, uint256 _amount) external nonpayable returns (bool) +``` + + + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| _recipient | address | undefined | +| _amount | uint256 | undefined | + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | bool | undefined | + + + + diff --git a/docs/bridge/wrappers/HarmonyBridgeZap.md b/docs/bridge/wrappers/HarmonyBridgeZap.md new file mode 100644 index 000000000..bc8aa3f4d --- /dev/null +++ b/docs/bridge/wrappers/HarmonyBridgeZap.md @@ -0,0 +1,303 @@ +# HarmonyBridgeZap + + + + + + + + + +## Methods + +### WETH_ADDRESS + +```solidity +function WETH_ADDRESS() external view returns (address payable) +``` + + + + + + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | address payable | undefined | + +### calculateSwap + +```solidity +function calculateSwap(contract IERC20 token, uint8 tokenIndexFrom, uint8 tokenIndexTo, uint256 dx) external view returns (uint256) +``` + +Calculate amount of tokens you receive on swap + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| token | contract IERC20 | undefined | +| tokenIndexFrom | uint8 | the token the user wants to sell | +| tokenIndexTo | uint8 | the token the user wants to buy | +| dx | uint256 | the amount of tokens the user wants to sell. If the token charges a fee on transfers, use the amount that gets transferred after the fee. | + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | uint256 | amount of tokens the user will receive | + +### deposit + +```solidity +function deposit(address to, uint256 chainId, contract IERC20 token, uint256 amount) external nonpayable +``` + +wraps SynapseBridge redeem() + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| to | address | address on other chain to redeem underlying assets to | +| chainId | uint256 | which underlying chain to bridge assets onto | +| token | contract IERC20 | ERC20 compatible token to deposit into the bridge | +| amount | uint256 | Amount in native token decimals to transfer cross-chain pre-fees* | + +### redeem + +```solidity +function redeem(address to, uint256 chainId, contract IERC20 token, uint256 amount) external nonpayable +``` + +wraps SynapseBridge redeem() + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| to | address | address on other chain to redeem underlying assets to | +| chainId | uint256 | which underlying chain to bridge assets onto | +| token | contract IERC20 | ERC20 compatible token to deposit into the bridge | +| amount | uint256 | Amount in native token decimals to transfer cross-chain pre-fees* | + +### redeemAndRemove + +```solidity +function redeemAndRemove(address to, uint256 chainId, contract IERC20 token, uint256 amount, uint8 liqTokenIndex, uint256 liqMinAmount, uint256 liqDeadline) external nonpayable +``` + +Wraps redeemAndRemove on SynapseBridge Relays to nodes that (typically) a wrapped synAsset ERC20 token has been burned and the underlying needs to be redeeemed on the native chain. This function indicates to the nodes that they should attempt to redeem the LP token for the underlying assets (E.g "swap" out of the LP token) + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| to | address | address on other chain to redeem underlying assets to | +| chainId | uint256 | which underlying chain to bridge assets onto | +| token | contract IERC20 | ERC20 compatible token to deposit into the bridge | +| amount | uint256 | Amount of (typically) LP token to pass to the nodes to attempt to removeLiquidity() with to redeem for the underlying assets of the LP token | +| liqTokenIndex | uint8 | Specifies which of the underlying LP assets the nodes should attempt to redeem for | +| liqMinAmount | uint256 | Specifies the minimum amount of the underlying asset needed for the nodes to execute the redeem/swap | +| liqDeadline | uint256 | Specificies the deadline that the nodes are allowed to try to redeem/swap the LP token* | + +### redeemAndSwap + +```solidity +function redeemAndSwap(address to, uint256 chainId, contract IERC20 token, uint256 amount, uint8 tokenIndexFrom, uint8 tokenIndexTo, uint256 minDy, uint256 deadline) external nonpayable +``` + +Wraps redeemAndSwap on SynapseBridge.sol Relays to nodes that (typically) a wrapped synAsset ERC20 token has been burned and the underlying needs to be redeeemed on the native chain. This function indicates to the nodes that they should attempt to redeem the LP token for the underlying assets (E.g "swap" out of the LP token) + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| to | address | address on other chain to redeem underlying assets to | +| chainId | uint256 | which underlying chain to bridge assets onto | +| token | contract IERC20 | ERC20 compatible token to deposit into the bridge | +| amount | uint256 | Amount in native token decimals to transfer cross-chain pre-fees | +| tokenIndexFrom | uint8 | the token the user wants to swap from | +| tokenIndexTo | uint8 | the token the user wants to swap to | +| minDy | uint256 | the min amount the user would like to receive, or revert to only minting the SynERC20 token crosschain. | +| deadline | uint256 | latest timestamp to accept this transaction* | + +### redeemv2 + +```solidity +function redeemv2(bytes32 to, uint256 chainId, contract IERC20 token, uint256 amount) external nonpayable +``` + +Wraps SynapseBridge redeemv2() function + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| to | bytes32 | address on other chain to bridge assets to | +| chainId | uint256 | which chain to bridge assets onto | +| token | contract IERC20 | ERC20 compatible token to redeem into the bridge | +| amount | uint256 | Amount in native token decimals to transfer cross-chain pre-fees* | + +### swapAndRedeem + +```solidity +function swapAndRedeem(address to, uint256 chainId, contract IERC20 token, uint8 tokenIndexFrom, uint8 tokenIndexTo, uint256 dx, uint256 minDy, uint256 deadline) external nonpayable +``` + + + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| to | address | undefined | +| chainId | uint256 | undefined | +| token | contract IERC20 | undefined | +| tokenIndexFrom | uint8 | undefined | +| tokenIndexTo | uint8 | undefined | +| dx | uint256 | undefined | +| minDy | uint256 | undefined | +| deadline | uint256 | undefined | + +### swapAndRedeemAndRemove + +```solidity +function swapAndRedeemAndRemove(address to, uint256 chainId, contract IERC20 token, uint8 tokenIndexFrom, uint8 tokenIndexTo, uint256 dx, uint256 minDy, uint256 deadline, uint8 liqTokenIndex, uint256 liqMinAmount, uint256 liqDeadline) external nonpayable +``` + + + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| to | address | undefined | +| chainId | uint256 | undefined | +| token | contract IERC20 | undefined | +| tokenIndexFrom | uint8 | undefined | +| tokenIndexTo | uint8 | undefined | +| dx | uint256 | undefined | +| minDy | uint256 | undefined | +| deadline | uint256 | undefined | +| liqTokenIndex | uint8 | undefined | +| liqMinAmount | uint256 | undefined | +| liqDeadline | uint256 | undefined | + +### swapAndRedeemAndSwap + +```solidity +function swapAndRedeemAndSwap(address to, uint256 chainId, contract IERC20 token, uint8 tokenIndexFrom, uint8 tokenIndexTo, uint256 dx, uint256 minDy, uint256 deadline, uint8 swapTokenIndexFrom, uint8 swapTokenIndexTo, uint256 swapMinDy, uint256 swapDeadline) external nonpayable +``` + + + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| to | address | undefined | +| chainId | uint256 | undefined | +| token | contract IERC20 | undefined | +| tokenIndexFrom | uint8 | undefined | +| tokenIndexTo | uint8 | undefined | +| dx | uint256 | undefined | +| minDy | uint256 | undefined | +| deadline | uint256 | undefined | +| swapTokenIndexFrom | uint8 | undefined | +| swapTokenIndexTo | uint8 | undefined | +| swapMinDy | uint256 | undefined | +| swapDeadline | uint256 | undefined | + +### swapETHAndRedeem + +```solidity +function swapETHAndRedeem(address to, uint256 chainId, contract IERC20 token, uint8 tokenIndexFrom, uint8 tokenIndexTo, uint256 dx, uint256 minDy, uint256 deadline) external payable +``` + + + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| to | address | undefined | +| chainId | uint256 | undefined | +| token | contract IERC20 | undefined | +| tokenIndexFrom | uint8 | undefined | +| tokenIndexTo | uint8 | undefined | +| dx | uint256 | undefined | +| minDy | uint256 | undefined | +| deadline | uint256 | undefined | + +### swapMap + +```solidity +function swapMap(address) external view returns (address) +``` + + + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| _0 | address | undefined | + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | address | undefined | + +### swapTokensMap + +```solidity +function swapTokensMap(address, uint256) external view returns (contract IERC20) +``` + + + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| _0 | address | undefined | +| _1 | uint256 | undefined | + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | contract IERC20 | undefined | + + + + diff --git a/docs/bridge/wrappers/IFrax.md b/docs/bridge/wrappers/IFrax.md new file mode 100644 index 000000000..6287777f5 --- /dev/null +++ b/docs/bridge/wrappers/IFrax.md @@ -0,0 +1,38 @@ +# IFrax + + + + + + + + + +## Methods + +### exchangeCanonicalForOld + +```solidity +function exchangeCanonicalForOld(address bridge_token_address, uint256 token_amount) external nonpayable returns (uint256) +``` + + + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| bridge_token_address | address | undefined | +| token_amount | uint256 | undefined | + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | uint256 | undefined | + + + + diff --git a/docs/bridge/wrappers/IGMX.md b/docs/bridge/wrappers/IGMX.md new file mode 100644 index 000000000..a04c32737 --- /dev/null +++ b/docs/bridge/wrappers/IGMX.md @@ -0,0 +1,71 @@ +# IGMX + + + + + + + + + +## Methods + +### balanceOf + +```solidity +function balanceOf(address account) external view returns (uint256) +``` + + + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| account | address | undefined | + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | uint256 | undefined | + +### burn + +```solidity +function burn(address _account, uint256 _amount) external nonpayable +``` + + + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| _account | address | undefined | +| _amount | uint256 | undefined | + +### mint + +```solidity +function mint(address _account, uint256 _amount) external nonpayable +``` + + + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| _account | address | undefined | +| _amount | uint256 | undefined | + + + + diff --git a/docs/bridge/wrappers/L1BridgeZap.md b/docs/bridge/wrappers/L1BridgeZap.md new file mode 100644 index 000000000..a4066af8a --- /dev/null +++ b/docs/bridge/wrappers/L1BridgeZap.md @@ -0,0 +1,266 @@ +# L1BridgeZap + + + +> L1BridgeZap + +This contract is responsible for handling user Zaps into the SynapseBridge contract, through the Synapse Swap contracts. It does so It does so by combining the action of addLiquidity() to the base swap pool, and then calling either deposit() or depositAndSwap() on the bridge. This is done in hopes of automating portions of the bridge user experience to users, while keeping the SynapseBridge contract logic small. + +*This contract should be deployed with a base Swap.sol address and a SynapseBridge.sol address, otherwise, it will not function.* + +## Methods + +### WETH_ADDRESS + +```solidity +function WETH_ADDRESS() external view returns (address payable) +``` + + + + + + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | address payable | undefined | + +### baseTokens + +```solidity +function baseTokens(uint256) external view returns (contract IERC20) +``` + + + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| _0 | uint256 | undefined | + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | contract IERC20 | undefined | + +### calculateRemoveLiquidityOneToken + +```solidity +function calculateRemoveLiquidityOneToken(uint256 tokenAmount, uint8 tokenIndex) external view returns (uint256 availableTokenAmount) +``` + +Calculate the amount of underlying token available to withdraw when withdrawing via only single token + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| tokenAmount | uint256 | the amount of LP token to burn | +| tokenIndex | uint8 | index of which token will be withdrawn | + +#### Returns + +| Name | Type | Description | +|---|---|---| +| availableTokenAmount | uint256 | calculated amount of underlying token available to withdraw | + +### calculateTokenAmount + +```solidity +function calculateTokenAmount(uint256[] amounts, bool deposit) external view returns (uint256) +``` + +A simple method to calculate prices from deposits or withdrawals, excluding fees but including slippage. This is helpful as an input into the various "min" parameters on calls to fight front-running + +*This shouldn't be used outside frontends for user estimates.* + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| amounts | uint256[] | an array of token amounts to deposit or withdrawal, corresponding to pooledTokens. The amount should be in each pooled token's native precision. | +| deposit | bool | whether this is a deposit or a withdrawal | + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | uint256 | token amount the user will receive | + +### deposit + +```solidity +function deposit(address to, uint256 chainId, contract IERC20 token, uint256 amount) external nonpayable +``` + +Wraps SynapseBridge deposit() function + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| to | address | address on other chain to bridge assets to | +| chainId | uint256 | which chain to bridge assets onto | +| token | contract IERC20 | ERC20 compatible token to deposit into the bridge | +| amount | uint256 | Amount in native token decimals to transfer cross-chain pre-fees* | + +### depositAndSwap + +```solidity +function depositAndSwap(address to, uint256 chainId, contract IERC20 token, uint256 amount, uint8 tokenIndexFrom, uint8 tokenIndexTo, uint256 minDy, uint256 deadline) external nonpayable +``` + +Wraps SynapseBridge depositAndSwap() function + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| to | address | address on other chain to bridge assets to | +| chainId | uint256 | which chain to bridge assets onto | +| token | contract IERC20 | ERC20 compatible token to deposit into the bridge | +| amount | uint256 | Amount in native token decimals to transfer cross-chain pre-fees | +| tokenIndexFrom | uint8 | the token the user wants to swap from | +| tokenIndexTo | uint8 | the token the user wants to swap to | +| minDy | uint256 | the min amount the user would like to receive, or revert to only minting the SynERC20 token crosschain. | +| deadline | uint256 | latest timestamp to accept this transaction* | + +### depositETH + +```solidity +function depositETH(address to, uint256 chainId, uint256 amount) external payable +``` + +Wraps SynapseBridge deposit() function to make it compatible w/ ETH -> WETH conversions + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| to | address | address on other chain to bridge assets to | +| chainId | uint256 | which chain to bridge assets onto | +| amount | uint256 | Amount in native token decimals to transfer cross-chain pre-fees* | + +### depositETHAndSwap + +```solidity +function depositETHAndSwap(address to, uint256 chainId, uint256 amount, uint8 tokenIndexFrom, uint8 tokenIndexTo, uint256 minDy, uint256 deadline) external payable +``` + +Wraps SynapseBridge depositAndSwap() function to make it compatible w/ ETH -> WETH conversions + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| to | address | address on other chain to bridge assets to | +| chainId | uint256 | which chain to bridge assets onto | +| amount | uint256 | Amount in native token decimals to transfer cross-chain pre-fees | +| tokenIndexFrom | uint8 | the token the user wants to swap from | +| tokenIndexTo | uint8 | the token the user wants to swap to | +| minDy | uint256 | the min amount the user would like to receive, or revert to only minting the SynERC20 token crosschain. | +| deadline | uint256 | latest timestamp to accept this transaction* | + +### redeem + +```solidity +function redeem(address to, uint256 chainId, contract IERC20 token, uint256 amount) external nonpayable +``` + +Wraps SynapseBridge redeem() function + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| to | address | address on other chain to bridge assets to | +| chainId | uint256 | which chain to bridge assets onto | +| token | contract IERC20 | ERC20 compatible token to redeem into the bridge | +| amount | uint256 | Amount in native token decimals to transfer cross-chain pre-fees* | + +### redeemv2 + +```solidity +function redeemv2(bytes32 to, uint256 chainId, contract IERC20 token, uint256 amount) external nonpayable +``` + +Wraps SynapseBridge redeemv2() function + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| to | bytes32 | address on other chain to bridge assets to | +| chainId | uint256 | which chain to bridge assets onto | +| token | contract IERC20 | ERC20 compatible token to redeem into the bridge | +| amount | uint256 | Amount in native token decimals to transfer cross-chain pre-fees* | + +### zapAndDeposit + +```solidity +function zapAndDeposit(address to, uint256 chainId, contract IERC20 token, uint256[] liquidityAmounts, uint256 minToMint, uint256 deadline) external nonpayable +``` + +Combines adding liquidity to the given Swap, and calls deposit() on the bridge using that LP token + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| to | address | address on other chain to bridge assets to | +| chainId | uint256 | which chain to bridge assets onto | +| token | contract IERC20 | ERC20 compatible token to deposit into the bridge | +| liquidityAmounts | uint256[] | the amounts of each token to add, in their native precision | +| minToMint | uint256 | the minimum LP tokens adding this amount of liquidity should mint, otherwise revert. Handy for front-running mitigation | +| deadline | uint256 | latest timestamp to accept this transaction* | + +### zapAndDepositAndSwap + +```solidity +function zapAndDepositAndSwap(address to, uint256 chainId, contract IERC20 token, uint256[] liquidityAmounts, uint256 minToMint, uint256 liqDeadline, uint8 tokenIndexFrom, uint8 tokenIndexTo, uint256 minDy, uint256 swapDeadline) external nonpayable +``` + +Combines adding liquidity to the given Swap, and calls depositAndSwap() on the bridge using that LP token + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| to | address | address on other chain to bridge assets to | +| chainId | uint256 | which chain to bridge assets onto | +| token | contract IERC20 | ERC20 compatible token to deposit into the bridge | +| liquidityAmounts | uint256[] | the amounts of each token to add, in their native precision | +| minToMint | uint256 | the minimum LP tokens adding this amount of liquidity should mint, otherwise revert. Handy for front-running mitigation | +| liqDeadline | uint256 | latest timestamp to accept this transaction | +| tokenIndexFrom | uint8 | the token the user wants to swap from | +| tokenIndexTo | uint8 | the token the user wants to swap to | +| minDy | uint256 | the min amount the user would like to receive, or revert to only minting the SynERC20 token crosschain. | +| swapDeadline | uint256 | latest timestamp to accept this transaction* | + + + + diff --git a/docs/bridge/wrappers/L2BridgeZap.md b/docs/bridge/wrappers/L2BridgeZap.md new file mode 100644 index 000000000..6df9a67de --- /dev/null +++ b/docs/bridge/wrappers/L2BridgeZap.md @@ -0,0 +1,348 @@ +# L2BridgeZap + + + + + + + + + +## Methods + +### WETH_ADDRESS + +```solidity +function WETH_ADDRESS() external view returns (address payable) +``` + + + + + + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | address payable | undefined | + +### calculateSwap + +```solidity +function calculateSwap(contract IERC20 token, uint8 tokenIndexFrom, uint8 tokenIndexTo, uint256 dx) external view returns (uint256) +``` + +Calculate amount of tokens you receive on swap + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| token | contract IERC20 | undefined | +| tokenIndexFrom | uint8 | the token the user wants to sell | +| tokenIndexTo | uint8 | the token the user wants to buy | +| dx | uint256 | the amount of tokens the user wants to sell. If the token charges a fee on transfers, use the amount that gets transferred after the fee. | + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | uint256 | amount of tokens the user will receive | + +### deposit + +```solidity +function deposit(address to, uint256 chainId, contract IERC20 token, uint256 amount) external nonpayable +``` + +wraps SynapseBridge redeem() + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| to | address | address on other chain to redeem underlying assets to | +| chainId | uint256 | which underlying chain to bridge assets onto | +| token | contract IERC20 | ERC20 compatible token to deposit into the bridge | +| amount | uint256 | Amount in native token decimals to transfer cross-chain pre-fees* | + +### depositETH + +```solidity +function depositETH(address to, uint256 chainId, uint256 amount) external payable +``` + +Wraps SynapseBridge deposit() function to make it compatible w/ ETH -> WETH conversions + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| to | address | address on other chain to bridge assets to | +| chainId | uint256 | which chain to bridge assets onto | +| amount | uint256 | Amount in native token decimals to transfer cross-chain pre-fees* | + +### redeem + +```solidity +function redeem(address to, uint256 chainId, contract IERC20 token, uint256 amount) external nonpayable +``` + +wraps SynapseBridge redeem() + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| to | address | address on other chain to redeem underlying assets to | +| chainId | uint256 | which underlying chain to bridge assets onto | +| token | contract IERC20 | ERC20 compatible token to deposit into the bridge | +| amount | uint256 | Amount in native token decimals to transfer cross-chain pre-fees* | + +### redeemAndRemove + +```solidity +function redeemAndRemove(address to, uint256 chainId, contract IERC20 token, uint256 amount, uint8 liqTokenIndex, uint256 liqMinAmount, uint256 liqDeadline) external nonpayable +``` + +Wraps redeemAndRemove on SynapseBridge Relays to nodes that (typically) a wrapped synAsset ERC20 token has been burned and the underlying needs to be redeeemed on the native chain. This function indicates to the nodes that they should attempt to redeem the LP token for the underlying assets (E.g "swap" out of the LP token) + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| to | address | address on other chain to redeem underlying assets to | +| chainId | uint256 | which underlying chain to bridge assets onto | +| token | contract IERC20 | ERC20 compatible token to deposit into the bridge | +| amount | uint256 | Amount of (typically) LP token to pass to the nodes to attempt to removeLiquidity() with to redeem for the underlying assets of the LP token | +| liqTokenIndex | uint8 | Specifies which of the underlying LP assets the nodes should attempt to redeem for | +| liqMinAmount | uint256 | Specifies the minimum amount of the underlying asset needed for the nodes to execute the redeem/swap | +| liqDeadline | uint256 | Specificies the deadline that the nodes are allowed to try to redeem/swap the LP token* | + +### redeemAndSwap + +```solidity +function redeemAndSwap(address to, uint256 chainId, contract IERC20 token, uint256 amount, uint8 tokenIndexFrom, uint8 tokenIndexTo, uint256 minDy, uint256 deadline) external nonpayable +``` + +Wraps redeemAndSwap on SynapseBridge.sol Relays to nodes that (typically) a wrapped synAsset ERC20 token has been burned and the underlying needs to be redeeemed on the native chain. This function indicates to the nodes that they should attempt to redeem the LP token for the underlying assets (E.g "swap" out of the LP token) + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| to | address | address on other chain to redeem underlying assets to | +| chainId | uint256 | which underlying chain to bridge assets onto | +| token | contract IERC20 | ERC20 compatible token to deposit into the bridge | +| amount | uint256 | Amount in native token decimals to transfer cross-chain pre-fees | +| tokenIndexFrom | uint8 | the token the user wants to swap from | +| tokenIndexTo | uint8 | the token the user wants to swap to | +| minDy | uint256 | the min amount the user would like to receive, or revert to only minting the SynERC20 token crosschain. | +| deadline | uint256 | latest timestamp to accept this transaction* | + +### redeemv2 + +```solidity +function redeemv2(bytes32 to, uint256 chainId, contract IERC20 token, uint256 amount) external nonpayable +``` + +Wraps SynapseBridge redeemv2() function + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| to | bytes32 | address on other chain to bridge assets to | +| chainId | uint256 | which chain to bridge assets onto | +| token | contract IERC20 | ERC20 compatible token to redeem into the bridge | +| amount | uint256 | Amount in native token decimals to transfer cross-chain pre-fees* | + +### swapAndRedeem + +```solidity +function swapAndRedeem(address to, uint256 chainId, contract IERC20 token, uint8 tokenIndexFrom, uint8 tokenIndexTo, uint256 dx, uint256 minDy, uint256 deadline) external nonpayable +``` + + + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| to | address | undefined | +| chainId | uint256 | undefined | +| token | contract IERC20 | undefined | +| tokenIndexFrom | uint8 | undefined | +| tokenIndexTo | uint8 | undefined | +| dx | uint256 | undefined | +| minDy | uint256 | undefined | +| deadline | uint256 | undefined | + +### swapAndRedeemAndRemove + +```solidity +function swapAndRedeemAndRemove(address to, uint256 chainId, contract IERC20 token, uint8 tokenIndexFrom, uint8 tokenIndexTo, uint256 dx, uint256 minDy, uint256 deadline, uint8 liqTokenIndex, uint256 liqMinAmount, uint256 liqDeadline) external nonpayable +``` + + + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| to | address | undefined | +| chainId | uint256 | undefined | +| token | contract IERC20 | undefined | +| tokenIndexFrom | uint8 | undefined | +| tokenIndexTo | uint8 | undefined | +| dx | uint256 | undefined | +| minDy | uint256 | undefined | +| deadline | uint256 | undefined | +| liqTokenIndex | uint8 | undefined | +| liqMinAmount | uint256 | undefined | +| liqDeadline | uint256 | undefined | + +### swapAndRedeemAndSwap + +```solidity +function swapAndRedeemAndSwap(address to, uint256 chainId, contract IERC20 token, uint8 tokenIndexFrom, uint8 tokenIndexTo, uint256 dx, uint256 minDy, uint256 deadline, uint8 swapTokenIndexFrom, uint8 swapTokenIndexTo, uint256 swapMinDy, uint256 swapDeadline) external nonpayable +``` + + + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| to | address | undefined | +| chainId | uint256 | undefined | +| token | contract IERC20 | undefined | +| tokenIndexFrom | uint8 | undefined | +| tokenIndexTo | uint8 | undefined | +| dx | uint256 | undefined | +| minDy | uint256 | undefined | +| deadline | uint256 | undefined | +| swapTokenIndexFrom | uint8 | undefined | +| swapTokenIndexTo | uint8 | undefined | +| swapMinDy | uint256 | undefined | +| swapDeadline | uint256 | undefined | + +### swapETHAndRedeem + +```solidity +function swapETHAndRedeem(address to, uint256 chainId, contract IERC20 token, uint8 tokenIndexFrom, uint8 tokenIndexTo, uint256 dx, uint256 minDy, uint256 deadline) external payable +``` + + + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| to | address | undefined | +| chainId | uint256 | undefined | +| token | contract IERC20 | undefined | +| tokenIndexFrom | uint8 | undefined | +| tokenIndexTo | uint8 | undefined | +| dx | uint256 | undefined | +| minDy | uint256 | undefined | +| deadline | uint256 | undefined | + +### swapETHAndRedeemAndSwap + +```solidity +function swapETHAndRedeemAndSwap(address to, uint256 chainId, contract IERC20 token, uint8 tokenIndexFrom, uint8 tokenIndexTo, uint256 dx, uint256 minDy, uint256 deadline, uint8 swapTokenIndexFrom, uint8 swapTokenIndexTo, uint256 swapMinDy, uint256 swapDeadline) external payable +``` + + + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| to | address | undefined | +| chainId | uint256 | undefined | +| token | contract IERC20 | undefined | +| tokenIndexFrom | uint8 | undefined | +| tokenIndexTo | uint8 | undefined | +| dx | uint256 | undefined | +| minDy | uint256 | undefined | +| deadline | uint256 | undefined | +| swapTokenIndexFrom | uint8 | undefined | +| swapTokenIndexTo | uint8 | undefined | +| swapMinDy | uint256 | undefined | +| swapDeadline | uint256 | undefined | + +### swapMap + +```solidity +function swapMap(address) external view returns (address) +``` + + + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| _0 | address | undefined | + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | address | undefined | + +### swapTokensMap + +```solidity +function swapTokensMap(address, uint256) external view returns (contract IERC20) +``` + + + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| _0 | address | undefined | +| _1 | uint256 | undefined | + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | contract IERC20 | undefined | + + + + diff --git a/docs/bridge/wrappers/MigratorBridgeZap.md b/docs/bridge/wrappers/MigratorBridgeZap.md new file mode 100644 index 000000000..ffd90c60d --- /dev/null +++ b/docs/bridge/wrappers/MigratorBridgeZap.md @@ -0,0 +1,49 @@ +# MigratorBridgeZap + + + + + + + + + +## Methods + +### migrate + +```solidity +function migrate(uint256 amount) external nonpayable +``` + + + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| amount | uint256 | undefined | + +### migrateAndBridge + +```solidity +function migrateAndBridge(uint256 amount, address to, uint256 chainId) external nonpayable +``` + + + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| amount | uint256 | undefined | +| to | address | undefined | +| chainId | uint256 | undefined | + + + + diff --git a/docs/bridge/wrappers/MoonriverBridgeZap.md b/docs/bridge/wrappers/MoonriverBridgeZap.md new file mode 100644 index 000000000..bb1707f7a --- /dev/null +++ b/docs/bridge/wrappers/MoonriverBridgeZap.md @@ -0,0 +1,321 @@ +# MoonriverBridgeZap + + + + + + + + + +## Methods + +### WETH_ADDRESS + +```solidity +function WETH_ADDRESS() external view returns (address payable) +``` + + + + + + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | address payable | undefined | + +### calculateSwap + +```solidity +function calculateSwap(contract IERC20 token, uint8 tokenIndexFrom, uint8 tokenIndexTo, uint256 dx) external view returns (uint256) +``` + +Calculate amount of tokens you receive on swap + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| token | contract IERC20 | undefined | +| tokenIndexFrom | uint8 | the token the user wants to sell | +| tokenIndexTo | uint8 | the token the user wants to buy | +| dx | uint256 | the amount of tokens the user wants to sell. If the token charges a fee on transfers, use the amount that gets transferred after the fee. | + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | uint256 | amount of tokens the user will receive | + +### deposit + +```solidity +function deposit(address to, uint256 chainId, contract IERC20 token, uint256 amount) external nonpayable +``` + +wraps SynapseBridge redeem() + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| to | address | address on other chain to redeem underlying assets to | +| chainId | uint256 | which underlying chain to bridge assets onto | +| token | contract IERC20 | ERC20 compatible token to deposit into the bridge | +| amount | uint256 | Amount in native token decimals to transfer cross-chain pre-fees* | + +### depositETH + +```solidity +function depositETH(address to, uint256 chainId, uint256 amount) external payable +``` + +Wraps SynapseBridge deposit() function to make it compatible w/ ETH -> WETH conversions + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| to | address | address on other chain to bridge assets to | +| chainId | uint256 | which chain to bridge assets onto | +| amount | uint256 | Amount in native token decimals to transfer cross-chain pre-fees* | + +### redeem + +```solidity +function redeem(address to, uint256 chainId, contract IERC20 token, uint256 amount) external nonpayable +``` + +wraps SynapseBridge redeem() + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| to | address | address on other chain to redeem underlying assets to | +| chainId | uint256 | which underlying chain to bridge assets onto | +| token | contract IERC20 | ERC20 compatible token to deposit into the bridge | +| amount | uint256 | Amount in native token decimals to transfer cross-chain pre-fees* | + +### redeemAndRemove + +```solidity +function redeemAndRemove(address to, uint256 chainId, contract IERC20 token, uint256 amount, uint8 liqTokenIndex, uint256 liqMinAmount, uint256 liqDeadline) external nonpayable +``` + +Wraps redeemAndRemove on SynapseBridge Relays to nodes that (typically) a wrapped synAsset ERC20 token has been burned and the underlying needs to be redeeemed on the native chain. This function indicates to the nodes that they should attempt to redeem the LP token for the underlying assets (E.g "swap" out of the LP token) + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| to | address | address on other chain to redeem underlying assets to | +| chainId | uint256 | which underlying chain to bridge assets onto | +| token | contract IERC20 | ERC20 compatible token to deposit into the bridge | +| amount | uint256 | Amount of (typically) LP token to pass to the nodes to attempt to removeLiquidity() with to redeem for the underlying assets of the LP token | +| liqTokenIndex | uint8 | Specifies which of the underlying LP assets the nodes should attempt to redeem for | +| liqMinAmount | uint256 | Specifies the minimum amount of the underlying asset needed for the nodes to execute the redeem/swap | +| liqDeadline | uint256 | Specificies the deadline that the nodes are allowed to try to redeem/swap the LP token* | + +### redeemAndSwap + +```solidity +function redeemAndSwap(address to, uint256 chainId, contract IERC20 token, uint256 amount, uint8 tokenIndexFrom, uint8 tokenIndexTo, uint256 minDy, uint256 deadline) external nonpayable +``` + +Wraps redeemAndSwap on SynapseBridge.sol Relays to nodes that (typically) a wrapped synAsset ERC20 token has been burned and the underlying needs to be redeeemed on the native chain. This function indicates to the nodes that they should attempt to redeem the LP token for the underlying assets (E.g "swap" out of the LP token) + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| to | address | address on other chain to redeem underlying assets to | +| chainId | uint256 | which underlying chain to bridge assets onto | +| token | contract IERC20 | ERC20 compatible token to deposit into the bridge | +| amount | uint256 | Amount in native token decimals to transfer cross-chain pre-fees | +| tokenIndexFrom | uint8 | the token the user wants to swap from | +| tokenIndexTo | uint8 | the token the user wants to swap to | +| minDy | uint256 | the min amount the user would like to receive, or revert to only minting the SynERC20 token crosschain. | +| deadline | uint256 | latest timestamp to accept this transaction* | + +### redeemv2 + +```solidity +function redeemv2(bytes32 to, uint256 chainId, contract IERC20 token, uint256 amount) external nonpayable +``` + +Wraps SynapseBridge redeemv2() function + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| to | bytes32 | address on other chain to bridge assets to | +| chainId | uint256 | which chain to bridge assets onto | +| token | contract IERC20 | ERC20 compatible token to redeem into the bridge | +| amount | uint256 | Amount in native token decimals to transfer cross-chain pre-fees* | + +### swapAndRedeem + +```solidity +function swapAndRedeem(address to, uint256 chainId, contract IERC20 token, uint8 tokenIndexFrom, uint8 tokenIndexTo, uint256 dx, uint256 minDy, uint256 deadline) external nonpayable +``` + + + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| to | address | undefined | +| chainId | uint256 | undefined | +| token | contract IERC20 | undefined | +| tokenIndexFrom | uint8 | undefined | +| tokenIndexTo | uint8 | undefined | +| dx | uint256 | undefined | +| minDy | uint256 | undefined | +| deadline | uint256 | undefined | + +### swapAndRedeemAndRemove + +```solidity +function swapAndRedeemAndRemove(address to, uint256 chainId, contract IERC20 token, uint8 tokenIndexFrom, uint8 tokenIndexTo, uint256 dx, uint256 minDy, uint256 deadline, uint8 liqTokenIndex, uint256 liqMinAmount, uint256 liqDeadline) external nonpayable +``` + + + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| to | address | undefined | +| chainId | uint256 | undefined | +| token | contract IERC20 | undefined | +| tokenIndexFrom | uint8 | undefined | +| tokenIndexTo | uint8 | undefined | +| dx | uint256 | undefined | +| minDy | uint256 | undefined | +| deadline | uint256 | undefined | +| liqTokenIndex | uint8 | undefined | +| liqMinAmount | uint256 | undefined | +| liqDeadline | uint256 | undefined | + +### swapAndRedeemAndSwap + +```solidity +function swapAndRedeemAndSwap(address to, uint256 chainId, contract IERC20 token, uint8 tokenIndexFrom, uint8 tokenIndexTo, uint256 dx, uint256 minDy, uint256 deadline, uint8 swapTokenIndexFrom, uint8 swapTokenIndexTo, uint256 swapMinDy, uint256 swapDeadline) external nonpayable +``` + + + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| to | address | undefined | +| chainId | uint256 | undefined | +| token | contract IERC20 | undefined | +| tokenIndexFrom | uint8 | undefined | +| tokenIndexTo | uint8 | undefined | +| dx | uint256 | undefined | +| minDy | uint256 | undefined | +| deadline | uint256 | undefined | +| swapTokenIndexFrom | uint8 | undefined | +| swapTokenIndexTo | uint8 | undefined | +| swapMinDy | uint256 | undefined | +| swapDeadline | uint256 | undefined | + +### swapETHAndRedeem + +```solidity +function swapETHAndRedeem(address to, uint256 chainId, contract IERC20 token, uint8 tokenIndexFrom, uint8 tokenIndexTo, uint256 dx, uint256 minDy, uint256 deadline) external payable +``` + + + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| to | address | undefined | +| chainId | uint256 | undefined | +| token | contract IERC20 | undefined | +| tokenIndexFrom | uint8 | undefined | +| tokenIndexTo | uint8 | undefined | +| dx | uint256 | undefined | +| minDy | uint256 | undefined | +| deadline | uint256 | undefined | + +### swapMap + +```solidity +function swapMap(address) external view returns (address) +``` + + + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| _0 | address | undefined | + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | address | undefined | + +### swapTokensMap + +```solidity +function swapTokensMap(address, uint256) external view returns (contract IERC20) +``` + + + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| _0 | address | undefined | +| _1 | uint256 | undefined | + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | contract IERC20 | undefined | + + + + diff --git a/docs/console.md b/docs/console.md new file mode 100644 index 000000000..8bab67a46 --- /dev/null +++ b/docs/console.md @@ -0,0 +1,12 @@ +# console + + + + + + + + + + + diff --git a/docs/elin/contracts-4.3.1-upgradeable/access/AccessControlUpgradeable.md b/docs/elin/contracts-4.3.1-upgradeable/access/AccessControlUpgradeable.md new file mode 100644 index 000000000..c52e7d992 --- /dev/null +++ b/docs/elin/contracts-4.3.1-upgradeable/access/AccessControlUpgradeable.md @@ -0,0 +1,207 @@ +# AccessControlUpgradeable + + + + + + + +*Contract module that allows children to implement role-based access control mechanisms. This is a lightweight version that doesn't allow enumerating role members except through off-chain means by accessing the contract event logs. Some applications may benefit from on-chain enumerability, for those cases see {AccessControlEnumerable}. Roles are referred to by their `bytes32` identifier. These should be exposed in the external API and be unique. The best way to achieve this is by using `public constant` hash digests: ``` bytes32 public constant MY_ROLE = keccak256("MY_ROLE"); ``` Roles can be used to represent a set of permissions. To restrict access to a function call, use {hasRole}: ``` function foo() public { require(hasRole(MY_ROLE, msg.sender)); ... } ``` Roles can be granted and revoked dynamically via the {grantRole} and {revokeRole} functions. Each role has an associated admin role, and only accounts that have a role's admin role can call {grantRole} and {revokeRole}. By default, the admin role for all roles is `DEFAULT_ADMIN_ROLE`, which means that only accounts with this role will be able to grant or revoke other roles. More complex role relationships can be created by using {_setRoleAdmin}. WARNING: The `DEFAULT_ADMIN_ROLE` is also its own admin: it has permission to grant and revoke this role. Extra precautions should be taken to secure accounts that have been granted it.* + +## Methods + +### DEFAULT_ADMIN_ROLE + +```solidity +function DEFAULT_ADMIN_ROLE() external view returns (bytes32) +``` + + + + + + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | bytes32 | undefined | + +### getRoleAdmin + +```solidity +function getRoleAdmin(bytes32 role) external view returns (bytes32) +``` + + + +*Returns the admin role that controls `role`. See {grantRole} and {revokeRole}. To change a role's admin, use {_setRoleAdmin}.* + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| role | bytes32 | undefined | + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | bytes32 | undefined | + +### grantRole + +```solidity +function grantRole(bytes32 role, address account) external nonpayable +``` + + + +*Grants `role` to `account`. If `account` had not been already granted `role`, emits a {RoleGranted} event. Requirements: - the caller must have ``role``'s admin role.* + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| role | bytes32 | undefined | +| account | address | undefined | + +### hasRole + +```solidity +function hasRole(bytes32 role, address account) external view returns (bool) +``` + + + +*Returns `true` if `account` has been granted `role`.* + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| role | bytes32 | undefined | +| account | address | undefined | + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | bool | undefined | + +### renounceRole + +```solidity +function renounceRole(bytes32 role, address account) external nonpayable +``` + + + +*Revokes `role` from the calling account. Roles are often managed via {grantRole} and {revokeRole}: this function's purpose is to provide a mechanism for accounts to lose their privileges if they are compromised (such as when a trusted device is misplaced). If the calling account had been revoked `role`, emits a {RoleRevoked} event. Requirements: - the caller must be `account`.* + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| role | bytes32 | undefined | +| account | address | undefined | + +### revokeRole + +```solidity +function revokeRole(bytes32 role, address account) external nonpayable +``` + + + +*Revokes `role` from `account`. If `account` had been granted `role`, emits a {RoleRevoked} event. Requirements: - the caller must have ``role``'s admin role.* + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| role | bytes32 | undefined | +| account | address | undefined | + +### supportsInterface + +```solidity +function supportsInterface(bytes4 interfaceId) external view returns (bool) +``` + + + +*See {IERC165-supportsInterface}.* + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| interfaceId | bytes4 | undefined | + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | bool | undefined | + + + +## Events + +### RoleAdminChanged + +```solidity +event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole) +``` + + + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| role `indexed` | bytes32 | undefined | +| previousAdminRole `indexed` | bytes32 | undefined | +| newAdminRole `indexed` | bytes32 | undefined | + +### RoleGranted + +```solidity +event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender) +``` + + + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| role `indexed` | bytes32 | undefined | +| account `indexed` | address | undefined | +| sender `indexed` | address | undefined | + +### RoleRevoked + +```solidity +event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender) +``` + + + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| role `indexed` | bytes32 | undefined | +| account `indexed` | address | undefined | +| sender `indexed` | address | undefined | + + + diff --git a/docs/elin/contracts-4.3.1-upgradeable/access/IAccessControlUpgradeable.md b/docs/elin/contracts-4.3.1-upgradeable/access/IAccessControlUpgradeable.md new file mode 100644 index 000000000..4ad76fe12 --- /dev/null +++ b/docs/elin/contracts-4.3.1-upgradeable/access/IAccessControlUpgradeable.md @@ -0,0 +1,168 @@ +# IAccessControlUpgradeable + + + + + + + +*External interface of AccessControl declared to support ERC165 detection.* + +## Methods + +### getRoleAdmin + +```solidity +function getRoleAdmin(bytes32 role) external view returns (bytes32) +``` + + + +*Returns the admin role that controls `role`. See {grantRole} and {revokeRole}. To change a role's admin, use {AccessControl-_setRoleAdmin}.* + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| role | bytes32 | undefined | + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | bytes32 | undefined | + +### grantRole + +```solidity +function grantRole(bytes32 role, address account) external nonpayable +``` + + + +*Grants `role` to `account`. If `account` had not been already granted `role`, emits a {RoleGranted} event. Requirements: - the caller must have ``role``'s admin role.* + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| role | bytes32 | undefined | +| account | address | undefined | + +### hasRole + +```solidity +function hasRole(bytes32 role, address account) external view returns (bool) +``` + + + +*Returns `true` if `account` has been granted `role`.* + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| role | bytes32 | undefined | +| account | address | undefined | + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | bool | undefined | + +### renounceRole + +```solidity +function renounceRole(bytes32 role, address account) external nonpayable +``` + + + +*Revokes `role` from the calling account. Roles are often managed via {grantRole} and {revokeRole}: this function's purpose is to provide a mechanism for accounts to lose their privileges if they are compromised (such as when a trusted device is misplaced). If the calling account had been granted `role`, emits a {RoleRevoked} event. Requirements: - the caller must be `account`.* + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| role | bytes32 | undefined | +| account | address | undefined | + +### revokeRole + +```solidity +function revokeRole(bytes32 role, address account) external nonpayable +``` + + + +*Revokes `role` from `account`. If `account` had been granted `role`, emits a {RoleRevoked} event. Requirements: - the caller must have ``role``'s admin role.* + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| role | bytes32 | undefined | +| account | address | undefined | + + + +## Events + +### RoleAdminChanged + +```solidity +event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole) +``` + + + +*Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole` `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite {RoleAdminChanged} not being emitted signaling this. _Available since v3.1._* + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| role `indexed` | bytes32 | undefined | +| previousAdminRole `indexed` | bytes32 | undefined | +| newAdminRole `indexed` | bytes32 | undefined | + +### RoleGranted + +```solidity +event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender) +``` + + + +*Emitted when `account` is granted `role`. `sender` is the account that originated the contract call, an admin role bearer except when using {AccessControl-_setupRole}.* + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| role `indexed` | bytes32 | undefined | +| account `indexed` | address | undefined | +| sender `indexed` | address | undefined | + +### RoleRevoked + +```solidity +event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender) +``` + + + +*Emitted when `account` is revoked `role`. `sender` is the account that originated the contract call: - if using `revokeRole`, it is the admin role bearer - if using `renounceRole`, it is the role bearer (i.e. `account`)* + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| role `indexed` | bytes32 | undefined | +| account `indexed` | address | undefined | +| sender `indexed` | address | undefined | + + + diff --git a/docs/elin/contracts-4.3.1-upgradeable/proxy/utils/Initializable.md b/docs/elin/contracts-4.3.1-upgradeable/proxy/utils/Initializable.md new file mode 100644 index 000000000..647d95b62 --- /dev/null +++ b/docs/elin/contracts-4.3.1-upgradeable/proxy/utils/Initializable.md @@ -0,0 +1,12 @@ +# Initializable + + + + + + + +*This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed behind a proxy. Since proxied contracts do not make use of a constructor, it's common to move constructor logic to an external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer function so it can only be called once. The {initializer} modifier provided by this contract will have this effect. TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as possible by providing the encoded function call as the `_data` argument to {ERC1967Proxy-constructor}. CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure that all initializers are idempotent. This is not verified automatically as constructors are by Solidity. [CAUTION] ==== Avoid leaving a contract uninitialized. An uninitialized contract can be taken over by an attacker. This applies to both a proxy and its implementation contract, which may impact the proxy. To initialize the implementation contract, you can either invoke the initializer manually, or you can include a constructor to automatically mark it as initialized when it is deployed: [.hljs-theme-light.nopadding] ```* + + + diff --git a/docs/elin/contracts-4.3.1-upgradeable/security/ReentrancyGuardUpgradeable.md b/docs/elin/contracts-4.3.1-upgradeable/security/ReentrancyGuardUpgradeable.md new file mode 100644 index 000000000..6955ca2de --- /dev/null +++ b/docs/elin/contracts-4.3.1-upgradeable/security/ReentrancyGuardUpgradeable.md @@ -0,0 +1,12 @@ +# ReentrancyGuardUpgradeable + + + + + + + +*Contract module that helps prevent reentrant calls to a function. Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier available, which can be applied to functions to make sure there are no nested (reentrant) calls to them. Note that because there is a single `nonReentrant` guard, functions marked as `nonReentrant` may not call one another. This can be worked around by making those functions `private`, and then adding `external` `nonReentrant` entry points to them. TIP: If you would like to learn more about reentrancy and alternative ways to protect against it, check out our blog post https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul].* + + + diff --git a/docs/elin/contracts-4.3.1-upgradeable/utils/AddressUpgradeable.md b/docs/elin/contracts-4.3.1-upgradeable/utils/AddressUpgradeable.md new file mode 100644 index 000000000..456cdd15d --- /dev/null +++ b/docs/elin/contracts-4.3.1-upgradeable/utils/AddressUpgradeable.md @@ -0,0 +1,12 @@ +# AddressUpgradeable + + + + + + + +*Collection of functions related to the address type* + + + diff --git a/docs/elin/contracts-4.3.1-upgradeable/utils/ContextUpgradeable.md b/docs/elin/contracts-4.3.1-upgradeable/utils/ContextUpgradeable.md new file mode 100644 index 000000000..18f33b80f --- /dev/null +++ b/docs/elin/contracts-4.3.1-upgradeable/utils/ContextUpgradeable.md @@ -0,0 +1,12 @@ +# ContextUpgradeable + + + + + + + +*Provides information about the current execution context, including the sender of the transaction and its data. While these are generally available via msg.sender and msg.data, they should not be accessed in such a direct manner, since when dealing with meta-transactions the account sending and paying for execution may not be the actual sender (as far as an application is concerned). This contract is only required for intermediate, library-like contracts.* + + + diff --git a/docs/elin/contracts-4.3.1-upgradeable/utils/StringsUpgradeable.md b/docs/elin/contracts-4.3.1-upgradeable/utils/StringsUpgradeable.md new file mode 100644 index 000000000..84464ba83 --- /dev/null +++ b/docs/elin/contracts-4.3.1-upgradeable/utils/StringsUpgradeable.md @@ -0,0 +1,12 @@ +# StringsUpgradeable + + + + + + + +*String operations.* + + + diff --git a/docs/elin/contracts-4.3.1-upgradeable/utils/introspection/ERC165Upgradeable.md b/docs/elin/contracts-4.3.1-upgradeable/utils/introspection/ERC165Upgradeable.md new file mode 100644 index 000000000..914b09248 --- /dev/null +++ b/docs/elin/contracts-4.3.1-upgradeable/utils/introspection/ERC165Upgradeable.md @@ -0,0 +1,37 @@ +# ERC165Upgradeable + + + + + + + +*Implementation of the {IERC165} interface. Contracts that want to implement ERC165 should inherit from this contract and override {supportsInterface} to check for the additional interface id that will be supported. For example: ```solidity function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) { return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId); } ``` Alternatively, {ERC165Storage} provides an easier to use but more expensive implementation.* + +## Methods + +### supportsInterface + +```solidity +function supportsInterface(bytes4 interfaceId) external view returns (bool) +``` + + + +*See {IERC165-supportsInterface}.* + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| interfaceId | bytes4 | undefined | + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | bool | undefined | + + + + diff --git a/docs/elin/contracts-4.3.1-upgradeable/utils/introspection/IERC165Upgradeable.md b/docs/elin/contracts-4.3.1-upgradeable/utils/introspection/IERC165Upgradeable.md new file mode 100644 index 000000000..40ec0512e --- /dev/null +++ b/docs/elin/contracts-4.3.1-upgradeable/utils/introspection/IERC165Upgradeable.md @@ -0,0 +1,37 @@ +# IERC165Upgradeable + + + + + + + +*Interface of the ERC165 standard, as defined in the https://eips.ethereum.org/EIPS/eip-165[EIP]. Implementers can declare support of contract interfaces, which can then be queried by others ({ERC165Checker}). For an implementation, see {ERC165}.* + +## Methods + +### supportsInterface + +```solidity +function supportsInterface(bytes4 interfaceId) external view returns (bool) +``` + + + +*Returns true if this contract implements the interface defined by `interfaceId`. See the corresponding https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section] to learn more about how these ids are created. This function call must use less than 30 000 gas.* + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| interfaceId | bytes4 | undefined | + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | bool | undefined | + + + + diff --git a/docs/elin/contracts-4.3.1-upgradeable/utils/math/MathUpgradeable.md b/docs/elin/contracts-4.3.1-upgradeable/utils/math/MathUpgradeable.md new file mode 100644 index 000000000..9c18c68bc --- /dev/null +++ b/docs/elin/contracts-4.3.1-upgradeable/utils/math/MathUpgradeable.md @@ -0,0 +1,12 @@ +# MathUpgradeable + + + + + + + +*Standard math utilities missing in the Solidity language.* + + + diff --git a/docs/elin/contracts-4.3.1/access/AccessControl.md b/docs/elin/contracts-4.3.1/access/AccessControl.md new file mode 100644 index 000000000..9fdf479dd --- /dev/null +++ b/docs/elin/contracts-4.3.1/access/AccessControl.md @@ -0,0 +1,207 @@ +# AccessControl + + + + + + + +*Contract module that allows children to implement role-based access control mechanisms. This is a lightweight version that doesn't allow enumerating role members except through off-chain means by accessing the contract event logs. Some applications may benefit from on-chain enumerability, for those cases see {AccessControlEnumerable}. Roles are referred to by their `bytes32` identifier. These should be exposed in the external API and be unique. The best way to achieve this is by using `public constant` hash digests: ``` bytes32 public constant MY_ROLE = keccak256("MY_ROLE"); ``` Roles can be used to represent a set of permissions. To restrict access to a function call, use {hasRole}: ``` function foo() public { require(hasRole(MY_ROLE, msg.sender)); ... } ``` Roles can be granted and revoked dynamically via the {grantRole} and {revokeRole} functions. Each role has an associated admin role, and only accounts that have a role's admin role can call {grantRole} and {revokeRole}. By default, the admin role for all roles is `DEFAULT_ADMIN_ROLE`, which means that only accounts with this role will be able to grant or revoke other roles. More complex role relationships can be created by using {_setRoleAdmin}. WARNING: The `DEFAULT_ADMIN_ROLE` is also its own admin: it has permission to grant and revoke this role. Extra precautions should be taken to secure accounts that have been granted it.* + +## Methods + +### DEFAULT_ADMIN_ROLE + +```solidity +function DEFAULT_ADMIN_ROLE() external view returns (bytes32) +``` + + + + + + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | bytes32 | undefined | + +### getRoleAdmin + +```solidity +function getRoleAdmin(bytes32 role) external view returns (bytes32) +``` + + + +*Returns the admin role that controls `role`. See {grantRole} and {revokeRole}. To change a role's admin, use {_setRoleAdmin}.* + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| role | bytes32 | undefined | + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | bytes32 | undefined | + +### grantRole + +```solidity +function grantRole(bytes32 role, address account) external nonpayable +``` + + + +*Grants `role` to `account`. If `account` had not been already granted `role`, emits a {RoleGranted} event. Requirements: - the caller must have ``role``'s admin role.* + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| role | bytes32 | undefined | +| account | address | undefined | + +### hasRole + +```solidity +function hasRole(bytes32 role, address account) external view returns (bool) +``` + + + +*Returns `true` if `account` has been granted `role`.* + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| role | bytes32 | undefined | +| account | address | undefined | + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | bool | undefined | + +### renounceRole + +```solidity +function renounceRole(bytes32 role, address account) external nonpayable +``` + + + +*Revokes `role` from the calling account. Roles are often managed via {grantRole} and {revokeRole}: this function's purpose is to provide a mechanism for accounts to lose their privileges if they are compromised (such as when a trusted device is misplaced). If the calling account had been revoked `role`, emits a {RoleRevoked} event. Requirements: - the caller must be `account`.* + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| role | bytes32 | undefined | +| account | address | undefined | + +### revokeRole + +```solidity +function revokeRole(bytes32 role, address account) external nonpayable +``` + + + +*Revokes `role` from `account`. If `account` had been granted `role`, emits a {RoleRevoked} event. Requirements: - the caller must have ``role``'s admin role.* + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| role | bytes32 | undefined | +| account | address | undefined | + +### supportsInterface + +```solidity +function supportsInterface(bytes4 interfaceId) external view returns (bool) +``` + + + +*See {IERC165-supportsInterface}.* + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| interfaceId | bytes4 | undefined | + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | bool | undefined | + + + +## Events + +### RoleAdminChanged + +```solidity +event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole) +``` + + + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| role `indexed` | bytes32 | undefined | +| previousAdminRole `indexed` | bytes32 | undefined | +| newAdminRole `indexed` | bytes32 | undefined | + +### RoleGranted + +```solidity +event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender) +``` + + + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| role `indexed` | bytes32 | undefined | +| account `indexed` | address | undefined | +| sender `indexed` | address | undefined | + +### RoleRevoked + +```solidity +event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender) +``` + + + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| role `indexed` | bytes32 | undefined | +| account `indexed` | address | undefined | +| sender `indexed` | address | undefined | + + + diff --git a/docs/elin/contracts-4.3.1/access/IAccessControl.md b/docs/elin/contracts-4.3.1/access/IAccessControl.md new file mode 100644 index 000000000..1916d28b3 --- /dev/null +++ b/docs/elin/contracts-4.3.1/access/IAccessControl.md @@ -0,0 +1,168 @@ +# IAccessControl + + + + + + + +*External interface of AccessControl declared to support ERC165 detection.* + +## Methods + +### getRoleAdmin + +```solidity +function getRoleAdmin(bytes32 role) external view returns (bytes32) +``` + + + +*Returns the admin role that controls `role`. See {grantRole} and {revokeRole}. To change a role's admin, use {AccessControl-_setRoleAdmin}.* + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| role | bytes32 | undefined | + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | bytes32 | undefined | + +### grantRole + +```solidity +function grantRole(bytes32 role, address account) external nonpayable +``` + + + +*Grants `role` to `account`. If `account` had not been already granted `role`, emits a {RoleGranted} event. Requirements: - the caller must have ``role``'s admin role.* + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| role | bytes32 | undefined | +| account | address | undefined | + +### hasRole + +```solidity +function hasRole(bytes32 role, address account) external view returns (bool) +``` + + + +*Returns `true` if `account` has been granted `role`.* + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| role | bytes32 | undefined | +| account | address | undefined | + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | bool | undefined | + +### renounceRole + +```solidity +function renounceRole(bytes32 role, address account) external nonpayable +``` + + + +*Revokes `role` from the calling account. Roles are often managed via {grantRole} and {revokeRole}: this function's purpose is to provide a mechanism for accounts to lose their privileges if they are compromised (such as when a trusted device is misplaced). If the calling account had been granted `role`, emits a {RoleRevoked} event. Requirements: - the caller must be `account`.* + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| role | bytes32 | undefined | +| account | address | undefined | + +### revokeRole + +```solidity +function revokeRole(bytes32 role, address account) external nonpayable +``` + + + +*Revokes `role` from `account`. If `account` had been granted `role`, emits a {RoleRevoked} event. Requirements: - the caller must have ``role``'s admin role.* + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| role | bytes32 | undefined | +| account | address | undefined | + + + +## Events + +### RoleAdminChanged + +```solidity +event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole) +``` + + + +*Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole` `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite {RoleAdminChanged} not being emitted signaling this. _Available since v3.1._* + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| role `indexed` | bytes32 | undefined | +| previousAdminRole `indexed` | bytes32 | undefined | +| newAdminRole `indexed` | bytes32 | undefined | + +### RoleGranted + +```solidity +event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender) +``` + + + +*Emitted when `account` is granted `role`. `sender` is the account that originated the contract call, an admin role bearer except when using {AccessControl-_setupRole}.* + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| role `indexed` | bytes32 | undefined | +| account `indexed` | address | undefined | +| sender `indexed` | address | undefined | + +### RoleRevoked + +```solidity +event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender) +``` + + + +*Emitted when `account` is revoked `role`. `sender` is the account that originated the contract call: - if using `revokeRole`, it is the admin role bearer - if using `renounceRole`, it is the role bearer (i.e. `account`)* + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| role `indexed` | bytes32 | undefined | +| account `indexed` | address | undefined | +| sender `indexed` | address | undefined | + + + diff --git a/docs/elin/contracts-4.3.1/utils/Context.md b/docs/elin/contracts-4.3.1/utils/Context.md new file mode 100644 index 000000000..4ab2a3548 --- /dev/null +++ b/docs/elin/contracts-4.3.1/utils/Context.md @@ -0,0 +1,12 @@ +# Context + + + + + + + +*Provides information about the current execution context, including the sender of the transaction and its data. While these are generally available via msg.sender and msg.data, they should not be accessed in such a direct manner, since when dealing with meta-transactions the account sending and paying for execution may not be the actual sender (as far as an application is concerned). This contract is only required for intermediate, library-like contracts.* + + + diff --git a/docs/elin/contracts-4.3.1/utils/Strings.md b/docs/elin/contracts-4.3.1/utils/Strings.md new file mode 100644 index 000000000..f85055d64 --- /dev/null +++ b/docs/elin/contracts-4.3.1/utils/Strings.md @@ -0,0 +1,12 @@ +# Strings + + + + + + + +*String operations.* + + + diff --git a/docs/elin/contracts-4.3.1/utils/introspection/ERC165.md b/docs/elin/contracts-4.3.1/utils/introspection/ERC165.md new file mode 100644 index 000000000..df8950ab9 --- /dev/null +++ b/docs/elin/contracts-4.3.1/utils/introspection/ERC165.md @@ -0,0 +1,37 @@ +# ERC165 + + + + + + + +*Implementation of the {IERC165} interface. Contracts that want to implement ERC165 should inherit from this contract and override {supportsInterface} to check for the additional interface id that will be supported. For example: ```solidity function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) { return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId); } ``` Alternatively, {ERC165Storage} provides an easier to use but more expensive implementation.* + +## Methods + +### supportsInterface + +```solidity +function supportsInterface(bytes4 interfaceId) external view returns (bool) +``` + + + +*See {IERC165-supportsInterface}.* + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| interfaceId | bytes4 | undefined | + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | bool | undefined | + + + + diff --git a/docs/elin/contracts-4.3.1/utils/introspection/IERC165.md b/docs/elin/contracts-4.3.1/utils/introspection/IERC165.md new file mode 100644 index 000000000..71a9f6e6d --- /dev/null +++ b/docs/elin/contracts-4.3.1/utils/introspection/IERC165.md @@ -0,0 +1,37 @@ +# IERC165 + + + + + + + +*Interface of the ERC165 standard, as defined in the https://eips.ethereum.org/EIPS/eip-165[EIP]. Implementers can declare support of contract interfaces, which can then be queried by others ({ERC165Checker}). For an implementation, see {ERC165}.* + +## Methods + +### supportsInterface + +```solidity +function supportsInterface(bytes4 interfaceId) external view returns (bool) +``` + + + +*Returns true if this contract implements the interface defined by `interfaceId`. See the corresponding https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section] to learn more about how these ids are created. This function call must use less than 30 000 gas.* + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| interfaceId | bytes4 | undefined | + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | bool | undefined | + + + + diff --git a/docs/elin/contracts-4.3.1/utils/math/SafeMath.md b/docs/elin/contracts-4.3.1/utils/math/SafeMath.md new file mode 100644 index 000000000..7bf9fd7a5 --- /dev/null +++ b/docs/elin/contracts-4.3.1/utils/math/SafeMath.md @@ -0,0 +1,12 @@ +# SafeMath + + + + + + + +*Wrappers over Solidity's arithmetic operations. NOTE: `SafeMath` is generally not needed starting with Solidity 0.8, since the compiler now has built in overflow checking.* + + + diff --git a/docs/elin/contracts-4.6.0-upgradeable/utils/structs/EnumerableMapUpgradeable.md b/docs/elin/contracts-4.6.0-upgradeable/utils/structs/EnumerableMapUpgradeable.md new file mode 100644 index 000000000..d028fe0d4 --- /dev/null +++ b/docs/elin/contracts-4.6.0-upgradeable/utils/structs/EnumerableMapUpgradeable.md @@ -0,0 +1,12 @@ +# EnumerableMapUpgradeable + + + + + + + +*Library for managing an enumerable variant of Solidity's https://solidity.readthedocs.io/en/latest/types.html#mapping-types[`mapping`] type. Maps have the following properties: - Entries are added, removed, and checked for existence in constant time (O(1)). - Entries are enumerated in O(n). No guarantees are made on the ordering. ``` contract Example { // Add the library methods using EnumerableMap for EnumerableMap.UintToAddressMap; // Declare a set state variable EnumerableMap.UintToAddressMap private myMap; } ``` The following map types are supported: - `uint256 -> address` (`UintToAddressMap`) since v3.0.0 - `address -> uint256` (`AddressToUintMap`) since v4.6.0 - `bytes32 -> bytes32` (`Bytes32ToBytes32`) since v4.6.0* + + + diff --git a/docs/elin/contracts-4.6.0-upgradeable/utils/structs/EnumerableSetUpgradeable.md b/docs/elin/contracts-4.6.0-upgradeable/utils/structs/EnumerableSetUpgradeable.md new file mode 100644 index 000000000..1a169e579 --- /dev/null +++ b/docs/elin/contracts-4.6.0-upgradeable/utils/structs/EnumerableSetUpgradeable.md @@ -0,0 +1,12 @@ +# EnumerableSetUpgradeable + + + + + + + +*Library for managing https://en.wikipedia.org/wiki/Set_(abstract_data_type)[sets] of primitive types. Sets have the following properties: - Elements are added, removed, and checked for existence in constant time (O(1)). - Elements are enumerated in O(n). No guarantees are made on the ordering. ``` contract Example { // Add the library methods using EnumerableSet for EnumerableSet.AddressSet; // Declare a set state variable EnumerableSet.AddressSet private mySet; } ``` As of v3.3.0, sets of type `bytes32` (`Bytes32Set`), `address` (`AddressSet`) and `uint256` (`UintSet`) are supported.* + + + diff --git a/docs/elin/contracts-upgradeable/access/AccessControlUpgradeable.md b/docs/elin/contracts-upgradeable/access/AccessControlUpgradeable.md new file mode 100644 index 000000000..8173dc159 --- /dev/null +++ b/docs/elin/contracts-upgradeable/access/AccessControlUpgradeable.md @@ -0,0 +1,230 @@ +# AccessControlUpgradeable + + + + + + + +*Contract module that allows children to implement role-based access control mechanisms. Roles are referred to by their `bytes32` identifier. These should be exposed in the external API and be unique. The best way to achieve this is by using `public constant` hash digests: ``` bytes32 public constant MY_ROLE = keccak256("MY_ROLE"); ``` Roles can be used to represent a set of permissions. To restrict access to a function call, use {hasRole}: ``` function foo() public { require(hasRole(MY_ROLE, msg.sender)); ... } ``` Roles can be granted and revoked dynamically via the {grantRole} and {revokeRole} functions. Each role has an associated admin role, and only accounts that have a role's admin role can call {grantRole} and {revokeRole}. By default, the admin role for all roles is `DEFAULT_ADMIN_ROLE`, which means that only accounts with this role will be able to grant or revoke other roles. More complex role relationships can be created by using {_setRoleAdmin}. WARNING: The `DEFAULT_ADMIN_ROLE` is also its own admin: it has permission to grant and revoke this role. Extra precautions should be taken to secure accounts that have been granted it.* + +## Methods + +### DEFAULT_ADMIN_ROLE + +```solidity +function DEFAULT_ADMIN_ROLE() external view returns (bytes32) +``` + + + + + + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | bytes32 | undefined | + +### getRoleAdmin + +```solidity +function getRoleAdmin(bytes32 role) external view returns (bytes32) +``` + + + +*Returns the admin role that controls `role`. See {grantRole} and {revokeRole}. To change a role's admin, use {_setRoleAdmin}.* + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| role | bytes32 | undefined | + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | bytes32 | undefined | + +### getRoleMember + +```solidity +function getRoleMember(bytes32 role, uint256 index) external view returns (address) +``` + + + +*Returns one of the accounts that have `role`. `index` must be a value between 0 and {getRoleMemberCount}, non-inclusive. Role bearers are not sorted in any particular way, and their ordering may change at any point. WARNING: When using {getRoleMember} and {getRoleMemberCount}, make sure you perform all queries on the same block. See the following https://forum.openzeppelin.com/t/iterating-over-elements-on-enumerableset-in-openzeppelin-contracts/2296[forum post] for more information.* + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| role | bytes32 | undefined | +| index | uint256 | undefined | + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | address | undefined | + +### getRoleMemberCount + +```solidity +function getRoleMemberCount(bytes32 role) external view returns (uint256) +``` + + + +*Returns the number of accounts that have `role`. Can be used together with {getRoleMember} to enumerate all bearers of a role.* + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| role | bytes32 | undefined | + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | uint256 | undefined | + +### grantRole + +```solidity +function grantRole(bytes32 role, address account) external nonpayable +``` + + + +*Grants `role` to `account`. If `account` had not been already granted `role`, emits a {RoleGranted} event. Requirements: - the caller must have ``role``'s admin role.* + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| role | bytes32 | undefined | +| account | address | undefined | + +### hasRole + +```solidity +function hasRole(bytes32 role, address account) external view returns (bool) +``` + + + +*Returns `true` if `account` has been granted `role`.* + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| role | bytes32 | undefined | +| account | address | undefined | + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | bool | undefined | + +### renounceRole + +```solidity +function renounceRole(bytes32 role, address account) external nonpayable +``` + + + +*Revokes `role` from the calling account. Roles are often managed via {grantRole} and {revokeRole}: this function's purpose is to provide a mechanism for accounts to lose their privileges if they are compromised (such as when a trusted device is misplaced). If the calling account had been granted `role`, emits a {RoleRevoked} event. Requirements: - the caller must be `account`.* + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| role | bytes32 | undefined | +| account | address | undefined | + +### revokeRole + +```solidity +function revokeRole(bytes32 role, address account) external nonpayable +``` + + + +*Revokes `role` from `account`. If `account` had been granted `role`, emits a {RoleRevoked} event. Requirements: - the caller must have ``role``'s admin role.* + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| role | bytes32 | undefined | +| account | address | undefined | + + + +## Events + +### RoleAdminChanged + +```solidity +event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole) +``` + + + +*Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole` `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite {RoleAdminChanged} not being emitted signaling this. _Available since v3.1._* + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| role `indexed` | bytes32 | undefined | +| previousAdminRole `indexed` | bytes32 | undefined | +| newAdminRole `indexed` | bytes32 | undefined | + +### RoleGranted + +```solidity +event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender) +``` + + + +*Emitted when `account` is granted `role`. `sender` is the account that originated the contract call, an admin role bearer except when using {_setupRole}.* + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| role `indexed` | bytes32 | undefined | +| account `indexed` | address | undefined | +| sender `indexed` | address | undefined | + +### RoleRevoked + +```solidity +event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender) +``` + + + +*Emitted when `account` is revoked `role`. `sender` is the account that originated the contract call: - if using `revokeRole`, it is the admin role bearer - if using `renounceRole`, it is the role bearer (i.e. `account`)* + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| role `indexed` | bytes32 | undefined | +| account `indexed` | address | undefined | +| sender `indexed` | address | undefined | + + + diff --git a/docs/elin/contracts-upgradeable/access/OwnableUpgradeable.md b/docs/elin/contracts-upgradeable/access/OwnableUpgradeable.md new file mode 100644 index 000000000..923f9d6ea --- /dev/null +++ b/docs/elin/contracts-upgradeable/access/OwnableUpgradeable.md @@ -0,0 +1,79 @@ +# OwnableUpgradeable + + + + + + + +*Contract module which provides a basic access control mechanism, where there is an account (an owner) that can be granted exclusive access to specific functions. By default, the owner account will be the one that deploys the contract. This can later be changed with {transferOwnership}. This module is used through inheritance. It will make available the modifier `onlyOwner`, which can be applied to your functions to restrict their use to the owner.* + +## Methods + +### owner + +```solidity +function owner() external view returns (address) +``` + + + +*Returns the address of the current owner.* + + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | address | undefined | + +### renounceOwnership + +```solidity +function renounceOwnership() external nonpayable +``` + + + +*Leaves the contract without owner. It will not be possible to call `onlyOwner` functions anymore. Can only be called by the current owner. NOTE: Renouncing ownership will leave the contract without an owner, thereby removing any functionality that is only available to the owner.* + + +### transferOwnership + +```solidity +function transferOwnership(address newOwner) external nonpayable +``` + + + +*Transfers ownership of the contract to a new account (`newOwner`). Can only be called by the current owner.* + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| newOwner | address | undefined | + + + +## Events + +### OwnershipTransferred + +```solidity +event OwnershipTransferred(address indexed previousOwner, address indexed newOwner) +``` + + + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| previousOwner `indexed` | address | undefined | +| newOwner `indexed` | address | undefined | + + + diff --git a/docs/elin/contracts-upgradeable/cryptography/ECDSAUpgradeable.md b/docs/elin/contracts-upgradeable/cryptography/ECDSAUpgradeable.md new file mode 100644 index 000000000..5035a7b74 --- /dev/null +++ b/docs/elin/contracts-upgradeable/cryptography/ECDSAUpgradeable.md @@ -0,0 +1,12 @@ +# ECDSAUpgradeable + + + + + + + +*Elliptic Curve Digital Signature Algorithm (ECDSA) operations. These functions can be used to verify that a message was signed by the holder of the private keys of a given address.* + + + diff --git a/docs/elin/contracts-upgradeable/drafts/EIP712Upgradeable.md b/docs/elin/contracts-upgradeable/drafts/EIP712Upgradeable.md new file mode 100644 index 000000000..5dfe58185 --- /dev/null +++ b/docs/elin/contracts-upgradeable/drafts/EIP712Upgradeable.md @@ -0,0 +1,12 @@ +# EIP712Upgradeable + + + + + + + +*https://eips.ethereum.org/EIPS/eip-712[EIP 712] is a standard for hashing and signing of typed structured data. The encoding specified in the EIP is very generic, and such a generic implementation in Solidity is not feasible, thus this contract does not implement the encoding itself. Protocols need to implement the type-specific encoding they need in their contracts using a combination of `abi.encode` and `keccak256`. This contract implements the EIP 712 domain separator ({_domainSeparatorV4}) that is used as part of the encoding scheme, and the final step of the encoding to obtain the message digest that is then signed via ECDSA ({_hashTypedDataV4}). The implementation of the domain separator was designed to be as efficient as possible while still properly updating the chain id to protect against replay attacks on an eventual fork of the chain. NOTE: This contract implements the version of the encoding known as "v4", as implemented by the JSON RPC method https://docs.metamask.io/guide/signing-data.html[`eth_signTypedDataV4` in MetaMask]. _Available since v3.4._* + + + diff --git a/docs/elin/contracts-upgradeable/drafts/ERC20PermitUpgradeable.md b/docs/elin/contracts-upgradeable/drafts/ERC20PermitUpgradeable.md new file mode 100644 index 000000000..d37d5a342 --- /dev/null +++ b/docs/elin/contracts-upgradeable/drafts/ERC20PermitUpgradeable.md @@ -0,0 +1,344 @@ +# ERC20PermitUpgradeable + + + + + + + +*Implementation of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in https://eips.ethereum.org/EIPS/eip-2612[EIP-2612]. Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by presenting a message signed by the account. By not relying on `{IERC20-approve}`, the token holder account doesn't need to send a transaction, and thus is not required to hold Ether at all. _Available since v3.4._* + +## Methods + +### DOMAIN_SEPARATOR + +```solidity +function DOMAIN_SEPARATOR() external view returns (bytes32) +``` + + + +*See {IERC20Permit-DOMAIN_SEPARATOR}.* + + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | bytes32 | undefined | + +### allowance + +```solidity +function allowance(address owner, address spender) external view returns (uint256) +``` + + + +*See {IERC20-allowance}.* + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| owner | address | undefined | +| spender | address | undefined | + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | uint256 | undefined | + +### approve + +```solidity +function approve(address spender, uint256 amount) external nonpayable returns (bool) +``` + + + +*See {IERC20-approve}. Requirements: - `spender` cannot be the zero address.* + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| spender | address | undefined | +| amount | uint256 | undefined | + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | bool | undefined | + +### balanceOf + +```solidity +function balanceOf(address account) external view returns (uint256) +``` + + + +*See {IERC20-balanceOf}.* + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| account | address | undefined | + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | uint256 | undefined | + +### decimals + +```solidity +function decimals() external view returns (uint8) +``` + + + +*Returns the number of decimals used to get its user representation. For example, if `decimals` equals `2`, a balance of `505` tokens should be displayed to a user as `5,05` (`505 / 10 ** 2`). Tokens usually opt for a value of 18, imitating the relationship between Ether and Wei. This is the value {ERC20} uses, unless {_setupDecimals} is called. NOTE: This information is only used for _display_ purposes: it in no way affects any of the arithmetic of the contract, including {IERC20-balanceOf} and {IERC20-transfer}.* + + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | uint8 | undefined | + +### decreaseAllowance + +```solidity +function decreaseAllowance(address spender, uint256 subtractedValue) external nonpayable returns (bool) +``` + + + +*Atomically decreases the allowance granted to `spender` by the caller. This is an alternative to {approve} that can be used as a mitigation for problems described in {IERC20-approve}. Emits an {Approval} event indicating the updated allowance. Requirements: - `spender` cannot be the zero address. - `spender` must have allowance for the caller of at least `subtractedValue`.* + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| spender | address | undefined | +| subtractedValue | uint256 | undefined | + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | bool | undefined | + +### increaseAllowance + +```solidity +function increaseAllowance(address spender, uint256 addedValue) external nonpayable returns (bool) +``` + + + +*Atomically increases the allowance granted to `spender` by the caller. This is an alternative to {approve} that can be used as a mitigation for problems described in {IERC20-approve}. Emits an {Approval} event indicating the updated allowance. Requirements: - `spender` cannot be the zero address.* + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| spender | address | undefined | +| addedValue | uint256 | undefined | + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | bool | undefined | + +### name + +```solidity +function name() external view returns (string) +``` + + + +*Returns the name of the token.* + + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | string | undefined | + +### nonces + +```solidity +function nonces(address owner) external view returns (uint256) +``` + + + +*See {IERC20Permit-nonces}.* + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| owner | address | undefined | + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | uint256 | undefined | + +### permit + +```solidity +function permit(address owner, address spender, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s) external nonpayable +``` + + + +*See {IERC20Permit-permit}.* + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| owner | address | undefined | +| spender | address | undefined | +| value | uint256 | undefined | +| deadline | uint256 | undefined | +| v | uint8 | undefined | +| r | bytes32 | undefined | +| s | bytes32 | undefined | + +### symbol + +```solidity +function symbol() external view returns (string) +``` + + + +*Returns the symbol of the token, usually a shorter version of the name.* + + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | string | undefined | + +### totalSupply + +```solidity +function totalSupply() external view returns (uint256) +``` + + + +*See {IERC20-totalSupply}.* + + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | uint256 | undefined | + +### transfer + +```solidity +function transfer(address recipient, uint256 amount) external nonpayable returns (bool) +``` + + + +*See {IERC20-transfer}. Requirements: - `recipient` cannot be the zero address. - the caller must have a balance of at least `amount`.* + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| recipient | address | undefined | +| amount | uint256 | undefined | + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | bool | undefined | + +### transferFrom + +```solidity +function transferFrom(address sender, address recipient, uint256 amount) external nonpayable returns (bool) +``` + + + +*See {IERC20-transferFrom}. Emits an {Approval} event indicating the updated allowance. This is not required by the EIP. See the note at the beginning of {ERC20}. Requirements: - `sender` and `recipient` cannot be the zero address. - `sender` must have a balance of at least `amount`. - the caller must have allowance for ``sender``'s tokens of at least `amount`.* + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| sender | address | undefined | +| recipient | address | undefined | +| amount | uint256 | undefined | + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | bool | undefined | + + + +## Events + +### Approval + +```solidity +event Approval(address indexed owner, address indexed spender, uint256 value) +``` + + + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| owner `indexed` | address | undefined | +| spender `indexed` | address | undefined | +| value | uint256 | undefined | + +### Transfer + +```solidity +event Transfer(address indexed from, address indexed to, uint256 value) +``` + + + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| from `indexed` | address | undefined | +| to `indexed` | address | undefined | +| value | uint256 | undefined | + + + diff --git a/docs/elin/contracts-upgradeable/drafts/IERC20PermitUpgradeable.md b/docs/elin/contracts-upgradeable/drafts/IERC20PermitUpgradeable.md new file mode 100644 index 000000000..484aadf15 --- /dev/null +++ b/docs/elin/contracts-upgradeable/drafts/IERC20PermitUpgradeable.md @@ -0,0 +1,76 @@ +# IERC20PermitUpgradeable + + + + + + + +*Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in https://eips.ethereum.org/EIPS/eip-2612[EIP-2612]. Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by presenting a message signed by the account. By not relying on `{IERC20-approve}`, the token holder account doesn't need to send a transaction, and thus is not required to hold Ether at all.* + +## Methods + +### DOMAIN_SEPARATOR + +```solidity +function DOMAIN_SEPARATOR() external view returns (bytes32) +``` + + + +*Returns the domain separator used in the encoding of the signature for `permit`, as defined by {EIP712}.* + + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | bytes32 | undefined | + +### nonces + +```solidity +function nonces(address owner) external view returns (uint256) +``` + + + +*Returns the current nonce for `owner`. This value must be included whenever a signature is generated for {permit}. Every successful call to {permit} increases ``owner``'s nonce by one. This prevents a signature from being used multiple times.* + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| owner | address | undefined | + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | uint256 | undefined | + +### permit + +```solidity +function permit(address owner, address spender, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s) external nonpayable +``` + + + +*Sets `value` as the allowance of `spender` over `owner`'s tokens, given `owner`'s signed approval. IMPORTANT: The same issues {IERC20-approve} has related to transaction ordering also apply here. Emits an {Approval} event. Requirements: - `spender` cannot be the zero address. - `deadline` must be a timestamp in the future. - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner` over the EIP712-formatted function arguments. - the signature must use ``owner``'s current nonce (see {nonces}). For more information on the signature format, see the https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP section].* + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| owner | address | undefined | +| spender | address | undefined | +| value | uint256 | undefined | +| deadline | uint256 | undefined | +| v | uint8 | undefined | +| r | bytes32 | undefined | +| s | bytes32 | undefined | + + + + diff --git a/docs/elin/contracts-upgradeable/math/SafeMathUpgradeable.md b/docs/elin/contracts-upgradeable/math/SafeMathUpgradeable.md new file mode 100644 index 000000000..5b66c328e --- /dev/null +++ b/docs/elin/contracts-upgradeable/math/SafeMathUpgradeable.md @@ -0,0 +1,12 @@ +# SafeMathUpgradeable + + + + + + + +*Wrappers over Solidity's arithmetic operations with added overflow checks. Arithmetic operations in Solidity wrap on overflow. This can easily result in bugs, because programmers usually assume that an overflow raises an error, which is the standard behavior in high level programming languages. `SafeMath` restores this intuition by reverting the transaction when an operation overflows. Using this library instead of the unchecked operations eliminates an entire class of bugs, so it's recommended to use it always.* + + + diff --git a/docs/elin/contracts-upgradeable/proxy/Initializable.md b/docs/elin/contracts-upgradeable/proxy/Initializable.md new file mode 100644 index 000000000..3621c4fc8 --- /dev/null +++ b/docs/elin/contracts-upgradeable/proxy/Initializable.md @@ -0,0 +1,12 @@ +# Initializable + + + + + + + +*This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed behind a proxy. Since a proxied contract can't have a constructor, it's common to move constructor logic to an external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer function so it can only be called once. The {initializer} modifier provided by this contract will have this effect. TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as possible by providing the encoded function call as the `_data` argument to {UpgradeableProxy-constructor}. CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure that all initializers are idempotent. This is not verified automatically as constructors are by Solidity.* + + + diff --git a/docs/elin/contracts-upgradeable/token/ERC20/ERC20BurnableUpgradeable.md b/docs/elin/contracts-upgradeable/token/ERC20/ERC20BurnableUpgradeable.md new file mode 100644 index 000000000..b91b7eafe --- /dev/null +++ b/docs/elin/contracts-upgradeable/token/ERC20/ERC20BurnableUpgradeable.md @@ -0,0 +1,316 @@ +# ERC20BurnableUpgradeable + + + + + + + +*Extension of {ERC20} that allows token holders to destroy both their own tokens and those that they have an allowance for, in a way that can be recognized off-chain (via event analysis).* + +## Methods + +### allowance + +```solidity +function allowance(address owner, address spender) external view returns (uint256) +``` + + + +*See {IERC20-allowance}.* + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| owner | address | undefined | +| spender | address | undefined | + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | uint256 | undefined | + +### approve + +```solidity +function approve(address spender, uint256 amount) external nonpayable returns (bool) +``` + + + +*See {IERC20-approve}. Requirements: - `spender` cannot be the zero address.* + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| spender | address | undefined | +| amount | uint256 | undefined | + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | bool | undefined | + +### balanceOf + +```solidity +function balanceOf(address account) external view returns (uint256) +``` + + + +*See {IERC20-balanceOf}.* + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| account | address | undefined | + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | uint256 | undefined | + +### burn + +```solidity +function burn(uint256 amount) external nonpayable +``` + + + +*Destroys `amount` tokens from the caller. See {ERC20-_burn}.* + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| amount | uint256 | undefined | + +### burnFrom + +```solidity +function burnFrom(address account, uint256 amount) external nonpayable +``` + + + +*Destroys `amount` tokens from `account`, deducting from the caller's allowance. See {ERC20-_burn} and {ERC20-allowance}. Requirements: - the caller must have allowance for ``accounts``'s tokens of at least `amount`.* + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| account | address | undefined | +| amount | uint256 | undefined | + +### decimals + +```solidity +function decimals() external view returns (uint8) +``` + + + +*Returns the number of decimals used to get its user representation. For example, if `decimals` equals `2`, a balance of `505` tokens should be displayed to a user as `5,05` (`505 / 10 ** 2`). Tokens usually opt for a value of 18, imitating the relationship between Ether and Wei. This is the value {ERC20} uses, unless {_setupDecimals} is called. NOTE: This information is only used for _display_ purposes: it in no way affects any of the arithmetic of the contract, including {IERC20-balanceOf} and {IERC20-transfer}.* + + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | uint8 | undefined | + +### decreaseAllowance + +```solidity +function decreaseAllowance(address spender, uint256 subtractedValue) external nonpayable returns (bool) +``` + + + +*Atomically decreases the allowance granted to `spender` by the caller. This is an alternative to {approve} that can be used as a mitigation for problems described in {IERC20-approve}. Emits an {Approval} event indicating the updated allowance. Requirements: - `spender` cannot be the zero address. - `spender` must have allowance for the caller of at least `subtractedValue`.* + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| spender | address | undefined | +| subtractedValue | uint256 | undefined | + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | bool | undefined | + +### increaseAllowance + +```solidity +function increaseAllowance(address spender, uint256 addedValue) external nonpayable returns (bool) +``` + + + +*Atomically increases the allowance granted to `spender` by the caller. This is an alternative to {approve} that can be used as a mitigation for problems described in {IERC20-approve}. Emits an {Approval} event indicating the updated allowance. Requirements: - `spender` cannot be the zero address.* + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| spender | address | undefined | +| addedValue | uint256 | undefined | + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | bool | undefined | + +### name + +```solidity +function name() external view returns (string) +``` + + + +*Returns the name of the token.* + + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | string | undefined | + +### symbol + +```solidity +function symbol() external view returns (string) +``` + + + +*Returns the symbol of the token, usually a shorter version of the name.* + + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | string | undefined | + +### totalSupply + +```solidity +function totalSupply() external view returns (uint256) +``` + + + +*See {IERC20-totalSupply}.* + + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | uint256 | undefined | + +### transfer + +```solidity +function transfer(address recipient, uint256 amount) external nonpayable returns (bool) +``` + + + +*See {IERC20-transfer}. Requirements: - `recipient` cannot be the zero address. - the caller must have a balance of at least `amount`.* + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| recipient | address | undefined | +| amount | uint256 | undefined | + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | bool | undefined | + +### transferFrom + +```solidity +function transferFrom(address sender, address recipient, uint256 amount) external nonpayable returns (bool) +``` + + + +*See {IERC20-transferFrom}. Emits an {Approval} event indicating the updated allowance. This is not required by the EIP. See the note at the beginning of {ERC20}. Requirements: - `sender` and `recipient` cannot be the zero address. - `sender` must have a balance of at least `amount`. - the caller must have allowance for ``sender``'s tokens of at least `amount`.* + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| sender | address | undefined | +| recipient | address | undefined | +| amount | uint256 | undefined | + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | bool | undefined | + + + +## Events + +### Approval + +```solidity +event Approval(address indexed owner, address indexed spender, uint256 value) +``` + + + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| owner `indexed` | address | undefined | +| spender `indexed` | address | undefined | +| value | uint256 | undefined | + +### Transfer + +```solidity +event Transfer(address indexed from, address indexed to, uint256 value) +``` + + + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| from `indexed` | address | undefined | +| to `indexed` | address | undefined | +| value | uint256 | undefined | + + + diff --git a/docs/elin/contracts-upgradeable/token/ERC20/ERC20Upgradeable.md b/docs/elin/contracts-upgradeable/token/ERC20/ERC20Upgradeable.md new file mode 100644 index 000000000..a65f0f391 --- /dev/null +++ b/docs/elin/contracts-upgradeable/token/ERC20/ERC20Upgradeable.md @@ -0,0 +1,283 @@ +# ERC20Upgradeable + + + + + + + +*Implementation of the {IERC20} interface. This implementation is agnostic to the way tokens are created. This means that a supply mechanism has to be added in a derived contract using {_mint}. For a generic mechanism see {ERC20PresetMinterPauser}. TIP: For a detailed writeup see our guide https://forum.zeppelin.solutions/t/how-to-implement-erc20-supply-mechanisms/226[How to implement supply mechanisms]. We have followed general OpenZeppelin guidelines: functions revert instead of returning `false` on failure. This behavior is nonetheless conventional and does not conflict with the expectations of ERC20 applications. Additionally, an {Approval} event is emitted on calls to {transferFrom}. This allows applications to reconstruct the allowance for all accounts just by listening to said events. Other implementations of the EIP may not emit these events, as it isn't required by the specification. Finally, the non-standard {decreaseAllowance} and {increaseAllowance} functions have been added to mitigate the well-known issues around setting allowances. See {IERC20-approve}.* + +## Methods + +### allowance + +```solidity +function allowance(address owner, address spender) external view returns (uint256) +``` + + + +*See {IERC20-allowance}.* + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| owner | address | undefined | +| spender | address | undefined | + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | uint256 | undefined | + +### approve + +```solidity +function approve(address spender, uint256 amount) external nonpayable returns (bool) +``` + + + +*See {IERC20-approve}. Requirements: - `spender` cannot be the zero address.* + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| spender | address | undefined | +| amount | uint256 | undefined | + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | bool | undefined | + +### balanceOf + +```solidity +function balanceOf(address account) external view returns (uint256) +``` + + + +*See {IERC20-balanceOf}.* + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| account | address | undefined | + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | uint256 | undefined | + +### decimals + +```solidity +function decimals() external view returns (uint8) +``` + + + +*Returns the number of decimals used to get its user representation. For example, if `decimals` equals `2`, a balance of `505` tokens should be displayed to a user as `5,05` (`505 / 10 ** 2`). Tokens usually opt for a value of 18, imitating the relationship between Ether and Wei. This is the value {ERC20} uses, unless {_setupDecimals} is called. NOTE: This information is only used for _display_ purposes: it in no way affects any of the arithmetic of the contract, including {IERC20-balanceOf} and {IERC20-transfer}.* + + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | uint8 | undefined | + +### decreaseAllowance + +```solidity +function decreaseAllowance(address spender, uint256 subtractedValue) external nonpayable returns (bool) +``` + + + +*Atomically decreases the allowance granted to `spender` by the caller. This is an alternative to {approve} that can be used as a mitigation for problems described in {IERC20-approve}. Emits an {Approval} event indicating the updated allowance. Requirements: - `spender` cannot be the zero address. - `spender` must have allowance for the caller of at least `subtractedValue`.* + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| spender | address | undefined | +| subtractedValue | uint256 | undefined | + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | bool | undefined | + +### increaseAllowance + +```solidity +function increaseAllowance(address spender, uint256 addedValue) external nonpayable returns (bool) +``` + + + +*Atomically increases the allowance granted to `spender` by the caller. This is an alternative to {approve} that can be used as a mitigation for problems described in {IERC20-approve}. Emits an {Approval} event indicating the updated allowance. Requirements: - `spender` cannot be the zero address.* + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| spender | address | undefined | +| addedValue | uint256 | undefined | + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | bool | undefined | + +### name + +```solidity +function name() external view returns (string) +``` + + + +*Returns the name of the token.* + + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | string | undefined | + +### symbol + +```solidity +function symbol() external view returns (string) +``` + + + +*Returns the symbol of the token, usually a shorter version of the name.* + + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | string | undefined | + +### totalSupply + +```solidity +function totalSupply() external view returns (uint256) +``` + + + +*See {IERC20-totalSupply}.* + + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | uint256 | undefined | + +### transfer + +```solidity +function transfer(address recipient, uint256 amount) external nonpayable returns (bool) +``` + + + +*See {IERC20-transfer}. Requirements: - `recipient` cannot be the zero address. - the caller must have a balance of at least `amount`.* + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| recipient | address | undefined | +| amount | uint256 | undefined | + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | bool | undefined | + +### transferFrom + +```solidity +function transferFrom(address sender, address recipient, uint256 amount) external nonpayable returns (bool) +``` + + + +*See {IERC20-transferFrom}. Emits an {Approval} event indicating the updated allowance. This is not required by the EIP. See the note at the beginning of {ERC20}. Requirements: - `sender` and `recipient` cannot be the zero address. - `sender` must have a balance of at least `amount`. - the caller must have allowance for ``sender``'s tokens of at least `amount`.* + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| sender | address | undefined | +| recipient | address | undefined | +| amount | uint256 | undefined | + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | bool | undefined | + + + +## Events + +### Approval + +```solidity +event Approval(address indexed owner, address indexed spender, uint256 value) +``` + + + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| owner `indexed` | address | undefined | +| spender `indexed` | address | undefined | +| value | uint256 | undefined | + +### Transfer + +```solidity +event Transfer(address indexed from, address indexed to, uint256 value) +``` + + + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| from `indexed` | address | undefined | +| to `indexed` | address | undefined | +| value | uint256 | undefined | + + + diff --git a/docs/elin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.md b/docs/elin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.md new file mode 100644 index 000000000..70af4f841 --- /dev/null +++ b/docs/elin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.md @@ -0,0 +1,186 @@ +# IERC20Upgradeable + + + + + + + +*Interface of the ERC20 standard as defined in the EIP.* + +## Methods + +### allowance + +```solidity +function allowance(address owner, address spender) external view returns (uint256) +``` + + + +*Returns the remaining number of tokens that `spender` will be allowed to spend on behalf of `owner` through {transferFrom}. This is zero by default. This value changes when {approve} or {transferFrom} are called.* + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| owner | address | undefined | +| spender | address | undefined | + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | uint256 | undefined | + +### approve + +```solidity +function approve(address spender, uint256 amount) external nonpayable returns (bool) +``` + + + +*Sets `amount` as the allowance of `spender` over the caller's tokens. Returns a boolean value indicating whether the operation succeeded. IMPORTANT: Beware that changing an allowance with this method brings the risk that someone may use both the old and the new allowance by unfortunate transaction ordering. One possible solution to mitigate this race condition is to first reduce the spender's allowance to 0 and set the desired value afterwards: https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729 Emits an {Approval} event.* + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| spender | address | undefined | +| amount | uint256 | undefined | + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | bool | undefined | + +### balanceOf + +```solidity +function balanceOf(address account) external view returns (uint256) +``` + + + +*Returns the amount of tokens owned by `account`.* + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| account | address | undefined | + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | uint256 | undefined | + +### totalSupply + +```solidity +function totalSupply() external view returns (uint256) +``` + + + +*Returns the amount of tokens in existence.* + + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | uint256 | undefined | + +### transfer + +```solidity +function transfer(address recipient, uint256 amount) external nonpayable returns (bool) +``` + + + +*Moves `amount` tokens from the caller's account to `recipient`. Returns a boolean value indicating whether the operation succeeded. Emits a {Transfer} event.* + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| recipient | address | undefined | +| amount | uint256 | undefined | + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | bool | undefined | + +### transferFrom + +```solidity +function transferFrom(address sender, address recipient, uint256 amount) external nonpayable returns (bool) +``` + + + +*Moves `amount` tokens from `sender` to `recipient` using the allowance mechanism. `amount` is then deducted from the caller's allowance. Returns a boolean value indicating whether the operation succeeded. Emits a {Transfer} event.* + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| sender | address | undefined | +| recipient | address | undefined | +| amount | uint256 | undefined | + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | bool | undefined | + + + +## Events + +### Approval + +```solidity +event Approval(address indexed owner, address indexed spender, uint256 value) +``` + + + +*Emitted when the allowance of a `spender` for an `owner` is set by a call to {approve}. `value` is the new allowance.* + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| owner `indexed` | address | undefined | +| spender `indexed` | address | undefined | +| value | uint256 | undefined | + +### Transfer + +```solidity +event Transfer(address indexed from, address indexed to, uint256 value) +``` + + + +*Emitted when `value` tokens are moved from one account (`from`) to another (`to`). Note that `value` may be zero.* + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| from `indexed` | address | undefined | +| to `indexed` | address | undefined | +| value | uint256 | undefined | + + + diff --git a/docs/elin/contracts-upgradeable/utils/AddressUpgradeable.md b/docs/elin/contracts-upgradeable/utils/AddressUpgradeable.md new file mode 100644 index 000000000..456cdd15d --- /dev/null +++ b/docs/elin/contracts-upgradeable/utils/AddressUpgradeable.md @@ -0,0 +1,12 @@ +# AddressUpgradeable + + + + + + + +*Collection of functions related to the address type* + + + diff --git a/docs/elin/contracts-upgradeable/utils/ContextUpgradeable.md b/docs/elin/contracts-upgradeable/utils/ContextUpgradeable.md new file mode 100644 index 000000000..8491abdc9 --- /dev/null +++ b/docs/elin/contracts-upgradeable/utils/ContextUpgradeable.md @@ -0,0 +1,12 @@ +# ContextUpgradeable + + + + + + + + + + + diff --git a/docs/elin/contracts-upgradeable/utils/CountersUpgradeable.md b/docs/elin/contracts-upgradeable/utils/CountersUpgradeable.md new file mode 100644 index 000000000..66c3ec40d --- /dev/null +++ b/docs/elin/contracts-upgradeable/utils/CountersUpgradeable.md @@ -0,0 +1,12 @@ +# CountersUpgradeable + +*Matt Condon (@shrugs)* + +> Counters + + + +*Provides counters that can only be incremented or decremented by one. This can be used e.g. to track the number of elements in a mapping, issuing ERC721 ids, or counting request ids. Include with `using Counters for Counters.Counter;` Since it is not possible to overflow a 256 bit integer with increments of one, `increment` can skip the {SafeMath} overflow check, thereby saving gas. This does assume however correct usage, in that the underlying `_value` is never directly accessed.* + + + diff --git a/docs/elin/contracts-upgradeable/utils/EnumerableSetUpgradeable.md b/docs/elin/contracts-upgradeable/utils/EnumerableSetUpgradeable.md new file mode 100644 index 000000000..1a169e579 --- /dev/null +++ b/docs/elin/contracts-upgradeable/utils/EnumerableSetUpgradeable.md @@ -0,0 +1,12 @@ +# EnumerableSetUpgradeable + + + + + + + +*Library for managing https://en.wikipedia.org/wiki/Set_(abstract_data_type)[sets] of primitive types. Sets have the following properties: - Elements are added, removed, and checked for existence in constant time (O(1)). - Elements are enumerated in O(n). No guarantees are made on the ordering. ``` contract Example { // Add the library methods using EnumerableSet for EnumerableSet.AddressSet; // Declare a set state variable EnumerableSet.AddressSet private mySet; } ``` As of v3.3.0, sets of type `bytes32` (`Bytes32Set`), `address` (`AddressSet`) and `uint256` (`UintSet`) are supported.* + + + diff --git a/docs/elin/contracts-upgradeable/utils/PausableUpgradeable.md b/docs/elin/contracts-upgradeable/utils/PausableUpgradeable.md new file mode 100644 index 000000000..38eb921ff --- /dev/null +++ b/docs/elin/contracts-upgradeable/utils/PausableUpgradeable.md @@ -0,0 +1,67 @@ +# PausableUpgradeable + + + + + + + +*Contract module which allows children to implement an emergency stop mechanism that can be triggered by an authorized account. This module is used through inheritance. It will make available the modifiers `whenNotPaused` and `whenPaused`, which can be applied to the functions of your contract. Note that they will not be pausable by simply including this module, only once the modifiers are put in place.* + +## Methods + +### paused + +```solidity +function paused() external view returns (bool) +``` + + + +*Returns true if the contract is paused, and false otherwise.* + + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | bool | undefined | + + + +## Events + +### Paused + +```solidity +event Paused(address account) +``` + + + +*Emitted when the pause is triggered by `account`.* + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| account | address | undefined | + +### Unpaused + +```solidity +event Unpaused(address account) +``` + + + +*Emitted when the pause is lifted by `account`.* + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| account | address | undefined | + + + diff --git a/docs/elin/contracts-upgradeable/utils/ReentrancyGuardUpgradeable.md b/docs/elin/contracts-upgradeable/utils/ReentrancyGuardUpgradeable.md new file mode 100644 index 000000000..6955ca2de --- /dev/null +++ b/docs/elin/contracts-upgradeable/utils/ReentrancyGuardUpgradeable.md @@ -0,0 +1,12 @@ +# ReentrancyGuardUpgradeable + + + + + + + +*Contract module that helps prevent reentrant calls to a function. Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier available, which can be applied to functions to make sure there are no nested (reentrant) calls to them. Note that because there is a single `nonReentrant` guard, functions marked as `nonReentrant` may not call one another. This can be worked around by making those functions `private`, and then adding `external` `nonReentrant` entry points to them. TIP: If you would like to learn more about reentrancy and alternative ways to protect against it, check out our blog post https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul].* + + + diff --git a/docs/elin/contracts/access/AccessControl.md b/docs/elin/contracts/access/AccessControl.md new file mode 100644 index 000000000..88ca92f78 --- /dev/null +++ b/docs/elin/contracts/access/AccessControl.md @@ -0,0 +1,230 @@ +# AccessControl + + + + + + + +*Contract module that allows children to implement role-based access control mechanisms. Roles are referred to by their `bytes32` identifier. These should be exposed in the external API and be unique. The best way to achieve this is by using `public constant` hash digests: ``` bytes32 public constant MY_ROLE = keccak256("MY_ROLE"); ``` Roles can be used to represent a set of permissions. To restrict access to a function call, use {hasRole}: ``` function foo() public { require(hasRole(MY_ROLE, msg.sender)); ... } ``` Roles can be granted and revoked dynamically via the {grantRole} and {revokeRole} functions. Each role has an associated admin role, and only accounts that have a role's admin role can call {grantRole} and {revokeRole}. By default, the admin role for all roles is `DEFAULT_ADMIN_ROLE`, which means that only accounts with this role will be able to grant or revoke other roles. More complex role relationships can be created by using {_setRoleAdmin}. WARNING: The `DEFAULT_ADMIN_ROLE` is also its own admin: it has permission to grant and revoke this role. Extra precautions should be taken to secure accounts that have been granted it.* + +## Methods + +### DEFAULT_ADMIN_ROLE + +```solidity +function DEFAULT_ADMIN_ROLE() external view returns (bytes32) +``` + + + + + + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | bytes32 | undefined | + +### getRoleAdmin + +```solidity +function getRoleAdmin(bytes32 role) external view returns (bytes32) +``` + + + +*Returns the admin role that controls `role`. See {grantRole} and {revokeRole}. To change a role's admin, use {_setRoleAdmin}.* + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| role | bytes32 | undefined | + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | bytes32 | undefined | + +### getRoleMember + +```solidity +function getRoleMember(bytes32 role, uint256 index) external view returns (address) +``` + + + +*Returns one of the accounts that have `role`. `index` must be a value between 0 and {getRoleMemberCount}, non-inclusive. Role bearers are not sorted in any particular way, and their ordering may change at any point. WARNING: When using {getRoleMember} and {getRoleMemberCount}, make sure you perform all queries on the same block. See the following https://forum.openzeppelin.com/t/iterating-over-elements-on-enumerableset-in-openzeppelin-contracts/2296[forum post] for more information.* + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| role | bytes32 | undefined | +| index | uint256 | undefined | + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | address | undefined | + +### getRoleMemberCount + +```solidity +function getRoleMemberCount(bytes32 role) external view returns (uint256) +``` + + + +*Returns the number of accounts that have `role`. Can be used together with {getRoleMember} to enumerate all bearers of a role.* + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| role | bytes32 | undefined | + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | uint256 | undefined | + +### grantRole + +```solidity +function grantRole(bytes32 role, address account) external nonpayable +``` + + + +*Grants `role` to `account`. If `account` had not been already granted `role`, emits a {RoleGranted} event. Requirements: - the caller must have ``role``'s admin role.* + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| role | bytes32 | undefined | +| account | address | undefined | + +### hasRole + +```solidity +function hasRole(bytes32 role, address account) external view returns (bool) +``` + + + +*Returns `true` if `account` has been granted `role`.* + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| role | bytes32 | undefined | +| account | address | undefined | + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | bool | undefined | + +### renounceRole + +```solidity +function renounceRole(bytes32 role, address account) external nonpayable +``` + + + +*Revokes `role` from the calling account. Roles are often managed via {grantRole} and {revokeRole}: this function's purpose is to provide a mechanism for accounts to lose their privileges if they are compromised (such as when a trusted device is misplaced). If the calling account had been granted `role`, emits a {RoleRevoked} event. Requirements: - the caller must be `account`.* + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| role | bytes32 | undefined | +| account | address | undefined | + +### revokeRole + +```solidity +function revokeRole(bytes32 role, address account) external nonpayable +``` + + + +*Revokes `role` from `account`. If `account` had been granted `role`, emits a {RoleRevoked} event. Requirements: - the caller must have ``role``'s admin role.* + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| role | bytes32 | undefined | +| account | address | undefined | + + + +## Events + +### RoleAdminChanged + +```solidity +event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole) +``` + + + +*Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole` `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite {RoleAdminChanged} not being emitted signaling this. _Available since v3.1._* + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| role `indexed` | bytes32 | undefined | +| previousAdminRole `indexed` | bytes32 | undefined | +| newAdminRole `indexed` | bytes32 | undefined | + +### RoleGranted + +```solidity +event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender) +``` + + + +*Emitted when `account` is granted `role`. `sender` is the account that originated the contract call, an admin role bearer except when using {_setupRole}.* + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| role `indexed` | bytes32 | undefined | +| account `indexed` | address | undefined | +| sender `indexed` | address | undefined | + +### RoleRevoked + +```solidity +event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender) +``` + + + +*Emitted when `account` is revoked `role`. `sender` is the account that originated the contract call: - if using `revokeRole`, it is the admin role bearer - if using `renounceRole`, it is the role bearer (i.e. `account`)* + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| role `indexed` | bytes32 | undefined | +| account `indexed` | address | undefined | +| sender `indexed` | address | undefined | + + + diff --git a/docs/elin/contracts/access/Ownable.md b/docs/elin/contracts/access/Ownable.md new file mode 100644 index 000000000..ac3973421 --- /dev/null +++ b/docs/elin/contracts/access/Ownable.md @@ -0,0 +1,79 @@ +# Ownable + + + + + + + +*Contract module which provides a basic access control mechanism, where there is an account (an owner) that can be granted exclusive access to specific functions. By default, the owner account will be the one that deploys the contract. This can later be changed with {transferOwnership}. This module is used through inheritance. It will make available the modifier `onlyOwner`, which can be applied to your functions to restrict their use to the owner.* + +## Methods + +### owner + +```solidity +function owner() external view returns (address) +``` + + + +*Returns the address of the current owner.* + + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | address | undefined | + +### renounceOwnership + +```solidity +function renounceOwnership() external nonpayable +``` + + + +*Leaves the contract without owner. It will not be possible to call `onlyOwner` functions anymore. Can only be called by the current owner. NOTE: Renouncing ownership will leave the contract without an owner, thereby removing any functionality that is only available to the owner.* + + +### transferOwnership + +```solidity +function transferOwnership(address newOwner) external nonpayable +``` + + + +*Transfers ownership of the contract to a new account (`newOwner`). Can only be called by the current owner.* + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| newOwner | address | undefined | + + + +## Events + +### OwnershipTransferred + +```solidity +event OwnershipTransferred(address indexed previousOwner, address indexed newOwner) +``` + + + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| previousOwner `indexed` | address | undefined | +| newOwner `indexed` | address | undefined | + + + diff --git a/docs/elin/contracts/cryptography/ECDSA.md b/docs/elin/contracts/cryptography/ECDSA.md new file mode 100644 index 000000000..d4fef0408 --- /dev/null +++ b/docs/elin/contracts/cryptography/ECDSA.md @@ -0,0 +1,12 @@ +# ECDSA + + + + + + + +*Elliptic Curve Digital Signature Algorithm (ECDSA) operations. These functions can be used to verify that a message was signed by the holder of the private keys of a given address.* + + + diff --git a/docs/elin/contracts/drafts/EIP712.md b/docs/elin/contracts/drafts/EIP712.md new file mode 100644 index 000000000..d93f4f4f4 --- /dev/null +++ b/docs/elin/contracts/drafts/EIP712.md @@ -0,0 +1,12 @@ +# EIP712 + + + + + + + +*https://eips.ethereum.org/EIPS/eip-712[EIP 712] is a standard for hashing and signing of typed structured data. The encoding specified in the EIP is very generic, and such a generic implementation in Solidity is not feasible, thus this contract does not implement the encoding itself. Protocols need to implement the type-specific encoding they need in their contracts using a combination of `abi.encode` and `keccak256`. This contract implements the EIP 712 domain separator ({_domainSeparatorV4}) that is used as part of the encoding scheme, and the final step of the encoding to obtain the message digest that is then signed via ECDSA ({_hashTypedDataV4}). The implementation of the domain separator was designed to be as efficient as possible while still properly updating the chain id to protect against replay attacks on an eventual fork of the chain. NOTE: This contract implements the version of the encoding known as "v4", as implemented by the JSON RPC method https://docs.metamask.io/guide/signing-data.html[`eth_signTypedDataV4` in MetaMask]. _Available since v3.4._* + + + diff --git a/docs/elin/contracts/drafts/ERC20Permit.md b/docs/elin/contracts/drafts/ERC20Permit.md new file mode 100644 index 000000000..abee0d6ef --- /dev/null +++ b/docs/elin/contracts/drafts/ERC20Permit.md @@ -0,0 +1,344 @@ +# ERC20Permit + + + + + + + +*Implementation of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in https://eips.ethereum.org/EIPS/eip-2612[EIP-2612]. Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by presenting a message signed by the account. By not relying on `{IERC20-approve}`, the token holder account doesn't need to send a transaction, and thus is not required to hold Ether at all. _Available since v3.4._* + +## Methods + +### DOMAIN_SEPARATOR + +```solidity +function DOMAIN_SEPARATOR() external view returns (bytes32) +``` + + + +*See {IERC20Permit-DOMAIN_SEPARATOR}.* + + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | bytes32 | undefined | + +### allowance + +```solidity +function allowance(address owner, address spender) external view returns (uint256) +``` + + + +*See {IERC20-allowance}.* + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| owner | address | undefined | +| spender | address | undefined | + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | uint256 | undefined | + +### approve + +```solidity +function approve(address spender, uint256 amount) external nonpayable returns (bool) +``` + + + +*See {IERC20-approve}. Requirements: - `spender` cannot be the zero address.* + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| spender | address | undefined | +| amount | uint256 | undefined | + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | bool | undefined | + +### balanceOf + +```solidity +function balanceOf(address account) external view returns (uint256) +``` + + + +*See {IERC20-balanceOf}.* + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| account | address | undefined | + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | uint256 | undefined | + +### decimals + +```solidity +function decimals() external view returns (uint8) +``` + + + +*Returns the number of decimals used to get its user representation. For example, if `decimals` equals `2`, a balance of `505` tokens should be displayed to a user as `5,05` (`505 / 10 ** 2`). Tokens usually opt for a value of 18, imitating the relationship between Ether and Wei. This is the value {ERC20} uses, unless {_setupDecimals} is called. NOTE: This information is only used for _display_ purposes: it in no way affects any of the arithmetic of the contract, including {IERC20-balanceOf} and {IERC20-transfer}.* + + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | uint8 | undefined | + +### decreaseAllowance + +```solidity +function decreaseAllowance(address spender, uint256 subtractedValue) external nonpayable returns (bool) +``` + + + +*Atomically decreases the allowance granted to `spender` by the caller. This is an alternative to {approve} that can be used as a mitigation for problems described in {IERC20-approve}. Emits an {Approval} event indicating the updated allowance. Requirements: - `spender` cannot be the zero address. - `spender` must have allowance for the caller of at least `subtractedValue`.* + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| spender | address | undefined | +| subtractedValue | uint256 | undefined | + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | bool | undefined | + +### increaseAllowance + +```solidity +function increaseAllowance(address spender, uint256 addedValue) external nonpayable returns (bool) +``` + + + +*Atomically increases the allowance granted to `spender` by the caller. This is an alternative to {approve} that can be used as a mitigation for problems described in {IERC20-approve}. Emits an {Approval} event indicating the updated allowance. Requirements: - `spender` cannot be the zero address.* + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| spender | address | undefined | +| addedValue | uint256 | undefined | + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | bool | undefined | + +### name + +```solidity +function name() external view returns (string) +``` + + + +*Returns the name of the token.* + + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | string | undefined | + +### nonces + +```solidity +function nonces(address owner) external view returns (uint256) +``` + + + +*See {IERC20Permit-nonces}.* + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| owner | address | undefined | + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | uint256 | undefined | + +### permit + +```solidity +function permit(address owner, address spender, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s) external nonpayable +``` + + + +*See {IERC20Permit-permit}.* + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| owner | address | undefined | +| spender | address | undefined | +| value | uint256 | undefined | +| deadline | uint256 | undefined | +| v | uint8 | undefined | +| r | bytes32 | undefined | +| s | bytes32 | undefined | + +### symbol + +```solidity +function symbol() external view returns (string) +``` + + + +*Returns the symbol of the token, usually a shorter version of the name.* + + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | string | undefined | + +### totalSupply + +```solidity +function totalSupply() external view returns (uint256) +``` + + + +*See {IERC20-totalSupply}.* + + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | uint256 | undefined | + +### transfer + +```solidity +function transfer(address recipient, uint256 amount) external nonpayable returns (bool) +``` + + + +*See {IERC20-transfer}. Requirements: - `recipient` cannot be the zero address. - the caller must have a balance of at least `amount`.* + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| recipient | address | undefined | +| amount | uint256 | undefined | + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | bool | undefined | + +### transferFrom + +```solidity +function transferFrom(address sender, address recipient, uint256 amount) external nonpayable returns (bool) +``` + + + +*See {IERC20-transferFrom}. Emits an {Approval} event indicating the updated allowance. This is not required by the EIP. See the note at the beginning of {ERC20}. Requirements: - `sender` and `recipient` cannot be the zero address. - `sender` must have a balance of at least `amount`. - the caller must have allowance for ``sender``'s tokens of at least `amount`.* + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| sender | address | undefined | +| recipient | address | undefined | +| amount | uint256 | undefined | + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | bool | undefined | + + + +## Events + +### Approval + +```solidity +event Approval(address indexed owner, address indexed spender, uint256 value) +``` + + + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| owner `indexed` | address | undefined | +| spender `indexed` | address | undefined | +| value | uint256 | undefined | + +### Transfer + +```solidity +event Transfer(address indexed from, address indexed to, uint256 value) +``` + + + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| from `indexed` | address | undefined | +| to `indexed` | address | undefined | +| value | uint256 | undefined | + + + diff --git a/docs/elin/contracts/drafts/IERC20Permit.md b/docs/elin/contracts/drafts/IERC20Permit.md new file mode 100644 index 000000000..92628dc39 --- /dev/null +++ b/docs/elin/contracts/drafts/IERC20Permit.md @@ -0,0 +1,76 @@ +# IERC20Permit + + + + + + + +*Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in https://eips.ethereum.org/EIPS/eip-2612[EIP-2612]. Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by presenting a message signed by the account. By not relying on `{IERC20-approve}`, the token holder account doesn't need to send a transaction, and thus is not required to hold Ether at all.* + +## Methods + +### DOMAIN_SEPARATOR + +```solidity +function DOMAIN_SEPARATOR() external view returns (bytes32) +``` + + + +*Returns the domain separator used in the encoding of the signature for `permit`, as defined by {EIP712}.* + + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | bytes32 | undefined | + +### nonces + +```solidity +function nonces(address owner) external view returns (uint256) +``` + + + +*Returns the current nonce for `owner`. This value must be included whenever a signature is generated for {permit}. Every successful call to {permit} increases ``owner``'s nonce by one. This prevents a signature from being used multiple times.* + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| owner | address | undefined | + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | uint256 | undefined | + +### permit + +```solidity +function permit(address owner, address spender, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s) external nonpayable +``` + + + +*Sets `value` as the allowance of `spender` over `owner`'s tokens, given `owner`'s signed approval. IMPORTANT: The same issues {IERC20-approve} has related to transaction ordering also apply here. Emits an {Approval} event. Requirements: - `spender` cannot be the zero address. - `deadline` must be a timestamp in the future. - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner` over the EIP712-formatted function arguments. - the signature must use ``owner``'s current nonce (see {nonces}). For more information on the signature format, see the https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP section].* + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| owner | address | undefined | +| spender | address | undefined | +| value | uint256 | undefined | +| deadline | uint256 | undefined | +| v | uint8 | undefined | +| r | bytes32 | undefined | +| s | bytes32 | undefined | + + + + diff --git a/docs/elin/contracts/math/SafeMath.md b/docs/elin/contracts/math/SafeMath.md new file mode 100644 index 000000000..7399e3033 --- /dev/null +++ b/docs/elin/contracts/math/SafeMath.md @@ -0,0 +1,12 @@ +# SafeMath + + + + + + + +*Wrappers over Solidity's arithmetic operations with added overflow checks. Arithmetic operations in Solidity wrap on overflow. This can easily result in bugs, because programmers usually assume that an overflow raises an error, which is the standard behavior in high level programming languages. `SafeMath` restores this intuition by reverting the transaction when an operation overflows. Using this library instead of the unchecked operations eliminates an entire class of bugs, so it's recommended to use it always.* + + + diff --git a/docs/elin/contracts/proxy/Clones.md b/docs/elin/contracts/proxy/Clones.md new file mode 100644 index 000000000..05da81c8f --- /dev/null +++ b/docs/elin/contracts/proxy/Clones.md @@ -0,0 +1,12 @@ +# Clones + + + + + + + +*https://eips.ethereum.org/EIPS/eip-1167[EIP 1167] is a standard for deploying minimal proxy contracts, also known as "clones". > To simply and cheaply clone contract functionality in an immutable way, this standard specifies > a minimal bytecode implementation that delegates all calls to a known, fixed address. The library includes functions to deploy a proxy using either `create` (traditional deployment) or `create2` (salted deterministic deployment). It also includes functions to predict the addresses of clones deployed using the deterministic method. _Available since v3.4._* + + + diff --git a/docs/elin/contracts/token/ERC20/ERC20.md b/docs/elin/contracts/token/ERC20/ERC20.md new file mode 100644 index 000000000..b61c7d252 --- /dev/null +++ b/docs/elin/contracts/token/ERC20/ERC20.md @@ -0,0 +1,283 @@ +# ERC20 + + + + + + + +*Implementation of the {IERC20} interface. This implementation is agnostic to the way tokens are created. This means that a supply mechanism has to be added in a derived contract using {_mint}. For a generic mechanism see {ERC20PresetMinterPauser}. TIP: For a detailed writeup see our guide https://forum.zeppelin.solutions/t/how-to-implement-erc20-supply-mechanisms/226[How to implement supply mechanisms]. We have followed general OpenZeppelin guidelines: functions revert instead of returning `false` on failure. This behavior is nonetheless conventional and does not conflict with the expectations of ERC20 applications. Additionally, an {Approval} event is emitted on calls to {transferFrom}. This allows applications to reconstruct the allowance for all accounts just by listening to said events. Other implementations of the EIP may not emit these events, as it isn't required by the specification. Finally, the non-standard {decreaseAllowance} and {increaseAllowance} functions have been added to mitigate the well-known issues around setting allowances. See {IERC20-approve}.* + +## Methods + +### allowance + +```solidity +function allowance(address owner, address spender) external view returns (uint256) +``` + + + +*See {IERC20-allowance}.* + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| owner | address | undefined | +| spender | address | undefined | + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | uint256 | undefined | + +### approve + +```solidity +function approve(address spender, uint256 amount) external nonpayable returns (bool) +``` + + + +*See {IERC20-approve}. Requirements: - `spender` cannot be the zero address.* + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| spender | address | undefined | +| amount | uint256 | undefined | + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | bool | undefined | + +### balanceOf + +```solidity +function balanceOf(address account) external view returns (uint256) +``` + + + +*See {IERC20-balanceOf}.* + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| account | address | undefined | + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | uint256 | undefined | + +### decimals + +```solidity +function decimals() external view returns (uint8) +``` + + + +*Returns the number of decimals used to get its user representation. For example, if `decimals` equals `2`, a balance of `505` tokens should be displayed to a user as `5,05` (`505 / 10 ** 2`). Tokens usually opt for a value of 18, imitating the relationship between Ether and Wei. This is the value {ERC20} uses, unless {_setupDecimals} is called. NOTE: This information is only used for _display_ purposes: it in no way affects any of the arithmetic of the contract, including {IERC20-balanceOf} and {IERC20-transfer}.* + + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | uint8 | undefined | + +### decreaseAllowance + +```solidity +function decreaseAllowance(address spender, uint256 subtractedValue) external nonpayable returns (bool) +``` + + + +*Atomically decreases the allowance granted to `spender` by the caller. This is an alternative to {approve} that can be used as a mitigation for problems described in {IERC20-approve}. Emits an {Approval} event indicating the updated allowance. Requirements: - `spender` cannot be the zero address. - `spender` must have allowance for the caller of at least `subtractedValue`.* + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| spender | address | undefined | +| subtractedValue | uint256 | undefined | + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | bool | undefined | + +### increaseAllowance + +```solidity +function increaseAllowance(address spender, uint256 addedValue) external nonpayable returns (bool) +``` + + + +*Atomically increases the allowance granted to `spender` by the caller. This is an alternative to {approve} that can be used as a mitigation for problems described in {IERC20-approve}. Emits an {Approval} event indicating the updated allowance. Requirements: - `spender` cannot be the zero address.* + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| spender | address | undefined | +| addedValue | uint256 | undefined | + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | bool | undefined | + +### name + +```solidity +function name() external view returns (string) +``` + + + +*Returns the name of the token.* + + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | string | undefined | + +### symbol + +```solidity +function symbol() external view returns (string) +``` + + + +*Returns the symbol of the token, usually a shorter version of the name.* + + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | string | undefined | + +### totalSupply + +```solidity +function totalSupply() external view returns (uint256) +``` + + + +*See {IERC20-totalSupply}.* + + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | uint256 | undefined | + +### transfer + +```solidity +function transfer(address recipient, uint256 amount) external nonpayable returns (bool) +``` + + + +*See {IERC20-transfer}. Requirements: - `recipient` cannot be the zero address. - the caller must have a balance of at least `amount`.* + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| recipient | address | undefined | +| amount | uint256 | undefined | + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | bool | undefined | + +### transferFrom + +```solidity +function transferFrom(address sender, address recipient, uint256 amount) external nonpayable returns (bool) +``` + + + +*See {IERC20-transferFrom}. Emits an {Approval} event indicating the updated allowance. This is not required by the EIP. See the note at the beginning of {ERC20}. Requirements: - `sender` and `recipient` cannot be the zero address. - `sender` must have a balance of at least `amount`. - the caller must have allowance for ``sender``'s tokens of at least `amount`.* + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| sender | address | undefined | +| recipient | address | undefined | +| amount | uint256 | undefined | + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | bool | undefined | + + + +## Events + +### Approval + +```solidity +event Approval(address indexed owner, address indexed spender, uint256 value) +``` + + + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| owner `indexed` | address | undefined | +| spender `indexed` | address | undefined | +| value | uint256 | undefined | + +### Transfer + +```solidity +event Transfer(address indexed from, address indexed to, uint256 value) +``` + + + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| from `indexed` | address | undefined | +| to `indexed` | address | undefined | +| value | uint256 | undefined | + + + diff --git a/docs/elin/contracts/token/ERC20/ERC20Burnable.md b/docs/elin/contracts/token/ERC20/ERC20Burnable.md new file mode 100644 index 000000000..b73b5034b --- /dev/null +++ b/docs/elin/contracts/token/ERC20/ERC20Burnable.md @@ -0,0 +1,316 @@ +# ERC20Burnable + + + + + + + +*Extension of {ERC20} that allows token holders to destroy both their own tokens and those that they have an allowance for, in a way that can be recognized off-chain (via event analysis).* + +## Methods + +### allowance + +```solidity +function allowance(address owner, address spender) external view returns (uint256) +``` + + + +*See {IERC20-allowance}.* + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| owner | address | undefined | +| spender | address | undefined | + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | uint256 | undefined | + +### approve + +```solidity +function approve(address spender, uint256 amount) external nonpayable returns (bool) +``` + + + +*See {IERC20-approve}. Requirements: - `spender` cannot be the zero address.* + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| spender | address | undefined | +| amount | uint256 | undefined | + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | bool | undefined | + +### balanceOf + +```solidity +function balanceOf(address account) external view returns (uint256) +``` + + + +*See {IERC20-balanceOf}.* + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| account | address | undefined | + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | uint256 | undefined | + +### burn + +```solidity +function burn(uint256 amount) external nonpayable +``` + + + +*Destroys `amount` tokens from the caller. See {ERC20-_burn}.* + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| amount | uint256 | undefined | + +### burnFrom + +```solidity +function burnFrom(address account, uint256 amount) external nonpayable +``` + + + +*Destroys `amount` tokens from `account`, deducting from the caller's allowance. See {ERC20-_burn} and {ERC20-allowance}. Requirements: - the caller must have allowance for ``accounts``'s tokens of at least `amount`.* + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| account | address | undefined | +| amount | uint256 | undefined | + +### decimals + +```solidity +function decimals() external view returns (uint8) +``` + + + +*Returns the number of decimals used to get its user representation. For example, if `decimals` equals `2`, a balance of `505` tokens should be displayed to a user as `5,05` (`505 / 10 ** 2`). Tokens usually opt for a value of 18, imitating the relationship between Ether and Wei. This is the value {ERC20} uses, unless {_setupDecimals} is called. NOTE: This information is only used for _display_ purposes: it in no way affects any of the arithmetic of the contract, including {IERC20-balanceOf} and {IERC20-transfer}.* + + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | uint8 | undefined | + +### decreaseAllowance + +```solidity +function decreaseAllowance(address spender, uint256 subtractedValue) external nonpayable returns (bool) +``` + + + +*Atomically decreases the allowance granted to `spender` by the caller. This is an alternative to {approve} that can be used as a mitigation for problems described in {IERC20-approve}. Emits an {Approval} event indicating the updated allowance. Requirements: - `spender` cannot be the zero address. - `spender` must have allowance for the caller of at least `subtractedValue`.* + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| spender | address | undefined | +| subtractedValue | uint256 | undefined | + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | bool | undefined | + +### increaseAllowance + +```solidity +function increaseAllowance(address spender, uint256 addedValue) external nonpayable returns (bool) +``` + + + +*Atomically increases the allowance granted to `spender` by the caller. This is an alternative to {approve} that can be used as a mitigation for problems described in {IERC20-approve}. Emits an {Approval} event indicating the updated allowance. Requirements: - `spender` cannot be the zero address.* + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| spender | address | undefined | +| addedValue | uint256 | undefined | + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | bool | undefined | + +### name + +```solidity +function name() external view returns (string) +``` + + + +*Returns the name of the token.* + + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | string | undefined | + +### symbol + +```solidity +function symbol() external view returns (string) +``` + + + +*Returns the symbol of the token, usually a shorter version of the name.* + + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | string | undefined | + +### totalSupply + +```solidity +function totalSupply() external view returns (uint256) +``` + + + +*See {IERC20-totalSupply}.* + + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | uint256 | undefined | + +### transfer + +```solidity +function transfer(address recipient, uint256 amount) external nonpayable returns (bool) +``` + + + +*See {IERC20-transfer}. Requirements: - `recipient` cannot be the zero address. - the caller must have a balance of at least `amount`.* + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| recipient | address | undefined | +| amount | uint256 | undefined | + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | bool | undefined | + +### transferFrom + +```solidity +function transferFrom(address sender, address recipient, uint256 amount) external nonpayable returns (bool) +``` + + + +*See {IERC20-transferFrom}. Emits an {Approval} event indicating the updated allowance. This is not required by the EIP. See the note at the beginning of {ERC20}. Requirements: - `sender` and `recipient` cannot be the zero address. - `sender` must have a balance of at least `amount`. - the caller must have allowance for ``sender``'s tokens of at least `amount`.* + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| sender | address | undefined | +| recipient | address | undefined | +| amount | uint256 | undefined | + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | bool | undefined | + + + +## Events + +### Approval + +```solidity +event Approval(address indexed owner, address indexed spender, uint256 value) +``` + + + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| owner `indexed` | address | undefined | +| spender `indexed` | address | undefined | +| value | uint256 | undefined | + +### Transfer + +```solidity +event Transfer(address indexed from, address indexed to, uint256 value) +``` + + + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| from `indexed` | address | undefined | +| to `indexed` | address | undefined | +| value | uint256 | undefined | + + + diff --git a/docs/elin/contracts/token/ERC20/IERC20.md b/docs/elin/contracts/token/ERC20/IERC20.md new file mode 100644 index 000000000..b50d0dbc3 --- /dev/null +++ b/docs/elin/contracts/token/ERC20/IERC20.md @@ -0,0 +1,186 @@ +# IERC20 + + + + + + + +*Interface of the ERC20 standard as defined in the EIP.* + +## Methods + +### allowance + +```solidity +function allowance(address owner, address spender) external view returns (uint256) +``` + + + +*Returns the remaining number of tokens that `spender` will be allowed to spend on behalf of `owner` through {transferFrom}. This is zero by default. This value changes when {approve} or {transferFrom} are called.* + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| owner | address | undefined | +| spender | address | undefined | + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | uint256 | undefined | + +### approve + +```solidity +function approve(address spender, uint256 amount) external nonpayable returns (bool) +``` + + + +*Sets `amount` as the allowance of `spender` over the caller's tokens. Returns a boolean value indicating whether the operation succeeded. IMPORTANT: Beware that changing an allowance with this method brings the risk that someone may use both the old and the new allowance by unfortunate transaction ordering. One possible solution to mitigate this race condition is to first reduce the spender's allowance to 0 and set the desired value afterwards: https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729 Emits an {Approval} event.* + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| spender | address | undefined | +| amount | uint256 | undefined | + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | bool | undefined | + +### balanceOf + +```solidity +function balanceOf(address account) external view returns (uint256) +``` + + + +*Returns the amount of tokens owned by `account`.* + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| account | address | undefined | + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | uint256 | undefined | + +### totalSupply + +```solidity +function totalSupply() external view returns (uint256) +``` + + + +*Returns the amount of tokens in existence.* + + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | uint256 | undefined | + +### transfer + +```solidity +function transfer(address recipient, uint256 amount) external nonpayable returns (bool) +``` + + + +*Moves `amount` tokens from the caller's account to `recipient`. Returns a boolean value indicating whether the operation succeeded. Emits a {Transfer} event.* + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| recipient | address | undefined | +| amount | uint256 | undefined | + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | bool | undefined | + +### transferFrom + +```solidity +function transferFrom(address sender, address recipient, uint256 amount) external nonpayable returns (bool) +``` + + + +*Moves `amount` tokens from `sender` to `recipient` using the allowance mechanism. `amount` is then deducted from the caller's allowance. Returns a boolean value indicating whether the operation succeeded. Emits a {Transfer} event.* + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| sender | address | undefined | +| recipient | address | undefined | +| amount | uint256 | undefined | + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | bool | undefined | + + + +## Events + +### Approval + +```solidity +event Approval(address indexed owner, address indexed spender, uint256 value) +``` + + + +*Emitted when the allowance of a `spender` for an `owner` is set by a call to {approve}. `value` is the new allowance.* + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| owner `indexed` | address | undefined | +| spender `indexed` | address | undefined | +| value | uint256 | undefined | + +### Transfer + +```solidity +event Transfer(address indexed from, address indexed to, uint256 value) +``` + + + +*Emitted when `value` tokens are moved from one account (`from`) to another (`to`). Note that `value` may be zero.* + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| from `indexed` | address | undefined | +| to `indexed` | address | undefined | +| value | uint256 | undefined | + + + diff --git a/docs/elin/contracts/token/ERC20/SafeERC20.md b/docs/elin/contracts/token/ERC20/SafeERC20.md new file mode 100644 index 000000000..80367d00d --- /dev/null +++ b/docs/elin/contracts/token/ERC20/SafeERC20.md @@ -0,0 +1,12 @@ +# SafeERC20 + + + +> SafeERC20 + + + +*Wrappers around ERC20 operations that throw on failure (when the token contract returns false). Tokens that return no value (and instead revert or throw on failure) are also supported, non-reverting calls are assumed to be successful. To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract, which allows you to call the safe operations as `token.safeTransfer(...)`, etc.* + + + diff --git a/docs/elin/contracts/utils/Address.md b/docs/elin/contracts/utils/Address.md new file mode 100644 index 000000000..927f4068e --- /dev/null +++ b/docs/elin/contracts/utils/Address.md @@ -0,0 +1,12 @@ +# Address + + + + + + + +*Collection of functions related to the address type* + + + diff --git a/docs/elin/contracts/utils/Context.md b/docs/elin/contracts/utils/Context.md new file mode 100644 index 000000000..e189a3929 --- /dev/null +++ b/docs/elin/contracts/utils/Context.md @@ -0,0 +1,12 @@ +# Context + + + + + + + + + + + diff --git a/docs/elin/contracts/utils/Counters.md b/docs/elin/contracts/utils/Counters.md new file mode 100644 index 000000000..d5e7265f7 --- /dev/null +++ b/docs/elin/contracts/utils/Counters.md @@ -0,0 +1,12 @@ +# Counters + +*Matt Condon (@shrugs)* + +> Counters + + + +*Provides counters that can only be incremented or decremented by one. This can be used e.g. to track the number of elements in a mapping, issuing ERC721 ids, or counting request ids. Include with `using Counters for Counters.Counter;` Since it is not possible to overflow a 256 bit integer with increments of one, `increment` can skip the {SafeMath} overflow check, thereby saving gas. This does assume however correct usage, in that the underlying `_value` is never directly accessed.* + + + diff --git a/docs/elin/contracts/utils/EnumerableSet.md b/docs/elin/contracts/utils/EnumerableSet.md new file mode 100644 index 000000000..e5b07f61a --- /dev/null +++ b/docs/elin/contracts/utils/EnumerableSet.md @@ -0,0 +1,12 @@ +# EnumerableSet + + + + + + + +*Library for managing https://en.wikipedia.org/wiki/Set_(abstract_data_type)[sets] of primitive types. Sets have the following properties: - Elements are added, removed, and checked for existence in constant time (O(1)). - Elements are enumerated in O(n). No guarantees are made on the ordering. ``` contract Example { // Add the library methods using EnumerableSet for EnumerableSet.AddressSet; // Declare a set state variable EnumerableSet.AddressSet private mySet; } ``` As of v3.3.0, sets of type `bytes32` (`Bytes32Set`), `address` (`AddressSet`) and `uint256` (`UintSet`) are supported.* + + + diff --git a/docs/elin/contracts/utils/ReentrancyGuard.md b/docs/elin/contracts/utils/ReentrancyGuard.md new file mode 100644 index 000000000..d15113fe5 --- /dev/null +++ b/docs/elin/contracts/utils/ReentrancyGuard.md @@ -0,0 +1,12 @@ +# ReentrancyGuard + + + + + + + +*Contract module that helps prevent reentrant calls to a function. Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier available, which can be applied to functions to make sure there are no nested (reentrant) calls to them. Note that because there is a single `nonReentrant` guard, functions marked as `nonReentrant` may not call one another. This can be worked around by making those functions `private`, and then adding `external` `nonReentrant` entry points to them. TIP: If you would like to learn more about reentrancy and alternative ways to protect against it, check out our blog post https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul].* + + + diff --git a/docs/ypto/boring-solidity/contracts/BaseBoringBatchable.md b/docs/ypto/boring-solidity/contracts/BaseBoringBatchable.md new file mode 100644 index 000000000..c2e7e1a6f --- /dev/null +++ b/docs/ypto/boring-solidity/contracts/BaseBoringBatchable.md @@ -0,0 +1,39 @@ +# BaseBoringBatchable + + + + + + + + + +## Methods + +### batch + +```solidity +function batch(bytes[] calls, bool revertOnFail) external payable returns (bool[] successes, bytes[] results) +``` + + + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| calls | bytes[] | undefined | +| revertOnFail | bool | undefined | + +#### Returns + +| Name | Type | Description | +|---|---|---| +| successes | bool[] | undefined | +| results | bytes[] | undefined | + + + + diff --git a/docs/ypto/boring-solidity/contracts/BoringBatchable.md b/docs/ypto/boring-solidity/contracts/BoringBatchable.md new file mode 100644 index 000000000..5e5ed83b8 --- /dev/null +++ b/docs/ypto/boring-solidity/contracts/BoringBatchable.md @@ -0,0 +1,62 @@ +# BoringBatchable + + + + + + + + + +## Methods + +### batch + +```solidity +function batch(bytes[] calls, bool revertOnFail) external payable returns (bool[] successes, bytes[] results) +``` + + + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| calls | bytes[] | undefined | +| revertOnFail | bool | undefined | + +#### Returns + +| Name | Type | Description | +|---|---|---| +| successes | bool[] | undefined | +| results | bytes[] | undefined | + +### permitToken + +```solidity +function permitToken(contract IERC20 token, address from, address to, uint256 amount, uint256 deadline, uint8 v, bytes32 r, bytes32 s) external nonpayable +``` + + + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| token | contract IERC20 | undefined | +| from | address | undefined | +| to | address | undefined | +| amount | uint256 | undefined | +| deadline | uint256 | undefined | +| v | uint8 | undefined | +| r | bytes32 | undefined | +| s | bytes32 | undefined | + + + + diff --git a/docs/ypto/boring-solidity/contracts/BoringOwnable.md b/docs/ypto/boring-solidity/contracts/BoringOwnable.md new file mode 100644 index 000000000..4f354f572 --- /dev/null +++ b/docs/ypto/boring-solidity/contracts/BoringOwnable.md @@ -0,0 +1,98 @@ +# BoringOwnable + + + + + + + + + +## Methods + +### claimOwnership + +```solidity +function claimOwnership() external nonpayable +``` + + + + + + +### owner + +```solidity +function owner() external view returns (address) +``` + + + + + + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | address | undefined | + +### pendingOwner + +```solidity +function pendingOwner() external view returns (address) +``` + + + + + + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | address | undefined | + +### transferOwnership + +```solidity +function transferOwnership(address newOwner, bool direct, bool renounce) external nonpayable +``` + + + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| newOwner | address | undefined | +| direct | bool | undefined | +| renounce | bool | undefined | + + + +## Events + +### OwnershipTransferred + +```solidity +event OwnershipTransferred(address indexed previousOwner, address indexed newOwner) +``` + + + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| previousOwner `indexed` | address | undefined | +| newOwner `indexed` | address | undefined | + + + diff --git a/docs/ypto/boring-solidity/contracts/BoringOwnableData.md b/docs/ypto/boring-solidity/contracts/BoringOwnableData.md new file mode 100644 index 000000000..b003c89e3 --- /dev/null +++ b/docs/ypto/boring-solidity/contracts/BoringOwnableData.md @@ -0,0 +1,49 @@ +# BoringOwnableData + + + + + + + + + +## Methods + +### owner + +```solidity +function owner() external view returns (address) +``` + + + + + + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | address | undefined | + +### pendingOwner + +```solidity +function pendingOwner() external view returns (address) +``` + + + + + + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | address | undefined | + + + + diff --git a/docs/ypto/boring-solidity/contracts/interfaces/IERC20.md b/docs/ypto/boring-solidity/contracts/interfaces/IERC20.md new file mode 100644 index 000000000..a2f26df8f --- /dev/null +++ b/docs/ypto/boring-solidity/contracts/interfaces/IERC20.md @@ -0,0 +1,161 @@ +# IERC20 + + + + + + + + + +## Methods + +### allowance + +```solidity +function allowance(address owner, address spender) external view returns (uint256) +``` + + + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| owner | address | undefined | +| spender | address | undefined | + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | uint256 | undefined | + +### approve + +```solidity +function approve(address spender, uint256 amount) external nonpayable returns (bool) +``` + + + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| spender | address | undefined | +| amount | uint256 | undefined | + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | bool | undefined | + +### balanceOf + +```solidity +function balanceOf(address account) external view returns (uint256) +``` + + + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| account | address | undefined | + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | uint256 | undefined | + +### permit + +```solidity +function permit(address owner, address spender, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s) external nonpayable +``` + + + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| owner | address | undefined | +| spender | address | undefined | +| value | uint256 | undefined | +| deadline | uint256 | undefined | +| v | uint8 | undefined | +| r | bytes32 | undefined | +| s | bytes32 | undefined | + +### totalSupply + +```solidity +function totalSupply() external view returns (uint256) +``` + + + + + + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | uint256 | undefined | + + + +## Events + +### Approval + +```solidity +event Approval(address indexed owner, address indexed spender, uint256 value) +``` + + + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| owner `indexed` | address | undefined | +| spender `indexed` | address | undefined | +| value | uint256 | undefined | + +### Transfer + +```solidity +event Transfer(address indexed from, address indexed to, uint256 value) +``` + + + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| from `indexed` | address | undefined | +| to `indexed` | address | undefined | +| value | uint256 | undefined | + + + diff --git a/docs/ypto/boring-solidity/contracts/libraries/BoringERC20.md b/docs/ypto/boring-solidity/contracts/libraries/BoringERC20.md new file mode 100644 index 000000000..0ef4c24dc --- /dev/null +++ b/docs/ypto/boring-solidity/contracts/libraries/BoringERC20.md @@ -0,0 +1,12 @@ +# BoringERC20 + + + + + + + + + + + diff --git a/docs/ypto/boring-solidity/contracts/libraries/BoringMath.md b/docs/ypto/boring-solidity/contracts/libraries/BoringMath.md new file mode 100644 index 000000000..c03e71afd --- /dev/null +++ b/docs/ypto/boring-solidity/contracts/libraries/BoringMath.md @@ -0,0 +1,12 @@ +# BoringMath + + + + + + + + + + + diff --git a/docs/ypto/boring-solidity/contracts/libraries/BoringMath128.md b/docs/ypto/boring-solidity/contracts/libraries/BoringMath128.md new file mode 100644 index 000000000..2a3cdec6a --- /dev/null +++ b/docs/ypto/boring-solidity/contracts/libraries/BoringMath128.md @@ -0,0 +1,12 @@ +# BoringMath128 + + + + + + + + + + + diff --git a/docs/ypto/boring-solidity/contracts/libraries/BoringMath32.md b/docs/ypto/boring-solidity/contracts/libraries/BoringMath32.md new file mode 100644 index 000000000..cc0879014 --- /dev/null +++ b/docs/ypto/boring-solidity/contracts/libraries/BoringMath32.md @@ -0,0 +1,12 @@ +# BoringMath32 + + + + + + + + + + + diff --git a/docs/ypto/boring-solidity/contracts/libraries/BoringMath64.md b/docs/ypto/boring-solidity/contracts/libraries/BoringMath64.md new file mode 100644 index 000000000..2094ecbda --- /dev/null +++ b/docs/ypto/boring-solidity/contracts/libraries/BoringMath64.md @@ -0,0 +1,12 @@ +# BoringMath64 + + + + + + + + + + + diff --git a/hardhat.config.ts b/hardhat.config.ts index 01a60bced..d96730c54 100644 --- a/hardhat.config.ts +++ b/hardhat.config.ts @@ -103,7 +103,7 @@ let config: HardhatUserConfig = { target: "ethers-v5", }, dodoc: { - runOnCompile: false, + runOnCompile: true, debugMode: false, // pre solidity 5 breaks docgen exclude: ["MultisigWallet", "WETH9"] From d1efa2908c160d45bb273afc928c3b75bd98395f Mon Sep 17 00:00:00 2001 From: Trajan0x Date: Sun, 10 Apr 2022 01:49:24 -0400 Subject: [PATCH 013/135] add forks --- .openzeppelin/unknown-31337.json | 243 +++++++++++++ contracts/bridge/SynapseBridge.sol | 5 +- contracts/bridge/interfaces/ISwap.sol | 38 +- contracts/bridge/testing/ProxyAdmin.sol | 10 + docs/bridge/SynapseBridge.md | 4 +- docs/bridge/interfaces/ISwap.md | 147 -------- hardhat.config.ts | 7 +- package-lock.json | 439 ++++++++++++++++++++++++ package.json | 1 + test/bridge/SynapseBridge.ts | 35 +- test/bridge/utilities/fork.ts | 46 +++ test/utils/testUtils.ts | 14 + 12 files changed, 793 insertions(+), 196 deletions(-) create mode 100644 .openzeppelin/unknown-31337.json create mode 100644 contracts/bridge/testing/ProxyAdmin.sol create mode 100644 test/bridge/utilities/fork.ts diff --git a/.openzeppelin/unknown-31337.json b/.openzeppelin/unknown-31337.json new file mode 100644 index 000000000..e9a303e78 --- /dev/null +++ b/.openzeppelin/unknown-31337.json @@ -0,0 +1,243 @@ +{ + "manifestVersion": "3.2", + "admin": { + "address": "0x7B3C1f09088Bdc9f136178E170aC668C8Ed095f2" + }, + "proxies": [ + { + "address": "0x2796317b0fF8538F253012862c06787Adfb8cEb6", + "kind": "transparent" + } + ], + "impls": { + "27ad20b2a62f59f274af0ae95636dfd39a718653858e63b6dd3003dbb5bd03bb": { + "address": "0x31fe393815822edacBd81C2262467402199EFD0D", + "layout": { + "storage": [ + { + "label": "_initialized", + "offset": 0, + "slot": "0", + "type": "t_bool", + "contract": "Initializable", + "src": "@openzeppelin/contracts-upgradeable/proxy/Initializable.sol:25" + }, + { + "label": "_initializing", + "offset": 1, + "slot": "0", + "type": "t_bool", + "contract": "Initializable", + "src": "@openzeppelin/contracts-upgradeable/proxy/Initializable.sol:30" + }, + { + "label": "__gap", + "offset": 0, + "slot": "1", + "type": "t_array(t_uint256)50_storage", + "contract": "ContextUpgradeable", + "src": "@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol:31" + }, + { + "label": "_roles", + "offset": 0, + "slot": "51", + "type": "t_mapping(t_bytes32,t_struct(RoleData)39_storage)", + "contract": "AccessControlUpgradeable", + "src": "@openzeppelin/contracts-upgradeable/access/AccessControlUpgradeable.sol:61" + }, + { + "label": "__gap", + "offset": 0, + "slot": "52", + "type": "t_array(t_uint256)49_storage", + "contract": "AccessControlUpgradeable", + "src": "@openzeppelin/contracts-upgradeable/access/AccessControlUpgradeable.sol:225" + }, + { + "label": "_status", + "offset": 0, + "slot": "101", + "type": "t_uint256", + "contract": "ReentrancyGuardUpgradeable", + "src": "@openzeppelin/contracts-upgradeable/utils/ReentrancyGuardUpgradeable.sol:37" + }, + { + "label": "__gap", + "offset": 0, + "slot": "102", + "type": "t_array(t_uint256)49_storage", + "contract": "ReentrancyGuardUpgradeable", + "src": "@openzeppelin/contracts-upgradeable/utils/ReentrancyGuardUpgradeable.sol:67" + }, + { + "label": "_paused", + "offset": 0, + "slot": "151", + "type": "t_bool", + "contract": "PausableUpgradeable", + "src": "@openzeppelin/contracts-upgradeable/utils/PausableUpgradeable.sol:28" + }, + { + "label": "__gap", + "offset": 0, + "slot": "152", + "type": "t_array(t_uint256)49_storage", + "contract": "PausableUpgradeable", + "src": "@openzeppelin/contracts-upgradeable/utils/PausableUpgradeable.sol:96" + }, + { + "label": "fees", + "offset": 0, + "slot": "201", + "type": "t_mapping(t_address,t_uint256)", + "contract": "SynapseBridge", + "src": "contracts/bridge/SynapseBridge.sol:62" + }, + { + "label": "startBlockNumber", + "offset": 0, + "slot": "202", + "type": "t_uint256", + "contract": "SynapseBridge", + "src": "contracts/bridge/SynapseBridge.sol:64" + }, + { + "label": "chainGasAmount", + "offset": 0, + "slot": "203", + "type": "t_uint256", + "contract": "SynapseBridge", + "src": "contracts/bridge/SynapseBridge.sol:66" + }, + { + "label": "WETH_ADDRESS", + "offset": 0, + "slot": "204", + "type": "t_address_payable", + "contract": "SynapseBridge", + "src": "contracts/bridge/SynapseBridge.sol:67" + }, + { + "label": "rateLimiter", + "offset": 0, + "slot": "205", + "type": "t_contract(IRateLimiter)21229", + "contract": "SynapseBridge", + "src": "contracts/bridge/SynapseBridge.sol:68" + }, + { + "label": "kappaMap", + "offset": 0, + "slot": "206", + "type": "t_mapping(t_bytes32,t_bool)", + "contract": "SynapseBridge", + "src": "contracts/bridge/SynapseBridge.sol:70" + } + ], + "types": { + "t_address": { + "label": "address", + "numberOfBytes": "20" + }, + "t_address_payable": { + "label": "address payable", + "numberOfBytes": "20" + }, + "t_array(t_bytes32)dyn_storage": { + "label": "bytes32[]", + "numberOfBytes": "32" + }, + "t_array(t_uint256)49_storage": { + "label": "uint256[49]", + "numberOfBytes": "1568" + }, + "t_array(t_uint256)50_storage": { + "label": "uint256[50]", + "numberOfBytes": "1600" + }, + "t_bool": { + "label": "bool", + "numberOfBytes": "1" + }, + "t_bytes32": { + "label": "bytes32", + "numberOfBytes": "32" + }, + "t_contract(IRateLimiter)21229": { + "label": "contract IRateLimiter", + "numberOfBytes": "20" + }, + "t_mapping(t_address,t_uint256)": { + "label": "mapping(address => uint256)", + "numberOfBytes": "32" + }, + "t_mapping(t_bytes32,t_bool)": { + "label": "mapping(bytes32 => bool)", + "numberOfBytes": "32" + }, + "t_mapping(t_bytes32,t_struct(RoleData)39_storage)": { + "label": "mapping(bytes32 => struct AccessControlUpgradeable.RoleData)", + "numberOfBytes": "32" + }, + "t_mapping(t_bytes32,t_uint256)": { + "label": "mapping(bytes32 => uint256)", + "numberOfBytes": "32" + }, + "t_struct(AddressSet)2652_storage": { + "label": "struct EnumerableSetUpgradeable.AddressSet", + "members": [ + { + "label": "_inner", + "type": "t_struct(Set)2387_storage", + "offset": 0, + "slot": "0" + } + ], + "numberOfBytes": "64" + }, + "t_struct(RoleData)39_storage": { + "label": "struct AccessControlUpgradeable.RoleData", + "members": [ + { + "label": "members", + "type": "t_struct(AddressSet)2652_storage", + "offset": 0, + "slot": "0" + }, + { + "label": "adminRole", + "type": "t_bytes32", + "offset": 0, + "slot": "2" + } + ], + "numberOfBytes": "96" + }, + "t_struct(Set)2387_storage": { + "label": "struct EnumerableSetUpgradeable.Set", + "members": [ + { + "label": "_values", + "type": "t_array(t_bytes32)dyn_storage", + "offset": 0, + "slot": "0" + }, + { + "label": "_indexes", + "type": "t_mapping(t_bytes32,t_uint256)", + "offset": 0, + "slot": "1" + } + ], + "numberOfBytes": "64" + }, + "t_uint256": { + "label": "uint256", + "numberOfBytes": "32" + } + } + } + } + } +} diff --git a/contracts/bridge/SynapseBridge.sol b/contracts/bridge/SynapseBridge.sol index 14fe7c4de..b2de3d5f8 100644 --- a/contracts/bridge/SynapseBridge.sol +++ b/contracts/bridge/SynapseBridge.sol @@ -14,6 +14,7 @@ import "@openzeppelin/contracts/math/SafeMath.sol"; import "./interfaces/ISwap.sol"; import "./interfaces/IWETH9.sol"; import "./interfaces/IRateLimiter.sol"; +import "hardhat/console.sol"; interface IERC20Mintable is IERC20 { function mint(address to, uint256 amount) external; @@ -310,7 +311,7 @@ contract SynapseBridge is **/ function retryWithdraw( address to, - IERC20 token, + address token, uint256 amount, uint256 fee, bytes32 kappa @@ -320,7 +321,7 @@ contract SynapseBridge is "Caller is not rate limiter" ); - doWithdraw(to, token, amount, fee, kappa); + doWithdraw(to, IERC20(token), amount, fee, kappa); } // doWithdraw bypasses the rate limiter. See withdraw for documentation diff --git a/contracts/bridge/interfaces/ISwap.sol b/contracts/bridge/interfaces/ISwap.sol index 93f7b2962..10080a953 100644 --- a/contracts/bridge/interfaces/ISwap.sol +++ b/contracts/bridge/interfaces/ISwap.sol @@ -5,17 +5,8 @@ pragma solidity 0.6.12; import '@openzeppelin/contracts/token/ERC20/ERC20.sol'; interface ISwap { - // pool data view functions - function getA() external view returns (uint256); - function getToken(uint8 index) external view returns (IERC20); - function getTokenIndex(address tokenAddress) external view returns (uint8); - - function getTokenBalance(uint8 index) external view returns (uint256); - - function getVirtualPrice() external view returns (uint256); - // min return calculation functions function calculateSwap( uint8 tokenIndexFrom, @@ -24,32 +15,15 @@ interface ISwap { ) external view returns (uint256); function calculateTokenAmount(uint256[] calldata amounts, bool deposit) - external - view - returns (uint256); - - function calculateRemoveLiquidity(uint256 amount) - external - view - returns (uint256[] memory); + external + view + returns (uint256); function calculateRemoveLiquidityOneToken( uint256 tokenAmount, uint8 tokenIndex ) external view returns (uint256 availableTokenAmount); - // state modifying functions - function initialize( - IERC20[] memory pooledTokens, - uint8[] memory decimals, - string memory lpTokenName, - string memory lpTokenSymbol, - uint256 a, - uint256 fee, - uint256 adminFee, - address lpTokenTargetAddress - ) external; - function swap( uint8 tokenIndexFrom, uint8 tokenIndexTo, @@ -64,12 +38,6 @@ interface ISwap { uint256 deadline ) external returns (uint256); - function removeLiquidity( - uint256 amount, - uint256[] calldata minAmounts, - uint256 deadline - ) external returns (uint256[] memory); - function removeLiquidityOneToken( uint256 tokenAmount, uint8 tokenIndex, diff --git a/contracts/bridge/testing/ProxyAdmin.sol b/contracts/bridge/testing/ProxyAdmin.sol new file mode 100644 index 000000000..54d140448 --- /dev/null +++ b/contracts/bridge/testing/ProxyAdmin.sol @@ -0,0 +1,10 @@ +// SPDX-License-Identifier: MIT + +pragma solidity 0.8.11; + +import "@openzeppelin/contracts-4.3.1/proxy/transparent/ProxyAdmin.sol"; + +// used to generate typechain for proxy admin +contract ProxyAdminInterface is ProxyAdmin { + +} \ No newline at end of file diff --git a/docs/bridge/SynapseBridge.md b/docs/bridge/SynapseBridge.md index d5a38c518..e9a7cf8af 100644 --- a/docs/bridge/SynapseBridge.md +++ b/docs/bridge/SynapseBridge.md @@ -587,7 +587,7 @@ RateLimiter call this function to retry a mint of a SynERC20 (or any asset that ### retryWithdraw ```solidity -function retryWithdraw(address to, contract IERC20 token, uint256 amount, uint256 fee, bytes32 kappa) external nonpayable +function retryWithdraw(address to, address token, uint256 amount, uint256 fee, bytes32 kappa) external nonpayable ``` Function to be called by the rate limiter to retry a withdraw bypassing the rate limiter @@ -599,7 +599,7 @@ Function to be called by the rate limiter to retry a withdraw bypassing the rate | Name | Type | Description | |---|---|---| | to | address | address on chain to send underlying assets to | -| token | contract IERC20 | ERC20 compatible token to withdraw from the bridge | +| token | address | ERC20 compatible token to withdraw from the bridge | | amount | uint256 | Amount in native token decimals to withdraw | | fee | uint256 | Amount in native token decimals to save to the contract as fees | | kappa | bytes32 | kappa* | diff --git a/docs/bridge/interfaces/ISwap.md b/docs/bridge/interfaces/ISwap.md index 46ee3b5ae..5dca971e1 100644 --- a/docs/bridge/interfaces/ISwap.md +++ b/docs/bridge/interfaces/ISwap.md @@ -34,28 +34,6 @@ function addLiquidity(uint256[] amounts, uint256 minToMint, uint256 deadline) ex |---|---|---| | _0 | uint256 | undefined | -### calculateRemoveLiquidity - -```solidity -function calculateRemoveLiquidity(uint256 amount) external view returns (uint256[]) -``` - - - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| amount | uint256 | undefined | - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | uint256[] | undefined | - ### calculateRemoveLiquidityOneToken ```solidity @@ -120,23 +98,6 @@ function calculateTokenAmount(uint256[] amounts, bool deposit) external view ret | amounts | uint256[] | undefined | | deposit | bool | undefined | -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | uint256 | undefined | - -### getA - -```solidity -function getA() external view returns (uint256) -``` - - - - - - #### Returns | Name | Type | Description | @@ -165,114 +126,6 @@ function getToken(uint8 index) external view returns (contract IERC20) |---|---|---| | _0 | contract IERC20 | undefined | -### getTokenBalance - -```solidity -function getTokenBalance(uint8 index) external view returns (uint256) -``` - - - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| index | uint8 | undefined | - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | uint256 | undefined | - -### getTokenIndex - -```solidity -function getTokenIndex(address tokenAddress) external view returns (uint8) -``` - - - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| tokenAddress | address | undefined | - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | uint8 | undefined | - -### getVirtualPrice - -```solidity -function getVirtualPrice() external view returns (uint256) -``` - - - - - - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | uint256 | undefined | - -### initialize - -```solidity -function initialize(contract IERC20[] pooledTokens, uint8[] decimals, string lpTokenName, string lpTokenSymbol, uint256 a, uint256 fee, uint256 adminFee, address lpTokenTargetAddress) external nonpayable -``` - - - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| pooledTokens | contract IERC20[] | undefined | -| decimals | uint8[] | undefined | -| lpTokenName | string | undefined | -| lpTokenSymbol | string | undefined | -| a | uint256 | undefined | -| fee | uint256 | undefined | -| adminFee | uint256 | undefined | -| lpTokenTargetAddress | address | undefined | - -### removeLiquidity - -```solidity -function removeLiquidity(uint256 amount, uint256[] minAmounts, uint256 deadline) external nonpayable returns (uint256[]) -``` - - - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| amount | uint256 | undefined | -| minAmounts | uint256[] | undefined | -| deadline | uint256 | undefined | - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | uint256[] | undefined | - ### removeLiquidityImbalance ```solidity diff --git a/hardhat.config.ts b/hardhat.config.ts index d96730c54..e035956ff 100644 --- a/hardhat.config.ts +++ b/hardhat.config.ts @@ -8,8 +8,9 @@ import "hardhat-gas-reporter" import "solidity-coverage" import "hardhat-deploy" import "hardhat-spdx-license-identifier" -import "hardhat-interface-generator"; -import "@primitivefi/hardhat-dodoc"; +import "hardhat-interface-generator" +import "@primitivefi/hardhat-dodoc" +import "@openzeppelin/hardhat-upgrades" import { HardhatUserConfig } from "hardhat/config" import dotenv from "dotenv" @@ -103,7 +104,7 @@ let config: HardhatUserConfig = { target: "ethers-v5", }, dodoc: { - runOnCompile: true, + runOnCompile: false, debugMode: false, // pre solidity 5 breaks docgen exclude: ["MultisigWallet", "WETH9"] diff --git a/package-lock.json b/package-lock.json index a99f92421..93e3253f8 100644 --- a/package-lock.json +++ b/package-lock.json @@ -35,6 +35,7 @@ "@nomiclabs/hardhat-etherscan": "^2.1.2", "@nomiclabs/hardhat-waffle": "^2.0.1", "@nomiclabs/hardhat-web3": "^2.0.0", + "@openzeppelin/hardhat-upgrades": "^1.17.0", "@primitivefi/hardhat-dodoc": "^0.2.3", "@stdlib/time-now": "^0.0.8", "@typechain/ethers-v5": "^7.0.0", @@ -2824,6 +2825,230 @@ "resolved": "https://registry.npmjs.org/@openzeppelin/contracts-upgradeable/-/contracts-upgradeable-3.4.1.tgz", "integrity": "sha512-wBGlUzEkOxcj/ghtcF2yKc8ZYh+PTUtm1mK38zoENulJ6aplij7eH8quo3lMugfzPJy+V6V5qI8QhdQmCn7hkQ==" }, + "node_modules/@openzeppelin/hardhat-upgrades": { + "version": "1.17.0", + "resolved": "https://registry.npmjs.org/@openzeppelin/hardhat-upgrades/-/hardhat-upgrades-1.17.0.tgz", + "integrity": "sha512-GNxR3/3fCKQsFpBi/r+5ib6U81UM9KCypmcOQxuCkVp9JKJ80/3hQdg1R+AQku/dlnhutPsfkCokH2LZFc5mNA==", + "dev": true, + "dependencies": { + "@openzeppelin/upgrades-core": "^1.14.1", + "chalk": "^4.1.0", + "proper-lockfile": "^4.1.1" + }, + "bin": { + "migrate-oz-cli-project": "dist/scripts/migrate-oz-cli-project.js" + }, + "peerDependencies": { + "@nomiclabs/hardhat-ethers": "^2.0.0", + "hardhat": "^2.0.2" + } + }, + "node_modules/@openzeppelin/hardhat-upgrades/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/@openzeppelin/hardhat-upgrades/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/@openzeppelin/hardhat-upgrades/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/@openzeppelin/hardhat-upgrades/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/@openzeppelin/hardhat-upgrades/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/@openzeppelin/hardhat-upgrades/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@openzeppelin/upgrades-core": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/@openzeppelin/upgrades-core/-/upgrades-core-1.14.1.tgz", + "integrity": "sha512-iKlh1mbUxyfdjdEiUFyhMkqirfas+DMUu7ED53nZbHEyhcYsm+5Fl/g0Bv6bZA+a7k8kO8+22DNEKsqaDUBc2Q==", + "dev": true, + "dependencies": { + "bn.js": "^5.1.2", + "cbor": "^8.0.0", + "chalk": "^4.1.0", + "compare-versions": "^4.0.0", + "debug": "^4.1.1", + "ethereumjs-util": "^7.0.3", + "proper-lockfile": "^4.1.1", + "solidity-ast": "^0.4.15" + } + }, + "node_modules/@openzeppelin/upgrades-core/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/@openzeppelin/upgrades-core/node_modules/bn.js": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-5.2.0.tgz", + "integrity": "sha512-D7iWRBvnZE8ecXiLj/9wbxH7Tk79fAh8IHaTNq1RWRixsS02W+5qS+iE9yq6RYl0asXx5tw0bLhmT5pIfbSquw==", + "dev": true + }, + "node_modules/@openzeppelin/upgrades-core/node_modules/cbor": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/cbor/-/cbor-8.1.0.tgz", + "integrity": "sha512-DwGjNW9omn6EwP70aXsn7FQJx5kO12tX0bZkaTjzdVFM6/7nhA4t0EENocKGx6D2Bch9PE2KzCUf5SceBdeijg==", + "dev": true, + "dependencies": { + "nofilter": "^3.1.0" + }, + "engines": { + "node": ">=12.19" + } + }, + "node_modules/@openzeppelin/upgrades-core/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/@openzeppelin/upgrades-core/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/@openzeppelin/upgrades-core/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/@openzeppelin/upgrades-core/node_modules/debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "dev": true, + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/@openzeppelin/upgrades-core/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/@openzeppelin/upgrades-core/node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, + "node_modules/@openzeppelin/upgrades-core/node_modules/nofilter": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/nofilter/-/nofilter-3.1.0.tgz", + "integrity": "sha512-l2NNj07e9afPnhAhvgVrCD/oy2Ai1yfLpuo3EpiO1jFTsB4sFz6oIfAfSZyQzVpkZQ9xS8ZS5g1jCBgq4Hwo0g==", + "dev": true, + "engines": { + "node": ">=12.19" + } + }, + "node_modules/@openzeppelin/upgrades-core/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/@primitivefi/hardhat-dodoc": { "version": "0.2.3", "resolved": "https://registry.npmjs.org/@primitivefi/hardhat-dodoc/-/hardhat-dodoc-0.2.3.tgz", @@ -5968,6 +6193,12 @@ "integrity": "sha512-Gar0ASD4BDyKC4hl4DwHqDrmvjoxWKZigVnAbn5H1owvm4CxCPdb0HQDehwNYMJpla5+M2tPmPARzhtYuwpHow==", "dev": true }, + "node_modules/compare-versions": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/compare-versions/-/compare-versions-4.1.3.tgz", + "integrity": "sha512-WQfnbDcrYnGr55UwbxKiQKASnTtNnaAWVi8jZyy8NTpVAXWACSne8lMD1iaIo9AiU6mnuLvSVshCzewVuWxHUg==", + "dev": true + }, "node_modules/component-emitter": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.3.0.tgz", @@ -26694,6 +26925,17 @@ "asap": "~2.0.6" } }, + "node_modules/proper-lockfile": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/proper-lockfile/-/proper-lockfile-4.1.2.tgz", + "integrity": "sha512-TjNPblN4BwAWMXU8s9AEz4JmQxnD1NNL7bNOY/AKUzyamc379FWASUhc/K1pL2noVb+XmZKLL68cjzLsiOAMaA==", + "dev": true, + "dependencies": { + "graceful-fs": "^4.2.4", + "retry": "^0.12.0", + "signal-exit": "^3.0.2" + } + }, "node_modules/proxy-addr": { "version": "2.0.6", "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.6.tgz", @@ -27189,6 +27431,15 @@ "node": ">=0.12" } }, + "node_modules/retry": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/retry/-/retry-0.12.0.tgz", + "integrity": "sha1-G0KmJmoh8HQh0bC1S33BZ7AcATs=", + "dev": true, + "engines": { + "node": ">= 4" + } + }, "node_modules/reusify": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", @@ -34914,6 +35165,171 @@ "resolved": "https://registry.npmjs.org/@openzeppelin/contracts-upgradeable/-/contracts-upgradeable-3.4.1.tgz", "integrity": "sha512-wBGlUzEkOxcj/ghtcF2yKc8ZYh+PTUtm1mK38zoENulJ6aplij7eH8quo3lMugfzPJy+V6V5qI8QhdQmCn7hkQ==" }, + "@openzeppelin/hardhat-upgrades": { + "version": "1.17.0", + "resolved": "https://registry.npmjs.org/@openzeppelin/hardhat-upgrades/-/hardhat-upgrades-1.17.0.tgz", + "integrity": "sha512-GNxR3/3fCKQsFpBi/r+5ib6U81UM9KCypmcOQxuCkVp9JKJ80/3hQdg1R+AQku/dlnhutPsfkCokH2LZFc5mNA==", + "dev": true, + "requires": { + "@openzeppelin/upgrades-core": "^1.14.1", + "chalk": "^4.1.0", + "proper-lockfile": "^4.1.1" + }, + "dependencies": { + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "requires": { + "color-convert": "^2.0.1" + } + }, + "chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + } + } + }, + "@openzeppelin/upgrades-core": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/@openzeppelin/upgrades-core/-/upgrades-core-1.14.1.tgz", + "integrity": "sha512-iKlh1mbUxyfdjdEiUFyhMkqirfas+DMUu7ED53nZbHEyhcYsm+5Fl/g0Bv6bZA+a7k8kO8+22DNEKsqaDUBc2Q==", + "dev": true, + "requires": { + "bn.js": "^5.1.2", + "cbor": "^8.0.0", + "chalk": "^4.1.0", + "compare-versions": "^4.0.0", + "debug": "^4.1.1", + "ethereumjs-util": "^7.0.3", + "proper-lockfile": "^4.1.1", + "solidity-ast": "^0.4.15" + }, + "dependencies": { + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "requires": { + "color-convert": "^2.0.1" + } + }, + "bn.js": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-5.2.0.tgz", + "integrity": "sha512-D7iWRBvnZE8ecXiLj/9wbxH7Tk79fAh8IHaTNq1RWRixsS02W+5qS+iE9yq6RYl0asXx5tw0bLhmT5pIfbSquw==", + "dev": true + }, + "cbor": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/cbor/-/cbor-8.1.0.tgz", + "integrity": "sha512-DwGjNW9omn6EwP70aXsn7FQJx5kO12tX0bZkaTjzdVFM6/7nhA4t0EENocKGx6D2Bch9PE2KzCUf5SceBdeijg==", + "dev": true, + "requires": { + "nofilter": "^3.1.0" + } + }, + "chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "dev": true, + "requires": { + "ms": "2.1.2" + } + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, + "nofilter": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/nofilter/-/nofilter-3.1.0.tgz", + "integrity": "sha512-l2NNj07e9afPnhAhvgVrCD/oy2Ai1yfLpuo3EpiO1jFTsB4sFz6oIfAfSZyQzVpkZQ9xS8ZS5g1jCBgq4Hwo0g==", + "dev": true + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + } + } + }, "@primitivefi/hardhat-dodoc": { "version": "0.2.3", "resolved": "https://registry.npmjs.org/@primitivefi/hardhat-dodoc/-/hardhat-dodoc-0.2.3.tgz", @@ -37288,6 +37704,12 @@ "integrity": "sha512-Gar0ASD4BDyKC4hl4DwHqDrmvjoxWKZigVnAbn5H1owvm4CxCPdb0HQDehwNYMJpla5+M2tPmPARzhtYuwpHow==", "dev": true }, + "compare-versions": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/compare-versions/-/compare-versions-4.1.3.tgz", + "integrity": "sha512-WQfnbDcrYnGr55UwbxKiQKASnTtNnaAWVi8jZyy8NTpVAXWACSne8lMD1iaIo9AiU6mnuLvSVshCzewVuWxHUg==", + "dev": true + }, "component-emitter": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.3.0.tgz", @@ -55082,6 +55504,17 @@ "asap": "~2.0.6" } }, + "proper-lockfile": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/proper-lockfile/-/proper-lockfile-4.1.2.tgz", + "integrity": "sha512-TjNPblN4BwAWMXU8s9AEz4JmQxnD1NNL7bNOY/AKUzyamc379FWASUhc/K1pL2noVb+XmZKLL68cjzLsiOAMaA==", + "dev": true, + "requires": { + "graceful-fs": "^4.2.4", + "retry": "^0.12.0", + "signal-exit": "^3.0.2" + } + }, "proxy-addr": { "version": "2.0.6", "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.6.tgz", @@ -55479,6 +55912,12 @@ "resolved": "https://registry.npmjs.org/ret/-/ret-0.1.15.tgz", "integrity": "sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg==" }, + "retry": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/retry/-/retry-0.12.0.tgz", + "integrity": "sha1-G0KmJmoh8HQh0bC1S33BZ7AcATs=", + "dev": true + }, "reusify": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", diff --git a/package.json b/package.json index 9a825c1a6..967d8c5e3 100644 --- a/package.json +++ b/package.json @@ -52,6 +52,7 @@ "@nomiclabs/hardhat-etherscan": "^2.1.2", "@nomiclabs/hardhat-waffle": "^2.0.1", "@nomiclabs/hardhat-web3": "^2.0.0", + "@openzeppelin/hardhat-upgrades": "^1.17.0", "@primitivefi/hardhat-dodoc": "^0.2.3", "@stdlib/time-now": "^0.0.8", "@typechain/ethers-v5": "^7.0.0", diff --git a/test/bridge/SynapseBridge.ts b/test/bridge/SynapseBridge.ts index 8291b09ad..545a69c31 100644 --- a/test/bridge/SynapseBridge.ts +++ b/test/bridge/SynapseBridge.ts @@ -10,13 +10,15 @@ import { forceAdvanceOneBlock, } from "./testUtils" import { solidity } from "ethereum-waffle" -import { deployments, ethers } from "hardhat" +import { deployments, ethers, upgrades } from "hardhat" import chai from "chai" import { GenericERC20, RateLimiter, SynapseBridge } from "../../build/typechain" import epochSeconds from "@stdlib/time-now" import { keccak256 } from "ethers/lib/utils" import { randomBytes } from "crypto" +import { forkChain } from "../utils" +import { addBridgeOwner, upgradeBridgeProxy } from "./utilities/fork" chai.use(solidity) const { expect } = chai @@ -36,6 +38,7 @@ describe.only("SynapseBridge", async () => { let bridge: SynapseBridge let rateLimiter: RateLimiter let USDC: GenericERC20 + const BRIDGE_ADDRESS = "0x2796317b0fF8538F253012862c06787Adfb8cEb6" const decimals = Math.pow(10, 6) @@ -51,12 +54,18 @@ describe.only("SynapseBridge", async () => { .connect(deployer) .grantRole(limiterRole, await owner.getAddress()) + const governanceRole = await rateLimiter.GOVERNANCE_ROLE() + + await rateLimiter + .connect(deployer) + .grantRole(governanceRole, await owner.getAddress()) + // connect the bridge config v3 with the owner. For unauthorized tests, this can be overriden rateLimiter = rateLimiter.connect(owner) } // deploys the bridge, grants role. Rate limiter *must* be deployed first - const deployBridge = async () => { + const upgradeBridge = async () => { if (rateLimiter == null) { throw "rate limiter must be deployed before bridge" } @@ -65,8 +74,14 @@ describe.only("SynapseBridge", async () => { const synapseBridgeFactory = await ethers.getContractFactory( "SynapseBridge", ) - bridge = (await synapseBridgeFactory.deploy()) as SynapseBridge - await bridge.initialize() + + await upgradeBridgeProxy(BRIDGE_ADDRESS) + + // attach to the deployed bridge + bridge = (await synapseBridgeFactory.attach( + BRIDGE_ADDRESS, + )) as SynapseBridge + await addBridgeOwner(BRIDGE_ADDRESS, await deployer.getAddress()) // grant rate limiter role on bridge to rate limiter const rateLimiterRole = await bridge.RATE_LIMITER_ROLE() @@ -86,6 +101,8 @@ describe.only("SynapseBridge", async () => { await rateLimiter .connect(deployer) .grantRole(await rateLimiter.BRIDGE_ROLE(), bridge.address) + + await rateLimiter.setBridgeAddress(bridge.address) } const setupTokens = async () => { @@ -107,12 +124,14 @@ describe.only("SynapseBridge", async () => { recipient = signers[4] await deployRateLimiter() - await deployBridge() + await upgradeBridge() await setupTokens() }, ) beforeEach(async () => { + // fork the chain + await forkChain(process.env.ALCHEMY_API, 14555470) await setupTest() }) @@ -123,7 +142,7 @@ describe.only("SynapseBridge", async () => { mintAmount: number, intervalMin: number = 60, ) => { - const lastReset = Math.floor(epochSeconds() / 60) + const lastReset = Math.floor((await getCurrentBlockTimestamp()) / 60) allowanceAmount = allowanceAmount * decimals await expect( @@ -137,7 +156,7 @@ describe.only("SynapseBridge", async () => { await expect(USDC.mint(bridge.address, mintAmount * decimals)) } - it("should add to retry queue if rate limit hit", async () => { + it("Withdraw: should add to retry queue if rate limit hit", async () => { const mintAmount = 50 await setupAllowanceTest(USDC, 100, mintAmount) @@ -157,5 +176,7 @@ describe.only("SynapseBridge", async () => { // now retry. This should bypass the rate limiter await expect(rateLimiter.retryByKappa(kappa)).to.be.not.reverted + + expect(await bridge.kappaExists(kappa)).to.be.true }) }) diff --git a/test/bridge/utilities/fork.ts b/test/bridge/utilities/fork.ts new file mode 100644 index 000000000..399a5f809 --- /dev/null +++ b/test/bridge/utilities/fork.ts @@ -0,0 +1,46 @@ +import { deployments, ethers, upgrades, network } from "hardhat" +import {ProxyAdmin, SynapseBridge} from "../../../build/typechain"; +import {impersonateAccount} from "../../utils"; + +// upgradeForkBridge upgrade a forked bridge to the latest version +export async function upgradeBridgeProxy(bridgeAddress: string){ + // set the current bridge to a SynapseBridge type so we can pull out the owner + const synapseBridge = await ethers.getContractFactory("SynapseBridge"); + + const proxyAdminContract = await ethers.getContractFactory("ProxyAdmin") + const proxyAdmin = (proxyAdminContract.attach(await getProxyAdmin(bridgeAddress))) as ProxyAdmin + const proxyAdminOwner = await proxyAdmin.owner() + + const signer = await impersonateAccount(proxyAdminOwner) + + // set the balance + await network.provider.send("hardhat_setBalance", [ + signer._address, + "0x1228610962826298768", + ]); + + // upgrade the contract + await proxyAdmin.connect(signer).upgrade(bridgeAddress, (await synapseBridge.deploy()).address) +} + +// addBridgeOwner adds a new bridge owner to a deployede bridge contract for forking +export async function addBridgeOwner(bridgeAddress: string, newOwner: string) { + // set the current bridge to a SynapseBridge type so we can pull out the owner + const synapseBridge = await ethers.getContractFactory("SynapseBridge"); + + const deployedBridge = (await synapseBridge.attach(bridgeAddress)) as SynapseBridge + const adminRole = await deployedBridge.DEFAULT_ADMIN_ROLE() + const currentOwner = await deployedBridge.getRoleMember(adminRole, 0) + + const signer = await impersonateAccount(currentOwner) + await deployedBridge.connect(signer).grantRole(adminRole, newOwner) +} + +// getAdmin gets the admin of a TransparentUpgradableProxy. +// see: https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/proxy/transparent/TransparentUpgradeableProxy.sol#L61 for the slot +export async function getProxyAdmin(proxyAddress: String){ + // @ts-ignore + const rawOwner = await ethers.getDefaultProvider().getStorageAt(proxyAddress, "0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103") + + return ethers.utils.defaultAbiCoder.decode(["address"], rawOwner)[0] +} diff --git a/test/utils/testUtils.ts b/test/utils/testUtils.ts index 167c9e9a1..fb90b6d9f 100644 --- a/test/utils/testUtils.ts +++ b/test/utils/testUtils.ts @@ -157,3 +157,17 @@ export async function asyncForEach( await callback(array[index], index) } } + +export async function forkChain(apiUrl: String, blockNumber: Number) { + await network.provider.request({ + method: "hardhat_reset", + params: [ + { + forking: { + jsonRpcUrl: apiUrl, + blockNumber: blockNumber, + }, + }, + ], + }) +} From fdf5ff97381d945d5af8d7bac4b59dc21b6b7647 Mon Sep 17 00:00:00 2001 From: Trajan0x Date: Sun, 10 Apr 2022 02:32:48 -0400 Subject: [PATCH 014/135] alchemy --- .github/workflows/coveralls.yaml | 3 ++ .github/workflows/lint.yaml | 3 ++ .github/workflows/test.yaml | 3 ++ test/bridge/SynapseBridge.ts | 58 +++++++++++------------ test/bridge/utilities/bridge.ts | 80 ++++++++++++++++++++++++++++++++ 5 files changed, 117 insertions(+), 30 deletions(-) create mode 100644 test/bridge/utilities/bridge.ts diff --git a/.github/workflows/coveralls.yaml b/.github/workflows/coveralls.yaml index 5e3ae92a5..7431fdfd6 100644 --- a/.github/workflows/coveralls.yaml +++ b/.github/workflows/coveralls.yaml @@ -7,6 +7,9 @@ jobs: coverage: name: Build runs-on: ubuntu-18.04 + env: + AVAX_API: https://api.avax.network/ext/bc/C/rpc + ALCHEMY_API: ${{ secrets.ALCHEMY_API }} steps: - uses: actions/checkout@v2 diff --git a/.github/workflows/lint.yaml b/.github/workflows/lint.yaml index 22e73d555..945e8021b 100644 --- a/.github/workflows/lint.yaml +++ b/.github/workflows/lint.yaml @@ -6,6 +6,9 @@ on: ["push", "pull_request"] jobs: test: runs-on: ubuntu-latest + env: + AVAX_API: https://api.avax.network/ext/bc/C/rpc + ALCHEMY_API: ${{ secrets.ALCHEMY_API }} steps: - uses: actions/checkout@v2 diff --git a/.github/workflows/test.yaml b/.github/workflows/test.yaml index f968216bc..aee772c70 100644 --- a/.github/workflows/test.yaml +++ b/.github/workflows/test.yaml @@ -6,6 +6,9 @@ on: ["push", "pull_request"] jobs: test: runs-on: ubuntu-latest + env: + AVAX_API: https://api.avax.network/ext/bc/C/rpc + ALCHEMY_API: ${{ secrets.ALCHEMY_API }} steps: - uses: actions/checkout@v2 diff --git a/test/bridge/SynapseBridge.ts b/test/bridge/SynapseBridge.ts index 545a69c31..9a7518d7f 100644 --- a/test/bridge/SynapseBridge.ts +++ b/test/bridge/SynapseBridge.ts @@ -19,6 +19,7 @@ import { keccak256 } from "ethers/lib/utils" import { randomBytes } from "crypto" import { forkChain } from "../utils" import { addBridgeOwner, upgradeBridgeProxy } from "./utilities/fork" +import {deployRateLimiter, setupForkedBridge} from "./utilities/bridge"; chai.use(solidity) const { expect } = chai @@ -39,30 +40,11 @@ describe.only("SynapseBridge", async () => { let rateLimiter: RateLimiter let USDC: GenericERC20 const BRIDGE_ADDRESS = "0x2796317b0fF8538F253012862c06787Adfb8cEb6" + const NUSD = "0x1B84765dE8B7566e4cEAF4D0fD3c5aF52D3DdE4F" + const NUSD_POOL = "0x1116898DdA4015eD8dDefb84b6e8Bc24528Af2d8" const decimals = Math.pow(10, 6) - // deploy rateLimiter deploys the rate limiter contract, sets it to RateLimiter and - // assigns owner the limiter role - const deployRateLimiter = async () => { - const rateLimiterFactory = await ethers.getContractFactory("RateLimiter") - rateLimiter = (await rateLimiterFactory.deploy()) as RateLimiter - await rateLimiter.initialize() - - const limiterRole = await rateLimiter.LIMITER_ROLE() - await rateLimiter - .connect(deployer) - .grantRole(limiterRole, await owner.getAddress()) - - const governanceRole = await rateLimiter.GOVERNANCE_ROLE() - - await rateLimiter - .connect(deployer) - .grantRole(governanceRole, await owner.getAddress()) - - // connect the bridge config v3 with the owner. For unauthorized tests, this can be overriden - rateLimiter = rateLimiter.connect(owner) - } // deploys the bridge, grants role. Rate limiter *must* be deployed first const upgradeBridge = async () => { @@ -123,8 +105,8 @@ describe.only("SynapseBridge", async () => { nodeGroup = signers[3] recipient = signers[4] - await deployRateLimiter() - await upgradeBridge() + rateLimiter = await deployRateLimiter(deployer, owner) + bridge = await setupForkedBridge(rateLimiter, BRIDGE_ADDRESS, deployer, nodeGroup) await setupTokens() }, ) @@ -137,9 +119,8 @@ describe.only("SynapseBridge", async () => { // ammounts are multiplied by 10^6 const setupAllowanceTest = async ( - token: GenericERC20, + tokenAddress: string, allowanceAmount: number, - mintAmount: number, intervalMin: number = 60, ) => { const lastReset = Math.floor((await getCurrentBlockTimestamp()) / 60) @@ -147,18 +128,19 @@ describe.only("SynapseBridge", async () => { await expect( rateLimiter.setAllowance( - token.address, + tokenAddress, allowanceAmount, intervalMin, lastReset, ), ).to.be.not.reverted - await expect(USDC.mint(bridge.address, mintAmount * decimals)) } it("Withdraw: should add to retry queue if rate limit hit", async () => { const mintAmount = 50 - await setupAllowanceTest(USDC, 100, mintAmount) + + await expect(USDC.mint(bridge.address, mintAmount * decimals)) + await setupAllowanceTest(USDC.address, 100) const kappa = keccak256(randomBytes(32)) @@ -174,9 +156,25 @@ describe.only("SynapseBridge", async () => { ) // now retry. This should bypass the rate limiter - await expect(rateLimiter.retryByKappa(kappa)).to.be.not.reverted - expect(await bridge.kappaExists(kappa)).to.be.true }) + + it('WithdrawAndRemove: should add to retry queue if rate limit hit', async () => { + const allowanceAmount = 500 + const withdrawAmount = 1000 + + await setupAllowanceTest(NUSD, allowanceAmount) + const kappa = keccak256(randomBytes(32)) + + await expect( + bridge + .connect(nodeGroup) + .withdrawAndRemove(await recipient.getAddress(), NUSD, withdrawAmount, 10, NUSD_POOL, 1, withdrawAmount, epochSeconds(), kappa) + ).to.be.not.reverted + + expect(await bridge.kappaExists(kappa)).to.be.false + await expect(rateLimiter.retryByKappa(kappa)).to.be.not.reverted + expect(await bridge.kappaExists(kappa)).to.be.true + }); }) diff --git a/test/bridge/utilities/bridge.ts b/test/bridge/utilities/bridge.ts new file mode 100644 index 000000000..be4309a53 --- /dev/null +++ b/test/bridge/utilities/bridge.ts @@ -0,0 +1,80 @@ +import {RateLimiter, SynapseBridge} from "../../../build/typechain"; +import { deployments, ethers, upgrades } from "hardhat" +import {Signer} from "ethers"; +import {addBridgeOwner, upgradeBridgeProxy} from "./fork"; + +/** + * deploys a rate limiter and sets it up with a role + * @param deployer - dpeloyer of the contract + * @param owner - owner of the rate limiter. + */ +export async function deployRateLimiter(deployer: Signer, owner: Signer): Promise { + const rateLimiterFactory = await ethers.getContractFactory("RateLimiter") + const rateLimiter = (await rateLimiterFactory.deploy()) as RateLimiter + await rateLimiter.initialize() + + const limiterRole = await rateLimiter.LIMITER_ROLE() + await rateLimiter + .connect(deployer) + .grantRole(limiterRole, await owner.getAddress()) + + const governanceRole = await rateLimiter.GOVERNANCE_ROLE() + + await rateLimiter + .connect(deployer) + .grantRole(governanceRole, await owner.getAddress()) + + // connect the bridge config v3 with the owner. For unauthorized tests, this can be overriden + return rateLimiter.connect(owner) +} + +export async function setupForkedBridge(rateLimiter: RateLimiter, bridgeAddress: string, deployer: Signer, nodeGroup: Signer): Promise { + if (rateLimiter == null) { + throw "rate limiter must be deployed before bridge" + } + + // deploy and initialize the rate limiter + const synapseBridgeFactory = await ethers.getContractFactory( + "SynapseBridge", + ) + + await upgradeBridgeProxy(bridgeAddress) + + // attach to the deployed bridge + let bridge = (await synapseBridgeFactory.attach( + bridgeAddress, + )) as SynapseBridge + + await addBridgeOwner(bridgeAddress, await deployer.getAddress()) + + // grant rate limiter role on bridge to rate limiter + const rateLimiterRole = await bridge.RATE_LIMITER_ROLE() + await bridge + .connect(deployer) + .grantRole(rateLimiterRole, rateLimiter.address) + + await bridge.setRateLimiter(rateLimiter.address) + + const nodeGroupRole = await bridge.NODEGROUP_ROLE() + await bridge + .connect(deployer) + .grantRole(nodeGroupRole, await nodeGroup.getAddress()) + + bridge = await bridge.connect(nodeGroup) + + await rateLimiter + .connect(deployer) + .grantRole(await rateLimiter.BRIDGE_ROLE(), bridge.address) + + await rateLimiter.setBridgeAddress(bridge.address) + + return bridge +} + +const BRIDGE_CONFIGS = { + 1: { + bridge: "0x2796317b0fF8538F253012862c06787Adfb8cEb6", + nusd: "0x1B84765dE8B7566e4cEAF4D0fD3c5aF52D3DdE4F", + nusd_pool: "0x1116898DdA4015eD8dDefb84b6e8Bc24528Af2d8" + } +} \ No newline at end of file From 7f7456cf799897242ca6cdf3843f2c79b3c635cb Mon Sep 17 00:00:00 2001 From: Trajan0x Date: Sun, 10 Apr 2022 02:58:50 -0400 Subject: [PATCH 015/135] mint update --- contracts/bridge/SynapseBridge.sol | 6 +-- .../{SynapseBridge.ts => SynapseBridgeETH.ts} | 52 +++++++++++++++---- test/bridge/utilities/bridge.ts | 8 --- 3 files changed, 44 insertions(+), 22 deletions(-) rename test/bridge/{SynapseBridge.ts => SynapseBridgeETH.ts} (79%) diff --git a/contracts/bridge/SynapseBridge.sol b/contracts/bridge/SynapseBridge.sol index b2de3d5f8..53ea40ea1 100644 --- a/contracts/bridge/SynapseBridge.sol +++ b/contracts/bridge/SynapseBridge.sol @@ -36,11 +36,7 @@ contract SynapseBridge is // selectors bytes4 private constant RETRY_MINT_SELECTOR = - bytes4( - keccak256( - "retryMint(address,IERC20Mintable,uint256,uint256,bytes32)" - ) - ); + bytes4(keccak256("retryMint(address,address,uint256,uint256,bytes32)")); bytes4 private constant RETRY_MINT_AND_SWAP_SELECTOR = bytes4( keccak256( diff --git a/test/bridge/SynapseBridge.ts b/test/bridge/SynapseBridgeETH.ts similarity index 79% rename from test/bridge/SynapseBridge.ts rename to test/bridge/SynapseBridgeETH.ts index 9a7518d7f..9701f10ca 100644 --- a/test/bridge/SynapseBridge.ts +++ b/test/bridge/SynapseBridgeETH.ts @@ -19,12 +19,12 @@ import { keccak256 } from "ethers/lib/utils" import { randomBytes } from "crypto" import { forkChain } from "../utils" import { addBridgeOwner, upgradeBridgeProxy } from "./utilities/fork" -import {deployRateLimiter, setupForkedBridge} from "./utilities/bridge"; +import { deployRateLimiter, setupForkedBridge } from "./utilities/bridge" chai.use(solidity) const { expect } = chai -describe.only("SynapseBridge", async () => { +describe("SynapseBridge", async () => { const { get } = deployments // signers @@ -39,13 +39,14 @@ describe.only("SynapseBridge", async () => { let bridge: SynapseBridge let rateLimiter: RateLimiter let USDC: GenericERC20 + const BRIDGE_ADDRESS = "0x2796317b0fF8538F253012862c06787Adfb8cEb6" const NUSD = "0x1B84765dE8B7566e4cEAF4D0fD3c5aF52D3DdE4F" const NUSD_POOL = "0x1116898DdA4015eD8dDefb84b6e8Bc24528Af2d8" + const SYN = "0x0f2D719407FdBeFF09D87557AbB7232601FD9F29" const decimals = Math.pow(10, 6) - // deploys the bridge, grants role. Rate limiter *must* be deployed first const upgradeBridge = async () => { if (rateLimiter == null) { @@ -106,7 +107,12 @@ describe.only("SynapseBridge", async () => { recipient = signers[4] rateLimiter = await deployRateLimiter(deployer, owner) - bridge = await setupForkedBridge(rateLimiter, BRIDGE_ADDRESS, deployer, nodeGroup) + bridge = await setupForkedBridge( + rateLimiter, + BRIDGE_ADDRESS, + deployer, + nodeGroup, + ) await setupTokens() }, ) @@ -160,7 +166,7 @@ describe.only("SynapseBridge", async () => { expect(await bridge.kappaExists(kappa)).to.be.true }) - it('WithdrawAndRemove: should add to retry queue if rate limit hit', async () => { + it("WithdrawAndRemove: should add to retry queue if rate limit hit", async () => { const allowanceAmount = 500 const withdrawAmount = 1000 @@ -168,13 +174,41 @@ describe.only("SynapseBridge", async () => { const kappa = keccak256(randomBytes(32)) await expect( - bridge - .connect(nodeGroup) - .withdrawAndRemove(await recipient.getAddress(), NUSD, withdrawAmount, 10, NUSD_POOL, 1, withdrawAmount, epochSeconds(), kappa) + bridge + .connect(nodeGroup) + .withdrawAndRemove( + await recipient.getAddress(), + NUSD, + withdrawAmount, + 10, + NUSD_POOL, + 1, + withdrawAmount, + epochSeconds(), + kappa, + ), ).to.be.not.reverted expect(await bridge.kappaExists(kappa)).to.be.false await expect(rateLimiter.retryByKappa(kappa)).to.be.not.reverted expect(await bridge.kappaExists(kappa)).to.be.true - }); + }) + + it.only("Mint: should add to retry queue if rate limit hit", async () => { + const allowanceAmount = 500 + const mintAmount = 1000 + + await setupAllowanceTest(SYN, allowanceAmount) + const kappa = keccak256(randomBytes(32)) + + await expect( + bridge + .connect(nodeGroup) + .mint(await recipient.getAddress(), SYN, mintAmount, 10, kappa), + ).to.be.not.reverted + + expect(await bridge.kappaExists(kappa)).to.be.false + await expect(rateLimiter.retryByKappa(kappa)).to.be.not.reverted + expect(await bridge.kappaExists(kappa)).to.be.true + }) }) diff --git a/test/bridge/utilities/bridge.ts b/test/bridge/utilities/bridge.ts index be4309a53..da7d93613 100644 --- a/test/bridge/utilities/bridge.ts +++ b/test/bridge/utilities/bridge.ts @@ -69,12 +69,4 @@ export async function setupForkedBridge(rateLimiter: RateLimiter, bridgeAddress: await rateLimiter.setBridgeAddress(bridge.address) return bridge -} - -const BRIDGE_CONFIGS = { - 1: { - bridge: "0x2796317b0fF8538F253012862c06787Adfb8cEb6", - nusd: "0x1B84765dE8B7566e4cEAF4D0fD3c5aF52D3DdE4F", - nusd_pool: "0x1116898DdA4015eD8dDefb84b6e8Bc24528Af2d8" - } } \ No newline at end of file From 38121f80d2e5fd8242bab7e58e2cf4d14b35f06e Mon Sep 17 00:00:00 2001 From: Trajan0x Date: Sun, 10 Apr 2022 04:08:44 -0400 Subject: [PATCH 016/135] mint and swap --- contracts/bridge/RateLimiter.sol | 34 ++++++++- contracts/bridge/SynapseBridge.sol | 1 + test/bridge/SynapseBridgeAvax.ts | 112 +++++++++++++++++++++++++++++ test/bridge/SynapseBridgeETH.ts | 62 ++-------------- 4 files changed, 150 insertions(+), 59 deletions(-) create mode 100644 test/bridge/SynapseBridgeAvax.ts diff --git a/contracts/bridge/RateLimiter.sol b/contracts/bridge/RateLimiter.sol index d26e2780c..55fff5123 100644 --- a/contracts/bridge/RateLimiter.sol +++ b/contracts/bridge/RateLimiter.sol @@ -8,6 +8,7 @@ import "@openzeppelin/contracts-4.3.1-upgradeable/utils/math/MathUpgradeable.sol import "./libraries/EnumerableMapUpgradeable.sol"; import "./interfaces/IRateLimiter.sol"; +import "hardhat/console.sol"; // @title RateLimiter // @dev a bridge asset rate limiter based on https://github.com/gnosis/safe-modules/blob/master/allowances/contracts/AlowanceModule.sol @@ -180,7 +181,10 @@ contract RateLimiter is function retryByKappa(bytes32 kappa) external onlyRole(LIMITER_ROLE) { bytes memory toRetry = EnumerableMapUpgradeable.get(limited, kappa); (bool success, bytes memory returnData) = BRIDGE_ADDRESS.call(toRetry); - require(success, "could not call bridge"); + require( + success, + append("could not call bridge:", _getRevertMsg(returnData)) + ); EnumerableMapUpgradeable.remove(limited, kappa); } @@ -201,7 +205,10 @@ contract RateLimiter is (bool success, bytes memory returnData) = BRIDGE_ADDRESS.call( toRetry ); - require(success, "could not call bridge"); + require( + success, + append("could not call bridge: ", _getRevertMsg(returnData)) + ); EnumerableMapUpgradeable.remove(limited, kappa); } } @@ -237,4 +244,27 @@ contract RateLimiter is uint256(allowance.lastResetMin) ]; } + + function _getRevertMsg(bytes memory _returnData) + internal + pure + returns (string memory) + { + // If the _res length is less than 68, then the transaction failed silently (without a revert message) + if (_returnData.length < 68) return "Transaction reverted silently"; + + assembly { + // Slice the sighash. + _returnData := add(_returnData, 0x04) + } + return abi.decode(_returnData, (string)); // All that remains is the revert string + } + + function append(string memory a, string memory b) + internal + pure + returns (string memory) + { + return string(abi.encodePacked(a, b)); + } } diff --git a/contracts/bridge/SynapseBridge.sol b/contracts/bridge/SynapseBridge.sol index 53ea40ea1..1be13cef1 100644 --- a/contracts/bridge/SynapseBridge.sol +++ b/contracts/bridge/SynapseBridge.sol @@ -662,6 +662,7 @@ contract SynapseBridge is if (chainGasAmount != 0 && address(this).balance > chainGasAmount) { to.call.value(chainGasAmount)(""); } + // first check to make sure more will be given than min amount required uint256 expectedOutput = ISwap(pool).calculateSwap( tokenIndexFrom, diff --git a/test/bridge/SynapseBridgeAvax.ts b/test/bridge/SynapseBridgeAvax.ts new file mode 100644 index 000000000..e40ccdcff --- /dev/null +++ b/test/bridge/SynapseBridgeAvax.ts @@ -0,0 +1,112 @@ +import { Signer } from "ethers" +import { getCurrentBlockTimestamp } from "./testUtils" +import { solidity } from "ethereum-waffle" +import { deployments, ethers } from "hardhat" + +import chai from "chai" +import { GenericERC20, RateLimiter, SynapseBridge } from "../../build/typechain" +import epochSeconds from "@stdlib/time-now" +import { keccak256 } from "ethers/lib/utils" +import { randomBytes } from "crypto" +import { forkChain } from "../utils" +import { deployRateLimiter, setupForkedBridge } from "./utilities/bridge" + +chai.use(solidity) +const { expect } = chai + +describe("SynapseBridgeAvax", async () => { + // signers + let signers: Array + let deployer: Signer + let owner: Signer + let limiter: Signer + let nodeGroup: Signer + let recipient: Signer + + const decimals = Math.pow(10, 6) + const NUSD = "0xCFc37A6AB183dd4aED08C204D1c2773c0b1BDf46" + const NUSD_POOL = "0xED2a7edd7413021d440b09D654f3b87712abAB66" + + // contracts + let bridge: SynapseBridge + let rateLimiter: RateLimiter + + const BRIDGE_ADDRESS = "0xC05e61d0E7a63D27546389B7aD62FdFf5A91aACE" + + const setupTest = deployments.createFixture( + async ({ deployments, ethers }) => { + await deployments.fixture() + + signers = await ethers.getSigners() + + // assign roles + deployer = signers[0] + owner = signers[1] + limiter = signers[2] + nodeGroup = signers[3] + recipient = signers[4] + + rateLimiter = await deployRateLimiter(deployer, owner) + bridge = await setupForkedBridge( + rateLimiter, + BRIDGE_ADDRESS, + deployer, + nodeGroup, + ) + }, + ) + + beforeEach(async () => { + // fork the chain + await forkChain(process.env.AVAX_API, 13229005) + await setupTest() + }) + + // ammounts are multiplied by 10^6 + const setupAllowanceTest = async ( + tokenAddress: string, + allowanceAmount: number, + intervalMin: number = 60, + ) => { + const lastReset = Math.floor((await getCurrentBlockTimestamp()) / 60) + allowanceAmount = allowanceAmount * decimals + + await expect( + rateLimiter.setAllowance( + tokenAddress, + allowanceAmount, + intervalMin, + lastReset, + ), + ).to.be.not.reverted + } + + it("MintAndSwap: should add to retry queue if rate limit hit", async () => { + const allowanceAmount = 500 + const mintAmount = 1000 + + await setupAllowanceTest(NUSD, allowanceAmount) + const kappa = keccak256(randomBytes(32)) + + await expect( + bridge + .connect(nodeGroup) + .mintAndSwap( + await recipient.getAddress(), + NUSD, + mintAmount, + 10, + NUSD_POOL, + 0, + 2, + mintAmount, + epochSeconds(), + kappa, + ), + ).to.be.not.reverted + + expect(await bridge.kappaExists(kappa)).to.be.false + await expect(rateLimiter.retryByKappa(kappa)).to.be.not.reverted + expect(await bridge.kappaExists(kappa)).to.be.true + }) +}) diff --git a/test/bridge/SynapseBridgeETH.ts b/test/bridge/SynapseBridgeETH.ts index 9701f10ca..b86e67294 100644 --- a/test/bridge/SynapseBridgeETH.ts +++ b/test/bridge/SynapseBridgeETH.ts @@ -1,16 +1,7 @@ -import { BigNumber, Signer } from "ethers" -import { - MAX_UINT256, - TIME, - ZERO_ADDRESS, - asyncForEach, - getCurrentBlockTimestamp, - setNextTimestamp, - setTimestamp, - forceAdvanceOneBlock, -} from "./testUtils" +import { Signer } from "ethers" +import { getCurrentBlockTimestamp } from "./testUtils" import { solidity } from "ethereum-waffle" -import { deployments, ethers, upgrades } from "hardhat" +import { deployments, ethers } from "hardhat" import chai from "chai" import { GenericERC20, RateLimiter, SynapseBridge } from "../../build/typechain" @@ -18,15 +9,12 @@ import epochSeconds from "@stdlib/time-now" import { keccak256 } from "ethers/lib/utils" import { randomBytes } from "crypto" import { forkChain } from "../utils" -import { addBridgeOwner, upgradeBridgeProxy } from "./utilities/fork" import { deployRateLimiter, setupForkedBridge } from "./utilities/bridge" chai.use(solidity) const { expect } = chai -describe("SynapseBridge", async () => { - const { get } = deployments - +describe("SynapseBridgeETH", async () => { // signers let signers: Array let deployer: Signer @@ -48,46 +36,6 @@ describe("SynapseBridge", async () => { const decimals = Math.pow(10, 6) // deploys the bridge, grants role. Rate limiter *must* be deployed first - const upgradeBridge = async () => { - if (rateLimiter == null) { - throw "rate limiter must be deployed before bridge" - } - - // deploy and initialize the rate limiter - const synapseBridgeFactory = await ethers.getContractFactory( - "SynapseBridge", - ) - - await upgradeBridgeProxy(BRIDGE_ADDRESS) - - // attach to the deployed bridge - bridge = (await synapseBridgeFactory.attach( - BRIDGE_ADDRESS, - )) as SynapseBridge - await addBridgeOwner(BRIDGE_ADDRESS, await deployer.getAddress()) - - // grant rate limiter role on bridge to rate limiter - const rateLimiterRole = await bridge.RATE_LIMITER_ROLE() - await bridge - .connect(deployer) - .grantRole(rateLimiterRole, rateLimiter.address) - - await bridge.setRateLimiter(rateLimiter.address) - - const nodeGroupRole = await bridge.NODEGROUP_ROLE() - await bridge - .connect(deployer) - .grantRole(nodeGroupRole, await nodeGroup.getAddress()) - - bridge = await bridge.connect(nodeGroup) - - await rateLimiter - .connect(deployer) - .grantRole(await rateLimiter.BRIDGE_ROLE(), bridge.address) - - await rateLimiter.setBridgeAddress(bridge.address) - } - const setupTokens = async () => { const erc20Factory = await ethers.getContractFactory("GenericERC20") USDC = (await erc20Factory.deploy("USDC", "USDC", "6")) as GenericERC20 @@ -194,7 +142,7 @@ describe("SynapseBridge", async () => { expect(await bridge.kappaExists(kappa)).to.be.true }) - it.only("Mint: should add to retry queue if rate limit hit", async () => { + it("Mint: should add to retry queue if rate limit hit", async () => { const allowanceAmount = 500 const mintAmount = 1000 From d0e76b45ef4f8d766705efacee3871b0b64e3a42 Mon Sep 17 00:00:00 2001 From: Trajan0x Date: Mon, 11 Apr 2022 13:22:48 -0400 Subject: [PATCH 017/135] struct refactor --- contracts/bridge/RateLimiter.sol | 21 ++++++++------------- package-lock.json | 9 ++++----- test/bridge/RateLimiter.ts | 2 +- 3 files changed, 13 insertions(+), 19 deletions(-) diff --git a/contracts/bridge/RateLimiter.sol b/contracts/bridge/RateLimiter.sol index 55fff5123..8b32f6c75 100644 --- a/contracts/bridge/RateLimiter.sol +++ b/contracts/bridge/RateLimiter.sol @@ -18,6 +18,7 @@ contract RateLimiter is ReentrancyGuardUpgradeable, IRateLimiter { + using EnumerableMapUpgradeable for EnumerableMapUpgradeable.Bytes32ToBytesMap; /*** STATE ***/ string public constant NAME = "Rate Limiter"; @@ -175,33 +176,27 @@ contract RateLimiter is external onlyRole(BRIDGE_ROLE) { - EnumerableMapUpgradeable.set(limited, kappa, rateLimited); + limited.set(kappa, rateLimited); } function retryByKappa(bytes32 kappa) external onlyRole(LIMITER_ROLE) { - bytes memory toRetry = EnumerableMapUpgradeable.get(limited, kappa); + bytes memory toRetry = limited.get(kappa); (bool success, bytes memory returnData) = BRIDGE_ADDRESS.call(toRetry); require( success, append("could not call bridge:", _getRevertMsg(returnData)) ); - EnumerableMapUpgradeable.remove(limited, kappa); + limited.remove(kappa); } function retryCount(uint8 count) external onlyRole(LIMITER_ROLE) { // no issues casting to uint8 here. If length is greater then 255, min is always taken uint8 attempts = uint8( - MathUpgradeable.min( - uint256(count), - EnumerableMapUpgradeable.length(limited) - ) + MathUpgradeable.min(uint256(count), limited.length()) ); for (uint8 i = 0; i < attempts; i++) { - (bytes32 kappa, bytes memory toRetry) = EnumerableMapUpgradeable.at( - limited, - i - ); + (bytes32 kappa, bytes memory toRetry) = limited.at(i); (bool success, bytes memory returnData) = BRIDGE_ADDRESS.call( toRetry ); @@ -209,12 +204,12 @@ contract RateLimiter is success, append("could not call bridge: ", _getRevertMsg(returnData)) ); - EnumerableMapUpgradeable.remove(limited, kappa); + limited.remove(kappa); } } function deleteByKappa(bytes32 kappa) external onlyRole(LIMITER_ROLE) { - EnumerableMapUpgradeable.remove(limited, kappa); + limited.remove(kappa); } /** diff --git a/package-lock.json b/package-lock.json index 93e3253f8..7db13ac89 100644 --- a/package-lock.json +++ b/package-lock.json @@ -5,7 +5,6 @@ "requires": true, "packages": { "": { - "name": "synapse-contracts", "version": "1.0.0", "license": "ISC", "dependencies": { @@ -29731,6 +29730,7 @@ "resolved": "https://registry.npmjs.org/squirrelly/-/squirrelly-8.0.8.tgz", "integrity": "sha512-7dyZJ9Gw86MmH0dYLiESsjGOTj6KG8IWToTaqBuB6LwPI+hyNb6mbQaZwrfnAQ4cMDnSWMUvX/zAYDLTSWLk/w==", "dev": true, + "peer": true, "engines": { "node": ">=6.0.0" }, @@ -35335,9 +35335,7 @@ "resolved": "https://registry.npmjs.org/@primitivefi/hardhat-dodoc/-/hardhat-dodoc-0.2.3.tgz", "integrity": "sha512-ver9uHa79LTDTeebOKZ/eOVRL/FP1k0s0x/5Bo/8ZaDdLWFVClKqZyZYVjjW4CJqTPCt8uU9b9p71P2vzH4O9A==", "dev": true, - "requires": { - "squirrelly": "^8.0.8" - } + "requires": {} }, "@resolver-engine/core": { "version": "0.3.3", @@ -57788,7 +57786,8 @@ "version": "8.0.8", "resolved": "https://registry.npmjs.org/squirrelly/-/squirrelly-8.0.8.tgz", "integrity": "sha512-7dyZJ9Gw86MmH0dYLiESsjGOTj6KG8IWToTaqBuB6LwPI+hyNb6mbQaZwrfnAQ4cMDnSWMUvX/zAYDLTSWLk/w==", - "dev": true + "dev": true, + "peer": true }, "sshpk": { "version": "1.16.1", diff --git a/test/bridge/RateLimiter.ts b/test/bridge/RateLimiter.ts index 14df1c0b5..1addbefbb 100644 --- a/test/bridge/RateLimiter.ts +++ b/test/bridge/RateLimiter.ts @@ -19,7 +19,7 @@ import epochSeconds from "@stdlib/time-now" chai.use(solidity) const { expect, assert } = chai -describe("Rate Limiter", () => { +describe.only("Rate Limiter", () => { let signers: Array let deployer: Signer let owner: Signer From de8be3d71da70e944a5398ead9e69ae07d299297 Mon Sep 17 00:00:00 2001 From: Trajan0x Date: Mon, 11 Apr 2022 14:54:49 -0400 Subject: [PATCH 018/135] add timestamps to rate limiter map --- contracts/bridge/RateLimiter.md | 3 + contracts/bridge/RateLimiter.sol | 18 +- .../libraries/EnumerableMapUpgradeable.sol | 64 ++++--- docs/bridge/testing/ProxyAdminInterface.md | 175 ++++++++++++++++++ docs/elin/contracts-4.3.1/access/Ownable.md | 79 ++++++++ .../proxy/ERC1967/ERC1967Proxy.md | 64 +++++++ .../proxy/ERC1967/ERC1967Upgrade.md | 64 +++++++ docs/elin/contracts-4.3.1/proxy/Proxy.md | 12 ++ .../contracts-4.3.1/proxy/beacon/IBeacon.md | 32 ++++ .../proxy/transparent/ProxyAdmin.md | 175 ++++++++++++++++++ .../TransparentUpgradeableProxy.md | 150 +++++++++++++++ docs/elin/contracts-4.3.1/utils/Address.md | 12 ++ .../elin/contracts-4.3.1/utils/StorageSlot.md | 12 ++ .../utils/structs/EnumerableMapUpgradeable.md | 12 -- hardhat.config.ts | 2 +- test/bridge/RateLimiter.ts | 2 +- 16 files changed, 829 insertions(+), 47 deletions(-) create mode 100644 contracts/bridge/RateLimiter.md create mode 100644 docs/bridge/testing/ProxyAdminInterface.md create mode 100644 docs/elin/contracts-4.3.1/access/Ownable.md create mode 100644 docs/elin/contracts-4.3.1/proxy/ERC1967/ERC1967Proxy.md create mode 100644 docs/elin/contracts-4.3.1/proxy/ERC1967/ERC1967Upgrade.md create mode 100644 docs/elin/contracts-4.3.1/proxy/Proxy.md create mode 100644 docs/elin/contracts-4.3.1/proxy/beacon/IBeacon.md create mode 100644 docs/elin/contracts-4.3.1/proxy/transparent/ProxyAdmin.md create mode 100644 docs/elin/contracts-4.3.1/proxy/transparent/TransparentUpgradeableProxy.md create mode 100644 docs/elin/contracts-4.3.1/utils/Address.md create mode 100644 docs/elin/contracts-4.3.1/utils/StorageSlot.md delete mode 100644 docs/elin/contracts-4.6.0-upgradeable/utils/structs/EnumerableMapUpgradeable.md diff --git a/contracts/bridge/RateLimiter.md b/contracts/bridge/RateLimiter.md new file mode 100644 index 000000000..6647d8f79 --- /dev/null +++ b/contracts/bridge/RateLimiter.md @@ -0,0 +1,3 @@ +# Rate Limiter + +Rate limiter is designed to make [withdraws/mints proportional to a preset-cap](https://twitter.com/hasufl/status/1506572435998625792) in a time period. It introduces latency for withdraws larger then a cap that can by bypassed if over a time period. \ No newline at end of file diff --git a/contracts/bridge/RateLimiter.sol b/contracts/bridge/RateLimiter.sol index 8b32f6c75..f9e4fc055 100644 --- a/contracts/bridge/RateLimiter.sol +++ b/contracts/bridge/RateLimiter.sol @@ -18,7 +18,7 @@ contract RateLimiter is ReentrancyGuardUpgradeable, IRateLimiter { - using EnumerableMapUpgradeable for EnumerableMapUpgradeable.Bytes32ToBytesMap; + using EnumerableMapUpgradeable for EnumerableMapUpgradeable.Bytes32ToStructMap; /*** STATE ***/ string public constant NAME = "Rate Limiter"; @@ -32,7 +32,7 @@ contract RateLimiter is // Token -> Allowance mapping(address => Allowance) public allowances; // Kappa->Retry Selector - EnumerableMapUpgradeable.Bytes32ToBytesMap private limited; + EnumerableMapUpgradeable.Bytes32ToStructMap private rateLimited; // Bridge Address address public BRIDGE_ADDRESS; @@ -176,27 +176,27 @@ contract RateLimiter is external onlyRole(BRIDGE_ROLE) { - limited.set(kappa, rateLimited); + rateLimited.set(kappa, rateLimited); } function retryByKappa(bytes32 kappa) external onlyRole(LIMITER_ROLE) { - bytes memory toRetry = limited.get(kappa); + (bytes memory toRetry, ) = rateLimited.get(kappa); (bool success, bytes memory returnData) = BRIDGE_ADDRESS.call(toRetry); require( success, append("could not call bridge:", _getRevertMsg(returnData)) ); - limited.remove(kappa); + rateLimited.remove(kappa); } function retryCount(uint8 count) external onlyRole(LIMITER_ROLE) { // no issues casting to uint8 here. If length is greater then 255, min is always taken uint8 attempts = uint8( - MathUpgradeable.min(uint256(count), limited.length()) + MathUpgradeable.min(uint256(count), rateLimited.length()) ); for (uint8 i = 0; i < attempts; i++) { - (bytes32 kappa, bytes memory toRetry) = limited.at(i); + (bytes32 kappa, bytes memory toRetry, ) = rateLimited.at(i); (bool success, bytes memory returnData) = BRIDGE_ADDRESS.call( toRetry ); @@ -204,12 +204,12 @@ contract RateLimiter is success, append("could not call bridge: ", _getRevertMsg(returnData)) ); - limited.remove(kappa); + rateLimited.remove(kappa); } } function deleteByKappa(bytes32 kappa) external onlyRole(LIMITER_ROLE) { - limited.remove(kappa); + rateLimited.remove(kappa); } /** diff --git a/contracts/bridge/libraries/EnumerableMapUpgradeable.sol b/contracts/bridge/libraries/EnumerableMapUpgradeable.sol index e5291e0bd..102d1bb05 100644 --- a/contracts/bridge/libraries/EnumerableMapUpgradeable.sol +++ b/contracts/bridge/libraries/EnumerableMapUpgradeable.sol @@ -13,6 +13,15 @@ import "@openzeppelin/contracts-4.6.0-upgradeable/utils/structs/EnumerableSetUpg library EnumerableMapUpgradeable { using EnumerableSetUpgradeable for EnumerableSetUpgradeable.Bytes32Set; + /** + * Contains a tx that should be retried and the timestamp it was stored at + */ + struct RetryableTx { + // @dev epoch time in minutes the tx was stored at. Always non-zero on initialized struct + uint32 storedAtMin; + bytes toRetry; + } + // To implement this library for multiple types with as little code // repetition as possible, we write it in terms of a generic Map type with // bytes32 keys and values. @@ -22,10 +31,10 @@ library EnumerableMapUpgradeable { // This means that we can only create new EnumerableMaps for types that fit // in bytes32. - struct Bytes32ToBytesMap { + struct Bytes32ToStructMap { // Storage of keys EnumerableSetUpgradeable.Bytes32Set _keys; - mapping(bytes32 => bytes) _values; + mapping(bytes32 => RetryableTx) _values; } @@ -37,11 +46,16 @@ library EnumerableMapUpgradeable { * already present. */ function set( - Bytes32ToBytesMap storage map, + Bytes32ToStructMap storage map, bytes32 key, bytes memory value ) internal returns (bool) { - map._values[key] = value; + RetryableTx memory retryable = RetryableTx({ + storedAtMin: uint32(block.timestamp / 60), + toRetry: value + }); + + map._values[key] = retryable; return map._keys.add(key); } @@ -50,7 +64,7 @@ library EnumerableMapUpgradeable { * * Returns true if the key was removed from the map, that is if it was present. */ - function remove(Bytes32ToBytesMap storage map, bytes32 key) internal returns (bool) { + function remove(Bytes32ToStructMap storage map, bytes32 key) internal returns (bool) { delete map._values[key]; return map._keys.remove(key); } @@ -58,19 +72,20 @@ library EnumerableMapUpgradeable { /** * @dev Returns true if the key is in the map. O(1). */ - function contains(Bytes32ToBytesMap storage map, bytes32 key) internal view returns (bool) { + function contains(Bytes32ToStructMap storage map, bytes32 key) internal view returns (bool) { return map._keys.contains(key); } /** * @dev Returns the number of key-value pairs in the map. O(1). */ - function length(Bytes32ToBytesMap storage map) internal view returns (uint256) { + function length(Bytes32ToStructMap storage map) internal view returns (uint256) { return map._keys.length(); } /** - * @dev Returns the key-value pair stored at position `index` in the map. O(1). + * @dev Returns the key-value pair stored at position `index` in the map and the time it was stored. + * O(1). * * Note that there are no guarantees on the ordering of entries inside the * array, and it may change when more entries are added or removed. @@ -79,21 +94,22 @@ library EnumerableMapUpgradeable { * * - `index` must be strictly less than {length}. */ - function at(Bytes32ToBytesMap storage map, uint256 index) internal view returns (bytes32, bytes memory) { + function at(Bytes32ToStructMap storage map, uint256 index) internal view returns (bytes32, bytes memory, uint32) { bytes32 key = map._keys.at(index); - return (key, map._values[key]); + RetryableTx memory retryable = map._values[key]; + return (key, retryable.toRetry, retryable.storedAtMin); } /** * @dev Tries to returns the value associated with `key`. O(1). * Does not revert if `key` is not in the map. */ - function tryGet(Bytes32ToBytesMap storage map, bytes32 key) internal view returns (bool, bytes memory) { - bytes memory value = map._values[key]; - if (value.length == 0) { - return (contains(map, key), bytes("")); + function tryGet(Bytes32ToStructMap storage map, bytes32 key) internal view returns (bool, bytes memory, uint32) { + RetryableTx memory value = map._values[key]; + if (value.storedAtMin == 0) { + return (contains(map, key), bytes(""), 0); } else { - return (true, value); + return (true, value.toRetry, value.storedAtMin); } } @@ -104,10 +120,10 @@ library EnumerableMapUpgradeable { * * - `key` must be in the map. */ - function get(Bytes32ToBytesMap storage map, bytes32 key) internal view returns (bytes memory) { - bytes memory value = map._values[key]; - require(value.length != 0 || contains(map, key), "EnumerableMap: nonexistent key"); - return value; + function get(Bytes32ToStructMap storage map, bytes32 key) internal view returns (bytes memory, uint32) { + RetryableTx memory value = map._values[key]; + require(value.storedAtMin != 0 || contains(map, key), "EnumerableMap: nonexistent key"); + return (value.toRetry, value.storedAtMin); } /** @@ -117,12 +133,12 @@ library EnumerableMapUpgradeable { * message unnecessarily. For custom revert reasons use {_tryGet}. */ function get( - Bytes32ToBytesMap storage map, + Bytes32ToStructMap storage map, bytes32 key, string memory errorMessage - ) internal view returns (bytes memory) { - bytes memory value = map._values[key]; - require(value.length != 0 || contains(map, key), errorMessage); - return value; + ) internal view returns (bytes memory, uint32) { + RetryableTx memory value = map._values[key]; + require(value.storedAtMin != 0 || contains(map, key), errorMessage); + return (value.toRetry, value.storedAtMin); } } \ No newline at end of file diff --git a/docs/bridge/testing/ProxyAdminInterface.md b/docs/bridge/testing/ProxyAdminInterface.md new file mode 100644 index 000000000..4c6a0a562 --- /dev/null +++ b/docs/bridge/testing/ProxyAdminInterface.md @@ -0,0 +1,175 @@ +# ProxyAdminInterface + + + + + + + + + +## Methods + +### changeProxyAdmin + +```solidity +function changeProxyAdmin(contract TransparentUpgradeableProxy proxy, address newAdmin) external nonpayable +``` + + + +*Changes the admin of `proxy` to `newAdmin`. Requirements: - This contract must be the current admin of `proxy`.* + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| proxy | contract TransparentUpgradeableProxy | undefined | +| newAdmin | address | undefined | + +### getProxyAdmin + +```solidity +function getProxyAdmin(contract TransparentUpgradeableProxy proxy) external view returns (address) +``` + + + +*Returns the current admin of `proxy`. Requirements: - This contract must be the admin of `proxy`.* + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| proxy | contract TransparentUpgradeableProxy | undefined | + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | address | undefined | + +### getProxyImplementation + +```solidity +function getProxyImplementation(contract TransparentUpgradeableProxy proxy) external view returns (address) +``` + + + +*Returns the current implementation of `proxy`. Requirements: - This contract must be the admin of `proxy`.* + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| proxy | contract TransparentUpgradeableProxy | undefined | + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | address | undefined | + +### owner + +```solidity +function owner() external view returns (address) +``` + + + +*Returns the address of the current owner.* + + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | address | undefined | + +### renounceOwnership + +```solidity +function renounceOwnership() external nonpayable +``` + + + +*Leaves the contract without owner. It will not be possible to call `onlyOwner` functions anymore. Can only be called by the current owner. NOTE: Renouncing ownership will leave the contract without an owner, thereby removing any functionality that is only available to the owner.* + + +### transferOwnership + +```solidity +function transferOwnership(address newOwner) external nonpayable +``` + + + +*Transfers ownership of the contract to a new account (`newOwner`). Can only be called by the current owner.* + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| newOwner | address | undefined | + +### upgrade + +```solidity +function upgrade(contract TransparentUpgradeableProxy proxy, address implementation) external nonpayable +``` + + + +*Upgrades `proxy` to `implementation`. See {TransparentUpgradeableProxy-upgradeTo}. Requirements: - This contract must be the admin of `proxy`.* + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| proxy | contract TransparentUpgradeableProxy | undefined | +| implementation | address | undefined | + +### upgradeAndCall + +```solidity +function upgradeAndCall(contract TransparentUpgradeableProxy proxy, address implementation, bytes data) external payable +``` + + + +*Upgrades `proxy` to `implementation` and calls a function on the new implementation. See {TransparentUpgradeableProxy-upgradeToAndCall}. Requirements: - This contract must be the admin of `proxy`.* + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| proxy | contract TransparentUpgradeableProxy | undefined | +| implementation | address | undefined | +| data | bytes | undefined | + + + +## Events + +### OwnershipTransferred + +```solidity +event OwnershipTransferred(address indexed previousOwner, address indexed newOwner) +``` + + + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| previousOwner `indexed` | address | undefined | +| newOwner `indexed` | address | undefined | + + + diff --git a/docs/elin/contracts-4.3.1/access/Ownable.md b/docs/elin/contracts-4.3.1/access/Ownable.md new file mode 100644 index 000000000..ac3973421 --- /dev/null +++ b/docs/elin/contracts-4.3.1/access/Ownable.md @@ -0,0 +1,79 @@ +# Ownable + + + + + + + +*Contract module which provides a basic access control mechanism, where there is an account (an owner) that can be granted exclusive access to specific functions. By default, the owner account will be the one that deploys the contract. This can later be changed with {transferOwnership}. This module is used through inheritance. It will make available the modifier `onlyOwner`, which can be applied to your functions to restrict their use to the owner.* + +## Methods + +### owner + +```solidity +function owner() external view returns (address) +``` + + + +*Returns the address of the current owner.* + + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | address | undefined | + +### renounceOwnership + +```solidity +function renounceOwnership() external nonpayable +``` + + + +*Leaves the contract without owner. It will not be possible to call `onlyOwner` functions anymore. Can only be called by the current owner. NOTE: Renouncing ownership will leave the contract without an owner, thereby removing any functionality that is only available to the owner.* + + +### transferOwnership + +```solidity +function transferOwnership(address newOwner) external nonpayable +``` + + + +*Transfers ownership of the contract to a new account (`newOwner`). Can only be called by the current owner.* + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| newOwner | address | undefined | + + + +## Events + +### OwnershipTransferred + +```solidity +event OwnershipTransferred(address indexed previousOwner, address indexed newOwner) +``` + + + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| previousOwner `indexed` | address | undefined | +| newOwner `indexed` | address | undefined | + + + diff --git a/docs/elin/contracts-4.3.1/proxy/ERC1967/ERC1967Proxy.md b/docs/elin/contracts-4.3.1/proxy/ERC1967/ERC1967Proxy.md new file mode 100644 index 000000000..30ff844d9 --- /dev/null +++ b/docs/elin/contracts-4.3.1/proxy/ERC1967/ERC1967Proxy.md @@ -0,0 +1,64 @@ +# ERC1967Proxy + + + + + + + +*This contract implements an upgradeable proxy. It is upgradeable because calls are delegated to an implementation address that can be changed. This address is stored in storage in the location specified by https://eips.ethereum.org/EIPS/eip-1967[EIP1967], so that it doesn't conflict with the storage layout of the implementation behind the proxy.* + + +## Events + +### AdminChanged + +```solidity +event AdminChanged(address previousAdmin, address newAdmin) +``` + + + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| previousAdmin | address | undefined | +| newAdmin | address | undefined | + +### BeaconUpgraded + +```solidity +event BeaconUpgraded(address indexed beacon) +``` + + + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| beacon `indexed` | address | undefined | + +### Upgraded + +```solidity +event Upgraded(address indexed implementation) +``` + + + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| implementation `indexed` | address | undefined | + + + diff --git a/docs/elin/contracts-4.3.1/proxy/ERC1967/ERC1967Upgrade.md b/docs/elin/contracts-4.3.1/proxy/ERC1967/ERC1967Upgrade.md new file mode 100644 index 000000000..96e9cbb70 --- /dev/null +++ b/docs/elin/contracts-4.3.1/proxy/ERC1967/ERC1967Upgrade.md @@ -0,0 +1,64 @@ +# ERC1967Upgrade + + + + + + + +*This abstract contract provides getters and event emitting update functions for https://eips.ethereum.org/EIPS/eip-1967[EIP1967] slots. _Available since v4.1._* + + +## Events + +### AdminChanged + +```solidity +event AdminChanged(address previousAdmin, address newAdmin) +``` + + + +*Emitted when the admin account has changed.* + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| previousAdmin | address | undefined | +| newAdmin | address | undefined | + +### BeaconUpgraded + +```solidity +event BeaconUpgraded(address indexed beacon) +``` + + + +*Emitted when the beacon is upgraded.* + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| beacon `indexed` | address | undefined | + +### Upgraded + +```solidity +event Upgraded(address indexed implementation) +``` + + + +*Emitted when the implementation is upgraded.* + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| implementation `indexed` | address | undefined | + + + diff --git a/docs/elin/contracts-4.3.1/proxy/Proxy.md b/docs/elin/contracts-4.3.1/proxy/Proxy.md new file mode 100644 index 000000000..30095d23a --- /dev/null +++ b/docs/elin/contracts-4.3.1/proxy/Proxy.md @@ -0,0 +1,12 @@ +# Proxy + + + + + + + +*This abstract contract provides a fallback function that delegates all calls to another contract using the EVM instruction `delegatecall`. We refer to the second contract as the _implementation_ behind the proxy, and it has to be specified by overriding the virtual {_implementation} function. Additionally, delegation to the implementation can be triggered manually through the {_fallback} function, or to a different contract through the {_delegate} function. The success and return data of the delegated call will be returned back to the caller of the proxy.* + + + diff --git a/docs/elin/contracts-4.3.1/proxy/beacon/IBeacon.md b/docs/elin/contracts-4.3.1/proxy/beacon/IBeacon.md new file mode 100644 index 000000000..ca5c35e3f --- /dev/null +++ b/docs/elin/contracts-4.3.1/proxy/beacon/IBeacon.md @@ -0,0 +1,32 @@ +# IBeacon + + + + + + + +*This is the interface that {BeaconProxy} expects of its beacon.* + +## Methods + +### implementation + +```solidity +function implementation() external view returns (address) +``` + + + +*Must return an address that can be used as a delegate call target. {BeaconProxy} will check that this address is a contract.* + + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | address | undefined | + + + + diff --git a/docs/elin/contracts-4.3.1/proxy/transparent/ProxyAdmin.md b/docs/elin/contracts-4.3.1/proxy/transparent/ProxyAdmin.md new file mode 100644 index 000000000..40569af50 --- /dev/null +++ b/docs/elin/contracts-4.3.1/proxy/transparent/ProxyAdmin.md @@ -0,0 +1,175 @@ +# ProxyAdmin + + + + + + + +*This is an auxiliary contract meant to be assigned as the admin of a {TransparentUpgradeableProxy}. For an explanation of why you would want to use this see the documentation for {TransparentUpgradeableProxy}.* + +## Methods + +### changeProxyAdmin + +```solidity +function changeProxyAdmin(contract TransparentUpgradeableProxy proxy, address newAdmin) external nonpayable +``` + + + +*Changes the admin of `proxy` to `newAdmin`. Requirements: - This contract must be the current admin of `proxy`.* + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| proxy | contract TransparentUpgradeableProxy | undefined | +| newAdmin | address | undefined | + +### getProxyAdmin + +```solidity +function getProxyAdmin(contract TransparentUpgradeableProxy proxy) external view returns (address) +``` + + + +*Returns the current admin of `proxy`. Requirements: - This contract must be the admin of `proxy`.* + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| proxy | contract TransparentUpgradeableProxy | undefined | + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | address | undefined | + +### getProxyImplementation + +```solidity +function getProxyImplementation(contract TransparentUpgradeableProxy proxy) external view returns (address) +``` + + + +*Returns the current implementation of `proxy`. Requirements: - This contract must be the admin of `proxy`.* + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| proxy | contract TransparentUpgradeableProxy | undefined | + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | address | undefined | + +### owner + +```solidity +function owner() external view returns (address) +``` + + + +*Returns the address of the current owner.* + + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | address | undefined | + +### renounceOwnership + +```solidity +function renounceOwnership() external nonpayable +``` + + + +*Leaves the contract without owner. It will not be possible to call `onlyOwner` functions anymore. Can only be called by the current owner. NOTE: Renouncing ownership will leave the contract without an owner, thereby removing any functionality that is only available to the owner.* + + +### transferOwnership + +```solidity +function transferOwnership(address newOwner) external nonpayable +``` + + + +*Transfers ownership of the contract to a new account (`newOwner`). Can only be called by the current owner.* + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| newOwner | address | undefined | + +### upgrade + +```solidity +function upgrade(contract TransparentUpgradeableProxy proxy, address implementation) external nonpayable +``` + + + +*Upgrades `proxy` to `implementation`. See {TransparentUpgradeableProxy-upgradeTo}. Requirements: - This contract must be the admin of `proxy`.* + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| proxy | contract TransparentUpgradeableProxy | undefined | +| implementation | address | undefined | + +### upgradeAndCall + +```solidity +function upgradeAndCall(contract TransparentUpgradeableProxy proxy, address implementation, bytes data) external payable +``` + + + +*Upgrades `proxy` to `implementation` and calls a function on the new implementation. See {TransparentUpgradeableProxy-upgradeToAndCall}. Requirements: - This contract must be the admin of `proxy`.* + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| proxy | contract TransparentUpgradeableProxy | undefined | +| implementation | address | undefined | +| data | bytes | undefined | + + + +## Events + +### OwnershipTransferred + +```solidity +event OwnershipTransferred(address indexed previousOwner, address indexed newOwner) +``` + + + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| previousOwner `indexed` | address | undefined | +| newOwner `indexed` | address | undefined | + + + diff --git a/docs/elin/contracts-4.3.1/proxy/transparent/TransparentUpgradeableProxy.md b/docs/elin/contracts-4.3.1/proxy/transparent/TransparentUpgradeableProxy.md new file mode 100644 index 000000000..536119073 --- /dev/null +++ b/docs/elin/contracts-4.3.1/proxy/transparent/TransparentUpgradeableProxy.md @@ -0,0 +1,150 @@ +# TransparentUpgradeableProxy + + + + + + + +*This contract implements a proxy that is upgradeable by an admin. To avoid https://medium.com/nomic-labs-blog/malicious-backdoors-in-ethereum-proxies-62629adf3357[proxy selector clashing], which can potentially be used in an attack, this contract uses the https://blog.openzeppelin.com/the-transparent-proxy-pattern/[transparent proxy pattern]. This pattern implies two things that go hand in hand: 1. If any account other than the admin calls the proxy, the call will be forwarded to the implementation, even if that call matches one of the admin functions exposed by the proxy itself. 2. If the admin calls the proxy, it can access the admin functions, but its calls will never be forwarded to the implementation. If the admin tries to call a function on the implementation it will fail with an error that says "admin cannot fallback to proxy target". These properties mean that the admin account can only be used for admin actions like upgrading the proxy or changing the admin, so it's best if it's a dedicated account that is not used for anything else. This will avoid headaches due to sudden errors when trying to call a function from the proxy implementation. Our recommendation is for the dedicated account to be an instance of the {ProxyAdmin} contract. If set up this way, you should think of the `ProxyAdmin` instance as the real administrative interface of your proxy.* + +## Methods + +### admin + +```solidity +function admin() external nonpayable returns (address admin_) +``` + + + +*Returns the current admin. NOTE: Only the admin can call this function. See {ProxyAdmin-getProxyAdmin}. TIP: To get this value clients can read directly from the storage slot shown below (specified by EIP1967) using the https://eth.wiki/json-rpc/API#eth_getstorageat[`eth_getStorageAt`] RPC call. `0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103`* + + +#### Returns + +| Name | Type | Description | +|---|---|---| +| admin_ | address | undefined | + +### changeAdmin + +```solidity +function changeAdmin(address newAdmin) external nonpayable +``` + + + +*Changes the admin of the proxy. Emits an {AdminChanged} event. NOTE: Only the admin can call this function. See {ProxyAdmin-changeProxyAdmin}.* + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| newAdmin | address | undefined | + +### implementation + +```solidity +function implementation() external nonpayable returns (address implementation_) +``` + + + +*Returns the current implementation. NOTE: Only the admin can call this function. See {ProxyAdmin-getProxyImplementation}. TIP: To get this value clients can read directly from the storage slot shown below (specified by EIP1967) using the https://eth.wiki/json-rpc/API#eth_getstorageat[`eth_getStorageAt`] RPC call. `0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc`* + + +#### Returns + +| Name | Type | Description | +|---|---|---| +| implementation_ | address | undefined | + +### upgradeTo + +```solidity +function upgradeTo(address newImplementation) external nonpayable +``` + + + +*Upgrade the implementation of the proxy. NOTE: Only the admin can call this function. See {ProxyAdmin-upgrade}.* + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| newImplementation | address | undefined | + +### upgradeToAndCall + +```solidity +function upgradeToAndCall(address newImplementation, bytes data) external payable +``` + + + +*Upgrade the implementation of the proxy, and then call a function from the new implementation as specified by `data`, which should be an encoded function call. This is useful to initialize new storage variables in the proxied contract. NOTE: Only the admin can call this function. See {ProxyAdmin-upgradeAndCall}.* + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| newImplementation | address | undefined | +| data | bytes | undefined | + + + +## Events + +### AdminChanged + +```solidity +event AdminChanged(address previousAdmin, address newAdmin) +``` + + + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| previousAdmin | address | undefined | +| newAdmin | address | undefined | + +### BeaconUpgraded + +```solidity +event BeaconUpgraded(address indexed beacon) +``` + + + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| beacon `indexed` | address | undefined | + +### Upgraded + +```solidity +event Upgraded(address indexed implementation) +``` + + + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| implementation `indexed` | address | undefined | + + + diff --git a/docs/elin/contracts-4.3.1/utils/Address.md b/docs/elin/contracts-4.3.1/utils/Address.md new file mode 100644 index 000000000..927f4068e --- /dev/null +++ b/docs/elin/contracts-4.3.1/utils/Address.md @@ -0,0 +1,12 @@ +# Address + + + + + + + +*Collection of functions related to the address type* + + + diff --git a/docs/elin/contracts-4.3.1/utils/StorageSlot.md b/docs/elin/contracts-4.3.1/utils/StorageSlot.md new file mode 100644 index 000000000..ebc1f786c --- /dev/null +++ b/docs/elin/contracts-4.3.1/utils/StorageSlot.md @@ -0,0 +1,12 @@ +# StorageSlot + + + + + + + +*Library for reading and writing primitive types to specific storage slots. Storage slots are often used to avoid storage conflict when dealing with upgradeable contracts. This library helps with reading and writing to such slots without the need for inline assembly. The functions in this library return Slot structs that contain a `value` member that can be used to read or write. Example usage to set ERC1967 implementation slot: ``` contract ERC1967 { bytes32 internal constant _IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc; function _getImplementation() internal view returns (address) { return StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value; } function _setImplementation(address newImplementation) internal { require(Address.isContract(newImplementation), "ERC1967: new implementation is not a contract"); StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value = newImplementation; } } ``` _Available since v4.1 for `address`, `bool`, `bytes32`, and `uint256`._* + + + diff --git a/docs/elin/contracts-4.6.0-upgradeable/utils/structs/EnumerableMapUpgradeable.md b/docs/elin/contracts-4.6.0-upgradeable/utils/structs/EnumerableMapUpgradeable.md deleted file mode 100644 index d028fe0d4..000000000 --- a/docs/elin/contracts-4.6.0-upgradeable/utils/structs/EnumerableMapUpgradeable.md +++ /dev/null @@ -1,12 +0,0 @@ -# EnumerableMapUpgradeable - - - - - - - -*Library for managing an enumerable variant of Solidity's https://solidity.readthedocs.io/en/latest/types.html#mapping-types[`mapping`] type. Maps have the following properties: - Entries are added, removed, and checked for existence in constant time (O(1)). - Entries are enumerated in O(n). No guarantees are made on the ordering. ``` contract Example { // Add the library methods using EnumerableMap for EnumerableMap.UintToAddressMap; // Declare a set state variable EnumerableMap.UintToAddressMap private myMap; } ``` The following map types are supported: - `uint256 -> address` (`UintToAddressMap`) since v3.0.0 - `address -> uint256` (`AddressToUintMap`) since v4.6.0 - `bytes32 -> bytes32` (`Bytes32ToBytes32`) since v4.6.0* - - - diff --git a/hardhat.config.ts b/hardhat.config.ts index e035956ff..55e118b2e 100644 --- a/hardhat.config.ts +++ b/hardhat.config.ts @@ -104,7 +104,7 @@ let config: HardhatUserConfig = { target: "ethers-v5", }, dodoc: { - runOnCompile: false, + runOnCompile: true, debugMode: false, // pre solidity 5 breaks docgen exclude: ["MultisigWallet", "WETH9"] diff --git a/test/bridge/RateLimiter.ts b/test/bridge/RateLimiter.ts index 1addbefbb..14df1c0b5 100644 --- a/test/bridge/RateLimiter.ts +++ b/test/bridge/RateLimiter.ts @@ -19,7 +19,7 @@ import epochSeconds from "@stdlib/time-now" chai.use(solidity) const { expect, assert } = chai -describe.only("Rate Limiter", () => { +describe("Rate Limiter", () => { let signers: Array let deployer: Signer let owner: Signer From 380ae0aa346294500ec4c34638f9e58eea4ba388 Mon Sep 17 00:00:00 2001 From: Trajan0x Date: Mon, 11 Apr 2022 15:28:50 -0400 Subject: [PATCH 019/135] revert tests --- contracts/bridge/RateLimiter.sol | 4 +-- docs/bridge/RateLimiter.md | 4 +-- test/bridge/SynapseBridgeETH.ts | 52 ++++++++++++++++++++++++++++++++ 3 files changed, 56 insertions(+), 4 deletions(-) diff --git a/contracts/bridge/RateLimiter.sol b/contracts/bridge/RateLimiter.sol index f9e4fc055..c1dd16c8d 100644 --- a/contracts/bridge/RateLimiter.sol +++ b/contracts/bridge/RateLimiter.sol @@ -172,11 +172,11 @@ contract RateLimiter is return true; } - function addToRetryQueue(bytes32 kappa, bytes memory rateLimited) + function addToRetryQueue(bytes32 kappa, bytes memory toRetry) external onlyRole(BRIDGE_ROLE) { - rateLimited.set(kappa, rateLimited); + rateLimited.set(kappa, toRetry); } function retryByKappa(bytes32 kappa) external onlyRole(LIMITER_ROLE) { diff --git a/docs/bridge/RateLimiter.md b/docs/bridge/RateLimiter.md index 6cd07a1e1..a30f08283 100644 --- a/docs/bridge/RateLimiter.md +++ b/docs/bridge/RateLimiter.md @@ -132,7 +132,7 @@ function VERSION() external view returns (string) ### addToRetryQueue ```solidity -function addToRetryQueue(bytes32 kappa, bytes rateLimited) external nonpayable +function addToRetryQueue(bytes32 kappa, bytes toRetry) external nonpayable ``` @@ -144,7 +144,7 @@ function addToRetryQueue(bytes32 kappa, bytes rateLimited) external nonpayable | Name | Type | Description | |---|---|---| | kappa | bytes32 | undefined | -| rateLimited | bytes | undefined | +| toRetry | bytes | undefined | ### allowances diff --git a/test/bridge/SynapseBridgeETH.ts b/test/bridge/SynapseBridgeETH.ts index b86e67294..c1f122738 100644 --- a/test/bridge/SynapseBridgeETH.ts +++ b/test/bridge/SynapseBridgeETH.ts @@ -22,6 +22,7 @@ describe("SynapseBridgeETH", async () => { let limiter: Signer let nodeGroup: Signer let recipient: Signer + let attacker: Signer // contracts let bridge: SynapseBridge @@ -32,6 +33,7 @@ describe("SynapseBridgeETH", async () => { const NUSD = "0x1B84765dE8B7566e4cEAF4D0fD3c5aF52D3DdE4F" const NUSD_POOL = "0x1116898DdA4015eD8dDefb84b6e8Bc24528Af2d8" const SYN = "0x0f2D719407FdBeFF09D87557AbB7232601FD9F29" + const WETH = "0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2" const decimals = Math.pow(10, 6) @@ -53,6 +55,7 @@ describe("SynapseBridgeETH", async () => { limiter = signers[2] nodeGroup = signers[3] recipient = signers[4] + attacker = signers[5] rateLimiter = await deployRateLimiter(deployer, owner) bridge = await setupForkedBridge( @@ -159,4 +162,53 @@ describe("SynapseBridgeETH", async () => { await expect(rateLimiter.retryByKappa(kappa)).to.be.not.reverted expect(await bridge.kappaExists(kappa)).to.be.true }) + + // check permissions + it("SetChainGasAmount: should reject non-admin roles", async () => { + await expect( + bridge.connect(attacker).setChainGasAmount(1000), + ).to.be.revertedWith("Not governance") + }) + + it("SetWethAddress: should reject non-admin roles", async () => { + await expect( + bridge.connect(attacker).setWethAddress(WETH), + ).to.be.revertedWith("Not admin") + }) + + it.skip("SetRateLimiter: should reject non-governance roles", async () => { + await expect( + bridge + .connect(attacker) + .withdrawFees(USDC.address, await recipient.getAddress()), + ).to.be.revertedWith("Not governance") + }) + + it("AddKappas: should reject non-admin roles", async () => { + const kappas = [keccak256(randomBytes(32)), keccak256(randomBytes(32))] + + await expect(bridge.connect(attacker).addKappas(kappas)).to.be.revertedWith( + "Not governance", + ) + }) + + it("WithdrawFees: should reject non-governance roles", async () => { + await expect( + bridge + .connect(attacker) + .withdrawFees(USDC.address, await recipient.getAddress()), + ).to.be.revertedWith("Not governance") + }) + + it("Pause: should reject non-governance roles", async () => { + await expect(bridge.connect(attacker).pause()).to.be.revertedWith( + "Not governance", + ) + }) + + it("Unpause: should reject non-governance roles", async () => { + await expect(bridge.connect(attacker).unpause()).to.be.revertedWith( + "Not governance", + ) + }) }) From 91c7bdc0ad6f6b8dd0dfed4422e1100cce4b6815 Mon Sep 17 00:00:00 2001 From: Trajan0x Date: Mon, 11 Apr 2022 15:44:34 -0400 Subject: [PATCH 020/135] move to internal rate limiter for deploy --- contracts/bridge/SynapseBridge.sol | 22 ++++++++++++++++++---- 1 file changed, 18 insertions(+), 4 deletions(-) diff --git a/contracts/bridge/SynapseBridge.sol b/contracts/bridge/SynapseBridge.sol index 1be13cef1..819228275 100644 --- a/contracts/bridge/SynapseBridge.sol +++ b/contracts/bridge/SynapseBridge.sol @@ -221,6 +221,20 @@ contract SynapseBridge is _unpause(); } + // RATE LIMITER FUNCTIONS ***/ + // @dev check and update the rate limiter allowances. Bypass the rate limiter + // if it is a 0-address + function isRateLimited(address token, uint256 amount) internal returns (bool) { + if (address(rateLimiter) == address (0)) { + return false; + } + + return rateLimiter.checkAndUpdateAllowance( + address(token), + amount + ); + } + /** * @notice Relays to nodes to transfers an ERC20 token cross-chain * @param to address on other chain to bridge assets to @@ -275,7 +289,7 @@ contract SynapseBridge is "Caller is not a node group" ); - bool rateLimited = rateLimiter.checkAndUpdateAllowance( + bool rateLimited = isRateLimited( address(token), amount ); @@ -364,7 +378,7 @@ contract SynapseBridge is "Caller is not a node group" ); - bool rateLimited = rateLimiter.checkAndUpdateAllowance( + bool rateLimited = isRateLimited( address(token), amount ); @@ -559,7 +573,7 @@ contract SynapseBridge is "Caller is not a node group" ); - bool rateLimited = rateLimiter.checkAndUpdateAllowance( + bool rateLimited = isRateLimited( address(token), amount ); @@ -780,7 +794,7 @@ contract SynapseBridge is "Caller is not a node group" ); - bool rateLimited = rateLimiter.checkAndUpdateAllowance( + bool rateLimited = isRateLimited( address(token), amount ); From 74e7fee2485dec6744c512108d73249bca0eb0e9 Mon Sep 17 00:00:00 2001 From: Trajan0x Date: Mon, 11 Apr 2022 15:48:14 -0400 Subject: [PATCH 021/135] lint --- contracts/bridge/SynapseBridge.sol | 34 ++++++++++-------------------- 1 file changed, 11 insertions(+), 23 deletions(-) diff --git a/contracts/bridge/SynapseBridge.sol b/contracts/bridge/SynapseBridge.sol index 819228275..afb91a39b 100644 --- a/contracts/bridge/SynapseBridge.sol +++ b/contracts/bridge/SynapseBridge.sol @@ -58,7 +58,7 @@ contract SynapseBridge is mapping(address => uint256) private fees; uint256 public startBlockNumber; - uint256 public constant bridgeVersion = 6; + uint256 public constant bridgeVersion = 7; uint256 public chainGasAmount; address payable public WETH_ADDRESS; IRateLimiter public rateLimiter; @@ -224,15 +224,15 @@ contract SynapseBridge is // RATE LIMITER FUNCTIONS ***/ // @dev check and update the rate limiter allowances. Bypass the rate limiter // if it is a 0-address - function isRateLimited(address token, uint256 amount) internal returns (bool) { - if (address(rateLimiter) == address (0)) { + function isRateLimited(address token, uint256 amount) + internal + returns (bool) + { + if (address(rateLimiter) == address(0)) { return false; } - return rateLimiter.checkAndUpdateAllowance( - address(token), - amount - ); + return rateLimiter.checkAndUpdateAllowance(address(token), amount); } /** @@ -289,10 +289,7 @@ contract SynapseBridge is "Caller is not a node group" ); - bool rateLimited = isRateLimited( - address(token), - amount - ); + bool rateLimited = isRateLimited(address(token), amount); if (rateLimited) { rateLimiter.addToRetryQueue( kappa, @@ -378,10 +375,7 @@ contract SynapseBridge is "Caller is not a node group" ); - bool rateLimited = isRateLimited( - address(token), - amount - ); + bool rateLimited = isRateLimited(address(token), amount); if (rateLimited) { rateLimiter.addToRetryQueue( kappa, @@ -573,10 +567,7 @@ contract SynapseBridge is "Caller is not a node group" ); - bool rateLimited = isRateLimited( - address(token), - amount - ); + bool rateLimited = isRateLimited(address(token), amount); if (rateLimited) { rateLimiter.addToRetryQueue( kappa, @@ -794,10 +785,7 @@ contract SynapseBridge is "Caller is not a node group" ); - bool rateLimited = isRateLimited( - address(token), - amount - ); + bool rateLimited = isRateLimited(address(token), amount); if (rateLimited) { rateLimiter.addToRetryQueue( From b13fce76fe6060eeaaba65838a9bc5efdfb7db02 Mon Sep 17 00:00:00 2001 From: Trajan0x Date: Mon, 11 Apr 2022 16:49:10 -0400 Subject: [PATCH 022/135] more verbose revert messages --- contracts/bridge/RateLimiter.sol | 11 +- .../libraries/EnumerableMapUpgradeable.sol | 1 - contracts/bridge/libraries/Strings.sol | 73 ++++++++++++ contracts/bridge/mocks/StringsMock.sol | 38 ++++++ docs/bridge/libraries/Strings.md | 12 ++ docs/bridge/mocks/StringsMock.md | 109 ++++++++++++++++++ test/bridge/Strings.ts | 67 +++++++++++ 7 files changed, 308 insertions(+), 3 deletions(-) create mode 100644 contracts/bridge/libraries/Strings.sol create mode 100644 contracts/bridge/mocks/StringsMock.sol create mode 100644 docs/bridge/libraries/Strings.md create mode 100644 docs/bridge/mocks/StringsMock.md create mode 100644 test/bridge/Strings.ts diff --git a/contracts/bridge/RateLimiter.sol b/contracts/bridge/RateLimiter.sol index c1dd16c8d..349f09356 100644 --- a/contracts/bridge/RateLimiter.sol +++ b/contracts/bridge/RateLimiter.sol @@ -8,6 +8,7 @@ import "@openzeppelin/contracts-4.3.1-upgradeable/utils/math/MathUpgradeable.sol import "./libraries/EnumerableMapUpgradeable.sol"; import "./interfaces/IRateLimiter.sol"; +import "./libraries/Strings.sol"; import "hardhat/console.sol"; // @title RateLimiter @@ -184,7 +185,7 @@ contract RateLimiter is (bool success, bytes memory returnData) = BRIDGE_ADDRESS.call(toRetry); require( success, - append("could not call bridge:", _getRevertMsg(returnData)) + Strings.append("could not call bridge:", _getRevertMsg(returnData)) ); rateLimited.remove(kappa); } @@ -202,8 +203,14 @@ contract RateLimiter is ); require( success, - append("could not call bridge: ", _getRevertMsg(returnData)) + Strings.append( + "could not call bridge for kappa: ", + Strings.toHex(kappa), + " reverted with: ", + _getRevertMsg(returnData) + ) ); + rateLimited.remove(kappa); } } diff --git a/contracts/bridge/libraries/EnumerableMapUpgradeable.sol b/contracts/bridge/libraries/EnumerableMapUpgradeable.sol index 102d1bb05..e01f4231d 100644 --- a/contracts/bridge/libraries/EnumerableMapUpgradeable.sol +++ b/contracts/bridge/libraries/EnumerableMapUpgradeable.sol @@ -9,7 +9,6 @@ import "@openzeppelin/contracts-4.6.0-upgradeable/utils/structs/EnumerableSetUpg * this extends https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v4.6.0-rc.0/contracts/utils/structs/EnumerableMap.sol * wth a bytes32 to bytes map */ - library EnumerableMapUpgradeable { using EnumerableSetUpgradeable for EnumerableSetUpgradeable.Bytes32Set; diff --git a/contracts/bridge/libraries/Strings.sol b/contracts/bridge/libraries/Strings.sol new file mode 100644 index 000000000..5e99da8c7 --- /dev/null +++ b/contracts/bridge/libraries/Strings.sol @@ -0,0 +1,73 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +import "hardhat/console.sol"; + +/** + * @dev Library for manipulating strings in solidity +*/ +library Strings { + /** + * @dev Concatenates a + b + */ + function append(string memory a, string memory b) + internal + pure + returns (string memory) + { + return string(abi.encodePacked(a, b)); + } + + + /** + * @dev Concatenates a + b + c + */ + function append(string memory a, string memory b, string memory c) + internal + pure + returns (string memory) + { + return string(abi.encodePacked(a, b, c)); + } + + /** + * @dev Concatenates a + b + c + d + */ + function append(string memory a, string memory b, string memory c, string memory d) + internal + pure + returns (string memory) + { + return string(abi.encodePacked(a, b, c,d)); + } + + /** + * @dev Converts a bytes16 to a string + * for a full explanation, see: https://stackoverflow.com/a/69266989 + */ + function toHex16 (bytes16 data) internal pure returns (bytes32 result) { + result = bytes32 (data) & 0xFFFFFFFFFFFFFFFF000000000000000000000000000000000000000000000000 | + (bytes32 (data) & 0x0000000000000000FFFFFFFFFFFFFFFF00000000000000000000000000000000) >> 64; + result = result & 0xFFFFFFFF000000000000000000000000FFFFFFFF000000000000000000000000 | + (result & 0x00000000FFFFFFFF000000000000000000000000FFFFFFFF0000000000000000) >> 32; + result = result & 0xFFFF000000000000FFFF000000000000FFFF000000000000FFFF000000000000 | + (result & 0x0000FFFF000000000000FFFF000000000000FFFF000000000000FFFF00000000) >> 16; + result = result & 0xFF000000FF000000FF000000FF000000FF000000FF000000FF000000FF000000 | + (result & 0x00FF000000FF000000FF000000FF000000FF000000FF000000FF000000FF0000) >> 8; + result = (result & 0xF000F000F000F000F000F000F000F000F000F000F000F000F000F000F000F000) >> 4 | + (result & 0x0F000F000F000F000F000F000F000F000F000F000F000F000F000F000F000F00) >> 8; + result = bytes32 (0x3030303030303030303030303030303030303030303030303030303030303030 + + uint256 (result) + + (uint256 (result) + 0x0606060606060606060606060606060606060606060606060606060606060606 >> 4 & + // 39 can be changed to 7 for lowercase output + 0x0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F) * 39); + } + + /** + * @dev Converts a bytes32 to a string + * for a full explanation, see: https://stackoverflow.com/a/69266989 + */ + function toHex(bytes32 data) internal pure returns (string memory) { + return string (abi.encodePacked ("0x", toHex16 (bytes16 (data)), toHex16 (bytes16 (data << 128)))); + } +} diff --git a/contracts/bridge/mocks/StringsMock.sol b/contracts/bridge/mocks/StringsMock.sol new file mode 100644 index 000000000..bee2aff6e --- /dev/null +++ b/contracts/bridge/mocks/StringsMock.sol @@ -0,0 +1,38 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +import "../libraries/Strings.sol"; + +// @dev StringsMock wraps strings for testing +contract StringsMock { + function append(string memory a, string memory b) + public + pure + returns (string memory) + { + return Strings.append(a,b); + } + + function append(string memory a, string memory b, string memory c) + public + pure + returns (string memory) + { + return Strings.append(a, b, c); + } + + function append(string memory a, string memory b, string memory c, string memory d) + public + pure + returns (string memory) + { + return Strings.append(a, b, c, d); + } + + + function toHex(bytes32 _bytes32) public pure returns (string memory) { + return Strings.toHex(_bytes32); + } + + +} \ No newline at end of file diff --git a/docs/bridge/libraries/Strings.md b/docs/bridge/libraries/Strings.md new file mode 100644 index 000000000..631d2f1be --- /dev/null +++ b/docs/bridge/libraries/Strings.md @@ -0,0 +1,12 @@ +# Strings + + + + + + + +*Library for manipulating strings in solidity* + + + diff --git a/docs/bridge/mocks/StringsMock.md b/docs/bridge/mocks/StringsMock.md new file mode 100644 index 000000000..7b8d68e39 --- /dev/null +++ b/docs/bridge/mocks/StringsMock.md @@ -0,0 +1,109 @@ +# StringsMock + + + + + + + + + +## Methods + +### append + +```solidity +function append(string a, string b, string c, string d) external pure returns (string) +``` + + + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| a | string | undefined | +| b | string | undefined | +| c | string | undefined | +| d | string | undefined | + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | string | undefined | + +### append + +```solidity +function append(string a, string b, string c) external pure returns (string) +``` + + + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| a | string | undefined | +| b | string | undefined | +| c | string | undefined | + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | string | undefined | + +### append + +```solidity +function append(string a, string b) external pure returns (string) +``` + + + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| a | string | undefined | +| b | string | undefined | + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | string | undefined | + +### toHex + +```solidity +function toHex(bytes32 _bytes32) external pure returns (string) +``` + + + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| _bytes32 | bytes32 | undefined | + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | string | undefined | + + + + diff --git a/test/bridge/Strings.ts b/test/bridge/Strings.ts new file mode 100644 index 000000000..67de50616 --- /dev/null +++ b/test/bridge/Strings.ts @@ -0,0 +1,67 @@ +import chai from "chai" +import { solidity } from "ethereum-waffle" +import { deployments, ethers } from "hardhat" +import { faker } from "@faker-js/faker" +import { StringsMock } from "../../build/typechain" +import { keccak256 } from "ethers/lib/utils" +import { randomBytes } from "crypto" + +chai.use(solidity) +const { expect } = chai + +// deterministic tests +faker.seed(123) + +describe("Strings Test", () => { + let stringsMock: StringsMock + + const setupTest = deployments.createFixture( + async ({ deployments, ethers }) => { + await deployments.fixture() + + const stringsMockFactory = await ethers.getContractFactory("StringsMock") + stringsMock = (await stringsMockFactory.deploy()) as StringsMock + }, + ) + + beforeEach(async () => { + await setupTest() + }) + + describe("append tests", () => { + it("should append a + b", async () => { + const a = faker.lorem.paragraph(1) + const b = faker.lorem.paragraph(2) + + expect(await stringsMock["append(string,string)"](a, b)).to.be.eq(a + b) + }) + + it("should append a + b + c", async () => { + const a = faker.lorem.paragraph(1) + const b = faker.lorem.paragraph(2) + const c = faker.lorem.paragraph(2) + + expect( + await stringsMock["append(string,string,string)"](a, b, c), + ).to.be.eq(a + b + c) + }) + + it("should append a + b + c", async () => { + const a = faker.lorem.paragraph(1) + const b = faker.lorem.paragraph(2) + const c = faker.lorem.paragraph(2) + const d = faker.lorem.paragraph(2) + + expect( + await stringsMock["append(string,string,string,string)"](a, b, c, d), + ).to.be.eq(a + b + c + d) + }) + }) + + describe("conversion tests", () => { + it("should convert bytes32 to string", async () => { + const bytes32 = keccak256(randomBytes(32)) + expect(await stringsMock.toHex(bytes32)).to.be.eq(bytes32) + }) + }) +}) From b98d42a29c6e1b4bd184ac159958995960cdfc14 Mon Sep 17 00:00:00 2001 From: Trajan0x Date: Mon, 11 Apr 2022 17:00:45 -0400 Subject: [PATCH 023/135] revert --- contracts/bridge/RateLimiter.sol | 8 -------- test/bridge/RateLimiter.ts | 6 ------ 2 files changed, 14 deletions(-) diff --git a/contracts/bridge/RateLimiter.sol b/contracts/bridge/RateLimiter.sol index 349f09356..7dbd96cb2 100644 --- a/contracts/bridge/RateLimiter.sol +++ b/contracts/bridge/RateLimiter.sol @@ -261,12 +261,4 @@ contract RateLimiter is } return abi.decode(_returnData, (string)); // All that remains is the revert string } - - function append(string memory a, string memory b) - internal - pure - returns (string memory) - { - return string(abi.encodePacked(a, b)); - } } diff --git a/test/bridge/RateLimiter.ts b/test/bridge/RateLimiter.ts index 14df1c0b5..4110cba46 100644 --- a/test/bridge/RateLimiter.ts +++ b/test/bridge/RateLimiter.ts @@ -2,15 +2,9 @@ import chai from "chai" import { solidity } from "ethereum-waffle" import { deployments, ethers } from "hardhat" import { BigNumber, BigNumberish, Signer } from "ethers" -import Wallet from "ethereumjs-wallet" import { RateLimiter } from "../../build/typechain/RateLimiter" -import { CHAIN_ID } from "../../utils/network" -import { Address } from "hardhat-deploy/dist/types" -import { faker } from "@faker-js/faker" -import { includes } from "lodash" import { - BridgeConfigV3, GenericERC20, RateLimiterTest, } from "../../build/typechain" From 91b631a9303bc3881cd35320bec797bbcc07cb71 Mon Sep 17 00:00:00 2001 From: Trajan0x Date: Mon, 11 Apr 2022 17:09:58 -0400 Subject: [PATCH 024/135] storage slot clash fix --- contracts/bridge/SynapseBridge.sol | 51 +++++++++++++++++------------- test/bridge/RateLimiter.ts | 5 +-- test/bridge/SynapseBridgeETH.ts | 3 +- 3 files changed, 32 insertions(+), 27 deletions(-) diff --git a/contracts/bridge/SynapseBridge.sol b/contracts/bridge/SynapseBridge.sol index afb91a39b..6f32b8b14 100644 --- a/contracts/bridge/SynapseBridge.sol +++ b/contracts/bridge/SynapseBridge.sol @@ -31,39 +31,46 @@ contract SynapseBridge is using SafeMath for uint256; bytes32 public constant NODEGROUP_ROLE = keccak256("NODEGROUP_ROLE"); - bytes32 public constant RATE_LIMITER_ROLE = keccak256("RATE_LIMITER_ROLE"); bytes32 public constant GOVERNANCE_ROLE = keccak256("GOVERNANCE_ROLE"); + mapping(address => uint256) private fees; + + uint256 public startBlockNumber; + uint256 public constant bridgeVersion = 7; + uint256 public chainGasAmount; + address payable public WETH_ADDRESS; + + mapping(bytes32 => bool) private kappaMap; + // selectors bytes4 private constant RETRY_MINT_SELECTOR = - bytes4(keccak256("retryMint(address,address,uint256,uint256,bytes32)")); + bytes4(keccak256("retryMint(address,address,uint256,uint256,bytes32)")); bytes4 private constant RETRY_MINT_AND_SWAP_SELECTOR = - bytes4( - keccak256( - "retryMintAndSwap(address,address,uint256,uint256,address,uint8,uint8,uint256,uint256,bytes32)" - ) - ); + bytes4( + keccak256( + "retryMintAndSwap(address,address,uint256,uint256,address,uint8,uint8,uint256,uint256,bytes32)" + ) + ); bytes4 private constant RETRY_WITHDRAW_AND_REMOVE_SELECTOR = - bytes4( - keccak256( - "retryWithdrawAndRemove(address,address,uint256,uint256,address,uint8,uint256,uint256,bytes32)" - ) - ); + bytes4( + keccak256( + "retryWithdrawAndRemove(address,address,uint256,uint256,address,uint8,uint256,uint256,bytes32)" + ) + ); bytes4 private constant RETRY_WITHDRAW_SELECTOR = - bytes4( - keccak256("retryWithdraw(address,address,uint256,uint256,bytes32)") - ); - - mapping(address => uint256) private fees; + bytes4( + keccak256("retryWithdraw(address,address,uint256,uint256,bytes32)") + ); - uint256 public startBlockNumber; - uint256 public constant bridgeVersion = 7; - uint256 public chainGasAmount; - address payable public WETH_ADDRESS; + // rate limiter IRateLimiter public rateLimiter; - mapping(bytes32 => bool) private kappaMap; + // new role + + bytes32 public constant RATE_LIMITER_ROLE = keccak256("RATE_LIMITER_ROLE"); + + receive() external payable {} diff --git a/test/bridge/RateLimiter.ts b/test/bridge/RateLimiter.ts index 4110cba46..4ee8fa90e 100644 --- a/test/bridge/RateLimiter.ts +++ b/test/bridge/RateLimiter.ts @@ -4,10 +4,7 @@ import { deployments, ethers } from "hardhat" import { BigNumber, BigNumberish, Signer } from "ethers" import { RateLimiter } from "../../build/typechain/RateLimiter" -import { - GenericERC20, - RateLimiterTest, -} from "../../build/typechain" +import { GenericERC20, RateLimiterTest } from "../../build/typechain" import epochSeconds from "@stdlib/time-now" chai.use(solidity) diff --git a/test/bridge/SynapseBridgeETH.ts b/test/bridge/SynapseBridgeETH.ts index c1f122738..ae782678f 100644 --- a/test/bridge/SynapseBridgeETH.ts +++ b/test/bridge/SynapseBridgeETH.ts @@ -93,7 +93,7 @@ describe("SynapseBridgeETH", async () => { ).to.be.not.reverted } - it("Withdraw: should add to retry queue if rate limit hit", async () => { + it.only("Withdraw: should add to retry queue if rate limit hit", async () => { const mintAmount = 50 await expect(USDC.mint(bridge.address, mintAmount * decimals)) @@ -111,6 +111,7 @@ describe("SynapseBridgeETH", async () => { expect(await USDC.balanceOf(bridge.address)).to.be.eq( (mintAmount * decimals).toString(), ) + console.log(kappa) // now retry. This should bypass the rate limiter await expect(rateLimiter.retryByKappa(kappa)).to.be.not.reverted From ece4bab53d1dcfc6a0e93cbc1cdce06f5278b2f5 Mon Sep 17 00:00:00 2001 From: Trajan0x Date: Mon, 11 Apr 2022 17:10:51 -0400 Subject: [PATCH 025/135] linter --- contracts/bridge/SynapseBridge.sol | 30 ++++++++++++++---------------- 1 file changed, 14 insertions(+), 16 deletions(-) diff --git a/contracts/bridge/SynapseBridge.sol b/contracts/bridge/SynapseBridge.sol index 6f32b8b14..64e5d9fc0 100644 --- a/contracts/bridge/SynapseBridge.sol +++ b/contracts/bridge/SynapseBridge.sol @@ -44,24 +44,24 @@ contract SynapseBridge is // selectors bytes4 private constant RETRY_MINT_SELECTOR = - bytes4(keccak256("retryMint(address,address,uint256,uint256,bytes32)")); + bytes4(keccak256("retryMint(address,address,uint256,uint256,bytes32)")); bytes4 private constant RETRY_MINT_AND_SWAP_SELECTOR = - bytes4( - keccak256( - "retryMintAndSwap(address,address,uint256,uint256,address,uint8,uint8,uint256,uint256,bytes32)" - ) - ); + bytes4( + keccak256( + "retryMintAndSwap(address,address,uint256,uint256,address,uint8,uint8,uint256,uint256,bytes32)" + ) + ); bytes4 private constant RETRY_WITHDRAW_AND_REMOVE_SELECTOR = - bytes4( - keccak256( - "retryWithdrawAndRemove(address,address,uint256,uint256,address,uint8,uint256,uint256,bytes32)" - ) - ); + bytes4( + keccak256( + "retryWithdrawAndRemove(address,address,uint256,uint256,address,uint8,uint256,uint256,bytes32)" + ) + ); bytes4 private constant RETRY_WITHDRAW_SELECTOR = - bytes4( - keccak256("retryWithdraw(address,address,uint256,uint256,bytes32)") - ); + bytes4( + keccak256("retryWithdraw(address,address,uint256,uint256,bytes32)") + ); // rate limiter IRateLimiter public rateLimiter; @@ -70,8 +70,6 @@ contract SynapseBridge is bytes32 public constant RATE_LIMITER_ROLE = keccak256("RATE_LIMITER_ROLE"); - - receive() external payable {} function initialize() external initializer { From e6b0e4c9871f27cec518e7078272361bda633b22 Mon Sep 17 00:00:00 2001 From: Trajan0x Date: Mon, 11 Apr 2022 17:21:53 -0400 Subject: [PATCH 026/135] upterm --- .github/workflows/coveralls.yaml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.github/workflows/coveralls.yaml b/.github/workflows/coveralls.yaml index 7431fdfd6..09bea75d6 100644 --- a/.github/workflows/coveralls.yaml +++ b/.github/workflows/coveralls.yaml @@ -42,6 +42,9 @@ jobs: - name: build run: npm run build + - name: Setup upterm session + uses: lhotari/action-upterm@v1 + - name: run test:coverage run: npm run test:coverage From 0bbf1dc61d8cbce24850a55c80fbe189eaceb2ca Mon Sep 17 00:00:00 2001 From: Trajan0x Date: Mon, 11 Apr 2022 17:27:41 -0400 Subject: [PATCH 027/135] tmate --- .github/workflows/coveralls.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/coveralls.yaml b/.github/workflows/coveralls.yaml index 09bea75d6..b1dbed8db 100644 --- a/.github/workflows/coveralls.yaml +++ b/.github/workflows/coveralls.yaml @@ -42,8 +42,8 @@ jobs: - name: build run: npm run build - - name: Setup upterm session - uses: lhotari/action-upterm@v1 + - name: Setup tmate session + uses: mxschmitt/action-tmate@v3 - name: run test:coverage run: npm run test:coverage From e5a3af449153e2b2bac2ec9cb104a3c98377af48 Mon Sep 17 00:00:00 2001 From: Trajan0x Date: Mon, 11 Apr 2022 17:46:14 -0400 Subject: [PATCH 028/135] skip upterm --- .github/workflows/coveralls.yaml | 4 +- .github/workflows/test.yaml | 2 +- package-lock.json | 220 +++++++++++++++++++++++++++++++ package.json | 3 +- test/bridge/upgrade.json | 12 ++ 5 files changed, 237 insertions(+), 4 deletions(-) create mode 100644 test/bridge/upgrade.json diff --git a/.github/workflows/coveralls.yaml b/.github/workflows/coveralls.yaml index b1dbed8db..9ce2a2ead 100644 --- a/.github/workflows/coveralls.yaml +++ b/.github/workflows/coveralls.yaml @@ -42,8 +42,8 @@ jobs: - name: build run: npm run build - - name: Setup tmate session - uses: mxschmitt/action-tmate@v3 +# - name: Setup tmate session +# uses: mxschmitt/action-tmate@v3 - name: run test:coverage run: npm run test:coverage diff --git a/.github/workflows/test.yaml b/.github/workflows/test.yaml index aee772c70..1ad2cc941 100644 --- a/.github/workflows/test.yaml +++ b/.github/workflows/test.yaml @@ -30,6 +30,6 @@ jobs: npm install npm run build - - name: Test and Coverage + - name: Test run: | npm run test \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index 7db13ac89..57de2ac4c 100644 --- a/package-lock.json +++ b/package-lock.json @@ -63,6 +63,7 @@ "prettier": "^2.3.0", "prettier-plugin-solidity": "^1.0.0-beta.11", "shelljs": "^0.8.4", + "sinon": "^13.0.1", "sol-merger": "^3.1.0", "solhint": "^3.3.6", "solhint-plugin-prettier": "0.0.5", @@ -3235,6 +3236,23 @@ "@sinonjs/commons": "^1.7.0" } }, + "node_modules/@sinonjs/samsam": { + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/@sinonjs/samsam/-/samsam-6.1.1.tgz", + "integrity": "sha512-cZ7rKJTLiE7u7Wi/v9Hc2fs3Ucc3jrWeMgPHbbTCeVAB2S0wOBbYlkJVeNSL04i7fdhT8wIbDq1zhC/PXTD2SA==", + "dev": true, + "dependencies": { + "@sinonjs/commons": "^1.6.0", + "lodash.get": "^4.4.2", + "type-detect": "^4.0.8" + } + }, + "node_modules/@sinonjs/text-encoding": { + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/@sinonjs/text-encoding/-/text-encoding-0.7.1.tgz", + "integrity": "sha512-+iTbntw2IZPb/anVDbypzfQa+ay64MW0Zo8aJ8gZPWMMK6/OubMVb6lUPMagqjOPnmtauXnFCACVl3O7ogjeqQ==", + "dev": true + }, "node_modules/@solidity-parser/parser": { "version": "0.14.1", "resolved": "https://registry.npmjs.org/@solidity-parser/parser/-/parser-0.14.1.tgz", @@ -24032,6 +24050,12 @@ "verror": "1.10.0" } }, + "node_modules/just-extend": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/just-extend/-/just-extend-4.2.1.tgz", + "integrity": "sha512-g3UB796vUFIY90VIv/WX3L2c8CS2MdWUww3CNrYmqza1Fg0DURc2K/O4YrnklBdQarSJ/y8JnJYDGc+1iumQjg==", + "dev": true + }, "node_modules/keccak": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/keccak/-/keccak-3.0.1.tgz", @@ -24627,6 +24651,12 @@ "integrity": "sha1-4j8/nE+Pvd6HJSnBBxhXoIblzO8=", "dev": true }, + "node_modules/lodash.get": { + "version": "4.4.2", + "resolved": "https://registry.npmjs.org/lodash.get/-/lodash.get-4.4.2.tgz", + "integrity": "sha1-LRd/ZS+jHpObRDjVNBSZ36OCXpk=", + "dev": true + }, "node_modules/lodash.merge": { "version": "4.6.2", "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", @@ -25755,6 +25785,34 @@ "resolved": "https://registry.npmjs.org/nice-try/-/nice-try-1.0.5.tgz", "integrity": "sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==" }, + "node_modules/nise": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/nise/-/nise-5.1.1.tgz", + "integrity": "sha512-yr5kW2THW1AkxVmCnKEh4nbYkJdB3I7LUkiUgOvEkOp414mc2UMaHMA7pjq1nYowhdoJZGwEKGaQVbxfpWj10A==", + "dev": true, + "dependencies": { + "@sinonjs/commons": "^1.8.3", + "@sinonjs/fake-timers": ">=5", + "@sinonjs/text-encoding": "^0.7.1", + "just-extend": "^4.0.2", + "path-to-regexp": "^1.7.0" + } + }, + "node_modules/nise/node_modules/isarray": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", + "dev": true + }, + "node_modules/nise/node_modules/path-to-regexp": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-1.8.0.tgz", + "integrity": "sha512-n43JRhlUKUAlibEJhPeir1ncUID16QnEjNpwzNdO3Lm4ywrBpBZ5oLD0I6br9evr1Y9JTqwRtAh7JLoOzAQdVA==", + "dev": true, + "dependencies": { + "isarray": "0.0.1" + } + }, "node_modules/node-abi": { "version": "2.30.0", "resolved": "https://registry.npmjs.org/node-abi/-/node-abi-2.30.0.tgz", @@ -27888,6 +27946,63 @@ "simple-concat": "^1.0.0" } }, + "node_modules/sinon": { + "version": "13.0.1", + "resolved": "https://registry.npmjs.org/sinon/-/sinon-13.0.1.tgz", + "integrity": "sha512-8yx2wIvkBjIq/MGY1D9h1LMraYW+z1X0mb648KZnKSdvLasvDu7maa0dFaNYdTDczFgbjNw2tOmWdTk9saVfwQ==", + "dev": true, + "dependencies": { + "@sinonjs/commons": "^1.8.3", + "@sinonjs/fake-timers": "^9.0.0", + "@sinonjs/samsam": "^6.1.1", + "diff": "^5.0.0", + "nise": "^5.1.1", + "supports-color": "^7.2.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/sinon" + } + }, + "node_modules/sinon/node_modules/@sinonjs/fake-timers": { + "version": "9.1.1", + "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-9.1.1.tgz", + "integrity": "sha512-Wp5vwlZ0lOqpSYGKqr53INws9HLkt6JDc/pDZcPf7bchQnrXJMXPns8CXx0hFikMSGSWfvtvvpb2gtMVfkWagA==", + "dev": true, + "dependencies": { + "@sinonjs/commons": "^1.7.0" + } + }, + "node_modules/sinon/node_modules/diff": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/diff/-/diff-5.0.0.tgz", + "integrity": "sha512-/VTCrvm5Z0JGty/BWHljh+BAiw3IK+2j87NGMu8Nwc/f48WoDAC395uomO9ZD117ZOBaHmkX1oyLvkVM/aIT3w==", + "dev": true, + "engines": { + "node": ">=0.3.1" + } + }, + "node_modules/sinon/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/sinon/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/slash": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/slash/-/slash-2.0.0.tgz", @@ -35487,6 +35602,23 @@ "@sinonjs/commons": "^1.7.0" } }, + "@sinonjs/samsam": { + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/@sinonjs/samsam/-/samsam-6.1.1.tgz", + "integrity": "sha512-cZ7rKJTLiE7u7Wi/v9Hc2fs3Ucc3jrWeMgPHbbTCeVAB2S0wOBbYlkJVeNSL04i7fdhT8wIbDq1zhC/PXTD2SA==", + "dev": true, + "requires": { + "@sinonjs/commons": "^1.6.0", + "lodash.get": "^4.4.2", + "type-detect": "^4.0.8" + } + }, + "@sinonjs/text-encoding": { + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/@sinonjs/text-encoding/-/text-encoding-0.7.1.tgz", + "integrity": "sha512-+iTbntw2IZPb/anVDbypzfQa+ay64MW0Zo8aJ8gZPWMMK6/OubMVb6lUPMagqjOPnmtauXnFCACVl3O7ogjeqQ==", + "dev": true + }, "@solidity-parser/parser": { "version": "0.14.1", "resolved": "https://registry.npmjs.org/@solidity-parser/parser/-/parser-0.14.1.tgz", @@ -53175,6 +53307,12 @@ "verror": "1.10.0" } }, + "just-extend": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/just-extend/-/just-extend-4.2.1.tgz", + "integrity": "sha512-g3UB796vUFIY90VIv/WX3L2c8CS2MdWUww3CNrYmqza1Fg0DURc2K/O4YrnklBdQarSJ/y8JnJYDGc+1iumQjg==", + "dev": true + }, "keccak": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/keccak/-/keccak-3.0.1.tgz", @@ -53646,6 +53784,12 @@ "integrity": "sha1-4j8/nE+Pvd6HJSnBBxhXoIblzO8=", "dev": true }, + "lodash.get": { + "version": "4.4.2", + "resolved": "https://registry.npmjs.org/lodash.get/-/lodash.get-4.4.2.tgz", + "integrity": "sha1-LRd/ZS+jHpObRDjVNBSZ36OCXpk=", + "dev": true + }, "lodash.merge": { "version": "4.6.2", "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", @@ -54579,6 +54723,36 @@ "resolved": "https://registry.npmjs.org/nice-try/-/nice-try-1.0.5.tgz", "integrity": "sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==" }, + "nise": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/nise/-/nise-5.1.1.tgz", + "integrity": "sha512-yr5kW2THW1AkxVmCnKEh4nbYkJdB3I7LUkiUgOvEkOp414mc2UMaHMA7pjq1nYowhdoJZGwEKGaQVbxfpWj10A==", + "dev": true, + "requires": { + "@sinonjs/commons": "^1.8.3", + "@sinonjs/fake-timers": ">=5", + "@sinonjs/text-encoding": "^0.7.1", + "just-extend": "^4.0.2", + "path-to-regexp": "^1.7.0" + }, + "dependencies": { + "isarray": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", + "dev": true + }, + "path-to-regexp": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-1.8.0.tgz", + "integrity": "sha512-n43JRhlUKUAlibEJhPeir1ncUID16QnEjNpwzNdO3Lm4ywrBpBZ5oLD0I6br9evr1Y9JTqwRtAh7JLoOzAQdVA==", + "dev": true, + "requires": { + "isarray": "0.0.1" + } + } + } + }, "node-abi": { "version": "2.30.0", "resolved": "https://registry.npmjs.org/node-abi/-/node-abi-2.30.0.tgz", @@ -56292,6 +56466,52 @@ "simple-concat": "^1.0.0" } }, + "sinon": { + "version": "13.0.1", + "resolved": "https://registry.npmjs.org/sinon/-/sinon-13.0.1.tgz", + "integrity": "sha512-8yx2wIvkBjIq/MGY1D9h1LMraYW+z1X0mb648KZnKSdvLasvDu7maa0dFaNYdTDczFgbjNw2tOmWdTk9saVfwQ==", + "dev": true, + "requires": { + "@sinonjs/commons": "^1.8.3", + "@sinonjs/fake-timers": "^9.0.0", + "@sinonjs/samsam": "^6.1.1", + "diff": "^5.0.0", + "nise": "^5.1.1", + "supports-color": "^7.2.0" + }, + "dependencies": { + "@sinonjs/fake-timers": { + "version": "9.1.1", + "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-9.1.1.tgz", + "integrity": "sha512-Wp5vwlZ0lOqpSYGKqr53INws9HLkt6JDc/pDZcPf7bchQnrXJMXPns8CXx0hFikMSGSWfvtvvpb2gtMVfkWagA==", + "dev": true, + "requires": { + "@sinonjs/commons": "^1.7.0" + } + }, + "diff": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/diff/-/diff-5.0.0.tgz", + "integrity": "sha512-/VTCrvm5Z0JGty/BWHljh+BAiw3IK+2j87NGMu8Nwc/f48WoDAC395uomO9ZD117ZOBaHmkX1oyLvkVM/aIT3w==", + "dev": true + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + } + } + }, "slash": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/slash/-/slash-2.0.0.tgz", diff --git a/package.json b/package.json index 967d8c5e3..24995e0c9 100644 --- a/package.json +++ b/package.json @@ -8,7 +8,7 @@ "build": "hardhat compile && npm run build-go", "build-go": "sol-merger \"./contracts/bridge/*.sol\" ./build --export-plugin SPDXLicenseRemovePlugin && sol-merger \"./contracts/bridge/wrappers/*.sol\" ./build --export-plugin SPDXLicenseRemovePlugin && sol-merger \"./contracts/bridge/testing/*.sol\" ./build --export-plugin SPDXLicenseRemovePlugin && sol-merger \"./contracts/amm/*.sol\" ./build --export-plugin SPDXLicenseRemovePlugin && sol-merger \"./contracts/amm/meta/*.sol\" ./build --export-plugin SPDXLicenseRemovePlugin", "post-install": "build-go", - "test:coverage": "cross-env NODE_OPTIONS=\"--max-old-space-size=2048\" hardhat coverage", + "test:coverage": "cross-env NODE_OPTIONS=\"--max-old-space-size=8192\" hardhat coverage", "prepublishOnly": "npm run build", "lint": "npm run prettier && solhint -c .solhint.json contracts/**/*.sol", "prettier": "prettier --write test/**/*.ts contracts/**/*.sol", @@ -81,6 +81,7 @@ "prettier": "^2.3.0", "prettier-plugin-solidity": "^1.0.0-beta.11", "shelljs": "^0.8.4", + "sinon": "^13.0.1", "sol-merger": "^3.1.0", "solhint": "^3.3.6", "solhint-plugin-prettier": "0.0.5", diff --git a/test/bridge/upgrade.json b/test/bridge/upgrade.json new file mode 100644 index 000000000..2bb708695 --- /dev/null +++ b/test/bridge/upgrade.json @@ -0,0 +1,12 @@ +{ + "1": { + "bridge_artifact": "SynapseBridge", + "bridge_address": "0x2796317b0fF8538F253012862c06787Adfb8cEb6", + "kappas": [ + "0x58b29a4cf220b60a7e46b76b9831686c0bfbdbfea19721ef8f2192ba28514485", + "0x3745754e018ed57dce0feda8b027f04b7e1369e7f74f1a247f5f7352d519021c", + "0xea5bc18a60d2f1b9ba5e5f8bfef3cd112c3b1a1ef74a0de8e5989441b1722524", + "0x1d4f3f6ed7690f1e5c1ff733d2040daa12fa484b3acbf37122ff334b46cf8b6d" + ] + } +} \ No newline at end of file From 9d78100bb51b0b9e933803a1ba638b92706e2326 Mon Sep 17 00:00:00 2001 From: Trajan0x Date: Mon, 11 Apr 2022 17:52:54 -0400 Subject: [PATCH 029/135] update mocha to fix mochajs/mocha#3090 (see: 1808c5b04d523b1eadaa6fdfc27355f89e5352cb) --- hardhat.config.ts | 3 +- package-lock.json | 2921 ++++++++++++++++++++------------------------- package.json | 1 + 3 files changed, 1330 insertions(+), 1595 deletions(-) diff --git a/hardhat.config.ts b/hardhat.config.ts index 55e118b2e..f873b5af9 100644 --- a/hardhat.config.ts +++ b/hardhat.config.ts @@ -104,7 +104,8 @@ let config: HardhatUserConfig = { target: "ethers-v5", }, dodoc: { - runOnCompile: true, + // skip doc generation on ci + runOnCompile: process.env.CI == "", debugMode: false, // pre solidity 5 breaks docgen exclude: ["MultisigWallet", "WETH9"] diff --git a/package-lock.json b/package-lock.json index 57de2ac4c..a1c5f6da7 100644 --- a/package-lock.json +++ b/package-lock.json @@ -60,6 +60,7 @@ "hardhat-spdx-license-identifier": "^2.0.3", "husky": "^6.0.0", "lint-staged": "^11.0.0", + "mocha": "^9.2.1", "prettier": "^2.3.0", "prettier-plugin-solidity": "^1.0.0-beta.11", "shelljs": "^0.8.4", @@ -7880,6 +7881,75 @@ "@types/node": "*" } }, + "node_modules/eth-gas-reporter/node_modules/ansi-colors": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-3.2.3.tgz", + "integrity": "sha512-LEHHyuhlPY3TmuUYMh2oz89lTShfvgbmzaBcxve9t/9Wuy7Dwf4yoAKcND7KFT1HAQfqZ12qtc+DUrBMeKF9nw==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/eth-gas-reporter/node_modules/ansi-regex": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.1.tgz", + "integrity": "sha512-ILlv4k/3f6vfQ4OoP2AGvirOktlQ98ZEL1k9FaQjxa3L1abBgbuTDAdPOpvbGncC0BTVQrl+OM8xZGK6tWXt7g==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/eth-gas-reporter/node_modules/camelcase": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", + "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/eth-gas-reporter/node_modules/chokidar": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.3.0.tgz", + "integrity": "sha512-dGmKLDdT3Gdl7fBUe8XK+gAtGmzy5Fn0XkkWQuYxGIgWVPPse2CxFA5mtrlD0TOHaHjEUqkWNyP1XdHoJES/4A==", + "dev": true, + "dependencies": { + "anymatch": "~3.1.1", + "braces": "~3.0.2", + "glob-parent": "~5.1.0", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.2.0" + }, + "engines": { + "node": ">= 8.10.0" + }, + "optionalDependencies": { + "fsevents": "~2.1.1" + } + }, + "node_modules/eth-gas-reporter/node_modules/cliui": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-5.0.0.tgz", + "integrity": "sha512-PYeGSEmmHM6zvoef2w8TPzlrnNpXIjTipYK780YswmIP9vjxmd6Y2a3CB2Ks6/AU8NHjZugXvo8w3oWM2qnwXA==", + "dev": true, + "dependencies": { + "string-width": "^3.1.0", + "strip-ansi": "^5.2.0", + "wrap-ansi": "^5.1.0" + } + }, + "node_modules/eth-gas-reporter/node_modules/debug": { + "version": "3.2.6", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", + "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", + "deprecated": "Debug versions >=3.2.0 <3.2.7 || >=4 <4.3.1 have a low-severity ReDos regression when used in a Node.js environment. It is recommended you upgrade to 3.2.7 or 4.3.1. (https://github.com/visionmedia/debug/issues/797)", + "dev": true, + "dependencies": { + "ms": "^2.1.1" + } + }, "node_modules/eth-gas-reporter/node_modules/ethereumjs-util": { "version": "6.2.0", "resolved": "https://registry.npmjs.org/ethereumjs-util/-/ethereumjs-util-6.2.0.tgz", @@ -7912,6 +7982,71 @@ "xmlhttprequest": "1.8.0" } }, + "node_modules/eth-gas-reporter/node_modules/find-up": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", + "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", + "dev": true, + "dependencies": { + "locate-path": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/eth-gas-reporter/node_modules/flat": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/flat/-/flat-4.1.1.tgz", + "integrity": "sha512-FmTtBsHskrU6FJ2VxCnsDb84wu9zhmO3cUX2kGFb5tuwhfXxGciiT0oRY+cck35QmG+NmGh5eLz6lLCpWTqwpA==", + "dev": true, + "dependencies": { + "is-buffer": "~2.0.3" + }, + "bin": { + "flat": "cli.js" + } + }, + "node_modules/eth-gas-reporter/node_modules/fsevents": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.1.3.tgz", + "integrity": "sha512-Auw9a4AxqWpa9GUfj370BMPzzyncfBABW8Mab7BGWBYDj4Isgq+cDKtx0i6u9jcX9pQDnswsaaOTgTmA5pEjuQ==", + "deprecated": "\"Please update to latest v2.3 or v2.2\"", + "dev": true, + "hasInstallScript": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, + "node_modules/eth-gas-reporter/node_modules/get-caller-file": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", + "dev": true, + "engines": { + "node": "6.* || 8.* || >= 10.*" + } + }, + "node_modules/eth-gas-reporter/node_modules/glob": { + "version": "7.1.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.3.tgz", + "integrity": "sha512-vcfuiIxogLV4DlGBHIUOwI0IbrJ8HWPc4MU7HzviGeNho/UJDfi6B5p3sHeWIQ0KGIU0Jpxi5ZHxemQfLkkAwQ==", + "dev": true, + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + } + }, "node_modules/eth-gas-reporter/node_modules/hash.js": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/hash.js/-/hash.js-1.1.3.tgz", @@ -7922,6 +8057,15 @@ "minimalistic-assert": "^1.0.0" } }, + "node_modules/eth-gas-reporter/node_modules/is-fullwidth-code-point": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", + "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", + "dev": true, + "engines": { + "node": ">=4" + } + }, "node_modules/eth-gas-reporter/node_modules/keccak": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/keccak/-/keccak-2.1.0.tgz", @@ -7938,6 +8082,158 @@ "node": ">=5.12.0" } }, + "node_modules/eth-gas-reporter/node_modules/locate-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", + "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", + "dev": true, + "dependencies": { + "p-locate": "^3.0.0", + "path-exists": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/eth-gas-reporter/node_modules/log-symbols": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-3.0.0.tgz", + "integrity": "sha512-dSkNGuI7iG3mfvDzUuYZyvk5dD9ocYCYzNU6CYDE6+Xqd+gwme6Z00NS3dUh8mq/73HaEtT7m6W+yUPtU6BZnQ==", + "dev": true, + "dependencies": { + "chalk": "^2.4.2" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/eth-gas-reporter/node_modules/mocha": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/mocha/-/mocha-7.2.0.tgz", + "integrity": "sha512-O9CIypScywTVpNaRrCAgoUnJgozpIofjKUYmJhiCIJMiuYnLI6otcb1/kpW9/n/tJODHGZ7i8aLQoDVsMtOKQQ==", + "dev": true, + "dependencies": { + "ansi-colors": "3.2.3", + "browser-stdout": "1.3.1", + "chokidar": "3.3.0", + "debug": "3.2.6", + "diff": "3.5.0", + "escape-string-regexp": "1.0.5", + "find-up": "3.0.0", + "glob": "7.1.3", + "growl": "1.10.5", + "he": "1.2.0", + "js-yaml": "3.13.1", + "log-symbols": "3.0.0", + "minimatch": "3.0.4", + "mkdirp": "0.5.5", + "ms": "2.1.1", + "node-environment-flags": "1.0.6", + "object.assign": "4.1.0", + "strip-json-comments": "2.0.1", + "supports-color": "6.0.0", + "which": "1.3.1", + "wide-align": "1.1.3", + "yargs": "13.3.2", + "yargs-parser": "13.1.2", + "yargs-unparser": "1.6.0" + }, + "bin": { + "_mocha": "bin/_mocha", + "mocha": "bin/mocha" + }, + "engines": { + "node": ">= 8.10.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/mochajs" + } + }, + "node_modules/eth-gas-reporter/node_modules/ms": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", + "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==", + "dev": true + }, + "node_modules/eth-gas-reporter/node_modules/object.assign": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.0.tgz", + "integrity": "sha512-exHJeq6kBKj58mqGyTQ9DFvrZC/eR6OwxzoM9YRoGBqrXYonaFyGiFMuc9VZrXf7DarreEwMpurG3dd+CNyW5w==", + "dev": true, + "dependencies": { + "define-properties": "^1.1.2", + "function-bind": "^1.1.1", + "has-symbols": "^1.0.0", + "object-keys": "^1.0.11" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/eth-gas-reporter/node_modules/p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "dev": true, + "dependencies": { + "p-try": "^2.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eth-gas-reporter/node_modules/p-locate": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", + "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", + "dev": true, + "dependencies": { + "p-limit": "^2.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/eth-gas-reporter/node_modules/p-try": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", + "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/eth-gas-reporter/node_modules/path-exists": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", + "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/eth-gas-reporter/node_modules/readdirp": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.2.0.tgz", + "integrity": "sha512-crk4Qu3pmXwgxdSgGhgA/eXiJAPQiX4GMOZZMXnqKxHX7TaoL+3gQVo/WeuAiogr07DpnfjIMpXXa+PAIvwPGQ==", + "dev": true, + "dependencies": { + "picomatch": "^2.0.4" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/eth-gas-reporter/node_modules/require-main-filename": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz", + "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==", + "dev": true + }, "node_modules/eth-gas-reporter/node_modules/scrypt-js": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/scrypt-js/-/scrypt-js-2.0.4.tgz", @@ -7970,6 +8266,44 @@ "integrity": "sha1-IOgd5iLUoCWIzgyNqJc8vPHTE48=", "dev": true }, + "node_modules/eth-gas-reporter/node_modules/string-width": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", + "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", + "dev": true, + "dependencies": { + "emoji-regex": "^7.0.1", + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^5.1.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/eth-gas-reporter/node_modules/strip-ansi": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", + "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", + "dev": true, + "dependencies": { + "ansi-regex": "^4.1.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/eth-gas-reporter/node_modules/supports-color": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.0.0.tgz", + "integrity": "sha512-on9Kwidc1IUQo+bQdhi8+Tijpo0e1SS6RoGo2guUwn5vdaxw8RXOF9Vb2ws+ihWOmh4JnCJOvaziZWP1VABaLg==", + "dev": true, + "dependencies": { + "has-flag": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, "node_modules/eth-gas-reporter/node_modules/uuid": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/uuid/-/uuid-2.0.1.tgz", @@ -7977,6 +8311,74 @@ "deprecated": "Please upgrade to version 7 or higher. Older versions may use Math.random() in certain circumstances, which is known to be problematic. See https://v8.dev/blog/math-random for details.", "dev": true }, + "node_modules/eth-gas-reporter/node_modules/which-module": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz", + "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=", + "dev": true + }, + "node_modules/eth-gas-reporter/node_modules/wrap-ansi": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-5.1.0.tgz", + "integrity": "sha512-QC1/iN/2/RPVJ5jYK8BGttj5z83LmSKmvbvrXPNCLZSEb32KKVDJDl/MOt2N01qU2H/FkzEa9PKto1BqDjtd7Q==", + "dev": true, + "dependencies": { + "ansi-styles": "^3.2.0", + "string-width": "^3.0.0", + "strip-ansi": "^5.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/eth-gas-reporter/node_modules/y18n": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.3.tgz", + "integrity": "sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ==", + "dev": true + }, + "node_modules/eth-gas-reporter/node_modules/yargs": { + "version": "13.3.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-13.3.2.tgz", + "integrity": "sha512-AX3Zw5iPruN5ie6xGRIDgqkT+ZhnRlZMLMHAs8tg7nRruy2Nb+i5o9bwghAogtM08q1dpr2LVoS8KSTMYpWXUw==", + "dev": true, + "dependencies": { + "cliui": "^5.0.0", + "find-up": "^3.0.0", + "get-caller-file": "^2.0.1", + "require-directory": "^2.1.1", + "require-main-filename": "^2.0.0", + "set-blocking": "^2.0.0", + "string-width": "^3.0.0", + "which-module": "^2.0.0", + "y18n": "^4.0.0", + "yargs-parser": "^13.1.2" + } + }, + "node_modules/eth-gas-reporter/node_modules/yargs-parser": { + "version": "13.1.2", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-13.1.2.tgz", + "integrity": "sha512-3lbsNRf/j+A4QuSZfDRA7HRSfWrzO0YjqTJd5kjAq37Zep1CEgaYmrH9Q3GwPiB9cHyd1Y1UwggGhJGoxipbzg==", + "dev": true, + "dependencies": { + "camelcase": "^5.0.0", + "decamelize": "^1.2.0" + } + }, + "node_modules/eth-gas-reporter/node_modules/yargs-unparser": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/yargs-unparser/-/yargs-unparser-1.6.0.tgz", + "integrity": "sha512-W9tKgmSn0DpSatfri0nx52Joq5hVXgeLiqR/5G0sZNDoLZFOr/xjBUDcShCOGNsBnEMNo1KAMBkTej1Hm62HTw==", + "dev": true, + "dependencies": { + "flat": "^4.1.0", + "lodash": "^4.17.15", + "yargs": "^13.3.0" + }, + "engines": { + "node": ">=6" + } + }, "node_modules/eth-lib": { "version": "0.2.8", "resolved": "https://registry.npmjs.org/eth-lib/-/eth-lib-0.2.8.tgz", @@ -10071,13 +10473,10 @@ } }, "node_modules/flat": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/flat/-/flat-4.1.1.tgz", - "integrity": "sha512-FmTtBsHskrU6FJ2VxCnsDb84wu9zhmO3cUX2kGFb5tuwhfXxGciiT0oRY+cck35QmG+NmGh5eLz6lLCpWTqwpA==", + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/flat/-/flat-5.0.2.tgz", + "integrity": "sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ==", "dev": true, - "dependencies": { - "is-buffer": "~2.0.3" - }, "bin": { "flat": "cli.js" } @@ -22140,77 +22539,6 @@ "resolved": "https://registry.npmjs.org/hardhat-typechain/-/hardhat-typechain-0.3.5.tgz", "integrity": "sha512-w9lm8sxqTJACY+V7vijiH+NkPExnmtiQEjsV9JKD1KgMdVk2q8y+RhvU/c4B7+7b1+HylRUCxpOIvFuB3rE4+w==" }, - "node_modules/hardhat/node_modules/ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/hardhat/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/hardhat/node_modules/argparse": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", - "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", - "dev": true - }, - "node_modules/hardhat/node_modules/camelcase": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", - "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/hardhat/node_modules/cliui": { - "version": "7.0.4", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", - "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==", - "dev": true, - "dependencies": { - "string-width": "^4.2.0", - "strip-ansi": "^6.0.0", - "wrap-ansi": "^7.0.0" - } - }, - "node_modules/hardhat/node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/hardhat/node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, "node_modules/hardhat/node_modules/debug": { "version": "4.3.3", "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.3.tgz", @@ -22228,45 +22556,6 @@ } } }, - "node_modules/hardhat/node_modules/decamelize": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-4.0.0.tgz", - "integrity": "sha512-9iE1PgSik9HeIIw2JO94IidnE3eBoQrFJ3w7sFuzSX4DpmZ3v5sZpUiV5Swcf6mQEF+Y0ru8Neo+p+nyh2J+hQ==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/hardhat/node_modules/diff": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/diff/-/diff-5.0.0.tgz", - "integrity": "sha512-/VTCrvm5Z0JGty/BWHljh+BAiw3IK+2j87NGMu8Nwc/f48WoDAC395uomO9ZD117ZOBaHmkX1oyLvkVM/aIT3w==", - "dev": true, - "engines": { - "node": ">=0.3.1" - } - }, - "node_modules/hardhat/node_modules/emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "dev": true - }, - "node_modules/hardhat/node_modules/escape-string-regexp": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", - "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/hardhat/node_modules/find-up": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz", @@ -22279,15 +22568,6 @@ "node": ">=4" } }, - "node_modules/hardhat/node_modules/flat": { - "version": "5.0.2", - "resolved": "https://registry.npmjs.org/flat/-/flat-5.0.2.tgz", - "integrity": "sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ==", - "dev": true, - "bin": { - "flat": "cli.js" - } - }, "node_modules/hardhat/node_modules/fs-extra": { "version": "7.0.1", "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-7.0.1.tgz", @@ -22302,60 +22582,12 @@ "node": ">=6 <7 || >=8" } }, - "node_modules/hardhat/node_modules/get-caller-file": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", - "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", - "dev": true, - "engines": { - "node": "6.* || 8.* || >= 10.*" - } - }, - "node_modules/hardhat/node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/hardhat/node_modules/is-fullwidth-code-point": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/hardhat/node_modules/is-plain-obj": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-2.1.0.tgz", - "integrity": "sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA==", - "dev": true, - "engines": { - "node": ">=8" - } - }, "node_modules/hardhat/node_modules/js-sha3": { "version": "0.8.0", "resolved": "https://registry.npmjs.org/js-sha3/-/js-sha3-0.8.0.tgz", "integrity": "sha512-gF1cRrHhIzNfToc802P800N8PpXS+evLLXfsVpowqmAFR9uwbi89WvXg2QspOmXL8QL86J4T1EpFu+yUkwJY3Q==", "dev": true }, - "node_modules/hardhat/node_modules/js-yaml": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", - "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", - "dev": true, - "dependencies": { - "argparse": "^2.0.1" - }, - "bin": { - "js-yaml": "bin/js-yaml.js" - } - }, "node_modules/hardhat/node_modules/jsonfile": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", @@ -22365,175 +22597,12 @@ "graceful-fs": "^4.1.6" } }, - "node_modules/hardhat/node_modules/log-symbols": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz", - "integrity": "sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==", - "dev": true, - "dependencies": { - "chalk": "^4.1.0", - "is-unicode-supported": "^0.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/hardhat/node_modules/log-symbols/node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/hardhat/node_modules/log-symbols/node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/hardhat/node_modules/mocha": { - "version": "9.2.1", - "resolved": "https://registry.npmjs.org/mocha/-/mocha-9.2.1.tgz", - "integrity": "sha512-T7uscqjJVS46Pq1XDXyo9Uvey9gd3huT/DD9cYBb4K2Xc/vbKRPUWK067bxDQRK0yIz6Jxk73IrnimvASzBNAQ==", - "dev": true, - "dependencies": { - "@ungap/promise-all-settled": "1.1.2", - "ansi-colors": "4.1.1", - "browser-stdout": "1.3.1", - "chokidar": "3.5.3", - "debug": "4.3.3", - "diff": "5.0.0", - "escape-string-regexp": "4.0.0", - "find-up": "5.0.0", - "glob": "7.2.0", - "growl": "1.10.5", - "he": "1.2.0", - "js-yaml": "4.1.0", - "log-symbols": "4.1.0", - "minimatch": "3.0.4", - "ms": "2.1.3", - "nanoid": "3.2.0", - "serialize-javascript": "6.0.0", - "strip-json-comments": "3.1.1", - "supports-color": "8.1.1", - "which": "2.0.2", - "workerpool": "6.2.0", - "yargs": "16.2.0", - "yargs-parser": "20.2.4", - "yargs-unparser": "2.0.0" - }, - "bin": { - "_mocha": "bin/_mocha", - "mocha": "bin/mocha" - }, - "engines": { - "node": ">= 12.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/mochajs" - } - }, - "node_modules/hardhat/node_modules/mocha/node_modules/find-up": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", - "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", - "dev": true, - "dependencies": { - "locate-path": "^6.0.0", - "path-exists": "^4.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/hardhat/node_modules/mocha/node_modules/locate-path": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", - "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", - "dev": true, - "dependencies": { - "p-locate": "^5.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/hardhat/node_modules/mocha/node_modules/ms": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", - "dev": true - }, "node_modules/hardhat/node_modules/ms": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", "dev": true }, - "node_modules/hardhat/node_modules/p-limit": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", - "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", - "dev": true, - "dependencies": { - "yocto-queue": "^0.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/hardhat/node_modules/p-locate": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", - "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", - "dev": true, - "dependencies": { - "p-limit": "^3.0.2" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/hardhat/node_modules/path-exists": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", - "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", - "dev": true, - "engines": { - "node": ">=8" - } - }, "node_modules/hardhat/node_modules/qs": { "version": "6.10.1", "resolved": "https://registry.npmjs.org/qs/-/qs-6.10.1.tgz", @@ -22636,59 +22705,6 @@ "semver": "bin/semver" } }, - "node_modules/hardhat/node_modules/string-width": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "dev": true, - "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/hardhat/node_modules/strip-ansi": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "dev": true, - "dependencies": { - "ansi-regex": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/hardhat/node_modules/strip-json-comments": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", - "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", - "dev": true, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/hardhat/node_modules/supports-color": { - "version": "8.1.1", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", - "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", - "dev": true, - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/supports-color?sponsor=1" - } - }, "node_modules/hardhat/node_modules/uuid": { "version": "8.3.2", "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", @@ -22698,89 +22714,6 @@ "uuid": "dist/bin/uuid" } }, - "node_modules/hardhat/node_modules/which": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", - "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", - "dev": true, - "dependencies": { - "isexe": "^2.0.0" - }, - "bin": { - "node-which": "bin/node-which" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/hardhat/node_modules/wrap-ansi": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", - "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", - "dev": true, - "dependencies": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/wrap-ansi?sponsor=1" - } - }, - "node_modules/hardhat/node_modules/y18n": { - "version": "5.0.8", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", - "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", - "dev": true, - "engines": { - "node": ">=10" - } - }, - "node_modules/hardhat/node_modules/yargs": { - "version": "16.2.0", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz", - "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==", - "dev": true, - "dependencies": { - "cliui": "^7.0.2", - "escalade": "^3.1.1", - "get-caller-file": "^2.0.5", - "require-directory": "^2.1.1", - "string-width": "^4.2.0", - "y18n": "^5.0.5", - "yargs-parser": "^20.2.2" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/hardhat/node_modules/yargs-parser": { - "version": "20.2.4", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.4.tgz", - "integrity": "sha512-WOkpgNhPTlE73h4VFAFsOnomJVaovO8VqLDzy5saChRBFQFBoMYirowyW+Q9HB4HFF4Z7VZTiG3iSzJJA29yRA==", - "dev": true, - "engines": { - "node": ">=10" - } - }, - "node_modules/hardhat/node_modules/yargs-unparser": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/yargs-unparser/-/yargs-unparser-2.0.0.tgz", - "integrity": "sha512-7pRTIA9Qc1caZ0bZ6RYRGbHJthJWuakf+WmHK0rVeLkNrrGhfoabBNdue6kdINI6r4if7ocq9aD/n7xwKOdzOA==", - "dev": true, - "dependencies": { - "camelcase": "^6.0.0", - "decamelize": "^4.0.0", - "flat": "^5.0.2", - "is-plain-obj": "^2.1.0" - }, - "engines": { - "node": ">=10" - } - }, "node_modules/has": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", @@ -24398,19 +24331,6 @@ "node": ">=8" } }, - "node_modules/lint-staged/node_modules/log-symbols": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz", - "integrity": "sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==", - "dev": true, - "dependencies": { - "chalk": "^4.1.0", - "is-unicode-supported": "^0.1.0" - }, - "engines": { - "node": ">=10" - } - }, "node_modules/lint-staged/node_modules/ms": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", @@ -24675,12 +24595,86 @@ "dev": true }, "node_modules/log-symbols": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-3.0.0.tgz", - "integrity": "sha512-dSkNGuI7iG3mfvDzUuYZyvk5dD9ocYCYzNU6CYDE6+Xqd+gwme6Z00NS3dUh8mq/73HaEtT7m6W+yUPtU6BZnQ==", + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz", + "integrity": "sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==", "dev": true, "dependencies": { - "chalk": "^2.4.2" + "chalk": "^4.1.0", + "is-unicode-supported": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/log-symbols/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/log-symbols/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/log-symbols/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/log-symbols/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/log-symbols/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/log-symbols/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" }, "engines": { "node": ">=8" @@ -25256,142 +25250,171 @@ } }, "node_modules/mocha": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/mocha/-/mocha-7.2.0.tgz", - "integrity": "sha512-O9CIypScywTVpNaRrCAgoUnJgozpIofjKUYmJhiCIJMiuYnLI6otcb1/kpW9/n/tJODHGZ7i8aLQoDVsMtOKQQ==", + "version": "9.2.2", + "resolved": "https://registry.npmjs.org/mocha/-/mocha-9.2.2.tgz", + "integrity": "sha512-L6XC3EdwT6YrIk0yXpavvLkn8h+EU+Y5UcCHKECyMbdUIxyMuZj4bX4U9e1nvnvUUvQVsV2VHQr5zLdcUkhW/g==", "dev": true, "dependencies": { - "ansi-colors": "3.2.3", + "@ungap/promise-all-settled": "1.1.2", + "ansi-colors": "4.1.1", "browser-stdout": "1.3.1", - "chokidar": "3.3.0", - "debug": "3.2.6", - "diff": "3.5.0", - "escape-string-regexp": "1.0.5", - "find-up": "3.0.0", - "glob": "7.1.3", + "chokidar": "3.5.3", + "debug": "4.3.3", + "diff": "5.0.0", + "escape-string-regexp": "4.0.0", + "find-up": "5.0.0", + "glob": "7.2.0", "growl": "1.10.5", "he": "1.2.0", - "js-yaml": "3.13.1", - "log-symbols": "3.0.0", - "minimatch": "3.0.4", - "mkdirp": "0.5.5", - "ms": "2.1.1", - "node-environment-flags": "1.0.6", - "object.assign": "4.1.0", - "strip-json-comments": "2.0.1", - "supports-color": "6.0.0", - "which": "1.3.1", - "wide-align": "1.1.3", - "yargs": "13.3.2", - "yargs-parser": "13.1.2", - "yargs-unparser": "1.6.0" + "js-yaml": "4.1.0", + "log-symbols": "4.1.0", + "minimatch": "4.2.1", + "ms": "2.1.3", + "nanoid": "3.3.1", + "serialize-javascript": "6.0.0", + "strip-json-comments": "3.1.1", + "supports-color": "8.1.1", + "which": "2.0.2", + "workerpool": "6.2.0", + "yargs": "16.2.0", + "yargs-parser": "20.2.4", + "yargs-unparser": "2.0.0" }, "bin": { "_mocha": "bin/_mocha", "mocha": "bin/mocha" }, "engines": { - "node": ">= 8.10.0" + "node": ">= 12.0.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/mochajs" } }, - "node_modules/mocha/node_modules/ansi-colors": { - "version": "3.2.3", - "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-3.2.3.tgz", - "integrity": "sha512-LEHHyuhlPY3TmuUYMh2oz89lTShfvgbmzaBcxve9t/9Wuy7Dwf4yoAKcND7KFT1HAQfqZ12qtc+DUrBMeKF9nw==", + "node_modules/mocha/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", "dev": true, "engines": { - "node": ">=6" + "node": ">=8" } }, - "node_modules/mocha/node_modules/ansi-regex": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", - "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", + "node_modules/mocha/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, "engines": { - "node": ">=6" + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/mocha/node_modules/camelcase": { - "version": "5.3.1", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", - "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", + "node_modules/mocha/node_modules/argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "dev": true + }, + "node_modules/mocha/node_modules/cliui": { + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", + "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==", + "dev": true, + "dependencies": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.0", + "wrap-ansi": "^7.0.0" + } + }, + "node_modules/mocha/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, "engines": { - "node": ">=6" + "node": ">=7.0.0" } }, - "node_modules/mocha/node_modules/chokidar": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.3.0.tgz", - "integrity": "sha512-dGmKLDdT3Gdl7fBUe8XK+gAtGmzy5Fn0XkkWQuYxGIgWVPPse2CxFA5mtrlD0TOHaHjEUqkWNyP1XdHoJES/4A==", + "node_modules/mocha/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/mocha/node_modules/debug": { + "version": "4.3.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.3.tgz", + "integrity": "sha512-/zxw5+vh1Tfv+4Qn7a5nsbcJKPaSvCDhojn6FEl9vupwK2VCSDtEiEtqr8DFtzYFOdz63LBkxec7DYuc2jon6Q==", "dev": true, "dependencies": { - "anymatch": "~3.1.1", - "braces": "~3.0.2", - "glob-parent": "~5.1.0", - "is-binary-path": "~2.1.0", - "is-glob": "~4.0.1", - "normalize-path": "~3.0.0", - "readdirp": "~3.2.0" + "ms": "2.1.2" }, "engines": { - "node": ">= 8.10.0" + "node": ">=6.0" }, - "optionalDependencies": { - "fsevents": "~2.1.1" + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } } }, - "node_modules/mocha/node_modules/cliui": { + "node_modules/mocha/node_modules/debug/node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, + "node_modules/mocha/node_modules/diff": { "version": "5.0.0", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-5.0.0.tgz", - "integrity": "sha512-PYeGSEmmHM6zvoef2w8TPzlrnNpXIjTipYK780YswmIP9vjxmd6Y2a3CB2Ks6/AU8NHjZugXvo8w3oWM2qnwXA==", + "resolved": "https://registry.npmjs.org/diff/-/diff-5.0.0.tgz", + "integrity": "sha512-/VTCrvm5Z0JGty/BWHljh+BAiw3IK+2j87NGMu8Nwc/f48WoDAC395uomO9ZD117ZOBaHmkX1oyLvkVM/aIT3w==", "dev": true, - "dependencies": { - "string-width": "^3.1.0", - "strip-ansi": "^5.2.0", - "wrap-ansi": "^5.1.0" + "engines": { + "node": ">=0.3.1" } }, - "node_modules/mocha/node_modules/debug": { - "version": "3.2.6", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", - "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", - "deprecated": "Debug versions >=3.2.0 <3.2.7 || >=4 <4.3.1 have a low-severity ReDos regression when used in a Node.js environment. It is recommended you upgrade to 3.2.7 or 4.3.1. (https://github.com/visionmedia/debug/issues/797)", + "node_modules/mocha/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true + }, + "node_modules/mocha/node_modules/escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", "dev": true, - "dependencies": { - "ms": "^2.1.1" + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/mocha/node_modules/find-up": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", - "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", + "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", "dev": true, "dependencies": { - "locate-path": "^3.0.0" + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" }, "engines": { - "node": ">=6" - } - }, - "node_modules/mocha/node_modules/fsevents": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.1.3.tgz", - "integrity": "sha512-Auw9a4AxqWpa9GUfj370BMPzzyncfBABW8Mab7BGWBYDj4Isgq+cDKtx0i6u9jcX9pQDnswsaaOTgTmA5pEjuQ==", - "deprecated": "\"Please update to latest v2.3 or v2.2\"", - "dev": true, - "hasInstallScript": true, - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/mocha/node_modules/get-caller-file": { @@ -25403,219 +25426,221 @@ "node": "6.* || 8.* || >= 10.*" } }, - "node_modules/mocha/node_modules/glob": { - "version": "7.1.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.3.tgz", - "integrity": "sha512-vcfuiIxogLV4DlGBHIUOwI0IbrJ8HWPc4MU7HzviGeNho/UJDfi6B5p3sHeWIQ0KGIU0Jpxi5ZHxemQfLkkAwQ==", + "node_modules/mocha/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", "dev": true, - "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.0.4", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - }, "engines": { - "node": "*" + "node": ">=8" } }, "node_modules/mocha/node_modules/is-fullwidth-code-point": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", - "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", "dev": true, "engines": { - "node": ">=4" + "node": ">=8" + } + }, + "node_modules/mocha/node_modules/js-yaml": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", + "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", + "dev": true, + "dependencies": { + "argparse": "^2.0.1" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" } }, "node_modules/mocha/node_modules/locate-path": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", - "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", + "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", "dev": true, "dependencies": { - "p-locate": "^3.0.0", - "path-exists": "^3.0.0" + "p-locate": "^5.0.0" }, "engines": { - "node": ">=6" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/mocha/node_modules/ms": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", - "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==", - "dev": true - }, - "node_modules/mocha/node_modules/object.assign": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.0.tgz", - "integrity": "sha512-exHJeq6kBKj58mqGyTQ9DFvrZC/eR6OwxzoM9YRoGBqrXYonaFyGiFMuc9VZrXf7DarreEwMpurG3dd+CNyW5w==", + "node_modules/mocha/node_modules/minimatch": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-4.2.1.tgz", + "integrity": "sha512-9Uq1ChtSZO+Mxa/CL1eGizn2vRn3MlLgzhT0Iz8zaY8NdvxvB0d5QdPFmCKf7JKA9Lerx5vRrnwO03jsSfGG9g==", "dev": true, "dependencies": { - "define-properties": "^1.1.2", - "function-bind": "^1.1.1", - "has-symbols": "^1.0.0", - "object-keys": "^1.0.11" + "brace-expansion": "^1.1.7" }, "engines": { - "node": ">= 0.4" + "node": ">=10" } }, "node_modules/mocha/node_modules/p-limit": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", - "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", "dev": true, "dependencies": { - "p-try": "^2.0.0" + "yocto-queue": "^0.1.0" }, "engines": { - "node": ">=6" + "node": ">=10" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/mocha/node_modules/p-locate": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", - "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", + "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", "dev": true, "dependencies": { - "p-limit": "^2.0.0" + "p-limit": "^3.0.2" }, "engines": { - "node": ">=6" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/mocha/node_modules/p-try": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", - "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", + "node_modules/mocha/node_modules/path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", "dev": true, "engines": { - "node": ">=6" + "node": ">=8" } }, - "node_modules/mocha/node_modules/path-exists": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", - "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=", + "node_modules/mocha/node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", "dev": true, + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, "engines": { - "node": ">=4" + "node": ">=8" } }, - "node_modules/mocha/node_modules/readdirp": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.2.0.tgz", - "integrity": "sha512-crk4Qu3pmXwgxdSgGhgA/eXiJAPQiX4GMOZZMXnqKxHX7TaoL+3gQVo/WeuAiogr07DpnfjIMpXXa+PAIvwPGQ==", + "node_modules/mocha/node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", "dev": true, "dependencies": { - "picomatch": "^2.0.4" + "ansi-regex": "^5.0.1" }, "engines": { - "node": ">= 8" + "node": ">=8" } }, - "node_modules/mocha/node_modules/require-main-filename": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz", - "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==", - "dev": true - }, - "node_modules/mocha/node_modules/string-width": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", - "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", + "node_modules/mocha/node_modules/strip-json-comments": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", + "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", "dev": true, - "dependencies": { - "emoji-regex": "^7.0.1", - "is-fullwidth-code-point": "^2.0.0", - "strip-ansi": "^5.1.0" - }, "engines": { - "node": ">=6" + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/mocha/node_modules/strip-ansi": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", - "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", + "node_modules/mocha/node_modules/supports-color": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", + "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", "dev": true, "dependencies": { - "ansi-regex": "^4.1.0" + "has-flag": "^4.0.0" }, "engines": { - "node": ">=6" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/supports-color?sponsor=1" } }, - "node_modules/mocha/node_modules/supports-color": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.0.0.tgz", - "integrity": "sha512-on9Kwidc1IUQo+bQdhi8+Tijpo0e1SS6RoGo2guUwn5vdaxw8RXOF9Vb2ws+ihWOmh4JnCJOvaziZWP1VABaLg==", + "node_modules/mocha/node_modules/which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", "dev": true, "dependencies": { - "has-flag": "^3.0.0" + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" }, "engines": { - "node": ">=6" + "node": ">= 8" } }, - "node_modules/mocha/node_modules/which-module": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz", - "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=", - "dev": true - }, "node_modules/mocha/node_modules/wrap-ansi": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-5.1.0.tgz", - "integrity": "sha512-QC1/iN/2/RPVJ5jYK8BGttj5z83LmSKmvbvrXPNCLZSEb32KKVDJDl/MOt2N01qU2H/FkzEa9PKto1BqDjtd7Q==", + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", "dev": true, "dependencies": { - "ansi-styles": "^3.2.0", - "string-width": "^3.0.0", - "strip-ansi": "^5.0.0" + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" }, "engines": { - "node": ">=6" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" } }, "node_modules/mocha/node_modules/y18n": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.3.tgz", - "integrity": "sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ==", - "dev": true + "version": "5.0.8", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", + "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", + "dev": true, + "engines": { + "node": ">=10" + } }, "node_modules/mocha/node_modules/yargs": { - "version": "13.3.2", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-13.3.2.tgz", - "integrity": "sha512-AX3Zw5iPruN5ie6xGRIDgqkT+ZhnRlZMLMHAs8tg7nRruy2Nb+i5o9bwghAogtM08q1dpr2LVoS8KSTMYpWXUw==", + "version": "16.2.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz", + "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==", "dev": true, "dependencies": { - "cliui": "^5.0.0", - "find-up": "^3.0.0", - "get-caller-file": "^2.0.1", + "cliui": "^7.0.2", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", "require-directory": "^2.1.1", - "require-main-filename": "^2.0.0", - "set-blocking": "^2.0.0", - "string-width": "^3.0.0", - "which-module": "^2.0.0", - "y18n": "^4.0.0", - "yargs-parser": "^13.1.2" + "string-width": "^4.2.0", + "y18n": "^5.0.5", + "yargs-parser": "^20.2.2" + }, + "engines": { + "node": ">=10" } }, "node_modules/mocha/node_modules/yargs-parser": { - "version": "13.1.2", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-13.1.2.tgz", - "integrity": "sha512-3lbsNRf/j+A4QuSZfDRA7HRSfWrzO0YjqTJd5kjAq37Zep1CEgaYmrH9Q3GwPiB9cHyd1Y1UwggGhJGoxipbzg==", + "version": "20.2.4", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.4.tgz", + "integrity": "sha512-WOkpgNhPTlE73h4VFAFsOnomJVaovO8VqLDzy5saChRBFQFBoMYirowyW+Q9HB4HFF4Z7VZTiG3iSzJJA29yRA==", "dev": true, - "dependencies": { - "camelcase": "^5.0.0", - "decamelize": "^1.2.0" + "engines": { + "node": ">=10" } }, "node_modules/mock-fs": { @@ -25699,9 +25724,9 @@ "dev": true }, "node_modules/nanoid": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.2.0.tgz", - "integrity": "sha512-fmsZYa9lpn69Ad5eDn7FMcnnSR+8R34W9qJEijxYhTbfOWzr22n1QxCMzXLK+ODyW2973V3Fux959iQoUxzUIA==", + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.1.tgz", + "integrity": "sha512-n6Vs/3KGyxPQd6uO0eH4Bv0ojGSUvuLlIHtC3Y0kEO23YRge8H9x1GCzLn28YX0H66pMkxuaeESFq4tKISKwdw==", "dev": true, "bin": { "nanoid": "bin/nanoid.cjs" @@ -32382,220 +32407,51 @@ } }, "node_modules/yargs-unparser": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/yargs-unparser/-/yargs-unparser-1.6.0.tgz", - "integrity": "sha512-W9tKgmSn0DpSatfri0nx52Joq5hVXgeLiqR/5G0sZNDoLZFOr/xjBUDcShCOGNsBnEMNo1KAMBkTej1Hm62HTw==", - "dev": true, - "dependencies": { - "flat": "^4.1.0", - "lodash": "^4.17.15", - "yargs": "^13.3.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/yargs-unparser/node_modules/ansi-regex": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", - "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/yargs-unparser/node_modules/camelcase": { - "version": "5.3.1", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", - "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/yargs-unparser/node_modules/cliui": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-5.0.0.tgz", - "integrity": "sha512-PYeGSEmmHM6zvoef2w8TPzlrnNpXIjTipYK780YswmIP9vjxmd6Y2a3CB2Ks6/AU8NHjZugXvo8w3oWM2qnwXA==", - "dev": true, - "dependencies": { - "string-width": "^3.1.0", - "strip-ansi": "^5.2.0", - "wrap-ansi": "^5.1.0" - } - }, - "node_modules/yargs-unparser/node_modules/find-up": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", - "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", - "dev": true, - "dependencies": { - "locate-path": "^3.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/yargs-unparser/node_modules/get-caller-file": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", - "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", - "dev": true, - "engines": { - "node": "6.* || 8.* || >= 10.*" - } - }, - "node_modules/yargs-unparser/node_modules/is-fullwidth-code-point": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", - "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/yargs-unparser/node_modules/locate-path": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", - "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", + "resolved": "https://registry.npmjs.org/yargs-unparser/-/yargs-unparser-2.0.0.tgz", + "integrity": "sha512-7pRTIA9Qc1caZ0bZ6RYRGbHJthJWuakf+WmHK0rVeLkNrrGhfoabBNdue6kdINI6r4if7ocq9aD/n7xwKOdzOA==", "dev": true, "dependencies": { - "p-locate": "^3.0.0", - "path-exists": "^3.0.0" + "camelcase": "^6.0.0", + "decamelize": "^4.0.0", + "flat": "^5.0.2", + "is-plain-obj": "^2.1.0" }, "engines": { - "node": ">=6" + "node": ">=10" } }, - "node_modules/yargs-unparser/node_modules/p-limit": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", - "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "node_modules/yargs-unparser/node_modules/camelcase": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", + "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", "dev": true, - "dependencies": { - "p-try": "^2.0.0" - }, "engines": { - "node": ">=6" + "node": ">=10" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/yargs-unparser/node_modules/p-locate": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", - "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", - "dev": true, - "dependencies": { - "p-limit": "^2.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/yargs-unparser/node_modules/p-try": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", - "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/yargs-unparser/node_modules/path-exists": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", - "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/yargs-unparser/node_modules/require-main-filename": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz", - "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==", - "dev": true - }, - "node_modules/yargs-unparser/node_modules/string-width": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", - "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", + "node_modules/yargs-unparser/node_modules/decamelize": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-4.0.0.tgz", + "integrity": "sha512-9iE1PgSik9HeIIw2JO94IidnE3eBoQrFJ3w7sFuzSX4DpmZ3v5sZpUiV5Swcf6mQEF+Y0ru8Neo+p+nyh2J+hQ==", "dev": true, - "dependencies": { - "emoji-regex": "^7.0.1", - "is-fullwidth-code-point": "^2.0.0", - "strip-ansi": "^5.1.0" - }, "engines": { - "node": ">=6" - } - }, - "node_modules/yargs-unparser/node_modules/strip-ansi": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", - "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", - "dev": true, - "dependencies": { - "ansi-regex": "^4.1.0" + "node": ">=10" }, - "engines": { - "node": ">=6" + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/yargs-unparser/node_modules/which-module": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz", - "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=", - "dev": true - }, - "node_modules/yargs-unparser/node_modules/wrap-ansi": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-5.1.0.tgz", - "integrity": "sha512-QC1/iN/2/RPVJ5jYK8BGttj5z83LmSKmvbvrXPNCLZSEb32KKVDJDl/MOt2N01qU2H/FkzEa9PKto1BqDjtd7Q==", + "node_modules/yargs-unparser/node_modules/is-plain-obj": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-2.1.0.tgz", + "integrity": "sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA==", "dev": true, - "dependencies": { - "ansi-styles": "^3.2.0", - "string-width": "^3.0.0", - "strip-ansi": "^5.0.0" - }, "engines": { - "node": ">=6" - } - }, - "node_modules/yargs-unparser/node_modules/y18n": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.3.tgz", - "integrity": "sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ==", - "dev": true - }, - "node_modules/yargs-unparser/node_modules/yargs": { - "version": "13.3.2", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-13.3.2.tgz", - "integrity": "sha512-AX3Zw5iPruN5ie6xGRIDgqkT+ZhnRlZMLMHAs8tg7nRruy2Nb+i5o9bwghAogtM08q1dpr2LVoS8KSTMYpWXUw==", - "dev": true, - "dependencies": { - "cliui": "^5.0.0", - "find-up": "^3.0.0", - "get-caller-file": "^2.0.1", - "require-directory": "^2.1.1", - "require-main-filename": "^2.0.0", - "set-blocking": "^2.0.0", - "string-width": "^3.0.0", - "which-module": "^2.0.0", - "y18n": "^4.0.0", - "yargs-parser": "^13.1.2" - } - }, - "node_modules/yargs-unparser/node_modules/yargs-parser": { - "version": "13.1.2", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-13.1.2.tgz", - "integrity": "sha512-3lbsNRf/j+A4QuSZfDRA7HRSfWrzO0YjqTJd5kjAq37Zep1CEgaYmrH9Q3GwPiB9cHyd1Y1UwggGhJGoxipbzg==", - "dev": true, - "dependencies": { - "camelcase": "^5.0.0", - "decamelize": "^1.2.0" + "node": ">=8" } }, "node_modules/yn": { @@ -39188,6 +39044,60 @@ "@types/node": "*" } }, + "ansi-colors": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-3.2.3.tgz", + "integrity": "sha512-LEHHyuhlPY3TmuUYMh2oz89lTShfvgbmzaBcxve9t/9Wuy7Dwf4yoAKcND7KFT1HAQfqZ12qtc+DUrBMeKF9nw==", + "dev": true + }, + "ansi-regex": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.1.tgz", + "integrity": "sha512-ILlv4k/3f6vfQ4OoP2AGvirOktlQ98ZEL1k9FaQjxa3L1abBgbuTDAdPOpvbGncC0BTVQrl+OM8xZGK6tWXt7g==", + "dev": true + }, + "camelcase": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", + "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", + "dev": true + }, + "chokidar": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.3.0.tgz", + "integrity": "sha512-dGmKLDdT3Gdl7fBUe8XK+gAtGmzy5Fn0XkkWQuYxGIgWVPPse2CxFA5mtrlD0TOHaHjEUqkWNyP1XdHoJES/4A==", + "dev": true, + "requires": { + "anymatch": "~3.1.1", + "braces": "~3.0.2", + "fsevents": "~2.1.1", + "glob-parent": "~5.1.0", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.2.0" + } + }, + "cliui": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-5.0.0.tgz", + "integrity": "sha512-PYeGSEmmHM6zvoef2w8TPzlrnNpXIjTipYK780YswmIP9vjxmd6Y2a3CB2Ks6/AU8NHjZugXvo8w3oWM2qnwXA==", + "dev": true, + "requires": { + "string-width": "^3.1.0", + "strip-ansi": "^5.2.0", + "wrap-ansi": "^5.1.0" + } + }, + "debug": { + "version": "3.2.6", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", + "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", + "dev": true, + "requires": { + "ms": "^2.1.1" + } + }, "ethereumjs-util": { "version": "6.2.0", "resolved": "https://registry.npmjs.org/ethereumjs-util/-/ethereumjs-util-6.2.0.tgz", @@ -39220,6 +39130,51 @@ "xmlhttprequest": "1.8.0" } }, + "find-up": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", + "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", + "dev": true, + "requires": { + "locate-path": "^3.0.0" + } + }, + "flat": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/flat/-/flat-4.1.1.tgz", + "integrity": "sha512-FmTtBsHskrU6FJ2VxCnsDb84wu9zhmO3cUX2kGFb5tuwhfXxGciiT0oRY+cck35QmG+NmGh5eLz6lLCpWTqwpA==", + "dev": true, + "requires": { + "is-buffer": "~2.0.3" + } + }, + "fsevents": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.1.3.tgz", + "integrity": "sha512-Auw9a4AxqWpa9GUfj370BMPzzyncfBABW8Mab7BGWBYDj4Isgq+cDKtx0i6u9jcX9pQDnswsaaOTgTmA5pEjuQ==", + "dev": true, + "optional": true + }, + "get-caller-file": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", + "dev": true + }, + "glob": { + "version": "7.1.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.3.tgz", + "integrity": "sha512-vcfuiIxogLV4DlGBHIUOwI0IbrJ8HWPc4MU7HzviGeNho/UJDfi6B5p3sHeWIQ0KGIU0Jpxi5ZHxemQfLkkAwQ==", + "dev": true, + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, "hash.js": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/hash.js/-/hash.js-1.1.3.tgz", @@ -39230,6 +39185,12 @@ "minimalistic-assert": "^1.0.0" } }, + "is-fullwidth-code-point": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", + "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", + "dev": true + }, "keccak": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/keccak/-/keccak-2.1.0.tgz", @@ -39242,6 +39203,120 @@ "safe-buffer": "^5.2.0" } }, + "locate-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", + "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", + "dev": true, + "requires": { + "p-locate": "^3.0.0", + "path-exists": "^3.0.0" + } + }, + "log-symbols": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-3.0.0.tgz", + "integrity": "sha512-dSkNGuI7iG3mfvDzUuYZyvk5dD9ocYCYzNU6CYDE6+Xqd+gwme6Z00NS3dUh8mq/73HaEtT7m6W+yUPtU6BZnQ==", + "dev": true, + "requires": { + "chalk": "^2.4.2" + } + }, + "mocha": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/mocha/-/mocha-7.2.0.tgz", + "integrity": "sha512-O9CIypScywTVpNaRrCAgoUnJgozpIofjKUYmJhiCIJMiuYnLI6otcb1/kpW9/n/tJODHGZ7i8aLQoDVsMtOKQQ==", + "dev": true, + "requires": { + "ansi-colors": "3.2.3", + "browser-stdout": "1.3.1", + "chokidar": "3.3.0", + "debug": "3.2.6", + "diff": "3.5.0", + "escape-string-regexp": "1.0.5", + "find-up": "3.0.0", + "glob": "7.1.3", + "growl": "1.10.5", + "he": "1.2.0", + "js-yaml": "3.13.1", + "log-symbols": "3.0.0", + "minimatch": "3.0.4", + "mkdirp": "0.5.5", + "ms": "2.1.1", + "node-environment-flags": "1.0.6", + "object.assign": "4.1.0", + "strip-json-comments": "2.0.1", + "supports-color": "6.0.0", + "which": "1.3.1", + "wide-align": "1.1.3", + "yargs": "13.3.2", + "yargs-parser": "13.1.2", + "yargs-unparser": "1.6.0" + } + }, + "ms": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", + "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==", + "dev": true + }, + "object.assign": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.0.tgz", + "integrity": "sha512-exHJeq6kBKj58mqGyTQ9DFvrZC/eR6OwxzoM9YRoGBqrXYonaFyGiFMuc9VZrXf7DarreEwMpurG3dd+CNyW5w==", + "dev": true, + "requires": { + "define-properties": "^1.1.2", + "function-bind": "^1.1.1", + "has-symbols": "^1.0.0", + "object-keys": "^1.0.11" + } + }, + "p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "dev": true, + "requires": { + "p-try": "^2.0.0" + } + }, + "p-locate": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", + "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", + "dev": true, + "requires": { + "p-limit": "^2.0.0" + } + }, + "p-try": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", + "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", + "dev": true + }, + "path-exists": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", + "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=", + "dev": true + }, + "readdirp": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.2.0.tgz", + "integrity": "sha512-crk4Qu3pmXwgxdSgGhgA/eXiJAPQiX4GMOZZMXnqKxHX7TaoL+3gQVo/WeuAiogr07DpnfjIMpXXa+PAIvwPGQ==", + "dev": true, + "requires": { + "picomatch": "^2.0.4" + } + }, + "require-main-filename": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz", + "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==", + "dev": true + }, "scrypt-js": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/scrypt-js/-/scrypt-js-2.0.4.tgz", @@ -39270,11 +39345,102 @@ "integrity": "sha1-IOgd5iLUoCWIzgyNqJc8vPHTE48=", "dev": true }, + "string-width": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", + "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", + "dev": true, + "requires": { + "emoji-regex": "^7.0.1", + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^5.1.0" + } + }, + "strip-ansi": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", + "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", + "dev": true, + "requires": { + "ansi-regex": "^4.1.0" + } + }, + "supports-color": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.0.0.tgz", + "integrity": "sha512-on9Kwidc1IUQo+bQdhi8+Tijpo0e1SS6RoGo2guUwn5vdaxw8RXOF9Vb2ws+ihWOmh4JnCJOvaziZWP1VABaLg==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + }, "uuid": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/uuid/-/uuid-2.0.1.tgz", "integrity": "sha1-wqMN7bPlNdcsz4LjQ5QaULqFM6w=", "dev": true + }, + "which-module": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz", + "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=", + "dev": true + }, + "wrap-ansi": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-5.1.0.tgz", + "integrity": "sha512-QC1/iN/2/RPVJ5jYK8BGttj5z83LmSKmvbvrXPNCLZSEb32KKVDJDl/MOt2N01qU2H/FkzEa9PKto1BqDjtd7Q==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.0", + "string-width": "^3.0.0", + "strip-ansi": "^5.0.0" + } + }, + "y18n": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.3.tgz", + "integrity": "sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ==", + "dev": true + }, + "yargs": { + "version": "13.3.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-13.3.2.tgz", + "integrity": "sha512-AX3Zw5iPruN5ie6xGRIDgqkT+ZhnRlZMLMHAs8tg7nRruy2Nb+i5o9bwghAogtM08q1dpr2LVoS8KSTMYpWXUw==", + "dev": true, + "requires": { + "cliui": "^5.0.0", + "find-up": "^3.0.0", + "get-caller-file": "^2.0.1", + "require-directory": "^2.1.1", + "require-main-filename": "^2.0.0", + "set-blocking": "^2.0.0", + "string-width": "^3.0.0", + "which-module": "^2.0.0", + "y18n": "^4.0.0", + "yargs-parser": "^13.1.2" + } + }, + "yargs-parser": { + "version": "13.1.2", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-13.1.2.tgz", + "integrity": "sha512-3lbsNRf/j+A4QuSZfDRA7HRSfWrzO0YjqTJd5kjAq37Zep1CEgaYmrH9Q3GwPiB9cHyd1Y1UwggGhJGoxipbzg==", + "dev": true, + "requires": { + "camelcase": "^5.0.0", + "decamelize": "^1.2.0" + } + }, + "yargs-unparser": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/yargs-unparser/-/yargs-unparser-1.6.0.tgz", + "integrity": "sha512-W9tKgmSn0DpSatfri0nx52Joq5hVXgeLiqR/5G0sZNDoLZFOr/xjBUDcShCOGNsBnEMNo1KAMBkTej1Hm62HTw==", + "dev": true, + "requires": { + "flat": "^4.1.0", + "lodash": "^4.17.15", + "yargs": "^13.3.0" + } } } }, @@ -41171,13 +41337,10 @@ } }, "flat": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/flat/-/flat-4.1.1.tgz", - "integrity": "sha512-FmTtBsHskrU6FJ2VxCnsDb84wu9zhmO3cUX2kGFb5tuwhfXxGciiT0oRY+cck35QmG+NmGh5eLz6lLCpWTqwpA==", - "dev": true, - "requires": { - "is-buffer": "~2.0.3" - } + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/flat/-/flat-5.0.2.tgz", + "integrity": "sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ==", + "dev": true }, "flat-cache": { "version": "3.0.4", @@ -51273,59 +51436,6 @@ "ws": "^7.4.6" }, "dependencies": { - "ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", - "dev": true - }, - "ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "requires": { - "color-convert": "^2.0.1" - } - }, - "argparse": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", - "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", - "dev": true - }, - "camelcase": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", - "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", - "dev": true - }, - "cliui": { - "version": "7.0.4", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", - "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==", - "dev": true, - "requires": { - "string-width": "^4.2.0", - "strip-ansi": "^6.0.0", - "wrap-ansi": "^7.0.0" - } - }, - "color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "requires": { - "color-name": "~1.1.4" - } - }, - "color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, "debug": { "version": "4.3.3", "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.3.tgz", @@ -51335,30 +51445,6 @@ "ms": "2.1.2" } }, - "decamelize": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-4.0.0.tgz", - "integrity": "sha512-9iE1PgSik9HeIIw2JO94IidnE3eBoQrFJ3w7sFuzSX4DpmZ3v5sZpUiV5Swcf6mQEF+Y0ru8Neo+p+nyh2J+hQ==", - "dev": true - }, - "diff": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/diff/-/diff-5.0.0.tgz", - "integrity": "sha512-/VTCrvm5Z0JGty/BWHljh+BAiw3IK+2j87NGMu8Nwc/f48WoDAC395uomO9ZD117ZOBaHmkX1oyLvkVM/aIT3w==", - "dev": true - }, - "emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "dev": true - }, - "escape-string-regexp": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", - "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", - "dev": true - }, "find-up": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz", @@ -51368,12 +51454,6 @@ "locate-path": "^2.0.0" } }, - "flat": { - "version": "5.0.2", - "resolved": "https://registry.npmjs.org/flat/-/flat-5.0.2.tgz", - "integrity": "sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ==", - "dev": true - }, "fs-extra": { "version": "7.0.1", "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-7.0.1.tgz", @@ -51385,45 +51465,12 @@ "universalify": "^0.1.0" } }, - "get-caller-file": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", - "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", - "dev": true - }, - "has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true - }, - "is-fullwidth-code-point": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", - "dev": true - }, - "is-plain-obj": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-2.1.0.tgz", - "integrity": "sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA==", - "dev": true - }, "js-sha3": { "version": "0.8.0", "resolved": "https://registry.npmjs.org/js-sha3/-/js-sha3-0.8.0.tgz", "integrity": "sha512-gF1cRrHhIzNfToc802P800N8PpXS+evLLXfsVpowqmAFR9uwbi89WvXg2QspOmXL8QL86J4T1EpFu+yUkwJY3Q==", "dev": true }, - "js-yaml": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", - "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", - "dev": true, - "requires": { - "argparse": "^2.0.1" - } - }, "jsonfile": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", @@ -51433,126 +51480,12 @@ "graceful-fs": "^4.1.6" } }, - "log-symbols": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz", - "integrity": "sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==", - "dev": true, - "requires": { - "chalk": "^4.1.0", - "is-unicode-supported": "^0.1.0" - }, - "dependencies": { - "chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "requires": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - } - }, - "supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "requires": { - "has-flag": "^4.0.0" - } - } - } - }, - "mocha": { - "version": "9.2.1", - "resolved": "https://registry.npmjs.org/mocha/-/mocha-9.2.1.tgz", - "integrity": "sha512-T7uscqjJVS46Pq1XDXyo9Uvey9gd3huT/DD9cYBb4K2Xc/vbKRPUWK067bxDQRK0yIz6Jxk73IrnimvASzBNAQ==", - "dev": true, - "requires": { - "@ungap/promise-all-settled": "1.1.2", - "ansi-colors": "4.1.1", - "browser-stdout": "1.3.1", - "chokidar": "3.5.3", - "debug": "4.3.3", - "diff": "5.0.0", - "escape-string-regexp": "4.0.0", - "find-up": "5.0.0", - "glob": "7.2.0", - "growl": "1.10.5", - "he": "1.2.0", - "js-yaml": "4.1.0", - "log-symbols": "4.1.0", - "minimatch": "3.0.4", - "ms": "2.1.3", - "nanoid": "3.2.0", - "serialize-javascript": "6.0.0", - "strip-json-comments": "3.1.1", - "supports-color": "8.1.1", - "which": "2.0.2", - "workerpool": "6.2.0", - "yargs": "16.2.0", - "yargs-parser": "20.2.4", - "yargs-unparser": "2.0.0" - }, - "dependencies": { - "find-up": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", - "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", - "dev": true, - "requires": { - "locate-path": "^6.0.0", - "path-exists": "^4.0.0" - } - }, - "locate-path": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", - "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", - "dev": true, - "requires": { - "p-locate": "^5.0.0" - } - }, - "ms": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", - "dev": true - } - } - }, "ms": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", "dev": true }, - "p-limit": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", - "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", - "dev": true, - "requires": { - "yocto-queue": "^0.1.0" - } - }, - "p-locate": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", - "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", - "dev": true, - "requires": { - "p-limit": "^3.0.2" - } - }, - "path-exists": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", - "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", - "dev": true - }, "qs": { "version": "6.10.1", "resolved": "https://registry.npmjs.org/qs/-/qs-6.10.1.tgz", @@ -51636,105 +51569,11 @@ } } }, - "string-width": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "dev": true, - "requires": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - } - }, - "strip-ansi": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "dev": true, - "requires": { - "ansi-regex": "^5.0.1" - } - }, - "strip-json-comments": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", - "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", - "dev": true - }, - "supports-color": { - "version": "8.1.1", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", - "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", - "dev": true, - "requires": { - "has-flag": "^4.0.0" - } - }, "uuid": { "version": "8.3.2", "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", "dev": true - }, - "which": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", - "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", - "dev": true, - "requires": { - "isexe": "^2.0.0" - } - }, - "wrap-ansi": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", - "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", - "dev": true, - "requires": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" - } - }, - "y18n": { - "version": "5.0.8", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", - "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", - "dev": true - }, - "yargs": { - "version": "16.2.0", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz", - "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==", - "dev": true, - "requires": { - "cliui": "^7.0.2", - "escalade": "^3.1.1", - "get-caller-file": "^2.0.5", - "require-directory": "^2.1.1", - "string-width": "^4.2.0", - "y18n": "^5.0.5", - "yargs-parser": "^20.2.2" - } - }, - "yargs-parser": { - "version": "20.2.4", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.4.tgz", - "integrity": "sha512-WOkpgNhPTlE73h4VFAFsOnomJVaovO8VqLDzy5saChRBFQFBoMYirowyW+Q9HB4HFF4Z7VZTiG3iSzJJA29yRA==", - "dev": true - }, - "yargs-unparser": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/yargs-unparser/-/yargs-unparser-2.0.0.tgz", - "integrity": "sha512-7pRTIA9Qc1caZ0bZ6RYRGbHJthJWuakf+WmHK0rVeLkNrrGhfoabBNdue6kdINI6r4if7ocq9aD/n7xwKOdzOA==", - "dev": true, - "requires": { - "camelcase": "^6.0.0", - "decamelize": "^4.0.0", - "flat": "^5.0.2", - "is-plain-obj": "^2.1.0" - } } } }, @@ -53582,16 +53421,6 @@ "integrity": "sha512-XCoy+WlUr7d1+Z8GgSuXmpuUFC9fOhRXglJMx+dwLKTkL44Cjd4W1Z5P+BQZpr+cR93aGP4S/s7Ftw6Nd/kiEw==", "dev": true }, - "log-symbols": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz", - "integrity": "sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==", - "dev": true, - "requires": { - "chalk": "^4.1.0", - "is-unicode-supported": "^0.1.0" - } - }, "ms": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", @@ -53808,12 +53637,64 @@ "dev": true }, "log-symbols": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-3.0.0.tgz", - "integrity": "sha512-dSkNGuI7iG3mfvDzUuYZyvk5dD9ocYCYzNU6CYDE6+Xqd+gwme6Z00NS3dUh8mq/73HaEtT7m6W+yUPtU6BZnQ==", + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz", + "integrity": "sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==", "dev": true, "requires": { - "chalk": "^2.4.2" + "chalk": "^4.1.0", + "is-unicode-supported": "^0.1.0" + }, + "dependencies": { + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "requires": { + "color-convert": "^2.0.1" + } + }, + "chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + } } }, "log-update": { @@ -54288,285 +54169,279 @@ } }, "mocha": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/mocha/-/mocha-7.2.0.tgz", - "integrity": "sha512-O9CIypScywTVpNaRrCAgoUnJgozpIofjKUYmJhiCIJMiuYnLI6otcb1/kpW9/n/tJODHGZ7i8aLQoDVsMtOKQQ==", + "version": "9.2.2", + "resolved": "https://registry.npmjs.org/mocha/-/mocha-9.2.2.tgz", + "integrity": "sha512-L6XC3EdwT6YrIk0yXpavvLkn8h+EU+Y5UcCHKECyMbdUIxyMuZj4bX4U9e1nvnvUUvQVsV2VHQr5zLdcUkhW/g==", "dev": true, "requires": { - "ansi-colors": "3.2.3", + "@ungap/promise-all-settled": "1.1.2", + "ansi-colors": "4.1.1", "browser-stdout": "1.3.1", - "chokidar": "3.3.0", - "debug": "3.2.6", - "diff": "3.5.0", - "escape-string-regexp": "1.0.5", - "find-up": "3.0.0", - "glob": "7.1.3", + "chokidar": "3.5.3", + "debug": "4.3.3", + "diff": "5.0.0", + "escape-string-regexp": "4.0.0", + "find-up": "5.0.0", + "glob": "7.2.0", "growl": "1.10.5", "he": "1.2.0", - "js-yaml": "3.13.1", - "log-symbols": "3.0.0", - "minimatch": "3.0.4", - "mkdirp": "0.5.5", - "ms": "2.1.1", - "node-environment-flags": "1.0.6", - "object.assign": "4.1.0", - "strip-json-comments": "2.0.1", - "supports-color": "6.0.0", - "which": "1.3.1", - "wide-align": "1.1.3", - "yargs": "13.3.2", - "yargs-parser": "13.1.2", - "yargs-unparser": "1.6.0" + "js-yaml": "4.1.0", + "log-symbols": "4.1.0", + "minimatch": "4.2.1", + "ms": "2.1.3", + "nanoid": "3.3.1", + "serialize-javascript": "6.0.0", + "strip-json-comments": "3.1.1", + "supports-color": "8.1.1", + "which": "2.0.2", + "workerpool": "6.2.0", + "yargs": "16.2.0", + "yargs-parser": "20.2.4", + "yargs-unparser": "2.0.0" }, "dependencies": { - "ansi-colors": { - "version": "3.2.3", - "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-3.2.3.tgz", - "integrity": "sha512-LEHHyuhlPY3TmuUYMh2oz89lTShfvgbmzaBcxve9t/9Wuy7Dwf4yoAKcND7KFT1HAQfqZ12qtc+DUrBMeKF9nw==", - "dev": true - }, "ansi-regex": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", - "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", "dev": true }, - "camelcase": { - "version": "5.3.1", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", - "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "requires": { + "color-convert": "^2.0.1" + } + }, + "argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", "dev": true }, - "chokidar": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.3.0.tgz", - "integrity": "sha512-dGmKLDdT3Gdl7fBUe8XK+gAtGmzy5Fn0XkkWQuYxGIgWVPPse2CxFA5mtrlD0TOHaHjEUqkWNyP1XdHoJES/4A==", + "cliui": { + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", + "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==", "dev": true, "requires": { - "anymatch": "~3.1.1", - "braces": "~3.0.2", - "fsevents": "~2.1.1", - "glob-parent": "~5.1.0", - "is-binary-path": "~2.1.0", - "is-glob": "~4.0.1", - "normalize-path": "~3.0.0", - "readdirp": "~3.2.0" + "string-width": "^4.2.0", + "strip-ansi": "^6.0.0", + "wrap-ansi": "^7.0.0" } }, - "cliui": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-5.0.0.tgz", - "integrity": "sha512-PYeGSEmmHM6zvoef2w8TPzlrnNpXIjTipYK780YswmIP9vjxmd6Y2a3CB2Ks6/AU8NHjZugXvo8w3oWM2qnwXA==", + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", "dev": true, "requires": { - "string-width": "^3.1.0", - "strip-ansi": "^5.2.0", - "wrap-ansi": "^5.1.0" + "color-name": "~1.1.4" } }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, "debug": { - "version": "3.2.6", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", - "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", + "version": "4.3.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.3.tgz", + "integrity": "sha512-/zxw5+vh1Tfv+4Qn7a5nsbcJKPaSvCDhojn6FEl9vupwK2VCSDtEiEtqr8DFtzYFOdz63LBkxec7DYuc2jon6Q==", "dev": true, "requires": { - "ms": "^2.1.1" + "ms": "2.1.2" + }, + "dependencies": { + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + } } }, + "diff": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/diff/-/diff-5.0.0.tgz", + "integrity": "sha512-/VTCrvm5Z0JGty/BWHljh+BAiw3IK+2j87NGMu8Nwc/f48WoDAC395uomO9ZD117ZOBaHmkX1oyLvkVM/aIT3w==", + "dev": true + }, + "emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true + }, + "escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "dev": true + }, "find-up": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", - "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", + "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", "dev": true, "requires": { - "locate-path": "^3.0.0" + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" } }, - "fsevents": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.1.3.tgz", - "integrity": "sha512-Auw9a4AxqWpa9GUfj370BMPzzyncfBABW8Mab7BGWBYDj4Isgq+cDKtx0i6u9jcX9pQDnswsaaOTgTmA5pEjuQ==", - "dev": true, - "optional": true - }, "get-caller-file": { "version": "2.0.5", "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", "dev": true }, - "glob": { - "version": "7.1.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.3.tgz", - "integrity": "sha512-vcfuiIxogLV4DlGBHIUOwI0IbrJ8HWPc4MU7HzviGeNho/UJDfi6B5p3sHeWIQ0KGIU0Jpxi5ZHxemQfLkkAwQ==", - "dev": true, - "requires": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.0.4", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - } + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true }, "is-fullwidth-code-point": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", - "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", "dev": true }, - "locate-path": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", - "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", + "js-yaml": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", + "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", "dev": true, "requires": { - "p-locate": "^3.0.0", - "path-exists": "^3.0.0" + "argparse": "^2.0.1" } }, - "ms": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", - "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==", - "dev": true - }, - "object.assign": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.0.tgz", - "integrity": "sha512-exHJeq6kBKj58mqGyTQ9DFvrZC/eR6OwxzoM9YRoGBqrXYonaFyGiFMuc9VZrXf7DarreEwMpurG3dd+CNyW5w==", + "locate-path": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", + "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", "dev": true, "requires": { - "define-properties": "^1.1.2", - "function-bind": "^1.1.1", - "has-symbols": "^1.0.0", - "object-keys": "^1.0.11" + "p-locate": "^5.0.0" } }, - "p-limit": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", - "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "minimatch": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-4.2.1.tgz", + "integrity": "sha512-9Uq1ChtSZO+Mxa/CL1eGizn2vRn3MlLgzhT0Iz8zaY8NdvxvB0d5QdPFmCKf7JKA9Lerx5vRrnwO03jsSfGG9g==", "dev": true, "requires": { - "p-try": "^2.0.0" + "brace-expansion": "^1.1.7" } }, - "p-locate": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", - "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", + "p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", "dev": true, "requires": { - "p-limit": "^2.0.0" + "yocto-queue": "^0.1.0" } }, - "p-try": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", - "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", - "dev": true - }, - "path-exists": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", - "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=", - "dev": true - }, - "readdirp": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.2.0.tgz", - "integrity": "sha512-crk4Qu3pmXwgxdSgGhgA/eXiJAPQiX4GMOZZMXnqKxHX7TaoL+3gQVo/WeuAiogr07DpnfjIMpXXa+PAIvwPGQ==", + "p-locate": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", + "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", "dev": true, "requires": { - "picomatch": "^2.0.4" + "p-limit": "^3.0.2" } }, - "require-main-filename": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz", - "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==", + "path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", "dev": true }, "string-width": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", - "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", "dev": true, "requires": { - "emoji-regex": "^7.0.1", - "is-fullwidth-code-point": "^2.0.0", - "strip-ansi": "^5.1.0" + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" } }, "strip-ansi": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", - "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", "dev": true, "requires": { - "ansi-regex": "^4.1.0" + "ansi-regex": "^5.0.1" } }, + "strip-json-comments": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", + "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", + "dev": true + }, "supports-color": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.0.0.tgz", - "integrity": "sha512-on9Kwidc1IUQo+bQdhi8+Tijpo0e1SS6RoGo2guUwn5vdaxw8RXOF9Vb2ws+ihWOmh4JnCJOvaziZWP1VABaLg==", + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", + "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", "dev": true, "requires": { - "has-flag": "^3.0.0" + "has-flag": "^4.0.0" } }, - "which-module": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz", - "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=", - "dev": true + "which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, + "requires": { + "isexe": "^2.0.0" + } }, "wrap-ansi": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-5.1.0.tgz", - "integrity": "sha512-QC1/iN/2/RPVJ5jYK8BGttj5z83LmSKmvbvrXPNCLZSEb32KKVDJDl/MOt2N01qU2H/FkzEa9PKto1BqDjtd7Q==", + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", "dev": true, "requires": { - "ansi-styles": "^3.2.0", - "string-width": "^3.0.0", - "strip-ansi": "^5.0.0" + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" } }, "y18n": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.3.tgz", - "integrity": "sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ==", + "version": "5.0.8", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", + "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", "dev": true }, "yargs": { - "version": "13.3.2", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-13.3.2.tgz", - "integrity": "sha512-AX3Zw5iPruN5ie6xGRIDgqkT+ZhnRlZMLMHAs8tg7nRruy2Nb+i5o9bwghAogtM08q1dpr2LVoS8KSTMYpWXUw==", + "version": "16.2.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz", + "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==", "dev": true, "requires": { - "cliui": "^5.0.0", - "find-up": "^3.0.0", - "get-caller-file": "^2.0.1", + "cliui": "^7.0.2", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", "require-directory": "^2.1.1", - "require-main-filename": "^2.0.0", - "set-blocking": "^2.0.0", - "string-width": "^3.0.0", - "which-module": "^2.0.0", - "y18n": "^4.0.0", - "yargs-parser": "^13.1.2" + "string-width": "^4.2.0", + "y18n": "^5.0.5", + "yargs-parser": "^20.2.2" } }, "yargs-parser": { - "version": "13.1.2", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-13.1.2.tgz", - "integrity": "sha512-3lbsNRf/j+A4QuSZfDRA7HRSfWrzO0YjqTJd5kjAq37Zep1CEgaYmrH9Q3GwPiB9cHyd1Y1UwggGhJGoxipbzg==", - "dev": true, - "requires": { - "camelcase": "^5.0.0", - "decamelize": "^1.2.0" - } + "version": "20.2.4", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.4.tgz", + "integrity": "sha512-WOkpgNhPTlE73h4VFAFsOnomJVaovO8VqLDzy5saChRBFQFBoMYirowyW+Q9HB4HFF4Z7VZTiG3iSzJJA29yRA==", + "dev": true } } }, @@ -54653,9 +54528,9 @@ "dev": true }, "nanoid": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.2.0.tgz", - "integrity": "sha512-fmsZYa9lpn69Ad5eDn7FMcnnSR+8R34W9qJEijxYhTbfOWzr22n1QxCMzXLK+ODyW2973V3Fux959iQoUxzUIA==", + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.1.tgz", + "integrity": "sha512-n6Vs/3KGyxPQd6uO0eH4Bv0ojGSUvuLlIHtC3Y0kEO23YRge8H9x1GCzLn28YX0H66pMkxuaeESFq4tKISKwdw==", "dev": true }, "nanomatch": { @@ -60181,176 +60056,34 @@ } }, "yargs-unparser": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/yargs-unparser/-/yargs-unparser-1.6.0.tgz", - "integrity": "sha512-W9tKgmSn0DpSatfri0nx52Joq5hVXgeLiqR/5G0sZNDoLZFOr/xjBUDcShCOGNsBnEMNo1KAMBkTej1Hm62HTw==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/yargs-unparser/-/yargs-unparser-2.0.0.tgz", + "integrity": "sha512-7pRTIA9Qc1caZ0bZ6RYRGbHJthJWuakf+WmHK0rVeLkNrrGhfoabBNdue6kdINI6r4if7ocq9aD/n7xwKOdzOA==", "dev": true, "requires": { - "flat": "^4.1.0", - "lodash": "^4.17.15", - "yargs": "^13.3.0" + "camelcase": "^6.0.0", + "decamelize": "^4.0.0", + "flat": "^5.0.2", + "is-plain-obj": "^2.1.0" }, "dependencies": { - "ansi-regex": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", - "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", - "dev": true - }, "camelcase": { - "version": "5.3.1", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", - "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", - "dev": true - }, - "cliui": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-5.0.0.tgz", - "integrity": "sha512-PYeGSEmmHM6zvoef2w8TPzlrnNpXIjTipYK780YswmIP9vjxmd6Y2a3CB2Ks6/AU8NHjZugXvo8w3oWM2qnwXA==", - "dev": true, - "requires": { - "string-width": "^3.1.0", - "strip-ansi": "^5.2.0", - "wrap-ansi": "^5.1.0" - } - }, - "find-up": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", - "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", - "dev": true, - "requires": { - "locate-path": "^3.0.0" - } - }, - "get-caller-file": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", - "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", - "dev": true - }, - "is-fullwidth-code-point": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", - "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", - "dev": true - }, - "locate-path": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", - "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", - "dev": true, - "requires": { - "p-locate": "^3.0.0", - "path-exists": "^3.0.0" - } - }, - "p-limit": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", - "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", - "dev": true, - "requires": { - "p-try": "^2.0.0" - } - }, - "p-locate": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", - "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", - "dev": true, - "requires": { - "p-limit": "^2.0.0" - } - }, - "p-try": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", - "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", - "dev": true - }, - "path-exists": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", - "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=", - "dev": true - }, - "require-main-filename": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz", - "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==", + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", + "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", "dev": true }, - "string-width": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", - "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", - "dev": true, - "requires": { - "emoji-regex": "^7.0.1", - "is-fullwidth-code-point": "^2.0.0", - "strip-ansi": "^5.1.0" - } - }, - "strip-ansi": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", - "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", - "dev": true, - "requires": { - "ansi-regex": "^4.1.0" - } - }, - "which-module": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz", - "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=", + "decamelize": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-4.0.0.tgz", + "integrity": "sha512-9iE1PgSik9HeIIw2JO94IidnE3eBoQrFJ3w7sFuzSX4DpmZ3v5sZpUiV5Swcf6mQEF+Y0ru8Neo+p+nyh2J+hQ==", "dev": true }, - "wrap-ansi": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-5.1.0.tgz", - "integrity": "sha512-QC1/iN/2/RPVJ5jYK8BGttj5z83LmSKmvbvrXPNCLZSEb32KKVDJDl/MOt2N01qU2H/FkzEa9PKto1BqDjtd7Q==", - "dev": true, - "requires": { - "ansi-styles": "^3.2.0", - "string-width": "^3.0.0", - "strip-ansi": "^5.0.0" - } - }, - "y18n": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.3.tgz", - "integrity": "sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ==", + "is-plain-obj": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-2.1.0.tgz", + "integrity": "sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA==", "dev": true - }, - "yargs": { - "version": "13.3.2", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-13.3.2.tgz", - "integrity": "sha512-AX3Zw5iPruN5ie6xGRIDgqkT+ZhnRlZMLMHAs8tg7nRruy2Nb+i5o9bwghAogtM08q1dpr2LVoS8KSTMYpWXUw==", - "dev": true, - "requires": { - "cliui": "^5.0.0", - "find-up": "^3.0.0", - "get-caller-file": "^2.0.1", - "require-directory": "^2.1.1", - "require-main-filename": "^2.0.0", - "set-blocking": "^2.0.0", - "string-width": "^3.0.0", - "which-module": "^2.0.0", - "y18n": "^4.0.0", - "yargs-parser": "^13.1.2" - } - }, - "yargs-parser": { - "version": "13.1.2", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-13.1.2.tgz", - "integrity": "sha512-3lbsNRf/j+A4QuSZfDRA7HRSfWrzO0YjqTJd5kjAq37Zep1CEgaYmrH9Q3GwPiB9cHyd1Y1UwggGhJGoxipbzg==", - "dev": true, - "requires": { - "camelcase": "^5.0.0", - "decamelize": "^1.2.0" - } } } }, diff --git a/package.json b/package.json index 24995e0c9..1baaf6f3b 100644 --- a/package.json +++ b/package.json @@ -78,6 +78,7 @@ "hardhat-spdx-license-identifier": "^2.0.3", "husky": "^6.0.0", "lint-staged": "^11.0.0", + "mocha": "^9.2.1", "prettier": "^2.3.0", "prettier-plugin-solidity": "^1.0.0-beta.11", "shelljs": "^0.8.4", From f3890b0152463083b76d0a1c012d7f61cfb79bce Mon Sep 17 00:00:00 2001 From: Trajan0x Date: Mon, 11 Apr 2022 17:57:47 -0400 Subject: [PATCH 030/135] ignore oz config --- .gitignore | 3 +- .openzeppelin/unknown-31337.json | 243 ------------------------------- 2 files changed, 2 insertions(+), 244 deletions(-) delete mode 100644 .openzeppelin/unknown-31337.json diff --git a/.gitignore b/.gitignore index ac3334077..c4c158680 100644 --- a/.gitignore +++ b/.gitignore @@ -54,4 +54,5 @@ build tenderly.yaml .env -doc/ \ No newline at end of file +doc/ +.openzeppelin \ No newline at end of file diff --git a/.openzeppelin/unknown-31337.json b/.openzeppelin/unknown-31337.json deleted file mode 100644 index e9a303e78..000000000 --- a/.openzeppelin/unknown-31337.json +++ /dev/null @@ -1,243 +0,0 @@ -{ - "manifestVersion": "3.2", - "admin": { - "address": "0x7B3C1f09088Bdc9f136178E170aC668C8Ed095f2" - }, - "proxies": [ - { - "address": "0x2796317b0fF8538F253012862c06787Adfb8cEb6", - "kind": "transparent" - } - ], - "impls": { - "27ad20b2a62f59f274af0ae95636dfd39a718653858e63b6dd3003dbb5bd03bb": { - "address": "0x31fe393815822edacBd81C2262467402199EFD0D", - "layout": { - "storage": [ - { - "label": "_initialized", - "offset": 0, - "slot": "0", - "type": "t_bool", - "contract": "Initializable", - "src": "@openzeppelin/contracts-upgradeable/proxy/Initializable.sol:25" - }, - { - "label": "_initializing", - "offset": 1, - "slot": "0", - "type": "t_bool", - "contract": "Initializable", - "src": "@openzeppelin/contracts-upgradeable/proxy/Initializable.sol:30" - }, - { - "label": "__gap", - "offset": 0, - "slot": "1", - "type": "t_array(t_uint256)50_storage", - "contract": "ContextUpgradeable", - "src": "@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol:31" - }, - { - "label": "_roles", - "offset": 0, - "slot": "51", - "type": "t_mapping(t_bytes32,t_struct(RoleData)39_storage)", - "contract": "AccessControlUpgradeable", - "src": "@openzeppelin/contracts-upgradeable/access/AccessControlUpgradeable.sol:61" - }, - { - "label": "__gap", - "offset": 0, - "slot": "52", - "type": "t_array(t_uint256)49_storage", - "contract": "AccessControlUpgradeable", - "src": "@openzeppelin/contracts-upgradeable/access/AccessControlUpgradeable.sol:225" - }, - { - "label": "_status", - "offset": 0, - "slot": "101", - "type": "t_uint256", - "contract": "ReentrancyGuardUpgradeable", - "src": "@openzeppelin/contracts-upgradeable/utils/ReentrancyGuardUpgradeable.sol:37" - }, - { - "label": "__gap", - "offset": 0, - "slot": "102", - "type": "t_array(t_uint256)49_storage", - "contract": "ReentrancyGuardUpgradeable", - "src": "@openzeppelin/contracts-upgradeable/utils/ReentrancyGuardUpgradeable.sol:67" - }, - { - "label": "_paused", - "offset": 0, - "slot": "151", - "type": "t_bool", - "contract": "PausableUpgradeable", - "src": "@openzeppelin/contracts-upgradeable/utils/PausableUpgradeable.sol:28" - }, - { - "label": "__gap", - "offset": 0, - "slot": "152", - "type": "t_array(t_uint256)49_storage", - "contract": "PausableUpgradeable", - "src": "@openzeppelin/contracts-upgradeable/utils/PausableUpgradeable.sol:96" - }, - { - "label": "fees", - "offset": 0, - "slot": "201", - "type": "t_mapping(t_address,t_uint256)", - "contract": "SynapseBridge", - "src": "contracts/bridge/SynapseBridge.sol:62" - }, - { - "label": "startBlockNumber", - "offset": 0, - "slot": "202", - "type": "t_uint256", - "contract": "SynapseBridge", - "src": "contracts/bridge/SynapseBridge.sol:64" - }, - { - "label": "chainGasAmount", - "offset": 0, - "slot": "203", - "type": "t_uint256", - "contract": "SynapseBridge", - "src": "contracts/bridge/SynapseBridge.sol:66" - }, - { - "label": "WETH_ADDRESS", - "offset": 0, - "slot": "204", - "type": "t_address_payable", - "contract": "SynapseBridge", - "src": "contracts/bridge/SynapseBridge.sol:67" - }, - { - "label": "rateLimiter", - "offset": 0, - "slot": "205", - "type": "t_contract(IRateLimiter)21229", - "contract": "SynapseBridge", - "src": "contracts/bridge/SynapseBridge.sol:68" - }, - { - "label": "kappaMap", - "offset": 0, - "slot": "206", - "type": "t_mapping(t_bytes32,t_bool)", - "contract": "SynapseBridge", - "src": "contracts/bridge/SynapseBridge.sol:70" - } - ], - "types": { - "t_address": { - "label": "address", - "numberOfBytes": "20" - }, - "t_address_payable": { - "label": "address payable", - "numberOfBytes": "20" - }, - "t_array(t_bytes32)dyn_storage": { - "label": "bytes32[]", - "numberOfBytes": "32" - }, - "t_array(t_uint256)49_storage": { - "label": "uint256[49]", - "numberOfBytes": "1568" - }, - "t_array(t_uint256)50_storage": { - "label": "uint256[50]", - "numberOfBytes": "1600" - }, - "t_bool": { - "label": "bool", - "numberOfBytes": "1" - }, - "t_bytes32": { - "label": "bytes32", - "numberOfBytes": "32" - }, - "t_contract(IRateLimiter)21229": { - "label": "contract IRateLimiter", - "numberOfBytes": "20" - }, - "t_mapping(t_address,t_uint256)": { - "label": "mapping(address => uint256)", - "numberOfBytes": "32" - }, - "t_mapping(t_bytes32,t_bool)": { - "label": "mapping(bytes32 => bool)", - "numberOfBytes": "32" - }, - "t_mapping(t_bytes32,t_struct(RoleData)39_storage)": { - "label": "mapping(bytes32 => struct AccessControlUpgradeable.RoleData)", - "numberOfBytes": "32" - }, - "t_mapping(t_bytes32,t_uint256)": { - "label": "mapping(bytes32 => uint256)", - "numberOfBytes": "32" - }, - "t_struct(AddressSet)2652_storage": { - "label": "struct EnumerableSetUpgradeable.AddressSet", - "members": [ - { - "label": "_inner", - "type": "t_struct(Set)2387_storage", - "offset": 0, - "slot": "0" - } - ], - "numberOfBytes": "64" - }, - "t_struct(RoleData)39_storage": { - "label": "struct AccessControlUpgradeable.RoleData", - "members": [ - { - "label": "members", - "type": "t_struct(AddressSet)2652_storage", - "offset": 0, - "slot": "0" - }, - { - "label": "adminRole", - "type": "t_bytes32", - "offset": 0, - "slot": "2" - } - ], - "numberOfBytes": "96" - }, - "t_struct(Set)2387_storage": { - "label": "struct EnumerableSetUpgradeable.Set", - "members": [ - { - "label": "_values", - "type": "t_array(t_bytes32)dyn_storage", - "offset": 0, - "slot": "0" - }, - { - "label": "_indexes", - "type": "t_mapping(t_bytes32,t_uint256)", - "offset": 0, - "slot": "1" - } - ], - "numberOfBytes": "64" - }, - "t_uint256": { - "label": "uint256", - "numberOfBytes": "32" - } - } - } - } - } -} From 184d76782b72c9ea27171d509cb47d6244630b1d Mon Sep 17 00:00:00 2001 From: trajan0x <83933037+trajan0x@users.noreply.github.com> Date: Mon, 11 Apr 2022 18:04:37 -0400 Subject: [PATCH 031/135] Update SynapseBridgeETH.ts --- test/bridge/SynapseBridgeETH.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/bridge/SynapseBridgeETH.ts b/test/bridge/SynapseBridgeETH.ts index ae782678f..83816f764 100644 --- a/test/bridge/SynapseBridgeETH.ts +++ b/test/bridge/SynapseBridgeETH.ts @@ -93,7 +93,7 @@ describe("SynapseBridgeETH", async () => { ).to.be.not.reverted } - it.only("Withdraw: should add to retry queue if rate limit hit", async () => { + it("Withdraw: should add to retry queue if rate limit hit", async () => { const mintAmount = 50 await expect(USDC.mint(bridge.address, mintAmount * decimals)) @@ -111,7 +111,7 @@ describe("SynapseBridgeETH", async () => { expect(await USDC.balanceOf(bridge.address)).to.be.eq( (mintAmount * decimals).toString(), ) - console.log(kappa) + // now retry. This should bypass the rate limiter await expect(rateLimiter.retryByKappa(kappa)).to.be.not.reverted From b1228b75790a3cd91f638a82ffa492863c3e57f0 Mon Sep 17 00:00:00 2001 From: Trajan0x Date: Mon, 11 Apr 2022 21:33:32 -0400 Subject: [PATCH 032/135] allowance correction --- test/bridge/RateLimiter.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/bridge/RateLimiter.ts b/test/bridge/RateLimiter.ts index 4ee8fa90e..7c14c57a4 100644 --- a/test/bridge/RateLimiter.ts +++ b/test/bridge/RateLimiter.ts @@ -70,7 +70,7 @@ describe("Rate Limiter", () => { }) describe("set allowance test", () => { - it("should set alowance correctly", async () => { + it("should set allowance correctly", async () => { const allowance = 100 * Math.pow(10, 6) // allowance of $100 const lastReset = Math.floor(epochSeconds() / hour) From 7d9f7a96f0a1c4ac76f8221cee4afcf74b9dfb10 Mon Sep 17 00:00:00 2001 From: Trajan0x Date: Mon, 11 Apr 2022 21:41:06 -0400 Subject: [PATCH 033/135] error --- test/bridge/RateLimiter.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/bridge/RateLimiter.ts b/test/bridge/RateLimiter.ts index 7c14c57a4..0b7905ebf 100644 --- a/test/bridge/RateLimiter.ts +++ b/test/bridge/RateLimiter.ts @@ -10,7 +10,7 @@ import epochSeconds from "@stdlib/time-now" chai.use(solidity) const { expect, assert } = chai -describe("Rate Limiter", () => { +describe.skip("Rate Limiter", () => { let signers: Array let deployer: Signer let owner: Signer @@ -78,7 +78,7 @@ describe("Rate Limiter", () => { // 1 hour await expect( rateLimiter.setAllowance(USDC.address, allowance, 60, lastReset), - ).to.be.not.reverted + ).to.be.revertedWith("test") let [amount, spent, resetTimeMin, lastResetMin] = await rateLimiter.getTokenAllowance(USDC.address) From ea2f2effccbb6169c588763409edcef178ac6714 Mon Sep 17 00:00:00 2001 From: Trajan0x Date: Mon, 11 Apr 2022 21:41:19 -0400 Subject: [PATCH 034/135] Revert "error" This reverts commit 43510d1672494808a23b4b3a9eafcd01d25e13c1. --- test/bridge/RateLimiter.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/bridge/RateLimiter.ts b/test/bridge/RateLimiter.ts index 0b7905ebf..7c14c57a4 100644 --- a/test/bridge/RateLimiter.ts +++ b/test/bridge/RateLimiter.ts @@ -10,7 +10,7 @@ import epochSeconds from "@stdlib/time-now" chai.use(solidity) const { expect, assert } = chai -describe.skip("Rate Limiter", () => { +describe("Rate Limiter", () => { let signers: Array let deployer: Signer let owner: Signer @@ -78,7 +78,7 @@ describe.skip("Rate Limiter", () => { // 1 hour await expect( rateLimiter.setAllowance(USDC.address, allowance, 60, lastReset), - ).to.be.revertedWith("test") + ).to.be.not.reverted let [amount, spent, resetTimeMin, lastResetMin] = await rateLimiter.getTokenAllowance(USDC.address) From b46482f4be5b61800132e35d277b1942adca4ff3 Mon Sep 17 00:00:00 2001 From: Trajan0x Date: Mon, 11 Apr 2022 21:50:13 -0400 Subject: [PATCH 035/135] get revert reason --- test/bridge/RateLimiter.ts | 2 +- test/bridge/SynapseBridgeETH.ts | 1 - test/bridge/upgrade.json | 1 + 3 files changed, 2 insertions(+), 2 deletions(-) diff --git a/test/bridge/RateLimiter.ts b/test/bridge/RateLimiter.ts index 7c14c57a4..982a2c5d6 100644 --- a/test/bridge/RateLimiter.ts +++ b/test/bridge/RateLimiter.ts @@ -78,7 +78,7 @@ describe("Rate Limiter", () => { // 1 hour await expect( rateLimiter.setAllowance(USDC.address, allowance, 60, lastReset), - ).to.be.not.reverted + ).to.be.revertedWith("test") let [amount, spent, resetTimeMin, lastResetMin] = await rateLimiter.getTokenAllowance(USDC.address) diff --git a/test/bridge/SynapseBridgeETH.ts b/test/bridge/SynapseBridgeETH.ts index 83816f764..c1f122738 100644 --- a/test/bridge/SynapseBridgeETH.ts +++ b/test/bridge/SynapseBridgeETH.ts @@ -112,7 +112,6 @@ describe("SynapseBridgeETH", async () => { (mintAmount * decimals).toString(), ) - // now retry. This should bypass the rate limiter await expect(rateLimiter.retryByKappa(kappa)).to.be.not.reverted expect(await bridge.kappaExists(kappa)).to.be.true diff --git a/test/bridge/upgrade.json b/test/bridge/upgrade.json index 2bb708695..ee6392396 100644 --- a/test/bridge/upgrade.json +++ b/test/bridge/upgrade.json @@ -2,6 +2,7 @@ "1": { "bridge_artifact": "SynapseBridge", "bridge_address": "0x2796317b0fF8538F253012862c06787Adfb8cEb6", + "rpcKey": "ALCHEMY_API", "kappas": [ "0x58b29a4cf220b60a7e46b76b9831686c0bfbdbfea19721ef8f2192ba28514485", "0x3745754e018ed57dce0feda8b027f04b7e1369e7f74f1a247f5f7352d519021c", From ff1bfd824355e51051f0322ba3901ca3bf6ce47b Mon Sep 17 00:00:00 2001 From: Trajan0x Date: Mon, 11 Apr 2022 22:39:14 -0400 Subject: [PATCH 036/135] upgradeable --- package-lock.json | 15 ++- package.json | 3 +- test/bridge/RateLimiter.ts | 2 +- test/bridge/Upgradeable.ts | 92 +++++++++++++++++++ .../{upgrade.json => upgrade_config.json} | 3 +- 5 files changed, 111 insertions(+), 4 deletions(-) create mode 100644 test/bridge/Upgradeable.ts rename test/bridge/{upgrade.json => upgrade_config.json} (92%) diff --git a/package-lock.json b/package-lock.json index a1c5f6da7..3f377c1d9 100644 --- a/package-lock.json +++ b/package-lock.json @@ -73,7 +73,8 @@ "ts-generator": "^0.1.1", "ts-node": "^10.0.0", "typechain": "^5.1.2", - "typescript": "^4.3.2" + "typescript": "^4.3.2", + "typescript-string-operations": "^1.4.1" } }, "node_modules/@babel/code-frame": { @@ -30948,6 +30949,12 @@ "node": ">=4.2.0" } }, + "node_modules/typescript-string-operations": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/typescript-string-operations/-/typescript-string-operations-1.4.1.tgz", + "integrity": "sha512-c+q+Tb0hxeebohdT9KpGUAm5zwxhU8pHeNOeuLCGFMXKN0OrldoAxtufrGLR3xSPCXDA4A3IBCEdRNNscVqLQg==", + "dev": true + }, "node_modules/typical": { "version": "2.6.1", "resolved": "https://registry.npmjs.org/typical/-/typical-2.6.1.tgz", @@ -58768,6 +58775,12 @@ "integrity": "sha512-zZ4hShnmnoVnAHpVHWpTcxdv7dWP60S2FsydQLV8V5PbS3FifjWFFRiHSWpDJahly88PRyV5teTSLoq4eG7mKw==", "dev": true }, + "typescript-string-operations": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/typescript-string-operations/-/typescript-string-operations-1.4.1.tgz", + "integrity": "sha512-c+q+Tb0hxeebohdT9KpGUAm5zwxhU8pHeNOeuLCGFMXKN0OrldoAxtufrGLR3xSPCXDA4A3IBCEdRNNscVqLQg==", + "dev": true + }, "typical": { "version": "2.6.1", "resolved": "https://registry.npmjs.org/typical/-/typical-2.6.1.tgz", diff --git a/package.json b/package.json index 1baaf6f3b..297b92b1f 100644 --- a/package.json +++ b/package.json @@ -91,6 +91,7 @@ "ts-generator": "^0.1.1", "ts-node": "^10.0.0", "typechain": "^5.1.2", - "typescript": "^4.3.2" + "typescript": "^4.3.2", + "typescript-string-operations": "^1.4.1" } } diff --git a/test/bridge/RateLimiter.ts b/test/bridge/RateLimiter.ts index 982a2c5d6..7c14c57a4 100644 --- a/test/bridge/RateLimiter.ts +++ b/test/bridge/RateLimiter.ts @@ -78,7 +78,7 @@ describe("Rate Limiter", () => { // 1 hour await expect( rateLimiter.setAllowance(USDC.address, allowance, 60, lastReset), - ).to.be.revertedWith("test") + ).to.be.not.reverted let [amount, spent, resetTimeMin, lastResetMin] = await rateLimiter.getTokenAllowance(USDC.address) diff --git a/test/bridge/Upgradeable.ts b/test/bridge/Upgradeable.ts new file mode 100644 index 000000000..820dccf4e --- /dev/null +++ b/test/bridge/Upgradeable.ts @@ -0,0 +1,92 @@ +import { Signer } from "ethers" +import { getCurrentBlockTimestamp } from "./testUtils" +import { String } from "typescript-string-operations" +import { solidity } from "ethereum-waffle" +import { deployments, ethers } from "hardhat" + +import chai from "chai" +import { GenericERC20, RateLimiter, SynapseBridge } from "../../build/typechain" +import epochSeconds from "@stdlib/time-now" +import { id, keccak256 } from "ethers/lib/utils" +import { randomBytes } from "crypto" +import { forkChain } from "../utils" +import { deployRateLimiter, setupForkedBridge } from "./utilities/bridge" +import sinon from "sinon" +import upgrade from "./upgrade_config.json" + +chai.use(solidity) +const { expect } = chai + +const chains = Object.keys(upgrade) + +type BridgeOptions = { + bridge_artifact: string + bridge_address: string + rpcKey: string + kappas: Array + block_number: number +} + +describe.only("Upgradeable", async () => { + // signers + let signers: Array + let deployer: Signer + let owner: Signer + let limiter: Signer + let nodeGroup: Signer + let recipient: Signer + + // contracts + let bridge: SynapseBridge + let rateLimiter: RateLimiter + let bridgeOptions: BridgeOptions + + // use a stub to return the proper configuration in `beforeEach` + // otherwise `before` is called all times before all `it` calls + let stub = sinon.stub() + chains.forEach(function (run, idx) { + stub.onCall(idx).returns(run) + }) + + const setupTest = deployments.createFixture( + async ({ deployments, ethers }) => { + await deployments.fixture() + + signers = await ethers.getSigners() + + // assign roles + deployer = signers[0] + owner = signers[1] + limiter = signers[2] + nodeGroup = signers[3] + recipient = signers[4] + + rateLimiter = await deployRateLimiter(deployer, owner) + bridge = await setupForkedBridge( + rateLimiter, + bridgeOptions.bridge_address, + deployer, + nodeGroup, + ) + }, + ) + + beforeEach(async () => { + const run = stub() + bridgeOptions = upgrade[run] + // fork the chain + await forkChain( + process.env[bridgeOptions.rpcKey], + bridgeOptions.block_number, + ) + await setupTest() + }) + + chains.forEach(function (run, idx) { + it(String.Format("Chain {0}: check kappas", run), async () => { + for (const kappa of bridgeOptions.kappas) { + expect(await bridge.kappaExists(kappa)).to.be.true + } + }) + }) +}) diff --git a/test/bridge/upgrade.json b/test/bridge/upgrade_config.json similarity index 92% rename from test/bridge/upgrade.json rename to test/bridge/upgrade_config.json index ee6392396..6011e50cb 100644 --- a/test/bridge/upgrade.json +++ b/test/bridge/upgrade_config.json @@ -8,6 +8,7 @@ "0x3745754e018ed57dce0feda8b027f04b7e1369e7f74f1a247f5f7352d519021c", "0xea5bc18a60d2f1b9ba5e5f8bfef3cd112c3b1a1ef74a0de8e5989441b1722524", "0x1d4f3f6ed7690f1e5c1ff733d2040daa12fa484b3acbf37122ff334b46cf8b6d" - ] + ], + "block_number": 14555470 } } \ No newline at end of file From f1dda43152f03fee1ab329d508761e3675c06c28 Mon Sep 17 00:00:00 2001 From: Trajan0x Date: Mon, 11 Apr 2022 22:46:11 -0400 Subject: [PATCH 037/135] rate limit --- test/bridge/RateLimiter.ts | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/test/bridge/RateLimiter.ts b/test/bridge/RateLimiter.ts index 7c14c57a4..74a4564da 100644 --- a/test/bridge/RateLimiter.ts +++ b/test/bridge/RateLimiter.ts @@ -2,7 +2,7 @@ import chai from "chai" import { solidity } from "ethereum-waffle" import { deployments, ethers } from "hardhat" import { BigNumber, BigNumberish, Signer } from "ethers" - +import { getCurrentBlockTimestamp } from "./testUtils" import { RateLimiter } from "../../build/typechain/RateLimiter" import { GenericERC20, RateLimiterTest } from "../../build/typechain" import epochSeconds from "@stdlib/time-now" @@ -73,7 +73,7 @@ describe("Rate Limiter", () => { it("should set allowance correctly", async () => { const allowance = 100 * Math.pow(10, 6) // allowance of $100 - const lastReset = Math.floor(epochSeconds() / hour) + const lastReset = Math.floor((await getCurrentBlockTimestamp()) / 60) // 1 hour await expect( @@ -90,7 +90,7 @@ describe("Rate Limiter", () => { it("should update allowance", async () => { const allowance = 100 * Math.pow(10, 6) // allowance of $100 - const lastReset = Math.floor(epochSeconds() / hour) + const lastReset = Math.floor((await getCurrentBlockTimestamp()) / 60) // reset every hour after current epoch time to an allowance of $100 expect(rateLimiter.setAllowance(USDC.address, allowance, hour, lastReset)) @@ -116,7 +116,7 @@ describe("Rate Limiter", () => { it("should return false if newSpent > allowance amount", async () => { const allowance = 1000 * Math.pow(10, 6) // allowance of $100 - const lastReset = Math.floor(epochSeconds() / hour) + const lastReset = Math.floor((await getCurrentBlockTimestamp()) / 60) // reset every hour after current epoch time to an allowance of $100 expect(rateLimiter.setAllowance(USDC.address, allowance, hour, lastReset)) @@ -141,7 +141,7 @@ describe("Rate Limiter", () => { it("should reset allowance", async () => { const allowance = 100 * Math.pow(10, 6) // allowance of $100 - const lastReset = Math.floor(epochSeconds() / hour) + const lastReset = Math.floor((await getCurrentBlockTimestamp()) / 60) // reset every hour after current epoch time to an allowance of $100 expect(rateLimiter.setAllowance(USDC.address, allowance, hour, lastReset)) From f66f596f6d90a41e942e5b1be6f928168087cb02 Mon Sep 17 00:00:00 2001 From: Trajan0x Date: Mon, 11 Apr 2022 22:53:00 -0400 Subject: [PATCH 038/135] upgrade test --- test/bridge/Upgradeable.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/bridge/Upgradeable.ts b/test/bridge/Upgradeable.ts index 820dccf4e..d936072f1 100644 --- a/test/bridge/Upgradeable.ts +++ b/test/bridge/Upgradeable.ts @@ -27,7 +27,7 @@ type BridgeOptions = { block_number: number } -describe.only("Upgradeable", async () => { +describe("Upgradeable", async () => { // signers let signers: Array let deployer: Signer From 4aad5bc41cae6a3196a3e92040c6b7b4782116ee Mon Sep 17 00:00:00 2001 From: ChiTimesChi <88190723+ChiTimesChi@users.noreply.github.com> Date: Tue, 12 Apr 2022 17:29:50 +0300 Subject: [PATCH 039/135] no more amount checks in swap/remove --- contracts/bridge/HarmonySynapseBridge.sol | 163 +++++++------------ contracts/bridge/MoonriverSynapseBridge.sol | 163 +++++++------------ contracts/bridge/SynapseBridge.sol | 164 +++++++------------- 3 files changed, 180 insertions(+), 310 deletions(-) diff --git a/contracts/bridge/HarmonySynapseBridge.sol b/contracts/bridge/HarmonySynapseBridge.sol index c124c7222..cb957a327 100644 --- a/contracts/bridge/HarmonySynapseBridge.sol +++ b/contracts/bridge/HarmonySynapseBridge.sol @@ -465,79 +465,56 @@ contract HarmonySynapseBridge is if (chainGasAmount != 0 && address(this).balance > chainGasAmount) { to.call.value(chainGasAmount)(""); } - // first check to make sure more will be given than min amount required - uint256 expectedOutput = ISwap(pool).calculateSwap( - tokenIndexFrom, - tokenIndexTo, - amount.sub(fee) - ); - if (expectedOutput >= minDy) { - // proceed with swap - token.mint(address(this), amount); - token.safeIncreaseAllowance(address(pool), amount); - try - ISwap(pool).swap( + // proceed with swap + token.mint(address(this), amount); + token.safeIncreaseAllowance(address(pool), amount.sub(fee)); + try + ISwap(pool).swap( + tokenIndexFrom, + tokenIndexTo, + amount.sub(fee), + minDy, + deadline + ) + returns (uint256 finalSwappedAmount) { + // Swap succeeded, transfer swapped asset + IERC20 swappedTokenTo = ISwap(pool).getToken(tokenIndexTo); + if ( + address(swappedTokenTo) == WETH_ADDRESS && + WETH_ADDRESS != address(0) + ) { + IWETH9(WETH_ADDRESS).withdraw(finalSwappedAmount); + (bool success, ) = to.call{value: finalSwappedAmount}(""); + require(success, "ETH_TRANSFER_FAILED"); + emit TokenMintAndSwap( + to, + token, + finalSwappedAmount, + fee, tokenIndexFrom, tokenIndexTo, - amount.sub(fee), minDy, - deadline - ) - returns (uint256 finalSwappedAmount) { - // Swap succeeded, transfer swapped asset - IERC20 swappedTokenTo = ISwap(pool).getToken(tokenIndexTo); - if ( - address(swappedTokenTo) == WETH_ADDRESS && - WETH_ADDRESS != address(0) - ) { - IWETH9(WETH_ADDRESS).withdraw(finalSwappedAmount); - (bool success, ) = to.call{value: finalSwappedAmount}(""); - require(success, "ETH_TRANSFER_FAILED"); - emit TokenMintAndSwap( - to, - token, - finalSwappedAmount, - fee, - tokenIndexFrom, - tokenIndexTo, - minDy, - deadline, - true, - kappa - ); - } else { - swappedTokenTo.safeTransfer(to, finalSwappedAmount); - emit TokenMintAndSwap( - to, - token, - finalSwappedAmount, - fee, - tokenIndexFrom, - tokenIndexTo, - minDy, - deadline, - true, - kappa - ); - } - } catch { - IERC20(token).safeTransfer(to, amount.sub(fee)); + deadline, + true, + kappa + ); + } else { + swappedTokenTo.safeTransfer(to, finalSwappedAmount); emit TokenMintAndSwap( to, token, - amount.sub(fee), + finalSwappedAmount, fee, tokenIndexFrom, tokenIndexTo, minDy, deadline, - false, + true, kappa ); } - } else { - token.mint(address(this), amount); + } catch { IERC20(token).safeTransfer(to, amount.sub(fee)); emit TokenMintAndSwap( to, @@ -585,52 +562,32 @@ contract HarmonySynapseBridge is require(!kappaMap[kappa], "Kappa is already present"); kappaMap[kappa] = true; fees[address(token)] = fees[address(token)].add(fee); - // first check to make sure more will be given than min amount required - uint256 expectedOutput = ISwap(pool).calculateRemoveLiquidityOneToken( - amount.sub(fee), - swapTokenIndex - ); - if (expectedOutput >= swapMinAmount) { - token.safeIncreaseAllowance(address(pool), amount.sub(fee)); - try - ISwap(pool).removeLiquidityOneToken( - amount.sub(fee), - swapTokenIndex, - swapMinAmount, - swapDeadline - ) - returns (uint256 finalSwappedAmount) { - // Swap succeeded, transfer swapped asset - IERC20 swappedTokenTo = ISwap(pool).getToken(swapTokenIndex); - swappedTokenTo.safeTransfer(to, finalSwappedAmount); - emit TokenWithdrawAndRemove( - to, - token, - finalSwappedAmount, - fee, - swapTokenIndex, - swapMinAmount, - swapDeadline, - true, - kappa - ); - } catch { - IERC20(token).safeTransfer(to, amount.sub(fee)); - emit TokenWithdrawAndRemove( - to, - token, - amount.sub(fee), - fee, - swapTokenIndex, - swapMinAmount, - swapDeadline, - false, - kappa - ); - } - } else { - token.safeTransfer(to, amount.sub(fee)); + token.safeIncreaseAllowance(address(pool), amount.sub(fee)); + try + ISwap(pool).removeLiquidityOneToken( + amount.sub(fee), + swapTokenIndex, + swapMinAmount, + swapDeadline + ) + returns (uint256 finalSwappedAmount) { + // Swap succeeded, transfer swapped asset + IERC20 swappedTokenTo = ISwap(pool).getToken(swapTokenIndex); + swappedTokenTo.safeTransfer(to, finalSwappedAmount); + emit TokenWithdrawAndRemove( + to, + token, + finalSwappedAmount, + fee, + swapTokenIndex, + swapMinAmount, + swapDeadline, + true, + kappa + ); + } catch { + IERC20(token).safeTransfer(to, amount.sub(fee)); emit TokenWithdrawAndRemove( to, token, diff --git a/contracts/bridge/MoonriverSynapseBridge.sol b/contracts/bridge/MoonriverSynapseBridge.sol index 8f7bbc722..80438c314 100644 --- a/contracts/bridge/MoonriverSynapseBridge.sol +++ b/contracts/bridge/MoonriverSynapseBridge.sol @@ -454,79 +454,56 @@ contract MRSynapseBridge is if (chainGasAmount != 0 && address(this).balance > chainGasAmount) { to.call.value(chainGasAmount)(""); } - // first check to make sure more will be given than min amount required - uint256 expectedOutput = ISwap(pool).calculateSwap( - tokenIndexFrom, - tokenIndexTo, - amount.sub(fee) - ); - if (expectedOutput >= minDy) { - // proceed with swap - token.mint(address(this), amount); - token.safeIncreaseAllowance(address(pool), amount); - try - ISwap(pool).swap( + // proceed with swap + token.mint(address(this), amount); + token.safeIncreaseAllowance(address(pool), amount.sub(fee)); + try + ISwap(pool).swap( + tokenIndexFrom, + tokenIndexTo, + amount.sub(fee), + minDy, + deadline + ) + returns (uint256 finalSwappedAmount) { + // Swap succeeded, transfer swapped asset + IERC20 swappedTokenTo = ISwap(pool).getToken(tokenIndexTo); + if ( + address(swappedTokenTo) == WETH_ADDRESS && + WETH_ADDRESS != address(0) + ) { + IWETH9(WETH_ADDRESS).withdraw(finalSwappedAmount); + (bool success, ) = to.call{value: finalSwappedAmount}(""); + require(success, "ETH_TRANSFER_FAILED"); + emit TokenMintAndSwap( + to, + token, + finalSwappedAmount, + fee, tokenIndexFrom, tokenIndexTo, - amount.sub(fee), minDy, - deadline - ) - returns (uint256 finalSwappedAmount) { - // Swap succeeded, transfer swapped asset - IERC20 swappedTokenTo = ISwap(pool).getToken(tokenIndexTo); - if ( - address(swappedTokenTo) == WETH_ADDRESS && - WETH_ADDRESS != address(0) - ) { - IWETH9(WETH_ADDRESS).withdraw(finalSwappedAmount); - (bool success, ) = to.call{value: finalSwappedAmount}(""); - require(success, "ETH_TRANSFER_FAILED"); - emit TokenMintAndSwap( - to, - token, - finalSwappedAmount, - fee, - tokenIndexFrom, - tokenIndexTo, - minDy, - deadline, - true, - kappa - ); - } else { - swappedTokenTo.safeTransfer(to, finalSwappedAmount); - emit TokenMintAndSwap( - to, - token, - finalSwappedAmount, - fee, - tokenIndexFrom, - tokenIndexTo, - minDy, - deadline, - true, - kappa - ); - } - } catch { - IERC20(token).safeTransfer(to, amount.sub(fee)); + deadline, + true, + kappa + ); + } else { + swappedTokenTo.safeTransfer(to, finalSwappedAmount); emit TokenMintAndSwap( to, token, - amount.sub(fee), + finalSwappedAmount, fee, tokenIndexFrom, tokenIndexTo, minDy, deadline, - false, + true, kappa ); } - } else { - token.mint(address(this), amount); + } catch { IERC20(token).safeTransfer(to, amount.sub(fee)); emit TokenMintAndSwap( to, @@ -574,52 +551,32 @@ contract MRSynapseBridge is require(!kappaMap[kappa], "Kappa is already present"); kappaMap[kappa] = true; fees[address(token)] = fees[address(token)].add(fee); - // first check to make sure more will be given than min amount required - uint256 expectedOutput = ISwap(pool).calculateRemoveLiquidityOneToken( - amount.sub(fee), - swapTokenIndex - ); - if (expectedOutput >= swapMinAmount) { - token.safeIncreaseAllowance(address(pool), amount.sub(fee)); - try - ISwap(pool).removeLiquidityOneToken( - amount.sub(fee), - swapTokenIndex, - swapMinAmount, - swapDeadline - ) - returns (uint256 finalSwappedAmount) { - // Swap succeeded, transfer swapped asset - IERC20 swappedTokenTo = ISwap(pool).getToken(swapTokenIndex); - swappedTokenTo.safeTransfer(to, finalSwappedAmount); - emit TokenWithdrawAndRemove( - to, - token, - finalSwappedAmount, - fee, - swapTokenIndex, - swapMinAmount, - swapDeadline, - true, - kappa - ); - } catch { - IERC20(token).safeTransfer(to, amount.sub(fee)); - emit TokenWithdrawAndRemove( - to, - token, - amount.sub(fee), - fee, - swapTokenIndex, - swapMinAmount, - swapDeadline, - false, - kappa - ); - } - } else { - token.safeTransfer(to, amount.sub(fee)); + token.safeIncreaseAllowance(address(pool), amount.sub(fee)); + try + ISwap(pool).removeLiquidityOneToken( + amount.sub(fee), + swapTokenIndex, + swapMinAmount, + swapDeadline + ) + returns (uint256 finalSwappedAmount) { + // Swap succeeded, transfer swapped asset + IERC20 swappedTokenTo = ISwap(pool).getToken(swapTokenIndex); + swappedTokenTo.safeTransfer(to, finalSwappedAmount); + emit TokenWithdrawAndRemove( + to, + token, + finalSwappedAmount, + fee, + swapTokenIndex, + swapMinAmount, + swapDeadline, + true, + kappa + ); + } catch { + IERC20(token).safeTransfer(to, amount.sub(fee)); emit TokenWithdrawAndRemove( to, token, diff --git a/contracts/bridge/SynapseBridge.sol b/contracts/bridge/SynapseBridge.sol index 64e5d9fc0..1635c510d 100644 --- a/contracts/bridge/SynapseBridge.sol +++ b/contracts/bridge/SynapseBridge.sol @@ -673,80 +673,56 @@ contract SynapseBridge is to.call.value(chainGasAmount)(""); } - // first check to make sure more will be given than min amount required - uint256 expectedOutput = ISwap(pool).calculateSwap( - tokenIndexFrom, - tokenIndexTo, - amount.sub(fee) - ); - - if (expectedOutput >= minDy) { - // proceed with swap - token.mint(address(this), amount); - token.safeIncreaseAllowance(address(pool), amount); - try - ISwap(pool).swap( + // proceed with swap + token.mint(address(this), amount); + token.safeIncreaseAllowance(address(pool), amount.sub(fee)); + try + ISwap(pool).swap( + tokenIndexFrom, + tokenIndexTo, + amount.sub(fee), + minDy, + deadline + ) + returns (uint256 finalSwappedAmount) { + // Swap succeeded, transfer swapped asset + IERC20 swappedTokenTo = ISwap(pool).getToken(tokenIndexTo); + if ( + address(swappedTokenTo) == WETH_ADDRESS && + WETH_ADDRESS != address(0) + ) { + IWETH9(WETH_ADDRESS).withdraw(finalSwappedAmount); + (bool success, ) = to.call{value: finalSwappedAmount}(""); + require(success, "ETH_TRANSFER_FAILED"); + emit TokenMintAndSwap( + to, + token, + finalSwappedAmount, + fee, tokenIndexFrom, tokenIndexTo, - amount.sub(fee), minDy, - deadline - ) - returns (uint256 finalSwappedAmount) { - // Swap succeeded, transfer swapped asset - IERC20 swappedTokenTo = ISwap(pool).getToken(tokenIndexTo); - if ( - address(swappedTokenTo) == WETH_ADDRESS && - WETH_ADDRESS != address(0) - ) { - IWETH9(WETH_ADDRESS).withdraw(finalSwappedAmount); - (bool success, ) = to.call{value: finalSwappedAmount}(""); - require(success, "ETH_TRANSFER_FAILED"); - emit TokenMintAndSwap( - to, - token, - finalSwappedAmount, - fee, - tokenIndexFrom, - tokenIndexTo, - minDy, - deadline, - true, - kappa - ); - } else { - swappedTokenTo.safeTransfer(to, finalSwappedAmount); - emit TokenMintAndSwap( - to, - token, - finalSwappedAmount, - fee, - tokenIndexFrom, - tokenIndexTo, - minDy, - deadline, - true, - kappa - ); - } - } catch { - IERC20(token).safeTransfer(to, amount.sub(fee)); + deadline, + true, + kappa + ); + } else { + swappedTokenTo.safeTransfer(to, finalSwappedAmount); emit TokenMintAndSwap( to, token, - amount.sub(fee), + finalSwappedAmount, fee, tokenIndexFrom, tokenIndexTo, minDy, deadline, - false, + true, kappa ); } - } else { - token.mint(address(this), amount); - IERC20(token).safeTransfer(to, amount.sub(fee)); + } catch { + token.safeTransfer(to, amount.sub(fee)); emit TokenMintAndSwap( to, token, @@ -881,51 +857,31 @@ contract SynapseBridge is require(!kappaMap[kappa], "Kappa is already present"); kappaMap[kappa] = true; fees[address(token)] = fees[address(token)].add(fee); - // first check to make sure more will be given than min amount required - uint256 expectedOutput = ISwap(pool).calculateRemoveLiquidityOneToken( - amount.sub(fee), - swapTokenIndex - ); - if (expectedOutput >= swapMinAmount) { - token.safeIncreaseAllowance(address(pool), amount.sub(fee)); - try - ISwap(pool).removeLiquidityOneToken( - amount.sub(fee), - swapTokenIndex, - swapMinAmount, - swapDeadline - ) - returns (uint256 finalSwappedAmount) { - // Swap succeeded, transfer swapped asset - IERC20 swappedTokenTo = ISwap(pool).getToken(swapTokenIndex); - swappedTokenTo.safeTransfer(to, finalSwappedAmount); - emit TokenWithdrawAndRemove( - to, - token, - finalSwappedAmount, - fee, - swapTokenIndex, - swapMinAmount, - swapDeadline, - true, - kappa - ); - } catch { - IERC20(token).safeTransfer(to, amount.sub(fee)); - emit TokenWithdrawAndRemove( - to, - token, - amount.sub(fee), - fee, - swapTokenIndex, - swapMinAmount, - swapDeadline, - false, - kappa - ); - } - } else { + token.safeIncreaseAllowance(address(pool), amount.sub(fee)); + try + ISwap(pool).removeLiquidityOneToken( + amount.sub(fee), + swapTokenIndex, + swapMinAmount, + swapDeadline + ) + returns (uint256 finalSwappedAmount) { + // Swap succeeded, transfer swapped asset + IERC20 swappedTokenTo = ISwap(pool).getToken(swapTokenIndex); + swappedTokenTo.safeTransfer(to, finalSwappedAmount); + emit TokenWithdrawAndRemove( + to, + token, + finalSwappedAmount, + fee, + swapTokenIndex, + swapMinAmount, + swapDeadline, + true, + kappa + ); + } catch { token.safeTransfer(to, amount.sub(fee)); emit TokenWithdrawAndRemove( to, From c5e0afc359b842e5fad14e9966a140b0c6e62399 Mon Sep 17 00:00:00 2001 From: ChiTimesChi <88190723+ChiTimesChi@users.noreply.github.com> Date: Tue, 12 Apr 2022 17:35:11 +0300 Subject: [PATCH 040/135] fix gas airdrop --- contracts/bridge/HarmonySynapseBridge.sol | 23 +++++++++++++++------ contracts/bridge/MoonriverSynapseBridge.sol | 23 +++++++++++++++------ contracts/bridge/SynapseBridge.sol | 22 ++++++++++++++------ 3 files changed, 50 insertions(+), 18 deletions(-) diff --git a/contracts/bridge/HarmonySynapseBridge.sol b/contracts/bridge/HarmonySynapseBridge.sol index cb957a327..e11ff6bd4 100644 --- a/contracts/bridge/HarmonySynapseBridge.sol +++ b/contracts/bridge/HarmonySynapseBridge.sol @@ -255,6 +255,10 @@ contract HarmonySynapseBridge is require(!kappaMap[kappa], "Kappa is already present"); kappaMap[kappa] = true; fees[address(token)] = fees[address(token)].add(fee); + + // withdraw can happen on chains other than mainnet + doGasAirdrop(to); + if (address(token) == WETH_ADDRESS && WETH_ADDRESS != address(0)) { IWETH9(WETH_ADDRESS).withdraw(amount.sub(fee)); (bool success, ) = to.call{value: amount.sub(fee)}(""); @@ -323,9 +327,8 @@ contract HarmonySynapseBridge is } else { IERC20(token).safeTransfer(to, amount.sub(fee)); } - if (chainGasAmount != 0 && address(this).balance > chainGasAmount) { - to.call.value(chainGasAmount)(""); - } + // Transfer gas airdrop + doGasAirdrop(to); } /** @@ -462,9 +465,7 @@ contract HarmonySynapseBridge is kappaMap[kappa] = true; fees[address(token)] = fees[address(token)].add(fee); // Transfer gas airdrop - if (chainGasAmount != 0 && address(this).balance > chainGasAmount) { - to.call.value(chainGasAmount)(""); - } + doGasAirdrop(to); // proceed with swap token.mint(address(this), amount); @@ -563,6 +564,8 @@ contract HarmonySynapseBridge is kappaMap[kappa] = true; fees[address(token)] = fees[address(token)].add(fee); + // withdrawAndRemove only on Mainnet => no airdrop + token.safeIncreaseAllowance(address(pool), amount.sub(fee)); try ISwap(pool).removeLiquidityOneToken( @@ -602,6 +605,14 @@ contract HarmonySynapseBridge is } } + // GAS AIRDROP + + function doGasAirdrop(address to) internal { + if (chainGasAmount != 0 && address(this).balance >= chainGasAmount) { + to.call{value: chainGasAmount}(""); + } + } + // BRIDGE FUNCTIONS TO HANDLE DIFF ADDRESSES /** * @notice Relays to nodes that (typically) a wrapped synAsset ERC20 token has been burned and the underlying needs to be redeeemed on the native chain diff --git a/contracts/bridge/MoonriverSynapseBridge.sol b/contracts/bridge/MoonriverSynapseBridge.sol index 80438c314..5107fd188 100644 --- a/contracts/bridge/MoonriverSynapseBridge.sol +++ b/contracts/bridge/MoonriverSynapseBridge.sol @@ -255,6 +255,10 @@ contract MRSynapseBridge is require(!kappaMap[kappa], "Kappa is already present"); kappaMap[kappa] = true; fees[address(token)] = fees[address(token)].add(fee); + + // withdraw can happen on chains other than mainnet + doGasAirdrop(to); + if (address(token) == WETH_ADDRESS && WETH_ADDRESS != address(0)) { IWETH9(WETH_ADDRESS).withdraw(amount.sub(fee)); (bool success, ) = to.call{value: amount.sub(fee)}(""); @@ -312,9 +316,8 @@ contract MRSynapseBridge is } else { IERC20(token).safeTransfer(to, amount.sub(fee)); } - if (chainGasAmount != 0 && address(this).balance > chainGasAmount) { - to.call.value(chainGasAmount)(""); - } + // Transfer gas airdrop + doGasAirdrop(to); } /** @@ -451,9 +454,7 @@ contract MRSynapseBridge is kappaMap[kappa] = true; fees[address(token)] = fees[address(token)].add(fee); // Transfer gas airdrop - if (chainGasAmount != 0 && address(this).balance > chainGasAmount) { - to.call.value(chainGasAmount)(""); - } + doGasAirdrop(to); // proceed with swap token.mint(address(this), amount); @@ -552,6 +553,8 @@ contract MRSynapseBridge is kappaMap[kappa] = true; fees[address(token)] = fees[address(token)].add(fee); + // withdrawAndRemove only on Mainnet => no airdrop + token.safeIncreaseAllowance(address(pool), amount.sub(fee)); try ISwap(pool).removeLiquidityOneToken( @@ -591,6 +594,14 @@ contract MRSynapseBridge is } } + // GAS AIRDROP + + function doGasAirdrop(address to) internal { + if (chainGasAmount != 0 && address(this).balance >= chainGasAmount) { + to.call{value: chainGasAmount}(""); + } + } + // BRIDGE FUNCTIONS TO HANDLE DIFF ADDRESSES /** * @notice Relays to nodes that (typically) a wrapped synAsset ERC20 token has been burned and the underlying needs to be redeeemed on the native chain diff --git a/contracts/bridge/SynapseBridge.sol b/contracts/bridge/SynapseBridge.sol index 1635c510d..a1fa90586 100644 --- a/contracts/bridge/SynapseBridge.sol +++ b/contracts/bridge/SynapseBridge.sol @@ -348,6 +348,10 @@ contract SynapseBridge is require(!kappaMap[kappa], "Kappa is already present"); kappaMap[kappa] = true; fees[address(token)] = fees[address(token)].add(fee); + + // withdraw can happen on chains other than mainnet + doGasAirdrop(to); + if (address(token) == WETH_ADDRESS && WETH_ADDRESS != address(0)) { IWETH9(WETH_ADDRESS).withdraw(amount.sub(fee)); (bool success, ) = to.call{value: amount.sub(fee)}(""); @@ -437,9 +441,7 @@ contract SynapseBridge is emit TokenMint(to, token, amount.sub(fee), fee, kappa); token.mint(address(this), amount); IERC20(token).safeTransfer(to, amount.sub(fee)); - if (chainGasAmount != 0 && address(this).balance > chainGasAmount) { - to.call.value(chainGasAmount)(""); - } + doGasAirdrop(to); } /** @@ -669,9 +671,7 @@ contract SynapseBridge is kappaMap[kappa] = true; fees[address(token)] = fees[address(token)].add(fee); // Transfer gas airdrop - if (chainGasAmount != 0 && address(this).balance > chainGasAmount) { - to.call.value(chainGasAmount)(""); - } + doGasAirdrop(to); // proceed with swap token.mint(address(this), amount); @@ -858,6 +858,8 @@ contract SynapseBridge is kappaMap[kappa] = true; fees[address(token)] = fees[address(token)].add(fee); + // withdrawAndRemove only on Mainnet => no airdrop + token.safeIncreaseAllowance(address(pool), amount.sub(fee)); try ISwap(pool).removeLiquidityOneToken( @@ -897,6 +899,14 @@ contract SynapseBridge is } } + // GAS AIRDROP + + function doGasAirdrop(address to) internal { + if (chainGasAmount != 0 && address(this).balance >= chainGasAmount) { + to.call{value: chainGasAmount}(""); + } + } + // BRIDGE FUNCTIONS TO HANDLE DIFF ADDRESSES /** * @notice Relays to nodes that (typically) a wrapped synAsset ERC20 token has been burned and the underlying needs to be redeeemed on the native chain From 3b739e03efd21550e2f6375783f84aec2508db2f Mon Sep 17 00:00:00 2001 From: ChiTimesChi <88190723+ChiTimesChi@users.noreply.github.com> Date: Tue, 12 Apr 2022 17:44:02 +0300 Subject: [PATCH 041/135] amount.sub(fee) cleanup --- contracts/bridge/HarmonySynapseBridge.sol | 50 +++++++++++++-------- contracts/bridge/MoonriverSynapseBridge.sol | 49 ++++++++++++-------- contracts/bridge/SynapseBridge.sol | 39 ++++++++++------ 3 files changed, 88 insertions(+), 50 deletions(-) diff --git a/contracts/bridge/HarmonySynapseBridge.sol b/contracts/bridge/HarmonySynapseBridge.sol index e11ff6bd4..4bf256703 100644 --- a/contracts/bridge/HarmonySynapseBridge.sol +++ b/contracts/bridge/HarmonySynapseBridge.sol @@ -259,14 +259,17 @@ contract HarmonySynapseBridge is // withdraw can happen on chains other than mainnet doGasAirdrop(to); + // apply fee + amount = amount.sub(fee); + if (address(token) == WETH_ADDRESS && WETH_ADDRESS != address(0)) { - IWETH9(WETH_ADDRESS).withdraw(amount.sub(fee)); - (bool success, ) = to.call{value: amount.sub(fee)}(""); + IWETH9(WETH_ADDRESS).withdraw(amount); + (bool success, ) = to.call{value: amount}(""); require(success, "ETH_TRANSFER_FAILED"); emit TokenWithdraw(to, token, amount, fee, kappa); } else { emit TokenWithdraw(to, token, amount, fee, kappa); - token.safeTransfer(to, amount.sub(fee)); + token.safeTransfer(to, amount); } } @@ -294,15 +297,20 @@ contract HarmonySynapseBridge is require(!kappaMap[kappa], "Kappa is already present"); kappaMap[kappa] = true; fees[address(token)] = fees[address(token)].add(fee); - emit TokenMint(to, token, amount.sub(fee), fee, kappa); + + // Transfer gas airdrop + doGasAirdrop(to); + token.mint(address(this), amount); + // apply fee + amount = amount.sub(fee); // checks if synFRAX if (address(token) == 0x1852F70512298d56e9c8FDd905e02581E04ddb2a) { if ( token.allowance( address(this), 0xFa7191D292d5633f702B0bd7E3E3BcCC0e633200 - ) < amount.sub(fee) + ) < amount ) { token.safeApprove( address(0xFa7191D292d5633f702B0bd7E3E3BcCC0e633200), @@ -315,20 +323,20 @@ contract HarmonySynapseBridge is } try IFrax(0xFa7191D292d5633f702B0bd7E3E3BcCC0e633200) - .exchangeOldForCanonical(address(token), amount.sub(fee)) + .exchangeOldForCanonical(address(token), amount) returns (uint256 canolical_tokens_out) { IERC20(0xFa7191D292d5633f702B0bd7E3E3BcCC0e633200).safeTransfer( to, canolical_tokens_out ); } catch { - IERC20(token).safeTransfer(to, amount.sub(fee)); + IERC20(token).safeTransfer(to, amount); } } else { - IERC20(token).safeTransfer(to, amount.sub(fee)); + IERC20(token).safeTransfer(to, amount); } - // Transfer gas airdrop - doGasAirdrop(to); + + emit TokenMint(to, token, amount, fee, kappa); } /** @@ -469,12 +477,15 @@ contract HarmonySynapseBridge is // proceed with swap token.mint(address(this), amount); - token.safeIncreaseAllowance(address(pool), amount.sub(fee)); + // apply fee + amount = amount.sub(fee); + + token.safeIncreaseAllowance(address(pool), amount); try ISwap(pool).swap( tokenIndexFrom, tokenIndexTo, - amount.sub(fee), + amount, minDy, deadline ) @@ -516,11 +527,11 @@ contract HarmonySynapseBridge is ); } } catch { - IERC20(token).safeTransfer(to, amount.sub(fee)); + IERC20(token).safeTransfer(to, amount); emit TokenMintAndSwap( to, token, - amount.sub(fee), + amount, fee, tokenIndexFrom, tokenIndexTo, @@ -566,10 +577,13 @@ contract HarmonySynapseBridge is // withdrawAndRemove only on Mainnet => no airdrop - token.safeIncreaseAllowance(address(pool), amount.sub(fee)); + // apply fee + amount = amount.sub(fee); + + token.safeIncreaseAllowance(address(pool), amount); try ISwap(pool).removeLiquidityOneToken( - amount.sub(fee), + amount, swapTokenIndex, swapMinAmount, swapDeadline @@ -590,11 +604,11 @@ contract HarmonySynapseBridge is kappa ); } catch { - IERC20(token).safeTransfer(to, amount.sub(fee)); + IERC20(token).safeTransfer(to, amount); emit TokenWithdrawAndRemove( to, token, - amount.sub(fee), + amount, fee, swapTokenIndex, swapMinAmount, diff --git a/contracts/bridge/MoonriverSynapseBridge.sol b/contracts/bridge/MoonriverSynapseBridge.sol index 5107fd188..fdf5ee19a 100644 --- a/contracts/bridge/MoonriverSynapseBridge.sol +++ b/contracts/bridge/MoonriverSynapseBridge.sol @@ -259,14 +259,17 @@ contract MRSynapseBridge is // withdraw can happen on chains other than mainnet doGasAirdrop(to); + // apply fee + amount = amount.sub(fee); + if (address(token) == WETH_ADDRESS && WETH_ADDRESS != address(0)) { - IWETH9(WETH_ADDRESS).withdraw(amount.sub(fee)); - (bool success, ) = to.call{value: amount.sub(fee)}(""); + IWETH9(WETH_ADDRESS).withdraw(amount); + (bool success, ) = to.call{value: amount}(""); require(success, "ETH_TRANSFER_FAILED"); emit TokenWithdraw(to, token, amount, fee, kappa); } else { emit TokenWithdraw(to, token, amount, fee, kappa); - token.safeTransfer(to, amount.sub(fee)); + token.safeTransfer(to, amount); } } @@ -294,30 +297,34 @@ contract MRSynapseBridge is require(!kappaMap[kappa], "Kappa is already present"); kappaMap[kappa] = true; fees[address(token)] = fees[address(token)].add(fee); - emit TokenMint(to, token, amount.sub(fee), fee, kappa); + // Transfer gas airdrop + doGasAirdrop(to); + token.mint(address(this), amount); + // apply fee + amount = amount.sub(fee); + // checks if synFRAX if (address(token) == 0xE96AC70907ffF3Efee79f502C985A7A21Bce407d) { token.safeIncreaseAllowance( 0x1A93B23281CC1CDE4C4741353F3064709A16197d, - amount.sub(fee) + amount ); try IFrax(0x1A93B23281CC1CDE4C4741353F3064709A16197d) - .exchangeOldForCanonical(address(token), amount.sub(fee)) + .exchangeOldForCanonical(address(token), amount) returns (uint256 canolical_tokens_out) { IERC20(0x1A93B23281CC1CDE4C4741353F3064709A16197d).safeTransfer( to, canolical_tokens_out ); } catch { - IERC20(token).safeTransfer(to, amount.sub(fee)); + IERC20(token).safeTransfer(to, amount); } } else { - IERC20(token).safeTransfer(to, amount.sub(fee)); + IERC20(token).safeTransfer(to, amount); } - // Transfer gas airdrop - doGasAirdrop(to); + emit TokenMint(to, token, amount, fee, kappa); } /** @@ -458,12 +465,15 @@ contract MRSynapseBridge is // proceed with swap token.mint(address(this), amount); - token.safeIncreaseAllowance(address(pool), amount.sub(fee)); + // apply fee + amount = amount.sub(fee); + + token.safeIncreaseAllowance(address(pool), amount); try ISwap(pool).swap( tokenIndexFrom, tokenIndexTo, - amount.sub(fee), + amount, minDy, deadline ) @@ -505,11 +515,11 @@ contract MRSynapseBridge is ); } } catch { - IERC20(token).safeTransfer(to, amount.sub(fee)); + IERC20(token).safeTransfer(to, amount); emit TokenMintAndSwap( to, token, - amount.sub(fee), + amount, fee, tokenIndexFrom, tokenIndexTo, @@ -555,10 +565,13 @@ contract MRSynapseBridge is // withdrawAndRemove only on Mainnet => no airdrop - token.safeIncreaseAllowance(address(pool), amount.sub(fee)); + // apply fee + amount = amount.sub(fee); + + token.safeIncreaseAllowance(address(pool), amount); try ISwap(pool).removeLiquidityOneToken( - amount.sub(fee), + amount, swapTokenIndex, swapMinAmount, swapDeadline @@ -579,11 +592,11 @@ contract MRSynapseBridge is kappa ); } catch { - IERC20(token).safeTransfer(to, amount.sub(fee)); + IERC20(token).safeTransfer(to, amount); emit TokenWithdrawAndRemove( to, token, - amount.sub(fee), + amount, fee, swapTokenIndex, swapMinAmount, diff --git a/contracts/bridge/SynapseBridge.sol b/contracts/bridge/SynapseBridge.sol index a1fa90586..7087718ec 100644 --- a/contracts/bridge/SynapseBridge.sol +++ b/contracts/bridge/SynapseBridge.sol @@ -352,14 +352,17 @@ contract SynapseBridge is // withdraw can happen on chains other than mainnet doGasAirdrop(to); + // apply fee + amount = amount.sub(fee); + if (address(token) == WETH_ADDRESS && WETH_ADDRESS != address(0)) { - IWETH9(WETH_ADDRESS).withdraw(amount.sub(fee)); - (bool success, ) = to.call{value: amount.sub(fee)}(""); + IWETH9(WETH_ADDRESS).withdraw(amount); + (bool success, ) = to.call{value: amount}(""); require(success, "ETH_TRANSFER_FAILED"); emit TokenWithdraw(to, token, amount, fee, kappa); } else { emit TokenWithdraw(to, token, amount, fee, kappa); - token.safeTransfer(to, amount.sub(fee)); + token.safeTransfer(to, amount); } } @@ -438,10 +441,14 @@ contract SynapseBridge is require(!kappaMap[kappa], "Kappa is already present"); kappaMap[kappa] = true; fees[address(token)] = fees[address(token)].add(fee); - emit TokenMint(to, token, amount.sub(fee), fee, kappa); - token.mint(address(this), amount); - IERC20(token).safeTransfer(to, amount.sub(fee)); doGasAirdrop(to); + + token.mint(address(this), amount); + // apply fee + amount = amount.sub(fee); + IERC20(token).safeTransfer(to, amount); + + emit TokenMint(to, token, amount, fee, kappa); } /** @@ -675,12 +682,14 @@ contract SynapseBridge is // proceed with swap token.mint(address(this), amount); - token.safeIncreaseAllowance(address(pool), amount.sub(fee)); + // apply fee + amount = amount.sub(fee); + token.safeIncreaseAllowance(address(pool), amount); try ISwap(pool).swap( tokenIndexFrom, tokenIndexTo, - amount.sub(fee), + amount, minDy, deadline ) @@ -722,11 +731,11 @@ contract SynapseBridge is ); } } catch { - token.safeTransfer(to, amount.sub(fee)); + token.safeTransfer(to, amount); emit TokenMintAndSwap( to, token, - amount.sub(fee), + amount, fee, tokenIndexFrom, tokenIndexTo, @@ -856,14 +865,16 @@ contract SynapseBridge is require(amount > fee, "Amount must be greater than fee"); require(!kappaMap[kappa], "Kappa is already present"); kappaMap[kappa] = true; + // apply fees fees[address(token)] = fees[address(token)].add(fee); + amount = amount.sub(fee); // withdrawAndRemove only on Mainnet => no airdrop - token.safeIncreaseAllowance(address(pool), amount.sub(fee)); + token.safeIncreaseAllowance(address(pool), amount); try ISwap(pool).removeLiquidityOneToken( - amount.sub(fee), + amount, swapTokenIndex, swapMinAmount, swapDeadline @@ -884,11 +895,11 @@ contract SynapseBridge is kappa ); } catch { - token.safeTransfer(to, amount.sub(fee)); + token.safeTransfer(to, amount); emit TokenWithdrawAndRemove( to, token, - amount.sub(fee), + amount, fee, swapTokenIndex, swapMinAmount, From acb00c0f72de8559f9465602d8ff6b430fa739d7 Mon Sep 17 00:00:00 2001 From: ChiTimesChi <88190723+ChiTimesChi@users.noreply.github.com> Date: Tue, 12 Apr 2022 17:53:30 +0300 Subject: [PATCH 042/135] clean up WGAS unwrapping --- contracts/bridge/HarmonySynapseBridge.sol | 76 +++++++++------------ contracts/bridge/MoonriverSynapseBridge.sol | 76 +++++++++------------ contracts/bridge/SynapseBridge.sol | 76 +++++++++------------ 3 files changed, 99 insertions(+), 129 deletions(-) diff --git a/contracts/bridge/HarmonySynapseBridge.sol b/contracts/bridge/HarmonySynapseBridge.sol index 4bf256703..afdd05461 100644 --- a/contracts/bridge/HarmonySynapseBridge.sol +++ b/contracts/bridge/HarmonySynapseBridge.sol @@ -262,15 +262,9 @@ contract HarmonySynapseBridge is // apply fee amount = amount.sub(fee); - if (address(token) == WETH_ADDRESS && WETH_ADDRESS != address(0)) { - IWETH9(WETH_ADDRESS).withdraw(amount); - (bool success, ) = to.call{value: amount}(""); - require(success, "ETH_TRANSFER_FAILED"); - emit TokenWithdraw(to, token, amount, fee, kappa); - } else { - emit TokenWithdraw(to, token, amount, fee, kappa); - token.safeTransfer(to, amount); - } + // If token is WGAS, this will send native chain GAS + transferTokenWithUnwrap(to, token, amount); + emit TokenWithdraw(to, token, amount, fee, kappa); } /** @@ -492,40 +486,20 @@ contract HarmonySynapseBridge is returns (uint256 finalSwappedAmount) { // Swap succeeded, transfer swapped asset IERC20 swappedTokenTo = ISwap(pool).getToken(tokenIndexTo); - if ( - address(swappedTokenTo) == WETH_ADDRESS && - WETH_ADDRESS != address(0) - ) { - IWETH9(WETH_ADDRESS).withdraw(finalSwappedAmount); - (bool success, ) = to.call{value: finalSwappedAmount}(""); - require(success, "ETH_TRANSFER_FAILED"); - emit TokenMintAndSwap( - to, - token, - finalSwappedAmount, - fee, - tokenIndexFrom, - tokenIndexTo, - minDy, - deadline, - true, - kappa - ); - } else { - swappedTokenTo.safeTransfer(to, finalSwappedAmount); - emit TokenMintAndSwap( - to, - token, - finalSwappedAmount, - fee, - tokenIndexFrom, - tokenIndexTo, - minDy, - deadline, - true, - kappa - ); - } + // If token is WGAS, this will send native chain GAS + transferTokenWithUnwrap(to, swappedTokenTo, finalSwappedAmount); + emit TokenMintAndSwap( + to, + token, + finalSwappedAmount, + fee, + tokenIndexFrom, + tokenIndexTo, + minDy, + deadline, + true, + kappa + ); } catch { IERC20(token).safeTransfer(to, amount); emit TokenMintAndSwap( @@ -619,6 +593,22 @@ contract HarmonySynapseBridge is } } + // TOKEN TRANSFER + + function transferTokenWithUnwrap( + address to, + IERC20 token, + uint256 amount + ) internal { + if (address(token) == WETH_ADDRESS && WETH_ADDRESS != address(0)) { + IWETH9(WETH_ADDRESS).withdraw(amount); + (bool success, ) = to.call{value: amount}(""); + require(success, "ETH_TRANSFER_FAILED"); + } else { + token.safeTransfer(to, amount); + } + } + // GAS AIRDROP function doGasAirdrop(address to) internal { diff --git a/contracts/bridge/MoonriverSynapseBridge.sol b/contracts/bridge/MoonriverSynapseBridge.sol index fdf5ee19a..e111c8fad 100644 --- a/contracts/bridge/MoonriverSynapseBridge.sol +++ b/contracts/bridge/MoonriverSynapseBridge.sol @@ -262,15 +262,9 @@ contract MRSynapseBridge is // apply fee amount = amount.sub(fee); - if (address(token) == WETH_ADDRESS && WETH_ADDRESS != address(0)) { - IWETH9(WETH_ADDRESS).withdraw(amount); - (bool success, ) = to.call{value: amount}(""); - require(success, "ETH_TRANSFER_FAILED"); - emit TokenWithdraw(to, token, amount, fee, kappa); - } else { - emit TokenWithdraw(to, token, amount, fee, kappa); - token.safeTransfer(to, amount); - } + // If token is WGAS, this will send native chain GAS + transferTokenWithUnwrap(to, token, amount); + emit TokenWithdraw(to, token, amount, fee, kappa); } /** @@ -480,40 +474,20 @@ contract MRSynapseBridge is returns (uint256 finalSwappedAmount) { // Swap succeeded, transfer swapped asset IERC20 swappedTokenTo = ISwap(pool).getToken(tokenIndexTo); - if ( - address(swappedTokenTo) == WETH_ADDRESS && - WETH_ADDRESS != address(0) - ) { - IWETH9(WETH_ADDRESS).withdraw(finalSwappedAmount); - (bool success, ) = to.call{value: finalSwappedAmount}(""); - require(success, "ETH_TRANSFER_FAILED"); - emit TokenMintAndSwap( - to, - token, - finalSwappedAmount, - fee, - tokenIndexFrom, - tokenIndexTo, - minDy, - deadline, - true, - kappa - ); - } else { - swappedTokenTo.safeTransfer(to, finalSwappedAmount); - emit TokenMintAndSwap( - to, - token, - finalSwappedAmount, - fee, - tokenIndexFrom, - tokenIndexTo, - minDy, - deadline, - true, - kappa - ); - } + // If token is WGAS, this will send native chain GAS + transferTokenWithUnwrap(to, swappedTokenTo, finalSwappedAmount); + emit TokenMintAndSwap( + to, + token, + finalSwappedAmount, + fee, + tokenIndexFrom, + tokenIndexTo, + minDy, + deadline, + true, + kappa + ); } catch { IERC20(token).safeTransfer(to, amount); emit TokenMintAndSwap( @@ -607,6 +581,22 @@ contract MRSynapseBridge is } } + // TOKEN TRANSFER + + function transferTokenWithUnwrap( + address to, + IERC20 token, + uint256 amount + ) internal { + if (address(token) == WETH_ADDRESS && WETH_ADDRESS != address(0)) { + IWETH9(WETH_ADDRESS).withdraw(amount); + (bool success, ) = to.call{value: amount}(""); + require(success, "ETH_TRANSFER_FAILED"); + } else { + token.safeTransfer(to, amount); + } + } + // GAS AIRDROP function doGasAirdrop(address to) internal { diff --git a/contracts/bridge/SynapseBridge.sol b/contracts/bridge/SynapseBridge.sol index 7087718ec..165a65933 100644 --- a/contracts/bridge/SynapseBridge.sol +++ b/contracts/bridge/SynapseBridge.sol @@ -355,15 +355,9 @@ contract SynapseBridge is // apply fee amount = amount.sub(fee); - if (address(token) == WETH_ADDRESS && WETH_ADDRESS != address(0)) { - IWETH9(WETH_ADDRESS).withdraw(amount); - (bool success, ) = to.call{value: amount}(""); - require(success, "ETH_TRANSFER_FAILED"); - emit TokenWithdraw(to, token, amount, fee, kappa); - } else { - emit TokenWithdraw(to, token, amount, fee, kappa); - token.safeTransfer(to, amount); - } + // If token is WGAS, this will send native chain GAS + transferTokenWithUnwrap(to, token, amount); + emit TokenWithdraw(to, token, amount, fee, kappa); } /** @@ -696,40 +690,20 @@ contract SynapseBridge is returns (uint256 finalSwappedAmount) { // Swap succeeded, transfer swapped asset IERC20 swappedTokenTo = ISwap(pool).getToken(tokenIndexTo); - if ( - address(swappedTokenTo) == WETH_ADDRESS && - WETH_ADDRESS != address(0) - ) { - IWETH9(WETH_ADDRESS).withdraw(finalSwappedAmount); - (bool success, ) = to.call{value: finalSwappedAmount}(""); - require(success, "ETH_TRANSFER_FAILED"); - emit TokenMintAndSwap( - to, - token, - finalSwappedAmount, - fee, - tokenIndexFrom, - tokenIndexTo, - minDy, - deadline, - true, - kappa - ); - } else { - swappedTokenTo.safeTransfer(to, finalSwappedAmount); - emit TokenMintAndSwap( - to, - token, - finalSwappedAmount, - fee, - tokenIndexFrom, - tokenIndexTo, - minDy, - deadline, - true, - kappa - ); - } + // If token is WGAS, this will send native chain GAS + transferTokenWithUnwrap(to, swappedTokenTo, finalSwappedAmount); + emit TokenMintAndSwap( + to, + token, + finalSwappedAmount, + fee, + tokenIndexFrom, + tokenIndexTo, + minDy, + deadline, + true, + kappa + ); } catch { token.safeTransfer(to, amount); emit TokenMintAndSwap( @@ -910,6 +884,22 @@ contract SynapseBridge is } } + // TOKEN TRANSFER + + function transferTokenWithUnwrap( + address to, + IERC20 token, + uint256 amount + ) internal { + if (address(token) == WETH_ADDRESS && WETH_ADDRESS != address(0)) { + IWETH9(WETH_ADDRESS).withdraw(amount); + (bool success, ) = to.call{value: amount}(""); + require(success, "ETH_TRANSFER_FAILED"); + } else { + token.safeTransfer(to, amount); + } + } + // GAS AIRDROP function doGasAirdrop(address to) internal { From 4207b4d773035e3f5697e41e25baeb8f7830ef6d Mon Sep 17 00:00:00 2001 From: ChiTimesChi <88190723+ChiTimesChi@users.noreply.github.com> Date: Tue, 12 Apr 2022 18:09:11 +0300 Subject: [PATCH 043/135] do not store selectors --- contracts/bridge/SynapseBridge.sol | 29 ++++------------------------- 1 file changed, 4 insertions(+), 25 deletions(-) diff --git a/contracts/bridge/SynapseBridge.sol b/contracts/bridge/SynapseBridge.sol index 165a65933..2e8614638 100644 --- a/contracts/bridge/SynapseBridge.sol +++ b/contracts/bridge/SynapseBridge.sol @@ -42,27 +42,6 @@ contract SynapseBridge is mapping(bytes32 => bool) private kappaMap; - // selectors - bytes4 private constant RETRY_MINT_SELECTOR = - bytes4(keccak256("retryMint(address,address,uint256,uint256,bytes32)")); - bytes4 private constant RETRY_MINT_AND_SWAP_SELECTOR = - bytes4( - keccak256( - "retryMintAndSwap(address,address,uint256,uint256,address,uint8,uint8,uint256,uint256,bytes32)" - ) - ); - bytes4 private constant RETRY_WITHDRAW_AND_REMOVE_SELECTOR = - bytes4( - keccak256( - "retryWithdrawAndRemove(address,address,uint256,uint256,address,uint8,uint256,uint256,bytes32)" - ) - ); - - bytes4 private constant RETRY_WITHDRAW_SELECTOR = - bytes4( - keccak256("retryWithdraw(address,address,uint256,uint256,bytes32)") - ); - // rate limiter IRateLimiter public rateLimiter; @@ -299,7 +278,7 @@ contract SynapseBridge is rateLimiter.addToRetryQueue( kappa, abi.encodeWithSelector( - RETRY_WITHDRAW_SELECTOR, + this.retryWithdraw.selector, to, address(token), amount, @@ -386,7 +365,7 @@ contract SynapseBridge is rateLimiter.addToRetryQueue( kappa, abi.encodeWithSelector( - RETRY_MINT_SELECTOR, + this.retryMint.selector, to, address(token), amount, @@ -580,7 +559,7 @@ contract SynapseBridge is rateLimiter.addToRetryQueue( kappa, abi.encodeWithSelector( - RETRY_MINT_AND_SWAP_SELECTOR, + this.retryMintAndSwap.selector, to, address(token), amount, @@ -755,7 +734,7 @@ contract SynapseBridge is rateLimiter.addToRetryQueue( kappa, abi.encodeWithSelector( - RETRY_WITHDRAW_AND_REMOVE_SELECTOR, + this.retryWithdrawAndRemove.selector, to, address(token), amount, From a4076eef41704b4602e99e53378afb1e25ba0eab Mon Sep 17 00:00:00 2001 From: ChiTimesChi <88190723+ChiTimesChi@users.noreply.github.com> Date: Wed, 13 Apr 2022 11:16:55 +0300 Subject: [PATCH 044/135] Queue for storing rate limited kappas --- .../libraries/EnumerableQueueUpgradeable.sol | 187 ++++++++++++++++++ 1 file changed, 187 insertions(+) create mode 100644 contracts/bridge/libraries/EnumerableQueueUpgradeable.sol diff --git a/contracts/bridge/libraries/EnumerableQueueUpgradeable.sol b/contracts/bridge/libraries/EnumerableQueueUpgradeable.sol new file mode 100644 index 000000000..a16d4176f --- /dev/null +++ b/contracts/bridge/libraries/EnumerableQueueUpgradeable.sol @@ -0,0 +1,187 @@ +// SPDX-License-Identifier: MIT + +pragma solidity ^0.8.0; + +library EnumerableQueueUpgradeable { + struct RetryableTx { + /// @dev epoch time in minutes the tx was stored at. Always non-zero on initialized struct + uint32 storedAtMin; + /// @dev bridge calldata for retrying + bytes toRetry; + } + + /** + * @dev New elements are added to the tail of queue: + * + * H=T=0 + * v + * Initial state: EMPTY [head (H) = 0, tail(T) = 0] + * + * H T + * add(1): [1] + * + * H T + * add(2): [1]<>[2] + * + * H T + * add(3): [1]<>[2]<>[3] + */ + + /** + * @dev Getting arbitrary elements is supported, but not their deletion: + * Initial state: [1]<>[2]<>[3] + * get(key=2) -> [2]: gets data for a given key + * at(index=0) -> [1]: gets data for a given queue index (queue head index is always 0) + */ + + /** + * @dev Elements are polled from the head of queue: + * H T + * State : [1]<>[2]<>[3] + * + * H T + * poll() : [2]<>[3] + * + * H T + * poll() : [3] + */ + + struct KappaQueue { + /// @dev Array of keys for data. Every existing key is unique. + /// Can't add the same key twice, but it's possible + /// to add the key again once it is deleted from the Queue. + mapping(uint256 => bytes32) _keys; + /// @dev Data map for each key. + mapping(bytes32 => RetryableTx) _data; + /// @dev Index of the first Queue key. + uint256 _head; + /// @dev Index following the last Queue key, i.e. + /// index, where newly added key would reside. + /// _head == _tail => Queue is empty + uint256 _tail; + } + + /** + * @notice Adds [key, value] pair to the `queue`. Will not to anything, if + * a key already exists in the `queue`. + * + * Returns true only if [key, value] was added to the Queue. + */ + function add( + KappaQueue storage queue, + bytes32 key, + bytes memory value + ) internal returns (bool) { + if (contains(queue, key)) { + // key already exists, don't add anything + return false; + } + + uint256 toInsert = queue._tail; + + queue._tail++; + queue._keys[toInsert] = key; + queue._data[key] = RetryableTx({ + storedAtMin: uint32(block.timestamp / 60), + toRetry: value + }); + + return true; + } + + /** + * @notice Returns data for N-th element of the Queue: + * key, value and the time it was stored. + * + * Will return zero values, if `index >= queue.length()`. + */ + function at(KappaQueue storage queue, uint256 index) + internal + view + returns ( + bytes32 key, + bytes memory value, + uint32 storedAtMin + ) + { + key = queue._keys[queue._head + index]; + (value, storedAtMin) = get(queue, key); + } + + /** + * @notice Checks whether `key` is present in the Queue. + */ + function contains(KappaQueue storage queue, bytes32 key) + internal + view + returns (bool) + { + return queue._data[key].toRetry.length > 0; + } + + /** + * @notice Checks whether Queue is empty. + */ + function isEmpty(KappaQueue storage queue) internal view returns (bool) { + return queue._head == queue._tail; + } + + /** + * @notice Gets data associated with the given `key`: + * value and the time it was stored. + * + * Will return zero values for `key` that is not the Queue. + */ + function get(KappaQueue storage queue, bytes32 key) + internal + view + returns (bytes memory value, uint32 storedAtMin) + { + RetryableTx memory data = queue._data[key]; + (value, storedAtMin) = (data.toRetry, data.storedAtMin); + } + + /** + * @notice Returns the number of elements in the Queue. + */ + function length(KappaQueue storage queue) internal view returns (uint256) { + // This never underflows + return queue._head - queue._tail; + } + + /** + * @notice Returns the head of Queue, without removing it: + * value and the time it was stored. + + * Will return zero values, if Queue is empty. + * + * Head is always the element that has been added first. + */ + function peek(KappaQueue storage queue) + internal + view + returns (bytes memory value, uint32 storedAtMin) + { + (value, storedAtMin) = get(queue, queue._keys[queue._head]); + } + + /** + * @notice Removes the first (head) element from the Queue. + * + * Returns true, only if element was deleted. + * Returns false, if Queue was empty. + */ + function poll(KappaQueue storage queue) internal returns (bool) { + uint256 head = queue._head; + uint256 tail = queue._tail; + if (head != tail) { + bytes32 headKey = queue._keys[head]; + + queue._head++; + delete queue._keys[head]; + delete queue._data[headKey]; + return true; + } + return false; + } +} From 9747599115577fde0f7449f81326b97d116b7be1 Mon Sep 17 00:00:00 2001 From: ChiTimesChi <88190723+ChiTimesChi@users.noreply.github.com> Date: Sun, 17 Apr 2022 13:13:06 +0300 Subject: [PATCH 045/135] fix rate limiter tests --- test/bridge/SynapseBridgeAvax.ts | 83 +++++++++-------- test/bridge/SynapseBridgeETH.ts | 150 ++++++++++++++++++++----------- 2 files changed, 144 insertions(+), 89 deletions(-) diff --git a/test/bridge/SynapseBridgeAvax.ts b/test/bridge/SynapseBridgeAvax.ts index e40ccdcff..6914e23d5 100644 --- a/test/bridge/SynapseBridgeAvax.ts +++ b/test/bridge/SynapseBridgeAvax.ts @@ -5,11 +5,11 @@ import { deployments, ethers } from "hardhat" import chai from "chai" import { GenericERC20, RateLimiter, SynapseBridge } from "../../build/typechain" -import epochSeconds from "@stdlib/time-now" import { keccak256 } from "ethers/lib/utils" import { randomBytes } from "crypto" -import { forkChain } from "../utils" +import { forkChain, MAX_UINT256 } from "../utils" import { deployRateLimiter, setupForkedBridge } from "./utilities/bridge" +import { getBigNumber } from "./utilities" chai.use(solidity) const { expect } = chai @@ -23,7 +23,6 @@ describe("SynapseBridgeAvax", async () => { let nodeGroup: Signer let recipient: Signer - const decimals = Math.pow(10, 6) const NUSD = "0xCFc37A6AB183dd4aED08C204D1c2773c0b1BDf46" const NUSD_POOL = "0xED2a7edd7413021d440b09D654f3b87712abAB66" @@ -62,48 +61,62 @@ describe("SynapseBridgeAvax", async () => { await setupTest() }) - // ammounts are multiplied by 10^6 const setupAllowanceTest = async ( tokenAddress: string, allowanceAmount: number, intervalMin: number = 60, ) => { const lastReset = Math.floor((await getCurrentBlockTimestamp()) / 60) - allowanceAmount = allowanceAmount * decimals - - await expect( - rateLimiter.setAllowance( - tokenAddress, - allowanceAmount, - intervalMin, - lastReset, - ), - ).to.be.not.reverted + + await rateLimiter.setAllowance( + tokenAddress, + allowanceAmount, + intervalMin, + lastReset, + ) } - it("MintAndSwap: should add to retry queue if rate limit hit", async () => { - const allowanceAmount = 500 - const mintAmount = 1000 + it("MintAndSwap: should add to retry queue only if rate limit hit", async () => { + const allowanceAmount = getBigNumber(100) + const firstAmount = allowanceAmount.sub(1) + const secondAmount = allowanceAmount.sub(firstAmount).add(1) await setupAllowanceTest(NUSD, allowanceAmount) - const kappa = keccak256(randomBytes(32)) - - await expect( - bridge - .connect(nodeGroup) - .mintAndSwap( - await recipient.getAddress(), - NUSD, - mintAmount, - 10, - NUSD_POOL, - 0, - 2, - mintAmount, - epochSeconds(), - kappa, - ), - ).to.be.not.reverted + let kappa = keccak256(randomBytes(32)) + + await bridge + .connect(nodeGroup) + .mintAndSwap( + await recipient.getAddress(), + NUSD, + firstAmount, + 0, + NUSD_POOL, + 0, + 2, + 0, + MAX_UINT256, + kappa, + ) + // This should NOT BE rate limited + expect(await bridge.kappaExists(kappa)).to.be.true + + kappa = keccak256(randomBytes(32)) + + await bridge + .connect(nodeGroup) + .mintAndSwap( + await recipient.getAddress(), + NUSD, + secondAmount, + 0, + NUSD_POOL, + 0, + 2, + 0, + MAX_UINT256, + kappa, + ) expect(await bridge.kappaExists(kappa)).to.be.false await expect(rateLimiter.retryByKappa(kappa)).to.be.not.reverted diff --git a/test/bridge/SynapseBridgeETH.ts b/test/bridge/SynapseBridgeETH.ts index c1f122738..341f79f5c 100644 --- a/test/bridge/SynapseBridgeETH.ts +++ b/test/bridge/SynapseBridgeETH.ts @@ -5,11 +5,11 @@ import { deployments, ethers } from "hardhat" import chai from "chai" import { GenericERC20, RateLimiter, SynapseBridge } from "../../build/typechain" -import epochSeconds from "@stdlib/time-now" import { keccak256 } from "ethers/lib/utils" import { randomBytes } from "crypto" -import { forkChain } from "../utils" +import { forkChain, MAX_UINT256 } from "../utils" import { deployRateLimiter, setupForkedBridge } from "./utilities/bridge" +import { getBigNumber } from "./utilities" chai.use(solidity) const { expect } = chai @@ -35,8 +35,6 @@ describe("SynapseBridgeETH", async () => { const SYN = "0x0f2D719407FdBeFF09D87557AbB7232601FD9F29" const WETH = "0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2" - const decimals = Math.pow(10, 6) - // deploys the bridge, grants role. Rate limiter *must* be deployed first const setupTokens = async () => { const erc20Factory = await ethers.getContractFactory("GenericERC20") @@ -74,92 +72,136 @@ describe("SynapseBridgeETH", async () => { await setupTest() }) - // ammounts are multiplied by 10^6 const setupAllowanceTest = async ( tokenAddress: string, allowanceAmount: number, intervalMin: number = 60, ) => { const lastReset = Math.floor((await getCurrentBlockTimestamp()) / 60) - allowanceAmount = allowanceAmount * decimals - await expect( - rateLimiter.setAllowance( - tokenAddress, - allowanceAmount, - intervalMin, - lastReset, - ), - ).to.be.not.reverted + await rateLimiter.setAllowance( + tokenAddress, + allowanceAmount, + intervalMin, + lastReset, + ) } - it("Withdraw: should add to retry queue if rate limit hit", async () => { - const mintAmount = 50 + it("Withdraw: should add to retry queue only if rate limit hit", async () => { + const mintAmount = getBigNumber(1000, 6) + const allowanceAmount = getBigNumber(100, 6) + const firstAmount = getBigNumber(42, 6) + const secondAmount = allowanceAmount.sub(firstAmount).add(1) - await expect(USDC.mint(bridge.address, mintAmount * decimals)) - await setupAllowanceTest(USDC.address, 100) + await USDC.mint(bridge.address, mintAmount) + await setupAllowanceTest(USDC.address, allowanceAmount) - const kappa = keccak256(randomBytes(32)) + let kappa = keccak256(randomBytes(32)) await expect( bridge .connect(nodeGroup) - .withdraw(await recipient.getAddress(), USDC.address, 101, 50, kappa), + .withdraw( + await recipient.getAddress(), + USDC.address, + firstAmount, + 0, + kappa, + ), ).to.be.not.reverted - - // make sure withdraw didn't happen - expect(await USDC.balanceOf(bridge.address)).to.be.eq( - (mintAmount * decimals).toString(), - ) - - // now retry. This should bypass the rate limiter - await expect(rateLimiter.retryByKappa(kappa)).to.be.not.reverted + // This should NOT BE rate limited expect(await bridge.kappaExists(kappa)).to.be.true - }) - - it("WithdrawAndRemove: should add to retry queue if rate limit hit", async () => { - const allowanceAmount = 500 - const withdrawAmount = 1000 - - await setupAllowanceTest(NUSD, allowanceAmount) - const kappa = keccak256(randomBytes(32)) + kappa = keccak256(randomBytes(32)) await expect( bridge .connect(nodeGroup) - .withdrawAndRemove( + .withdraw( await recipient.getAddress(), - NUSD, - withdrawAmount, - 10, - NUSD_POOL, - 1, - withdrawAmount, - epochSeconds(), + USDC.address, + secondAmount, + 0, kappa, ), ).to.be.not.reverted + // This should BE rate limited expect(await bridge.kappaExists(kappa)).to.be.false + + // now retry. This should bypass the rate limiter await expect(rateLimiter.retryByKappa(kappa)).to.be.not.reverted expect(await bridge.kappaExists(kappa)).to.be.true }) - it("Mint: should add to retry queue if rate limit hit", async () => { - const allowanceAmount = 500 - const mintAmount = 1000 + it("WithdrawAndRemove: should add to retry queue only if rate limit hit", async () => { + const allowanceAmount = getBigNumber(100) + const firstAmount = getBigNumber(69) + const secondAmount = allowanceAmount.sub(firstAmount).add(1) + + await setupAllowanceTest(NUSD, allowanceAmount) + let kappa = keccak256(randomBytes(32)) + + await bridge + .connect(nodeGroup) + .withdrawAndRemove( + await recipient.getAddress(), + NUSD, + firstAmount, + 0, + NUSD_POOL, + 1, + 0, + MAX_UINT256, + kappa, + ) + + // This should NOT BE rate limited + expect(await bridge.kappaExists(kappa)).to.be.true + + kappa = keccak256(randomBytes(32)) + + await bridge + .connect(nodeGroup) + .withdrawAndRemove( + await recipient.getAddress(), + NUSD, + secondAmount, + 0, + NUSD_POOL, + 1, + 0, + MAX_UINT256, + kappa, + ) + // This should BE rate limited + expect(await bridge.kappaExists(kappa)).to.be.false + + await rateLimiter.retryByKappa(kappa) + expect(await bridge.kappaExists(kappa)).to.be.true + }) + + it("Mint: should add to retry queue only if rate limit hit", async () => { + const allowanceAmount = getBigNumber(100) + const firstAmount = getBigNumber(100) + const secondAmount = allowanceAmount.sub(firstAmount).add(1) await setupAllowanceTest(SYN, allowanceAmount) - const kappa = keccak256(randomBytes(32)) + let kappa = keccak256(randomBytes(32)) - await expect( - bridge - .connect(nodeGroup) - .mint(await recipient.getAddress(), SYN, mintAmount, 10, kappa), - ).to.be.not.reverted + await bridge + .connect(nodeGroup) + .mint(await recipient.getAddress(), SYN, firstAmount, 0, kappa) + + // This should NOT BE rate limited + expect(await bridge.kappaExists(kappa)).to.be.true + kappa = keccak256(randomBytes(32)) + await bridge + .connect(nodeGroup) + .mint(await recipient.getAddress(), SYN, secondAmount, 0, kappa) + // This should BE rate limited expect(await bridge.kappaExists(kappa)).to.be.false - await expect(rateLimiter.retryByKappa(kappa)).to.be.not.reverted + await rateLimiter.retryByKappa(kappa) expect(await bridge.kappaExists(kappa)).to.be.true }) From a3b895e94298f47a557f263da4df3abc0f89f1db Mon Sep 17 00:00:00 2001 From: ChiTimesChi <88190723+ChiTimesChi@users.noreply.github.com> Date: Sun, 17 Apr 2022 13:14:25 +0300 Subject: [PATCH 046/135] return correct isRateLimited --- contracts/bridge/SynapseBridge.sol | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/contracts/bridge/SynapseBridge.sol b/contracts/bridge/SynapseBridge.sol index 2e8614638..815e6f6df 100644 --- a/contracts/bridge/SynapseBridge.sol +++ b/contracts/bridge/SynapseBridge.sol @@ -216,7 +216,8 @@ contract SynapseBridge is return false; } - return rateLimiter.checkAndUpdateAllowance(address(token), amount); + // rate limiter returns true on the successful allowance update + return !rateLimiter.checkAndUpdateAllowance(address(token), amount); } /** From ad21ec09146213c0ef373a5653118e753dde4ae9 Mon Sep 17 00:00:00 2001 From: ChiTimesChi <88190723+ChiTimesChi@users.noreply.github.com> Date: Sun, 17 Apr 2022 13:17:58 +0300 Subject: [PATCH 047/135] should be able to spend exact allowance --- contracts/bridge/RateLimiter.sol | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contracts/bridge/RateLimiter.sol b/contracts/bridge/RateLimiter.sol index 7dbd96cb2..f5db30e20 100644 --- a/contracts/bridge/RateLimiter.sol +++ b/contracts/bridge/RateLimiter.sol @@ -163,7 +163,7 @@ contract RateLimiter is ); // do not proceed. Store the transaction for later - if (newSpent >= allowance.amount) { + if (newSpent > allowance.amount) { return false; } From 8552d911178f830079d362dcffcb7729ba88722a Mon Sep 17 00:00:00 2001 From: ChiTimesChi <88190723+ChiTimesChi@users.noreply.github.com> Date: Sun, 17 Apr 2022 13:45:18 +0300 Subject: [PATCH 048/135] retryCount tests --- contracts/bridge/RateLimiter.sol | 3 +- test/bridge/SynapseBridgeETH.ts | 62 ++++++++++++++++++++++++++++++++ 2 files changed, 64 insertions(+), 1 deletion(-) diff --git a/contracts/bridge/RateLimiter.sol b/contracts/bridge/RateLimiter.sol index f5db30e20..c958c3f62 100644 --- a/contracts/bridge/RateLimiter.sol +++ b/contracts/bridge/RateLimiter.sol @@ -197,7 +197,8 @@ contract RateLimiter is ); for (uint8 i = 0; i < attempts; i++) { - (bytes32 kappa, bytes memory toRetry, ) = rateLimited.at(i); + // check out the first element + (bytes32 kappa, bytes memory toRetry, ) = rateLimited.at(0); (bool success, bytes memory returnData) = BRIDGE_ADDRESS.call( toRetry ); diff --git a/test/bridge/SynapseBridgeETH.ts b/test/bridge/SynapseBridgeETH.ts index 341f79f5c..89e833c05 100644 --- a/test/bridge/SynapseBridgeETH.ts +++ b/test/bridge/SynapseBridgeETH.ts @@ -205,6 +205,68 @@ describe("SynapseBridgeETH", async () => { expect(await bridge.kappaExists(kappa)).to.be.true }) + it("RetryCount: should be able to clear the Retry Queue", async () => { + const allowanceAmount = getBigNumber(100) + const amount = allowanceAmount.add(1) + const kappas = [ + keccak256(randomBytes(32)), + keccak256(randomBytes(32)), + keccak256(randomBytes(32)), + keccak256(randomBytes(32)), + ] + + await setupAllowanceTest(SYN, allowanceAmount) + + for (let kappa of kappas) { + await bridge + .connect(nodeGroup) + .mint(await recipient.getAddress(), SYN, amount, 0, kappa) + + // This should BE rate limited + expect(await bridge.kappaExists(kappa)).to.be.false + } + + await rateLimiter.retryCount(kappas.length) + + for (let kappa of kappas) { + expect(await bridge.kappaExists(kappa)).to.be.true + } + }) + + it("RetryCount: should work correctly after retryByKappa", async () => { + const allowanceAmount = getBigNumber(100) + const amount = allowanceAmount.add(1) + const kappas = [ + keccak256(randomBytes(32)), + keccak256(randomBytes(32)), + keccak256(randomBytes(32)), + keccak256(randomBytes(32)), + ] + + await setupAllowanceTest(SYN, allowanceAmount) + + for (let kappa of kappas) { + await bridge + .connect(nodeGroup) + .mint(await recipient.getAddress(), SYN, amount, 0, kappa) + + // This should BE rate limited + expect(await bridge.kappaExists(kappa)).to.be.false + } + + await rateLimiter.retryByKappa(kappas[1]) + expect(await bridge.kappaExists(kappas[1])).to.be.true + + await rateLimiter.retryByKappa(kappas[3]) + expect(await bridge.kappaExists(kappas[3])).to.be.true + + await rateLimiter.retryCount(kappas.length) + + for (let kappa of kappas) { + expect(await bridge.kappaExists(kappa)).to.be.true + } + }) + // check permissions it("SetChainGasAmount: should reject non-admin roles", async () => { await expect( From 98e5b4f71cba6120f89232a035d6abc7cd3b5d12 Mon Sep 17 00:00:00 2001 From: ChiTimesChi <88190723+ChiTimesChi@users.noreply.github.com> Date: Sun, 17 Apr 2022 13:51:07 +0300 Subject: [PATCH 049/135] upd RateLimiter test: newSpent == allowance --- test/bridge/RateLimiter.ts | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/test/bridge/RateLimiter.ts b/test/bridge/RateLimiter.ts index 74a4564da..f0084696e 100644 --- a/test/bridge/RateLimiter.ts +++ b/test/bridge/RateLimiter.ts @@ -123,7 +123,10 @@ describe("Rate Limiter", () => { .to.be.not.reverted await expect( - rateLimiterTest.storeCheckAndUpdateAllowance(USDC.address, allowance), + rateLimiterTest.storeCheckAndUpdateAllowance( + USDC.address, + allowance + 1, + ), ).to.be.not.reverted // make sure method returned false From cf32c0f3582e378f9c61702f90578f80a28d8cc8 Mon Sep 17 00:00:00 2001 From: ChiTimesChi <88190723+ChiTimesChi@users.noreply.github.com> Date: Sun, 17 Apr 2022 14:08:27 +0300 Subject: [PATCH 050/135] this actually underflowed --- contracts/bridge/libraries/EnumerableQueueUpgradeable.sol | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/contracts/bridge/libraries/EnumerableQueueUpgradeable.sol b/contracts/bridge/libraries/EnumerableQueueUpgradeable.sol index a16d4176f..adf5622d8 100644 --- a/contracts/bridge/libraries/EnumerableQueueUpgradeable.sol +++ b/contracts/bridge/libraries/EnumerableQueueUpgradeable.sol @@ -146,7 +146,7 @@ library EnumerableQueueUpgradeable { */ function length(KappaQueue storage queue) internal view returns (uint256) { // This never underflows - return queue._head - queue._tail; + return queue._tail - queue._head; } /** @@ -160,9 +160,10 @@ library EnumerableQueueUpgradeable { function peek(KappaQueue storage queue) internal view - returns (bytes memory value, uint32 storedAtMin) + returns (bytes32 key, bytes memory value, uint32 storedAtMin) { - (value, storedAtMin) = get(queue, queue._keys[queue._head]); + key = queue._keys[queue._head]; + (value, storedAtMin) = get(queue, key); } /** From 725e01e02fdea426e8401c55d3e9d41fef1e4976 Mon Sep 17 00:00:00 2001 From: ChiTimesChi <88190723+ChiTimesChi@users.noreply.github.com> Date: Sun, 17 Apr 2022 16:40:13 +0300 Subject: [PATCH 051/135] Use Queue for storing rate limited kappas --- contracts/bridge/RateLimiter.sol | 57 +++++++-------- .../libraries/EnumerableQueueUpgradeable.sol | 72 ++++++++++++------- test/bridge/SynapseBridgeETH.ts | 43 +++++------ 3 files changed, 99 insertions(+), 73 deletions(-) diff --git a/contracts/bridge/RateLimiter.sol b/contracts/bridge/RateLimiter.sol index c958c3f62..25c40f0c8 100644 --- a/contracts/bridge/RateLimiter.sol +++ b/contracts/bridge/RateLimiter.sol @@ -6,7 +6,7 @@ import "@openzeppelin/contracts-4.3.1-upgradeable/access/AccessControlUpgradeabl import "@openzeppelin/contracts-4.3.1-upgradeable/security/ReentrancyGuardUpgradeable.sol"; import "@openzeppelin/contracts-4.3.1-upgradeable/utils/math/MathUpgradeable.sol"; -import "./libraries/EnumerableMapUpgradeable.sol"; +import "./libraries/EnumerableQueueUpgradeable.sol"; import "./interfaces/IRateLimiter.sol"; import "./libraries/Strings.sol"; import "hardhat/console.sol"; @@ -19,7 +19,7 @@ contract RateLimiter is ReentrancyGuardUpgradeable, IRateLimiter { - using EnumerableMapUpgradeable for EnumerableMapUpgradeable.Bytes32ToStructMap; + using EnumerableQueueUpgradeable for EnumerableQueueUpgradeable.KappaQueue; /*** STATE ***/ string public constant NAME = "Rate Limiter"; @@ -33,7 +33,7 @@ contract RateLimiter is // Token -> Allowance mapping(address => Allowance) public allowances; // Kappa->Retry Selector - EnumerableMapUpgradeable.Bytes32ToStructMap private rateLimited; + EnumerableQueueUpgradeable.KappaQueue private rateLimitedQueue; // Bridge Address address public BRIDGE_ADDRESS; @@ -177,47 +177,48 @@ contract RateLimiter is external onlyRole(BRIDGE_ROLE) { - rateLimited.set(kappa, toRetry); + rateLimitedQueue.add(kappa, toRetry); } function retryByKappa(bytes32 kappa) external onlyRole(LIMITER_ROLE) { - (bytes memory toRetry, ) = rateLimited.get(kappa); - (bool success, bytes memory returnData) = BRIDGE_ADDRESS.call(toRetry); - require( - success, - Strings.append("could not call bridge:", _getRevertMsg(returnData)) - ); - rateLimited.remove(kappa); + (bytes memory toRetry, ) = rateLimitedQueue.get(kappa); + if (toRetry.length > 0) { + _retry(kappa, toRetry); + rateLimitedQueue.deleteKey(kappa); + } } function retryCount(uint8 count) external onlyRole(LIMITER_ROLE) { // no issues casting to uint8 here. If length is greater then 255, min is always taken uint8 attempts = uint8( - MathUpgradeable.min(uint256(count), rateLimited.length()) + MathUpgradeable.min(uint256(count), rateLimitedQueue.length()) ); for (uint8 i = 0; i < attempts; i++) { // check out the first element - (bytes32 kappa, bytes memory toRetry, ) = rateLimited.at(0); - (bool success, bytes memory returnData) = BRIDGE_ADDRESS.call( - toRetry - ); - require( - success, - Strings.append( - "could not call bridge for kappa: ", - Strings.toHex(kappa), - " reverted with: ", - _getRevertMsg(returnData) - ) - ); - - rateLimited.remove(kappa); + (bytes32 kappa, bytes memory toRetry, ) = rateLimitedQueue.poll(); + + if (toRetry.length > 0) { + _retry(kappa, toRetry); + } } } + function _retry(bytes32 kappa, bytes memory toRetry) internal { + (bool success, bytes memory returnData) = BRIDGE_ADDRESS.call(toRetry); + require( + success, + Strings.append( + "could not call bridge for kappa: ", + Strings.toHex(kappa), + " reverted with: ", + _getRevertMsg(returnData) + ) + ); + } + function deleteByKappa(bytes32 kappa) external onlyRole(LIMITER_ROLE) { - rateLimited.remove(kappa); + rateLimitedQueue.deleteKey(kappa); } /** diff --git a/contracts/bridge/libraries/EnumerableQueueUpgradeable.sol b/contracts/bridge/libraries/EnumerableQueueUpgradeable.sol index adf5622d8..b549d5c71 100644 --- a/contracts/bridge/libraries/EnumerableQueueUpgradeable.sol +++ b/contracts/bridge/libraries/EnumerableQueueUpgradeable.sol @@ -92,8 +92,8 @@ library EnumerableQueueUpgradeable { /** * @notice Returns data for N-th element of the Queue: * key, value and the time it was stored. - * - * Will return zero values, if `index >= queue.length()`. + * @dev All return variables will be zero, if `index >= queue.length()`. + * `value` will be zero, if `deleteKey(key)` was called previously. */ function at(KappaQueue storage queue, uint256 index) internal @@ -116,7 +116,18 @@ library EnumerableQueueUpgradeable { view returns (bool) { - return queue._data[key].toRetry.length > 0; + return queue._data[key].storedAtMin != 0; + } + + /** + * @notice Delete key from the Queue. + * @dev For gas efficiency we don't use the double-linked queue implementation, + * allowing to remove an arbitrary element. All we're doing is setting + * the stored value for the given key to zero. + * It means, that one should check value obtained by `get(key)` before using it. + */ + function deleteKey(KappaQueue storage queue, bytes32 key) internal { + queue._data[key].toRetry = bytes(""); } /** @@ -127,18 +138,19 @@ library EnumerableQueueUpgradeable { } /** - * @notice Gets data associated with the given `key`: - * value and the time it was stored. - * - * Will return zero values for `key` that is not the Queue. + * @notice Gets data associated with the given `key`: value and the time it was stored. + * @dev All return variables will be zero, if `key` is not added to the Queue. + * `value` will be zero, if `deleteKey(key)` was called previously. */ function get(KappaQueue storage queue, bytes32 key) internal view returns (bytes memory value, uint32 storedAtMin) { - RetryableTx memory data = queue._data[key]; - (value, storedAtMin) = (data.toRetry, data.storedAtMin); + (value, storedAtMin) = ( + queue._data[key].toRetry, + queue._data[key].storedAtMin + ); } /** @@ -150,39 +162,49 @@ library EnumerableQueueUpgradeable { } /** - * @notice Returns the head of Queue, without removing it: - * value and the time it was stored. - - * Will return zero values, if Queue is empty. - * - * Head is always the element that has been added first. + * @notice Returns data for the first (head) element from + * the Queue, without removing it. + * Data: key, value and the time it was stored. + * @dev All return variables will be zero, Queue is empty. + * `value` will be zero, if `deleteKey(key)` was called previously. */ function peek(KappaQueue storage queue) internal view - returns (bytes32 key, bytes memory value, uint32 storedAtMin) + returns ( + bytes32 key, + bytes memory value, + uint32 storedAtMin + ) { key = queue._keys[queue._head]; (value, storedAtMin) = get(queue, key); } /** - * @notice Removes the first (head) element from the Queue. - * - * Returns true, only if element was deleted. - * Returns false, if Queue was empty. + * @notice Returns data for the first (head) element from + * the Queue and removes the element from Queue. + * Data: key, value and the time it was stored. + * @dev All return variables will be zero, Queue is empty. + * `value` will be zero, if `deleteKey(key)` was called previously. */ - function poll(KappaQueue storage queue) internal returns (bool) { + function poll(KappaQueue storage queue) + internal + returns ( + bytes32 key, + bytes memory value, + uint32 storedAtMin + ) + { uint256 head = queue._head; uint256 tail = queue._tail; if (head != tail) { - bytes32 headKey = queue._keys[head]; + key = queue._keys[head]; + (value, storedAtMin) = get(queue, key); queue._head++; delete queue._keys[head]; - delete queue._data[headKey]; - return true; + delete queue._data[key]; } - return false; } } diff --git a/test/bridge/SynapseBridgeETH.ts b/test/bridge/SynapseBridgeETH.ts index 89e833c05..6b8d39299 100644 --- a/test/bridge/SynapseBridgeETH.ts +++ b/test/bridge/SynapseBridgeETH.ts @@ -208,28 +208,31 @@ describe("SynapseBridgeETH", async () => { it("RetryCount: should be able to clear the Retry Queue", async () => { const allowanceAmount = getBigNumber(100) const amount = allowanceAmount.add(1) - const kappas = [ - keccak256(randomBytes(32)), - keccak256(randomBytes(32)), - keccak256(randomBytes(32)), - keccak256(randomBytes(32)), - ] - await setupAllowanceTest(SYN, allowanceAmount) - for (let kappa of kappas) { - await bridge - .connect(nodeGroup) - .mint(await recipient.getAddress(), SYN, amount, 0, kappa) - - // This should BE rate limited - expect(await bridge.kappaExists(kappa)).to.be.false - } - - await rateLimiter.retryCount(kappas.length) - - for (let kappa of kappas) { - expect(await bridge.kappaExists(kappa)).to.be.true + // Should be able to fully clear twice + for (let i = 0; i <= 1; ++i) { + const kappas = [ + keccak256(randomBytes(32)), + keccak256(randomBytes(32)), + keccak256(randomBytes(32)), + keccak256(randomBytes(32)), + ] + + for (let kappa of kappas) { + await bridge + .connect(nodeGroup) + .mint(await recipient.getAddress(), SYN, amount, 0, kappa) + + // This should BE rate limited + expect(await bridge.kappaExists(kappa)).to.be.false + } + + await rateLimiter.retryCount(kappas.length) + + for (let kappa of kappas) { + expect(await bridge.kappaExists(kappa)).to.be.true + } } }) From ce2ce55790eef7a4a659c05d198de1de38dd3db3 Mon Sep 17 00:00:00 2001 From: ChiTimesChi <88190723+ChiTimesChi@users.noreply.github.com> Date: Sun, 17 Apr 2022 16:42:03 +0300 Subject: [PATCH 052/135] no need to check for overflow in 0.8+ --- contracts/bridge/RateLimiter.sol | 6 ------ 1 file changed, 6 deletions(-) diff --git a/contracts/bridge/RateLimiter.sol b/contracts/bridge/RateLimiter.sol index 25c40f0c8..9fc43e071 100644 --- a/contracts/bridge/RateLimiter.sol +++ b/contracts/bridge/RateLimiter.sol @@ -156,12 +156,6 @@ contract RateLimiter is // @dev reverts if amount > (2^96 - 1) uint96 newSpent = allowance.spent + uint96(amount); - // Check overflow - require( - newSpent > allowance.spent, - "overflow detected: newSpent > allowance.spent" - ); - // do not proceed. Store the transaction for later if (newSpent > allowance.amount) { return false; From 4b3a83fea6df3508e2e9b951808df6a189682e77 Mon Sep 17 00:00:00 2001 From: ChiTimesChi <88190723+ChiTimesChi@users.noreply.github.com> Date: Mon, 18 Apr 2022 00:05:58 +0300 Subject: [PATCH 053/135] add permissionless retry timeout --- contracts/bridge/RateLimiter.sol | 27 ++++++++++++++++++++++-- test/bridge/SynapseBridgeETH.ts | 35 ++++++++++++++++++++++++++------ 2 files changed, 54 insertions(+), 8 deletions(-) diff --git a/contracts/bridge/RateLimiter.sol b/contracts/bridge/RateLimiter.sol index 9fc43e071..2cac190e7 100644 --- a/contracts/bridge/RateLimiter.sol +++ b/contracts/bridge/RateLimiter.sol @@ -11,6 +11,8 @@ import "./interfaces/IRateLimiter.sol"; import "./libraries/Strings.sol"; import "hardhat/console.sol"; +// solhint-disable not-rely-on-time + // @title RateLimiter // @dev a bridge asset rate limiter based on https://github.com/gnosis/safe-modules/blob/master/allowances/contracts/AlowanceModule.sol contract RateLimiter is @@ -36,6 +38,9 @@ contract RateLimiter is EnumerableQueueUpgradeable.KappaQueue private rateLimitedQueue; // Bridge Address address public BRIDGE_ADDRESS; + // Time period after anyone can retry a rate limited tx + uint32 public retryTimeout = 360; + uint32 public constant MIN_RETRY_TIMEOUT = 60; // List of tokens address[] public tokens; @@ -74,6 +79,14 @@ contract RateLimiter is BRIDGE_ADDRESS = bridge; } + function setRetryTimeout(uint32 _retryTimeout) + external + onlyRole(GOVERNANCE_ROLE) + { + require(_retryTimeout >= MIN_RETRY_TIMEOUT, "Timeout too short"); + retryTimeout = _retryTimeout; + } + /** * @notice Updates the allowance for a given token * @param token to update the allowance for @@ -174,9 +187,19 @@ contract RateLimiter is rateLimitedQueue.add(kappa, toRetry); } - function retryByKappa(bytes32 kappa) external onlyRole(LIMITER_ROLE) { - (bytes memory toRetry, ) = rateLimitedQueue.get(kappa); + function retryByKappa(bytes32 kappa) external { + (bytes memory toRetry, uint32 storedAtMin) = rateLimitedQueue.get( + kappa + ); if (toRetry.length > 0) { + if (!hasRole(LIMITER_ROLE, msg.sender)) { + // Permissionless retry is only available once timeout is finished + uint32 currentMin = uint32(block.timestamp / 60); + require( + currentMin >= storedAtMin + retryTimeout, + "Retry timeout not finished" + ); + } _retry(kappa, toRetry); rateLimitedQueue.deleteKey(kappa); } diff --git a/test/bridge/SynapseBridgeETH.ts b/test/bridge/SynapseBridgeETH.ts index 6b8d39299..246d6e9a5 100644 --- a/test/bridge/SynapseBridgeETH.ts +++ b/test/bridge/SynapseBridgeETH.ts @@ -9,7 +9,7 @@ import { keccak256 } from "ethers/lib/utils" import { randomBytes } from "crypto" import { forkChain, MAX_UINT256 } from "../utils" import { deployRateLimiter, setupForkedBridge } from "./utilities/bridge" -import { getBigNumber } from "./utilities" +import { advanceTime, getBigNumber } from "./utilities" chai.use(solidity) const { expect } = chai @@ -270,6 +270,31 @@ describe("SynapseBridgeETH", async () => { } }) + it("Permissionless timeout for retryByKappa", async () => { + const allowanceAmount = getBigNumber(100) + const amount = allowanceAmount.add(1) + + const kappa = keccak256(randomBytes(32)) + await setupAllowanceTest(SYN, allowanceAmount) + + await bridge + .connect(nodeGroup) + .mint(await recipient.getAddress(), SYN, amount, 0, kappa) + + // This should BE rate limited + expect(await bridge.kappaExists(kappa)).to.be.false + + await expect( + rateLimiter.connect(deployer).retryByKappa(kappa), + ).to.be.revertedWith("Retry timeout not finished") + + await advanceTime(360 * 60) + + await rateLimiter.connect(deployer).retryByKappa(kappa) + // Timeout finished, should be good to go + expect(await bridge.kappaExists(kappa)).to.be.true + }) + // check permissions it("SetChainGasAmount: should reject non-admin roles", async () => { await expect( @@ -283,12 +308,10 @@ describe("SynapseBridgeETH", async () => { ).to.be.revertedWith("Not admin") }) - it.skip("SetRateLimiter: should reject non-governance roles", async () => { + it("SetRateLimiter: should reject non-admin roles", async () => { await expect( - bridge - .connect(attacker) - .withdrawFees(USDC.address, await recipient.getAddress()), - ).to.be.revertedWith("Not governance") + bridge.connect(attacker).setRateLimiter(rateLimiter.address), + ).to.be.revertedWith("Not admin") }) it("AddKappas: should reject non-admin roles", async () => { From 5eac97618cb0325714a61e84e59a1fc6aa0d3d71 Mon Sep 17 00:00:00 2001 From: ChiTimesChi <88190723+ChiTimesChi@users.noreply.github.com> Date: Mon, 18 Apr 2022 01:49:19 +0300 Subject: [PATCH 054/135] store failed txs separately --- contracts/bridge/RateLimiter.sol | 40 ++++++++++++++++++++++++-------- 1 file changed, 30 insertions(+), 10 deletions(-) diff --git a/contracts/bridge/RateLimiter.sol b/contracts/bridge/RateLimiter.sol index 2cac190e7..57c8eb9b1 100644 --- a/contracts/bridge/RateLimiter.sol +++ b/contracts/bridge/RateLimiter.sol @@ -13,6 +13,10 @@ import "hardhat/console.sol"; // solhint-disable not-rely-on-time +interface IBridge { + function kappaExists(bytes32 kappa) external view returns (bool); +} + // @title RateLimiter // @dev a bridge asset rate limiter based on https://github.com/gnosis/safe-modules/blob/master/allowances/contracts/AlowanceModule.sol contract RateLimiter is @@ -36,6 +40,7 @@ contract RateLimiter is mapping(address => Allowance) public allowances; // Kappa->Retry Selector EnumerableQueueUpgradeable.KappaQueue private rateLimitedQueue; + mapping(bytes32 => bytes) private failedRetries; // Bridge Address address public BRIDGE_ADDRESS; // Time period after anyone can retry a rate limited tx @@ -221,17 +226,32 @@ contract RateLimiter is } } + function retryFailed(bytes32 kappa) external { + bytes memory toRetry = failedRetries[kappa]; + if (toRetry.length > 0) { + (bool success, bytes memory returnData) = BRIDGE_ADDRESS.call( + toRetry + ); + require( + success, + Strings.append( + "could not call bridge for kappa: ", + Strings.toHex(kappa), + " reverted with: ", + _getRevertMsg(returnData) + ) + ); + } + failedRetries[kappa] = bytes(""); + } + function _retry(bytes32 kappa, bytes memory toRetry) internal { - (bool success, bytes memory returnData) = BRIDGE_ADDRESS.call(toRetry); - require( - success, - Strings.append( - "could not call bridge for kappa: ", - Strings.toHex(kappa), - " reverted with: ", - _getRevertMsg(returnData) - ) - ); + (bool success, ) = BRIDGE_ADDRESS.call(toRetry); + if (!success && !IBridge(BRIDGE_ADDRESS).kappaExists(kappa)) { + // save payload for failed transactions + // that haven't been processed by Bridge yet + failedRetries[kappa] = toRetry; + } } function deleteByKappa(bytes32 kappa) external onlyRole(LIMITER_ROLE) { From 248120ea3cc7a241264c7032621f3549a61214b0 Mon Sep 17 00:00:00 2001 From: ChiTimesChi <88190723+ChiTimesChi@users.noreply.github.com> Date: Mon, 18 Apr 2022 17:53:25 +0300 Subject: [PATCH 055/135] retryByKappa can now retry a failed tx --- contracts/bridge/RateLimiter.sol | 8 +++-- test/bridge/SynapseBridgeETH.ts | 60 ++++++++++++++++++++++++++++++-- 2 files changed, 64 insertions(+), 4 deletions(-) diff --git a/contracts/bridge/RateLimiter.sol b/contracts/bridge/RateLimiter.sol index 57c8eb9b1..eaa338a28 100644 --- a/contracts/bridge/RateLimiter.sol +++ b/contracts/bridge/RateLimiter.sol @@ -207,6 +207,10 @@ contract RateLimiter is } _retry(kappa, toRetry); rateLimitedQueue.deleteKey(kappa); + } else { + // Try looking up in the failed txs: + // anyone should be able to do so, with no timeout + _retryFailed(kappa); } } @@ -226,7 +230,7 @@ contract RateLimiter is } } - function retryFailed(bytes32 kappa) external { + function _retryFailed(bytes32 kappa) internal { bytes memory toRetry = failedRetries[kappa]; if (toRetry.length > 0) { (bool success, bytes memory returnData) = BRIDGE_ADDRESS.call( @@ -241,8 +245,8 @@ contract RateLimiter is _getRevertMsg(returnData) ) ); + failedRetries[kappa] = bytes(""); } - failedRetries[kappa] = bytes(""); } function _retry(bytes32 kappa, bytes memory toRetry) internal { diff --git a/test/bridge/SynapseBridgeETH.ts b/test/bridge/SynapseBridgeETH.ts index 246d6e9a5..58166e263 100644 --- a/test/bridge/SynapseBridgeETH.ts +++ b/test/bridge/SynapseBridgeETH.ts @@ -4,10 +4,15 @@ import { solidity } from "ethereum-waffle" import { deployments, ethers } from "hardhat" import chai from "chai" -import { GenericERC20, RateLimiter, SynapseBridge } from "../../build/typechain" +import { + GenericERC20, + RateLimiter, + SynapseBridge, + SynapseERC20, +} from "../../build/typechain" import { keccak256 } from "ethers/lib/utils" import { randomBytes } from "crypto" -import { forkChain, MAX_UINT256 } from "../utils" +import { forkChain, impersonateAccount, MAX_UINT256 } from "../utils" import { deployRateLimiter, setupForkedBridge } from "./utilities/bridge" import { advanceTime, getBigNumber } from "./utilities" @@ -295,6 +300,57 @@ describe("SynapseBridgeETH", async () => { expect(await bridge.kappaExists(kappa)).to.be.true }) + it("Failed retried txs are saved for later use", async () => { + let syn = (await ethers.getContractAt("SynapseERC20", SYN)) as SynapseERC20 + const adminAddress = await syn.getRoleMember( + await syn.DEFAULT_ADMIN_ROLE(), + 0, + ) + const admin = await impersonateAccount(adminAddress) + syn = syn.connect(admin) + + const allowanceAmount = getBigNumber(100) + const amount = allowanceAmount.add(1) + + await setupAllowanceTest(SYN, allowanceAmount) + await setupAllowanceTest(NUSD, allowanceAmount) + + const kappas = [ + keccak256(randomBytes(32)), + keccak256(randomBytes(32)), + keccak256(randomBytes(32)), + ] + + // [withdraw NUSD, mint SYN, withdraw NUSD] + for (let index in kappas) { + const kappa = kappas[index] + if (index === "1") { + await bridge + .connect(nodeGroup) + .mint(await recipient.getAddress(), SYN, amount, 0, kappa) + } else { + await bridge + .connect(nodeGroup) + .withdraw(await recipient.getAddress(), NUSD, amount, 0, kappa) + } + // This should BE rate limited + expect(await bridge.kappaExists(kappa)).to.be.false + } + + // Minting SYN is not possible => minting tx will fail on retry + await syn.revokeRole(await syn.MINTER_ROLE(), bridge.address) + + await rateLimiter.retryCount(kappas.length) + expect(await bridge.kappaExists(kappas[0])).to.be.true + expect(await bridge.kappaExists(kappas[1])).to.be.false + expect(await bridge.kappaExists(kappas[2])).to.be.true + + await syn.grantRole(await syn.MINTER_ROLE(), bridge.address) + + await rateLimiter.retryByKappa(kappas[1]) + expect(await bridge.kappaExists(kappas[1])).to.be.true + }) + // check permissions it("SetChainGasAmount: should reject non-admin roles", async () => { await expect( From 06b95c84ff8975ea30c1b408a5ead1829b8d7f82 Mon Sep 17 00:00:00 2001 From: Trajan0x Date: Thu, 21 Apr 2022 21:27:50 -0400 Subject: [PATCH 056/135] rate-limiter --- contracts/bridge/SynapseBridge.sol | 10 ++++++++-- package-lock.json | 9 +++++---- test/bridge/RateLimiter.ts | 1 - test/bridge/SynapseBridgeETH.ts | 2 +- test/bridge/Upgradeable.ts | 4 ---- test/bridge/utilities/bridge.ts | 7 +++++++ 6 files changed, 21 insertions(+), 12 deletions(-) diff --git a/contracts/bridge/SynapseBridge.sol b/contracts/bridge/SynapseBridge.sol index 2e8614638..606d4bb4c 100644 --- a/contracts/bridge/SynapseBridge.sol +++ b/contracts/bridge/SynapseBridge.sol @@ -44,6 +44,7 @@ contract SynapseBridge is // rate limiter IRateLimiter public rateLimiter; + bool rateLimiterEnabled; // new role @@ -68,10 +69,15 @@ contract SynapseBridge is } function setRateLimiter(IRateLimiter _rateLimiter) external { - require(hasRole(DEFAULT_ADMIN_ROLE, msg.sender), "Not admin"); + require(hasRole(GOVERNANCE_ROLE, msg.sender), "Not governance"); rateLimiter = _rateLimiter; } + function setRateLimiterEnabled(bool enabled) external { + require(hasRole(GOVERNANCE_ROLE, msg.sender), "Not governance"); + rateLimiterEnabled = enabled; + } + function addKappas(bytes32[] calldata kappas) external { require(hasRole(GOVERNANCE_ROLE, msg.sender), "Not governance"); for (uint256 i = 0; i < kappas.length; ++i) { @@ -212,7 +218,7 @@ contract SynapseBridge is internal returns (bool) { - if (address(rateLimiter) == address(0)) { + if (!rateLimiterEnabled || address(rateLimiter) == address(0)) { return false; } diff --git a/package-lock.json b/package-lock.json index 3f377c1d9..4d5498505 100644 --- a/package-lock.json +++ b/package-lock.json @@ -5,6 +5,7 @@ "requires": true, "packages": { "": { + "name": "synapse-contracts", "version": "1.0.0", "license": "ISC", "dependencies": { @@ -29871,7 +29872,6 @@ "resolved": "https://registry.npmjs.org/squirrelly/-/squirrelly-8.0.8.tgz", "integrity": "sha512-7dyZJ9Gw86MmH0dYLiESsjGOTj6KG8IWToTaqBuB6LwPI+hyNb6mbQaZwrfnAQ4cMDnSWMUvX/zAYDLTSWLk/w==", "dev": true, - "peer": true, "engines": { "node": ">=6.0.0" }, @@ -35313,7 +35313,9 @@ "resolved": "https://registry.npmjs.org/@primitivefi/hardhat-dodoc/-/hardhat-dodoc-0.2.3.tgz", "integrity": "sha512-ver9uHa79LTDTeebOKZ/eOVRL/FP1k0s0x/5Bo/8ZaDdLWFVClKqZyZYVjjW4CJqTPCt8uU9b9p71P2vzH4O9A==", "dev": true, - "requires": {} + "requires": { + "squirrelly": "^8.0.8" + } }, "@resolver-engine/core": { "version": "0.3.3", @@ -57888,8 +57890,7 @@ "version": "8.0.8", "resolved": "https://registry.npmjs.org/squirrelly/-/squirrelly-8.0.8.tgz", "integrity": "sha512-7dyZJ9Gw86MmH0dYLiESsjGOTj6KG8IWToTaqBuB6LwPI+hyNb6mbQaZwrfnAQ4cMDnSWMUvX/zAYDLTSWLk/w==", - "dev": true, - "peer": true + "dev": true }, "sshpk": { "version": "1.16.1", diff --git a/test/bridge/RateLimiter.ts b/test/bridge/RateLimiter.ts index 74a4564da..5fbce779e 100644 --- a/test/bridge/RateLimiter.ts +++ b/test/bridge/RateLimiter.ts @@ -5,7 +5,6 @@ import { BigNumber, BigNumberish, Signer } from "ethers" import { getCurrentBlockTimestamp } from "./testUtils" import { RateLimiter } from "../../build/typechain/RateLimiter" import { GenericERC20, RateLimiterTest } from "../../build/typechain" -import epochSeconds from "@stdlib/time-now" chai.use(solidity) const { expect, assert } = chai diff --git a/test/bridge/SynapseBridgeETH.ts b/test/bridge/SynapseBridgeETH.ts index c1f122738..9c9518961 100644 --- a/test/bridge/SynapseBridgeETH.ts +++ b/test/bridge/SynapseBridgeETH.ts @@ -176,7 +176,7 @@ describe("SynapseBridgeETH", async () => { ).to.be.revertedWith("Not admin") }) - it.skip("SetRateLimiter: should reject non-governance roles", async () => { + it("SetRateLimiter: should reject non-governance roles", async () => { await expect( bridge .connect(attacker) diff --git a/test/bridge/Upgradeable.ts b/test/bridge/Upgradeable.ts index d936072f1..cf73abd25 100644 --- a/test/bridge/Upgradeable.ts +++ b/test/bridge/Upgradeable.ts @@ -1,14 +1,10 @@ import { Signer } from "ethers" -import { getCurrentBlockTimestamp } from "./testUtils" import { String } from "typescript-string-operations" import { solidity } from "ethereum-waffle" import { deployments, ethers } from "hardhat" import chai from "chai" import { GenericERC20, RateLimiter, SynapseBridge } from "../../build/typechain" -import epochSeconds from "@stdlib/time-now" -import { id, keccak256 } from "ethers/lib/utils" -import { randomBytes } from "crypto" import { forkChain } from "../utils" import { deployRateLimiter, setupForkedBridge } from "./utilities/bridge" import sinon from "sinon" diff --git a/test/bridge/utilities/bridge.ts b/test/bridge/utilities/bridge.ts index da7d93613..641ba9057 100644 --- a/test/bridge/utilities/bridge.ts +++ b/test/bridge/utilities/bridge.ts @@ -53,7 +53,14 @@ export async function setupForkedBridge(rateLimiter: RateLimiter, bridgeAddress: .connect(deployer) .grantRole(rateLimiterRole, rateLimiter.address) + // grant governance role so rate limiter can be set + const governanceRole = await bridge.GOVERNANCE_ROLE() + await bridge + .connect(deployer) + .grantRole(governanceRole, await deployer.getAddress()) + await bridge.setRateLimiter(rateLimiter.address) + await bridge.setRateLimiterEnabled(true) const nodeGroupRole = await bridge.NODEGROUP_ROLE() await bridge From 2afb9663974d6bd7aeffdd70167809d8e0496eeb Mon Sep 17 00:00:00 2001 From: ChiTimesChi <88190723+ChiTimesChi@users.noreply.github.com> Date: Wed, 20 Apr 2022 17:50:48 +0300 Subject: [PATCH 057/135] forge install: forge-std --- .gitmodules | 3 +++ lib/forge-std | 1 + 2 files changed, 4 insertions(+) create mode 100644 .gitmodules create mode 160000 lib/forge-std diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 000000000..888d42dcd --- /dev/null +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "lib/forge-std"] + path = lib/forge-std + url = https://github.com/foundry-rs/forge-std diff --git a/lib/forge-std b/lib/forge-std new file mode 160000 index 000000000..bcc9992b5 --- /dev/null +++ b/lib/forge-std @@ -0,0 +1 @@ +Subproject commit bcc9992b5fddb91f1c515da6341de087922efcd7 From 4a74723670a797f120de94a7d0aaf8fa8a90271c Mon Sep 17 00:00:00 2001 From: ChiTimesChi <88190723+ChiTimesChi@users.noreply.github.com> Date: Wed, 20 Apr 2022 17:51:08 +0300 Subject: [PATCH 058/135] forge install: ds-test --- .gitmodules | 3 +++ lib/ds-test | 1 + 2 files changed, 4 insertions(+) create mode 160000 lib/ds-test diff --git a/.gitmodules b/.gitmodules index 888d42dcd..4b4c42b75 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,3 +1,6 @@ [submodule "lib/forge-std"] path = lib/forge-std url = https://github.com/foundry-rs/forge-std +[submodule "lib/ds-test"] + path = lib/ds-test + url = https://github.com/dapphub/ds-test diff --git a/lib/ds-test b/lib/ds-test new file mode 160000 index 000000000..2c7dbcc85 --- /dev/null +++ b/lib/ds-test @@ -0,0 +1 @@ +Subproject commit 2c7dbcc8586b33f358e3307a443e524490c17666 From 033913ffa871ea1d5b7041822456d2c79368c0e3 Mon Sep 17 00:00:00 2001 From: ChiTimesChi <88190723+ChiTimesChi@users.noreply.github.com> Date: Wed, 20 Apr 2022 17:54:27 +0300 Subject: [PATCH 059/135] foundry setup --- foundry.toml | 19 +++++++++++++++++++ remappings.txt | 2 ++ 2 files changed, 21 insertions(+) create mode 100644 foundry.toml create mode 100644 remappings.txt diff --git a/foundry.toml b/foundry.toml new file mode 100644 index 000000000..0cf91d2a0 --- /dev/null +++ b/foundry.toml @@ -0,0 +1,19 @@ +[default] +optimizer = true +optimizer_runs = 200 +auto_detect_solc = true +src = "contracts" +out = "artifacts" +libs = ["node_modules"] +verbosity = 2 + +## set only when the `hardhat` profile is selected +[hardhat] +src = "contracts" +out = "artifacts" +libs = ["node_modules"] + +[ci] +verbosity = 4 + +# See more config options https://github.com/gakonst/foundry/tree/master/config \ No newline at end of file diff --git a/remappings.txt b/remappings.txt new file mode 100644 index 000000000..ab4c302d3 --- /dev/null +++ b/remappings.txt @@ -0,0 +1,2 @@ +ds-test/=lib/ds-test/src/ +forge-std=lib/forge-std/src \ No newline at end of file From 7daa4b3d27e912de54b6ea4cc3fdb6dbd0cb9992 Mon Sep 17 00:00:00 2001 From: ChiTimesChi <88190723+ChiTimesChi@users.noreply.github.com> Date: Sat, 23 Apr 2022 17:04:05 +0300 Subject: [PATCH 060/135] implementation without FIFO + tests --- .../libraries/EnumerableQueueUpgradeable.sol | 22 ++-- .../bridge/libraries/KappaMapUpgradeable.sol | 83 +++++++++++++ test/bridge/limiter/FasterMap.t.sol | 109 ++++++++++++++++++ test/bridge/limiter/Map.t.sol | 104 +++++++++++++++++ test/bridge/limiter/Queue.t.sol | 105 +++++++++++++++++ 5 files changed, 414 insertions(+), 9 deletions(-) create mode 100644 contracts/bridge/libraries/KappaMapUpgradeable.sol create mode 100644 test/bridge/limiter/FasterMap.t.sol create mode 100644 test/bridge/limiter/Map.t.sol create mode 100644 test/bridge/limiter/Queue.t.sol diff --git a/contracts/bridge/libraries/EnumerableQueueUpgradeable.sol b/contracts/bridge/libraries/EnumerableQueueUpgradeable.sol index b549d5c71..ac9176e48 100644 --- a/contracts/bridge/libraries/EnumerableQueueUpgradeable.sol +++ b/contracts/bridge/libraries/EnumerableQueueUpgradeable.sol @@ -54,11 +54,11 @@ library EnumerableQueueUpgradeable { /// @dev Data map for each key. mapping(bytes32 => RetryableTx) _data; /// @dev Index of the first Queue key. - uint256 _head; + uint128 _head; /// @dev Index following the last Queue key, i.e. /// index, where newly added key would reside. /// _head == _tail => Queue is empty - uint256 _tail; + uint128 _tail; } /** @@ -77,15 +77,14 @@ library EnumerableQueueUpgradeable { return false; } - uint256 toInsert = queue._tail; - - queue._tail++; - queue._keys[toInsert] = key; + queue._keys[queue._tail] = key; queue._data[key] = RetryableTx({ storedAtMin: uint32(block.timestamp / 60), toRetry: value }); + ++queue._tail; + return true; } @@ -196,15 +195,20 @@ library EnumerableQueueUpgradeable { uint32 storedAtMin ) { - uint256 head = queue._head; - uint256 tail = queue._tail; + (uint256 head, uint256 tail) = (queue._head, queue._tail); if (head != tail) { key = queue._keys[head]; (value, storedAtMin) = get(queue, key); - queue._head++; delete queue._keys[head]; delete queue._data[key]; + + ++head; + if (head == tail) { + (queue._head, queue._tail) = (0, 0); + } else { + queue._head = uint128(head); + } } } } diff --git a/contracts/bridge/libraries/KappaMapUpgradeable.sol b/contracts/bridge/libraries/KappaMapUpgradeable.sol new file mode 100644 index 000000000..83d07139a --- /dev/null +++ b/contracts/bridge/libraries/KappaMapUpgradeable.sol @@ -0,0 +1,83 @@ +// SPDX-License-Identifier: MIT + +pragma solidity ^0.8.0; + +library KappaMapUpgradeable { + struct RetryableTx { + /// @dev epoch time in minutes the tx was stored at. Always non-zero on initialized struct + uint32 storedAtMin; + /// @dev bridge calldata for retrying + bytes toRetry; + } + + struct KappaMap { + mapping(bytes32 => RetryableTx) _data; + } + + /** + * @notice Adds [key, value] pair to the `map`. Will not to anything, if + * a key already exists in the `map`. + * + * Returns true only if [key, value] was added to the Queue. + */ + function add( + KappaMap storage map, + bytes32 key, + bytes memory value + ) internal returns (bool) { + if (contains(map, key)) { + // key already exists, don't add anything + return false; + } + + map._data[key] = RetryableTx({ + storedAtMin: uint32(block.timestamp / 60), + toRetry: value + }); + + return true; + } + + /** + * @notice Checks whether `key` is present in the Queue. + */ + function contains(KappaMap storage map, bytes32 key) + internal + view + returns (bool) + { + return map._data[key].storedAtMin != 0; + } + + /** + * @notice Gets data associated with the given `key`: value and the time it was stored, + * without removing `key` from the Map. + * @dev All return variables will be zero, if `key` is not added to the Map. + */ + function get(KappaMap storage map, bytes32 key) + internal + view + returns (bytes memory value, uint32 storedAtMin) + { + (value, storedAtMin) = ( + map._data[key].toRetry, + map._data[key].storedAtMin + ); + } + + /** + * @notice Gets data associated with the given `key`: value and the time it was stored, + * while removing `key` from the Map. + * @dev All return variables will be zero, if `key` is not added to the Map. + */ + function remove(KappaMap storage map, bytes32 key) + internal + returns (bytes memory value, uint32 storedAtMin) + { + (value, storedAtMin) = ( + map._data[key].toRetry, + map._data[key].storedAtMin + ); + delete map._data[key]; + } +} diff --git a/test/bridge/limiter/FasterMap.t.sol b/test/bridge/limiter/FasterMap.t.sol new file mode 100644 index 000000000..8b75b35cb --- /dev/null +++ b/test/bridge/limiter/FasterMap.t.sol @@ -0,0 +1,109 @@ +// SPDX-License-Identifier: MIT +pragma solidity >=0.8.0; + +import "forge-std/Test.sol"; + +import {KappaMapUpgradeable} from "contracts/bridge/libraries/KappaMapUpgradeable.sol"; + +contract FasterMapTest is Test { + using KappaMapUpgradeable for KappaMapUpgradeable.KappaMap; + + KappaMapUpgradeable.KappaMap internal map; + + uint256 internal constant AMOUNT = 5; + + function setUp() public { + vm.warp(14000000); + } + + // Add to Full (F) map, then remove all + function testAdd1F(bytes32 key) public { + vm.assume(key != bytes32(0)); + _add(key, 4 * AMOUNT); + _poll(key, 4 * AMOUNT); + } + + // Add to map, then remove until it's empty (E) two times + function testAdd2E(bytes32 key) public { + vm.assume(key != bytes32(0)); + for (uint256 i = 0; i < 2; ++i) { + bytes32 newKey = _add(key, 2 * AMOUNT); + _poll(key, 2 * AMOUNT); + key = newKey; + } + } + + // Add to map, then remove until it's empty (E) three times + function testAdd3E(bytes32 key) public { + vm.assume(key != bytes32(0)); + for (uint256 i = 0; i < 3; ++i) { + uint256 amount = i == 0 ? 2 * AMOUNT : AMOUNT; + bytes32 newKey = _add(key, amount); + _poll(key, amount); + key = newKey; + } + } + + // Add to map, then remove until it's empty (E) four times + function testAdd4E(bytes32 key) public { + vm.assume(key != bytes32(0)); + for (uint256 i = 0; i < 4; ++i) { + bytes32 newKey = _add(key, AMOUNT); + _poll(key, AMOUNT); + key = newKey; + } + } + + function testUsage(bytes32 key) public { + vm.assume(key != bytes32(0)); + for (uint256 i = 0; i < 4; ++i) { + bytes32 newKey = _addCheck(key, AMOUNT); + _pollCheck(key, AMOUNT); + key = newKey; + } + } + + function _add(bytes32 key, uint256 amount) internal returns (bytes32) { + for (uint256 i = 0; i < amount; i++) { + bytes memory value = abi.encode(key); + assertTrue(map.add(key, value)); + key = keccak256(value); + } + return key; + } + + function _addCheck(bytes32 key, uint256 amount) internal returns (bytes32) { + for (uint256 i = 0; i < amount; i++) { + assertTrue(!map.contains(key), "Key already present"); + bytes memory value = abi.encode(key); + assertTrue(map.add(key, value), "Key not added"); + assertTrue(map.contains(key), "New key not found"); + + (bytes memory _value, ) = map.get(key); + key = keccak256(value); + assertTrue(key == keccak256(_value), "Value doesn't match"); + } + return key; + } + + function _poll(bytes32 key, uint256 amount) internal { + for (uint256 i = 0; i < amount; i++) { + map.remove(key); + key = keccak256(abi.encode(key)); + } + } + + function _pollCheck(bytes32 key, uint256 amount) internal { + for (uint256 i = 0; i < amount; i++) { + (bytes memory value, ) = map.remove(key); + bytes32 newKey = keccak256(abi.encode(key)); + + assertTrue(!map.contains(key), "Key not deleted"); + assertTrue(newKey == keccak256(value), "Wrong value"); + + (value, ) = map.get(key); + assertTrue(value.length == 0, "Data remains after deletion"); + key = newKey; + } + } +} diff --git a/test/bridge/limiter/Map.t.sol b/test/bridge/limiter/Map.t.sol new file mode 100644 index 000000000..c7ca20a02 --- /dev/null +++ b/test/bridge/limiter/Map.t.sol @@ -0,0 +1,104 @@ +// SPDX-License-Identifier: MIT +pragma solidity >=0.8.0; + +import "forge-std/Test.sol"; + +import {EnumerableMapUpgradeable} from "contracts/bridge/libraries/EnumerableMapUpgradeable.sol"; + +contract MapTest is Test { + using EnumerableMapUpgradeable for EnumerableMapUpgradeable.Bytes32ToStructMap; + + EnumerableMapUpgradeable.Bytes32ToStructMap internal map; + + uint256 internal constant AMOUNT = 5; + + function setUp() public { + vm.warp(14000000); + } + + // Add to Full (F) map, then remove all + function testAdd1F(bytes32 key) public { + vm.assume(key != bytes32(0)); + _add(key, 4 * AMOUNT); + _poll(4 * AMOUNT); + } + + // Add to map, then remove until it's empty (E) two times + function testAdd2E(bytes32 key) public { + vm.assume(key != bytes32(0)); + for (uint256 i = 0; i < 2; ++i) { + key = _add(key, 2 * AMOUNT); + _poll(2 * AMOUNT); + } + } + + // Add to map, then remove until it's empty (E) three times + function testAdd3E(bytes32 key) public { + vm.assume(key != bytes32(0)); + for (uint256 i = 0; i < 3; ++i) { + uint256 amount = i == 0 ? 2 * AMOUNT : AMOUNT; + key = _add(key, amount); + _poll(amount); + } + } + + // Add to map, then remove until it's empty (E) four times + function testAdd4E(bytes32 key) public { + vm.assume(key != bytes32(0)); + for (uint256 i = 0; i < 4; ++i) { + key = _add(key, AMOUNT); + _poll(AMOUNT); + } + } + + function testUsage(bytes32 key) public { + vm.assume(key != bytes32(0)); + for (uint256 i = 0; i < 4; ++i) { + key = _addCheck(key, AMOUNT); + _pollCheck(AMOUNT); + } + } + + function _add(bytes32 key, uint256 amount) internal returns (bytes32) { + for (uint256 i = 0; i < amount; i++) { + bytes memory value = abi.encode(key); + assertTrue(map.set(key, value)); + key = keccak256(value); + } + return key; + } + + function _addCheck(bytes32 key, uint256 amount) internal returns (bytes32) { + for (uint256 i = 0; i < amount; i++) { + assertTrue(!map.contains(key), "Key already present"); + bytes memory value = abi.encode(key); + assertTrue(map.set(key, value), "Key not added"); + assertTrue(map.contains(key), "New key not found"); + + (bytes memory _value, ) = map.get(key); + key = keccak256(value); + assertTrue(key == keccak256(_value), "Value doesn't match"); + } + return key; + } + + function _poll(uint256 amount) internal { + for (uint256 i = 0; i < amount; i++) { + (bytes32 key, , ) = map.at(0); + map.remove(key); + } + } + + function _pollCheck(uint256 amount) internal { + for (uint256 i = 0; i < amount; i++) { + (bytes32 key, bytes memory value, ) = map.at(0); + + assertTrue(map.remove(key), "Key removal failed"); + assertTrue(!map.contains(key), "Key not deleted"); + assertTrue( + keccak256(abi.encode(key)) == keccak256(value), + "Wrong value" + ); + } + } +} diff --git a/test/bridge/limiter/Queue.t.sol b/test/bridge/limiter/Queue.t.sol new file mode 100644 index 000000000..616efdc4a --- /dev/null +++ b/test/bridge/limiter/Queue.t.sol @@ -0,0 +1,105 @@ +// SPDX-License-Identifier: MIT +pragma solidity >=0.8.0; + +import "forge-std/Test.sol"; + +import {EnumerableQueueUpgradeable} from "contracts/bridge/libraries/EnumerableQueueUpgradeable.sol"; + +contract QueueTest is Test { + using EnumerableQueueUpgradeable for EnumerableQueueUpgradeable.KappaQueue; + + EnumerableQueueUpgradeable.KappaQueue internal queue; + + uint256 internal constant AMOUNT = 5; + + function setUp() public { + vm.warp(14000000); + } + + // Add to Full (F) queue, then poll all + function testAdd1F(bytes32 key) public { + vm.assume(key != bytes32(0)); + _add(key, 4 * AMOUNT); + _poll(4 * AMOUNT); + } + + // Add to queue, then poll until it's empty (E) two times + function testAdd2E(bytes32 key) public { + vm.assume(key != bytes32(0)); + for (uint256 i = 0; i < 2; ++i) { + key = _add(key, 2 * AMOUNT); + _poll(2 * AMOUNT); + } + } + + // Add to queue, then poll until it's empty (E) three times + function testAdd3E(bytes32 key) public { + vm.assume(key != bytes32(0)); + for (uint256 i = 0; i < 3; ++i) { + uint256 amount = i == 0 ? 2 * AMOUNT : AMOUNT; + key = _add(key, amount); + _poll(amount); + } + } + + // Add to queue, then poll until it's empty (E) four times + function testAdd4E(bytes32 key) public { + vm.assume(key != bytes32(0)); + for (uint256 i = 0; i < 4; ++i) { + key = _add(key, AMOUNT); + _poll(AMOUNT); + } + } + + function testUsage(bytes32 key) public { + vm.assume(key != bytes32(0)); + for (uint256 i = 0; i < 4; ++i) { + key = _addCheck(key, AMOUNT); + _pollCheck(AMOUNT); + } + } + + function _add(bytes32 key, uint256 amount) internal returns (bytes32) { + for (uint256 i = 0; i < amount; i++) { + bytes memory value = abi.encode(key); + assertTrue(queue.add(key, value)); + key = keccak256(value); + } + return key; + } + + function _addCheck(bytes32 key, uint256 amount) internal returns (bytes32) { + for (uint256 i = 0; i < amount; i++) { + assertTrue(!queue.contains(key), "Key already present"); + bytes memory value = abi.encode(key); + assertTrue(queue.add(key, value), "Key not added"); + assertTrue(queue.contains(key), "New key not found"); + + (bytes memory _value, ) = queue.get(key); + key = keccak256(value); + assertTrue(key == keccak256(_value), "Value doesn't match"); + } + return key; + } + + function _poll(uint256 amount) internal { + for (uint256 i = 0; i < amount; i++) { + queue.poll(); + } + } + + function _pollCheck(uint256 amount) internal { + for (uint256 i = 0; i < amount; i++) { + (bytes32 key, bytes memory value, ) = queue.poll(); + + assertTrue(!queue.contains(key), "Key not deleted"); + assertTrue( + keccak256(abi.encode(key)) == keccak256(value), + "Wrong value" + ); + + (value, ) = queue.get(key); + assertTrue(value.length == 0, "Data remains after deletion"); + } + } +} From 8607f5fa77074c63aecaf456a7653958192f266d Mon Sep 17 00:00:00 2001 From: ChiTimesChi <88190723+ChiTimesChi@users.noreply.github.com> Date: Sat, 23 Apr 2022 18:54:12 +0300 Subject: [PATCH 061/135] merge optimism-usdc --- .../bridge/wrappers/AvaxJewelMigration.sol | 45 + .../bridge/wrappers/AvaxJewelMigrationV2.sol | 75 + contracts/bridge/wrappers/AvaxJewelSwap.sol | 23 + .../bridge/wrappers/HarmonyBridgeZap.sol | 42 + contracts/bridge/wrappers/L1BridgeZap.sol | 76 + contracts/bridge/wrappers/L2BridgeZap.sol | 25 + deploy/000_check_Multisig.ts | 2 +- deploy/007_L2BridgeZap.ts | 26 +- deploy/013_deploy_USDC.ts | 72 + deploy/060_deploy_AVAX.ts | 72 + deploy/060_deploy_JEWEL.ts | 73 + deploy/060_deploy_UST.ts | 2 +- deploy/060_deploy_synJEWEL.ts | 73 + deploy/060_deploy_xJEWEL.ts | 71 + deploy/061_deploy_VST.ts | 72 + deploy/amm/002_deploy_LPToken.ts | 6 +- deploy/amm/003_deploy_AmplificationUtils.ts | 7 +- deploy/amm/004_deploy_SwapUtils.ts | 6 +- deploy/amm/005_deploy_SwapDeployer.ts | 6 +- deploy/amm/006_deploy_Swap.ts | 7 +- deploy/amm/006_deploy_SwapFlashLoan.ts | 6 +- deploy/amm/100_deploy_nUSDV2Pool.ts | 2 +- deploy/amm/100_deploy_nUSDV3Pool.ts | 17 +- .../avalanche/011_deploy_AvaxRevertedSwap.ts | 20 + deploy/avalanche/011_deploy_JewelMigration.ts | 34 + deploy/boba/012_deploy_nETHPool.ts | 2 +- deploy/fantom/012_deploy_nETHPool.ts | 2 +- deploy/harmony/012_deploy_AVAXPool.ts | 93 + deploy/harmony/012_deploy_JewelBridgeSwap.ts | 21 + deploy/harmony/012_deploy_nETHPool.ts | 2 +- deploy/mainnet/006_BridgeNerveZap.ts | 14 + deploy/optimism/000_deploy_DummyWethProxy.ts | 22 +- deploy/optimism/201_deploy_nETH.ts | 44 +- deployments/avalanche/AvaxJewelMigration.json | 233 +++ deployments/avalanche/AvaxJewelSwap.json | 108 + deployments/avalanche/JEWEL.json | 668 +++++++ deployments/avalanche/L2BridgeZap.json | 291 ++- .../176148eace03d1f556691bfef59d8130.json | 37 + .../4d8253a299fa09b105ed2b87dd0189d4.json | 304 +++ .../f830a0c701b69b2055ae5caebfbd7bc2.json | 304 +++ deployments/cronos/DAI.json | 366 ++++ deployments/cronos/USDC.json | 226 +++ deployments/cronos/USDT.json | 366 ++++ deployments/cronos/nETH.json | 1104 ++++++++++ deployments/cronos/nUSDPoolV3-LPToken.json | 668 +++++++ deployments/cronos/nUSDPoolV3.json | 1001 ++++++++++ .../4d8253a299fa09b105ed2b87dd0189d4.json | 304 +++ deployments/dfk/.chainId | 1 + deployments/dfk/AVAX.json | 668 +++++++ deployments/dfk/DefaultProxyAdmin.json | 258 +++ deployments/dfk/DevMultisig.json | 4 + deployments/dfk/L1BridgeZap.json | 754 +++++++ deployments/dfk/L2BridgeZap.json | 814 ++++++++ deployments/dfk/MiniChefV2.json | 1160 +++++++++++ deployments/dfk/MultiSigWalletFactory.json | 151 ++ deployments/dfk/Multicall2.json | 353 ++++ deployments/dfk/SynapseBridge.json | 1521 ++++++++++++++ .../dfk/SynapseBridge_Implementation.json | 1776 +++++++++++++++++ deployments/dfk/SynapseBridge_Proxy.json | 205 ++ deployments/dfk/SynapseERC20.json | 1104 ++++++++++ deployments/dfk/SynapseERC20Factory.json | 114 ++ deployments/dfk/SynapseToken.json | 668 +++++++ deployments/dfk/TimelockController.json | 1075 ++++++++++ deployments/dfk/USDC.json | 668 +++++++ deployments/dfk/UST.json | 668 +++++++ deployments/dfk/WJEWEL.json | 366 ++++ deployments/dfk/nETH.json | 1104 ++++++++++ deployments/dfk/nUSD.json | 668 +++++++ .../1635d55d57a0a2552952c0d22586ed23.json | 56 + .../4081879ecbcad532ab272d265ceb1761.json | 56 + .../67709d0e6d2903fa456800932c6c2db8.json | 35 + .../76b4e8a3d6fd1a3364758c7f6c169cd0.json | 67 + .../95380060a7ec73498bb886cdc300b807.json | 304 +++ .../cefd51132bfcd0aab10340ca057c092d.json | 295 +++ .../d9ddc44152056b9c2865111aa614cbcf.json | 302 +++ .../f2fd7140f46faca58f086e028b2ac3b2.json | 59 + .../f830a0c701b69b2055ae5caebfbd7bc2.json | 304 +++ .../f890e19d95a4324c05c431b6e8cd0070.json | 298 +++ deployments/dfk/xJEWEL.json | 668 +++++++ deployments/harmony/AVAX.json | 668 +++++++ deployments/harmony/BridgedAVAXPool.json | 1001 ++++++++++ .../harmony/BridgedAVAXPoolLPToken.json | 225 +++ deployments/harmony/JewelBridgeSwap.json | 260 +++ deployments/harmony/L2BridgeZap.json | 308 ++- deployments/harmony/multiAVAX.json | 226 +++ .../a0c105fd41656175868de59f7c100fca.json | 304 +++ deployments/harmony/synJEWEL.json | 668 +++++++ deployments/mainnet/VSTA.json | 668 +++++++ deployments/optimism/L2BridgeZap.json | 257 ++- deployments/optimism/nUSDPoolV3-LPToken.json | 668 +++++++ deployments/optimism/nUSDPoolV3.json | 1001 ++++++++++ .../c16492a84c84927e5b757d9d97068ec0.json | 301 +++ .../e661cf0d58b25467456dc889376e25c1.json | 301 +++ docs/bridge/wrappers/AvaxJewelMigration.md | 124 ++ docs/bridge/wrappers/AvaxJewelMigrationV2.md | 175 ++ docs/bridge/wrappers/AvaxJewelSwap.md | 65 + docs/bridge/wrappers/IERC20Mintable.md | 203 ++ docs/bridge/wrappers/L1BridgeZap.md | 45 + docs/bridge/wrappers/L2BridgeZap.md | 22 + hardhat.config.ts | 11 +- test/bridge/BridgeConfigV3.ts | 12 +- test/bridge/wrappers/AvaxJewelMigration.ts | 257 +++ test/bridge/wrappers/AvaxJewelSwap.ts | 129 ++ utils/network.ts | 1 + 104 files changed, 31204 insertions(+), 280 deletions(-) create mode 100644 contracts/bridge/wrappers/AvaxJewelMigration.sol create mode 100644 contracts/bridge/wrappers/AvaxJewelMigrationV2.sol create mode 100644 contracts/bridge/wrappers/AvaxJewelSwap.sol create mode 100644 deploy/013_deploy_USDC.ts create mode 100644 deploy/060_deploy_AVAX.ts create mode 100644 deploy/060_deploy_JEWEL.ts create mode 100644 deploy/060_deploy_synJEWEL.ts create mode 100644 deploy/060_deploy_xJEWEL.ts create mode 100644 deploy/061_deploy_VST.ts create mode 100644 deploy/avalanche/011_deploy_AvaxRevertedSwap.ts create mode 100644 deploy/avalanche/011_deploy_JewelMigration.ts create mode 100644 deploy/harmony/012_deploy_AVAXPool.ts create mode 100644 deploy/harmony/012_deploy_JewelBridgeSwap.ts create mode 100644 deployments/avalanche/AvaxJewelMigration.json create mode 100644 deployments/avalanche/AvaxJewelSwap.json create mode 100644 deployments/avalanche/JEWEL.json create mode 100644 deployments/avalanche/solcInputs/176148eace03d1f556691bfef59d8130.json create mode 100644 deployments/avalanche/solcInputs/4d8253a299fa09b105ed2b87dd0189d4.json create mode 100644 deployments/avalanche/solcInputs/f830a0c701b69b2055ae5caebfbd7bc2.json create mode 100644 deployments/cronos/DAI.json create mode 100644 deployments/cronos/USDC.json create mode 100644 deployments/cronos/USDT.json create mode 100644 deployments/cronos/nETH.json create mode 100644 deployments/cronos/nUSDPoolV3-LPToken.json create mode 100644 deployments/cronos/nUSDPoolV3.json create mode 100644 deployments/cronos/solcInputs/4d8253a299fa09b105ed2b87dd0189d4.json create mode 100644 deployments/dfk/.chainId create mode 100644 deployments/dfk/AVAX.json create mode 100644 deployments/dfk/DefaultProxyAdmin.json create mode 100644 deployments/dfk/DevMultisig.json create mode 100644 deployments/dfk/L1BridgeZap.json create mode 100644 deployments/dfk/L2BridgeZap.json create mode 100644 deployments/dfk/MiniChefV2.json create mode 100644 deployments/dfk/MultiSigWalletFactory.json create mode 100644 deployments/dfk/Multicall2.json create mode 100644 deployments/dfk/SynapseBridge.json create mode 100644 deployments/dfk/SynapseBridge_Implementation.json create mode 100644 deployments/dfk/SynapseBridge_Proxy.json create mode 100644 deployments/dfk/SynapseERC20.json create mode 100644 deployments/dfk/SynapseERC20Factory.json create mode 100644 deployments/dfk/SynapseToken.json create mode 100644 deployments/dfk/TimelockController.json create mode 100644 deployments/dfk/USDC.json create mode 100644 deployments/dfk/UST.json create mode 100644 deployments/dfk/WJEWEL.json create mode 100644 deployments/dfk/nETH.json create mode 100644 deployments/dfk/nUSD.json create mode 100644 deployments/dfk/solcInputs/1635d55d57a0a2552952c0d22586ed23.json create mode 100644 deployments/dfk/solcInputs/4081879ecbcad532ab272d265ceb1761.json create mode 100644 deployments/dfk/solcInputs/67709d0e6d2903fa456800932c6c2db8.json create mode 100644 deployments/dfk/solcInputs/76b4e8a3d6fd1a3364758c7f6c169cd0.json create mode 100644 deployments/dfk/solcInputs/95380060a7ec73498bb886cdc300b807.json create mode 100644 deployments/dfk/solcInputs/cefd51132bfcd0aab10340ca057c092d.json create mode 100644 deployments/dfk/solcInputs/d9ddc44152056b9c2865111aa614cbcf.json create mode 100644 deployments/dfk/solcInputs/f2fd7140f46faca58f086e028b2ac3b2.json create mode 100644 deployments/dfk/solcInputs/f830a0c701b69b2055ae5caebfbd7bc2.json create mode 100644 deployments/dfk/solcInputs/f890e19d95a4324c05c431b6e8cd0070.json create mode 100644 deployments/dfk/xJEWEL.json create mode 100644 deployments/harmony/AVAX.json create mode 100644 deployments/harmony/BridgedAVAXPool.json create mode 100644 deployments/harmony/BridgedAVAXPoolLPToken.json create mode 100644 deployments/harmony/JewelBridgeSwap.json create mode 100644 deployments/harmony/multiAVAX.json create mode 100644 deployments/harmony/solcInputs/a0c105fd41656175868de59f7c100fca.json create mode 100644 deployments/harmony/synJEWEL.json create mode 100644 deployments/mainnet/VSTA.json create mode 100644 deployments/optimism/nUSDPoolV3-LPToken.json create mode 100644 deployments/optimism/nUSDPoolV3.json create mode 100644 deployments/optimism/solcInputs/c16492a84c84927e5b757d9d97068ec0.json create mode 100644 deployments/optimism/solcInputs/e661cf0d58b25467456dc889376e25c1.json create mode 100644 docs/bridge/wrappers/AvaxJewelMigration.md create mode 100644 docs/bridge/wrappers/AvaxJewelMigrationV2.md create mode 100644 docs/bridge/wrappers/AvaxJewelSwap.md create mode 100644 docs/bridge/wrappers/IERC20Mintable.md create mode 100644 test/bridge/wrappers/AvaxJewelMigration.ts create mode 100644 test/bridge/wrappers/AvaxJewelSwap.ts diff --git a/contracts/bridge/wrappers/AvaxJewelMigration.sol b/contracts/bridge/wrappers/AvaxJewelMigration.sol new file mode 100644 index 000000000..e96ad0903 --- /dev/null +++ b/contracts/bridge/wrappers/AvaxJewelMigration.sol @@ -0,0 +1,45 @@ +// SPDX-License-Identifier: MIT + +pragma solidity 0.6.12; + +import '@openzeppelin/contracts/token/ERC20/ERC20.sol'; +import "@openzeppelin/contracts/token/ERC20/SafeERC20.sol"; +import "@openzeppelin/contracts/access/Ownable.sol"; + +import '../interfaces/ISynapseBridge.sol'; + +interface IERC20Mintable is IERC20 { + function mint(address to, uint256 amount) external; +} + +contract AvaxJewelMigration is Ownable { + using SafeERC20 for IERC20; + using SafeERC20 for IERC20Mintable; + + + ISynapseBridge constant synapseBridge = ISynapseBridge(0xC05e61d0E7a63D27546389B7aD62FdFf5A91aACE); + // MULTICHAIN JEWEL + IERC20 constant legacyToken = IERC20(0x4f60a160D8C2DDdaAfe16FCC57566dB84D674BD6); + // SYNAPSE JEWEL + IERC20 constant newToken = IERC20(0x997Ddaa07d716995DE90577C123Db411584E5E46); + uint256 constant MAX_UINT256 = 2**256 - 1; + + constructor() public { + newToken.safeApprove(address(synapseBridge), MAX_UINT256); + } + + function migrate(uint256 amount) public { + legacyToken.safeTransferFrom(msg.sender, address(this), amount); + IERC20Mintable(address(newToken)).mint(msg.sender, amount); + } + + function migrateAndBridge(uint256 amount, address to, uint256 chainId) external { + migrate(amount); + synapseBridge.redeem(to, chainId, newToken, amount); + } + + function redeemLegacy() external onlyOwner { + uint256 legacyBalance = legacyToken.balanceOf(address(this)); + legacyToken.safeTransfer(owner(), legacyBalance); + } +} \ No newline at end of file diff --git a/contracts/bridge/wrappers/AvaxJewelMigrationV2.sol b/contracts/bridge/wrappers/AvaxJewelMigrationV2.sol new file mode 100644 index 000000000..5aecf18da --- /dev/null +++ b/contracts/bridge/wrappers/AvaxJewelMigrationV2.sol @@ -0,0 +1,75 @@ +// SPDX-License-Identifier: MIT + +pragma solidity 0.6.12; + +import "@openzeppelin/contracts/token/ERC20/ERC20.sol"; +import "@openzeppelin/contracts/token/ERC20/SafeERC20.sol"; +import "@openzeppelin/contracts/access/Ownable.sol"; + +import "../interfaces/ISynapseBridge.sol"; + +interface IERC20Mintable is IERC20 { + function mint(address to, uint256 amount) external; +} + +contract AvaxJewelMigrationV2 is Ownable { + using SafeERC20 for IERC20; + using SafeERC20 for IERC20Mintable; + + ISynapseBridge public constant SYNAPSE_BRIDGE = + ISynapseBridge(0xC05e61d0E7a63D27546389B7aD62FdFf5A91aACE); + // MULTICHAIN JEWEL + IERC20 public constant LEGACY_TOKEN = + IERC20(0x4f60a160D8C2DDdaAfe16FCC57566dB84D674BD6); + // SYNAPSE JEWEL + IERC20Mintable public constant NEW_TOKEN = + IERC20Mintable(0x997Ddaa07d716995DE90577C123Db411584E5E46); + uint256 private constant MAX_UINT256 = 2**256 - 1; + + uint256 private constant HARMONY_ID = 1666600000; + + constructor() public { + NEW_TOKEN.safeApprove(address(SYNAPSE_BRIDGE), MAX_UINT256); + } + + function migrate(uint256 amount) external { + _migrate(amount, msg.sender); + } + + function migrateAndBridge( + uint256 amount, + address to, + uint256 chainId + ) external { + // First, mint new tokens to this contract, as Bridge burns tokens + // from msg.sender, which would be AvaxJewelMigration + _migrate(amount, address(this)); + // Initiate bridging and specify `to` as receiver on destination chain + if (chainId == HARMONY_ID) { + SYNAPSE_BRIDGE.redeemAndSwap( + to, + chainId, + NEW_TOKEN, + amount, + 1, // indexFrom + 0, // indexTo + 0, // minDy + type(uint256).max // deadline + ); + } else { + SYNAPSE_BRIDGE.redeem(to, chainId, NEW_TOKEN, amount); + } + } + + /// @notice Pull old tokens from user and mint new ones to account + function _migrate(uint256 amount, address account) internal { + require(amount != 0, "Amount must be greater than zero"); + LEGACY_TOKEN.safeTransferFrom(msg.sender, address(this), amount); + NEW_TOKEN.mint(account, amount); + } + + function redeemLegacy() external onlyOwner { + uint256 legacyBalance = LEGACY_TOKEN.balanceOf(address(this)); + LEGACY_TOKEN.safeTransfer(owner(), legacyBalance); + } +} diff --git a/contracts/bridge/wrappers/AvaxJewelSwap.sol b/contracts/bridge/wrappers/AvaxJewelSwap.sol new file mode 100644 index 000000000..cf31cb01e --- /dev/null +++ b/contracts/bridge/wrappers/AvaxJewelSwap.sol @@ -0,0 +1,23 @@ +// SPDX-License-Identifier: MIT + +pragma solidity 0.6.12; + +contract AvaxJewelSwap { + function calculateSwap( + uint8 tokenIndexFrom, + uint8 tokenIndexTo, + uint256 dx + ) external view returns (uint256) { + return 0; + } + + function swap( + uint8 tokenIndexFrom, + uint8 tokenIndexTo, + uint256 dx, + uint256 minDy, + uint256 deadline + ) external returns (uint256) { + revert("There is no swap"); + } +} diff --git a/contracts/bridge/wrappers/HarmonyBridgeZap.sol b/contracts/bridge/wrappers/HarmonyBridgeZap.sol index 12be2cd62..67f66b96c 100644 --- a/contracts/bridge/wrappers/HarmonyBridgeZap.sol +++ b/contracts/bridge/wrappers/HarmonyBridgeZap.sol @@ -30,12 +30,18 @@ contract HarmonyBridgeZap { address tokenOne, address _swapTwo, address tokenTwo, + address _swapThree, + address tokenThree, + address _swapFour, + address tokenFour, ISynapseBridge _synapseBridge ) public { WETH_ADDRESS = _wethAddress; synapseBridge = _synapseBridge; swapMap[tokenOne] = _swapOne; swapMap[tokenTwo] = _swapTwo; + swapMap[tokenThree] = _swapThree; + swapMap[tokenFour] = _swapFour; if (address(_swapOne) != address(0)) { { @@ -71,6 +77,42 @@ contract HarmonyBridgeZap { require(i > 1, "swap must have at least 2 tokens"); } } + + if (address(_swapThree) != address(0)) { + { + uint8 i; + for (; i < 32; i++) { + try ISwap(_swapThree).getToken(i) returns ( + IERC20 token + ) { + swapTokensMap[_swapThree].push(token); + token.safeApprove(address(_swapThree), MAX_UINT256); + token.safeApprove(address(synapseBridge), MAX_UINT256); + } catch { + break; + } + } + require(i > 1, "swap must have at least 2 tokens"); + } + } + + if (address(_swapFour) != address(0)) { + { + uint8 i; + for (; i < 32; i++) { + try ISwap(_swapFour).getToken(i) returns ( + IERC20 token + ) { + swapTokensMap[_swapFour].push(token); + token.safeApprove(address(_swapFour), MAX_UINT256); + token.safeApprove(address(synapseBridge), MAX_UINT256); + } catch { + break; + } + } + require(i > 1, "swap must have at least 2 tokens"); + } + } } /** diff --git a/contracts/bridge/wrappers/L1BridgeZap.sol b/contracts/bridge/wrappers/L1BridgeZap.sol index dde394ecb..bcbc4daae 100644 --- a/contracts/bridge/wrappers/L1BridgeZap.sol +++ b/contracts/bridge/wrappers/L1BridgeZap.sol @@ -35,6 +35,7 @@ contract L1BridgeZap { baseSwap = _baseSwap; synapseBridge = _synapseBridge; IERC20(_wethAddress).safeIncreaseAllowance(address(_synapseBridge), MAX_UINT256); + if (address(_baseSwap) != address(0)) { { uint8 i; for (; i < 32; i++) { @@ -47,6 +48,7 @@ contract L1BridgeZap { } require(i > 1, 'baseSwap must have at least 2 tokens'); } + } } /** @@ -300,6 +302,80 @@ contract L1BridgeZap { synapseBridge.redeem(to, chainId, token, amount); } + /** + * @notice Wraps redeemAndSwap on SynapseBridge.sol + * Relays to nodes that (typically) a wrapped synAsset ERC20 token has been burned and the underlying needs to be redeeemed on the native chain. This function indicates to the nodes that they should attempt to redeem the LP token for the underlying assets (E.g "swap" out of the LP token) + * @param to address on other chain to redeem underlying assets to + * @param chainId which underlying chain to bridge assets onto + * @param token ERC20 compatible token to deposit into the bridge + * @param amount Amount in native token decimals to transfer cross-chain pre-fees + * @param tokenIndexFrom the token the user wants to swap from + * @param tokenIndexTo the token the user wants to swap to + * @param minDy the min amount the user would like to receive, or revert to only minting the SynERC20 token crosschain. + * @param deadline latest timestamp to accept this transaction + **/ + function redeemAndSwap( + address to, + uint256 chainId, + IERC20 token, + uint256 amount, + uint8 tokenIndexFrom, + uint8 tokenIndexTo, + uint256 minDy, + uint256 deadline + ) external { + token.safeTransferFrom(msg.sender, address(this), amount); + if (token.allowance(address(this), address(synapseBridge)) < amount) { + token.safeApprove(address(synapseBridge), MAX_UINT256); + } + synapseBridge.redeemAndSwap( + to, + chainId, + token, + amount, + tokenIndexFrom, + tokenIndexTo, + minDy, + deadline + ); + } + + /** + * @notice Wraps redeemAndRemove on SynapseBridge + * Relays to nodes that (typically) a wrapped synAsset ERC20 token has been burned and the underlying needs to be redeeemed on the native chain. This function indicates to the nodes that they should attempt to redeem the LP token for the underlying assets (E.g "swap" out of the LP token) + * @param to address on other chain to redeem underlying assets to + * @param chainId which underlying chain to bridge assets onto + * @param token ERC20 compatible token to deposit into the bridge + * @param amount Amount of (typically) LP token to pass to the nodes to attempt to removeLiquidity() with to redeem for the underlying assets of the LP token + * @param liqTokenIndex Specifies which of the underlying LP assets the nodes should attempt to redeem for + * @param liqMinAmount Specifies the minimum amount of the underlying asset needed for the nodes to execute the redeem/swap + * @param liqDeadline Specificies the deadline that the nodes are allowed to try to redeem/swap the LP token + **/ + function redeemAndRemove( + address to, + uint256 chainId, + IERC20 token, + uint256 amount, + uint8 liqTokenIndex, + uint256 liqMinAmount, + uint256 liqDeadline + ) external { + token.safeTransferFrom(msg.sender, address(this), amount); + if (token.allowance(address(this), address(synapseBridge)) < amount) { + token.safeApprove(address(synapseBridge), MAX_UINT256); + } + synapseBridge.redeemAndRemove( + to, + chainId, + token, + amount, + liqTokenIndex, + liqMinAmount, + liqDeadline + ); + } + + /** * @notice Wraps SynapseBridge redeemv2() function * @param to address on other chain to bridge assets to diff --git a/contracts/bridge/wrappers/L2BridgeZap.sol b/contracts/bridge/wrappers/L2BridgeZap.sol index 1c0a74990..7523eb1f6 100644 --- a/contracts/bridge/wrappers/L2BridgeZap.sol +++ b/contracts/bridge/wrappers/L2BridgeZap.sol @@ -279,6 +279,31 @@ contract L2BridgeZap { } + /** + * @notice Wraps SynapseBridge depositAndSwap() function to make it compatible w/ ETH -> WETH conversions + * @param to address on other chain to bridge assets to + * @param chainId which chain to bridge assets onto + * @param amount Amount in native token decimals to transfer cross-chain pre-fees + * @param tokenIndexFrom the token the user wants to swap from + * @param tokenIndexTo the token the user wants to swap to + * @param minDy the min amount the user would like to receive, or revert to only minting the SynERC20 token crosschain. + * @param deadline latest timestamp to accept this transaction + **/ + function depositETHAndSwap( + address to, + uint256 chainId, + uint256 amount, + uint8 tokenIndexFrom, + uint8 tokenIndexTo, + uint256 minDy, + uint256 deadline + ) external payable { + require(msg.value > 0 && msg.value == amount, 'INCORRECT MSG VALUE'); + IWETH9(WETH_ADDRESS).deposit{value: msg.value}(); + synapseBridge.depositAndSwap(to, chainId, IERC20(WETH_ADDRESS), amount, tokenIndexFrom, tokenIndexTo, minDy, deadline); + } + + function swapETHAndRedeem( address to, uint256 chainId, diff --git a/deploy/000_check_Multisig.ts b/deploy/000_check_Multisig.ts index f5a61585e..138caf9b0 100644 --- a/deploy/000_check_Multisig.ts +++ b/deploy/000_check_Multisig.ts @@ -354,7 +354,7 @@ const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) { }) } - if ((includes([CHAIN_ID.MOONBEAM, CHAIN_ID.CRONOS, CHAIN_ID.METIS], await getChainId()))) { + if ((includes([CHAIN_ID.MOONBEAM, CHAIN_ID.CRONOS, CHAIN_ID.METIS, CHAIN_ID.DFK], await getChainId()))) { await deploy("MultiSigWalletFactory", { from: deployer, log: true, diff --git a/deploy/007_L2BridgeZap.ts b/deploy/007_L2BridgeZap.ts index 146382887..0b9249856 100644 --- a/deploy/007_L2BridgeZap.ts +++ b/deploy/007_L2BridgeZap.ts @@ -86,6 +86,23 @@ const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) { }) } + if ((await getChainId()) === CHAIN_ID.DFK) { + await deploy("L2BridgeZap", { + from: deployer, + log: true, + skipIfAlreadyDeployed: true, + args: [ + "0x0000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000", + (await get("SynapseBridge")).address, + ], + }) + } + + if ((await getChainId()) === CHAIN_ID.METIS) { await deploy("L2BridgeZap", { from: deployer, @@ -164,10 +181,11 @@ const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) { (await get("WETH")).address, (await get("ETHPool")).address, (await get("nETH")).address, - "0x0000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000", + (await get("nUSDPoolV3")).address, + (await get("nUSD")).address, (await get("SynapseBridge")).address, ], + gasLimit: 5000000, }) } @@ -184,6 +202,10 @@ const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) { (await get("nUSD")).address, (await get("ETHPool")).address, (await get("nETH")).address, + (await get("JewelBridgeSwap")).address, + (await get("synJEWEL")).address, + (await get("BridgedAVAXPool")).address, + (await get("AVAX")).address, (await get("SynapseBridge")).address, ], }) diff --git a/deploy/013_deploy_USDC.ts b/deploy/013_deploy_USDC.ts new file mode 100644 index 000000000..46b51be3d --- /dev/null +++ b/deploy/013_deploy_USDC.ts @@ -0,0 +1,72 @@ +import { HardhatRuntimeEnvironment } from "hardhat/types" +import { DeployFunction } from "hardhat-deploy/types" +import { CHAIN_ID } from "../utils/network" +import {includes} from "lodash"; + +const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) { + const { deployments, getNamedAccounts, getChainId } = hre + const { deploy, get, execute, getOrNull, log, save } = deployments + const { deployer } = await getNamedAccounts() + + if ((includes([CHAIN_ID.DFK], await getChainId()))) { + if ((await getOrNull("USDC")) == null) { + const receipt = await execute( + "SynapseERC20Factory", + { from: deployer, log: true }, + "deploy", + ( + await get("SynapseERC20") + ).address, + "USD Coin", + "USDC", + "18", + deployer, + // ( + // await get("DevMultisig") + // ).address, + ) + + const newTokenEvent = receipt?.events?.find( + (e: any) => e["event"] == "SynapseERC20Created", + ) + const tokenAddress = newTokenEvent["args"]["contractAddress"] + log(`deployed USDC token at ${tokenAddress}`) + + await save("USDC", { + abi: (await get("SynapseERC20")).abi, // Generic ERC20 ABI + address: tokenAddress, + }) + + await execute( + "USDC", + { from: deployer, log: true }, + "grantRole", + "0x9f2df0fed2c77648de5860a4cc508cd0818c85b8b8a1ab4ceeef8d981c8956a6", + ( + await get("SynapseBridge") + ).address, + ) + + await execute( + "USDC", + { from: deployer, log: true }, + "grantRole", + "0x0000000000000000000000000000000000000000000000000000000000000000", + ( + await get("DevMultisig") + ).address, + ) + + await execute( + "USDC", + { from: deployer, log: true }, + "renounceRole", + "0x0000000000000000000000000000000000000000000000000000000000000000", + deployer, + ) + } + } +} + +export default func +func.tags = ["USDC"] diff --git a/deploy/060_deploy_AVAX.ts b/deploy/060_deploy_AVAX.ts new file mode 100644 index 000000000..1f296f218 --- /dev/null +++ b/deploy/060_deploy_AVAX.ts @@ -0,0 +1,72 @@ +import { HardhatRuntimeEnvironment } from "hardhat/types" +import { DeployFunction } from "hardhat-deploy/types" +import { CHAIN_ID } from "../utils/network" +import {includes} from "lodash"; + +const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) { + const { deployments, getNamedAccounts, getChainId } = hre + const { deploy, get, execute, getOrNull, log, save } = deployments + const { deployer } = await getNamedAccounts() + + if ((includes([CHAIN_ID.DFK, CHAIN_ID.HARMONY], await getChainId()))) { + if ((await getOrNull("AVAX")) == null) { + const receipt = await execute( + "SynapseERC20Factory", + { from: deployer, log: true }, + "deploy", + ( + await get("SynapseERC20") + ).address, + "Avalanche", + "AVAX", + "18", + deployer, + // ( + // await get("DevMultisig") + // ).address, + ) + + const newTokenEvent = receipt?.events?.find( + (e: any) => e["event"] == "SynapseERC20Created", + ) + const tokenAddress = newTokenEvent["args"]["contractAddress"] + log(`deployed AVAX token at ${tokenAddress}`) + + await save("AVAX", { + abi: (await get("SynapseERC20")).abi, // Generic ERC20 ABI + address: tokenAddress, + }) + + await execute( + "AVAX", + { from: deployer, log: true }, + "grantRole", + "0x9f2df0fed2c77648de5860a4cc508cd0818c85b8b8a1ab4ceeef8d981c8956a6", + ( + await get("SynapseBridge") + ).address, + ) + + await execute( + "AVAX", + { from: deployer, log: true }, + "grantRole", + "0x0000000000000000000000000000000000000000000000000000000000000000", + ( + await get("DevMultisig") + ).address, + ) + + await execute( + "AVAX", + { from: deployer, log: true }, + "renounceRole", + "0x0000000000000000000000000000000000000000000000000000000000000000", + deployer, + ) + } + } +} + +export default func +func.tags = ["AVAX"] diff --git a/deploy/060_deploy_JEWEL.ts b/deploy/060_deploy_JEWEL.ts new file mode 100644 index 000000000..3f1501857 --- /dev/null +++ b/deploy/060_deploy_JEWEL.ts @@ -0,0 +1,73 @@ +import { HardhatRuntimeEnvironment } from "hardhat/types" +import { DeployFunction } from "hardhat-deploy/types" +import { CHAIN_ID } from "../utils/network" + +const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) { + const { deployments, getNamedAccounts, getChainId } = hre + const { get, execute, getOrNull, log, save } = deployments + const { deployer } = await getNamedAccounts() + + if (await getChainId() == CHAIN_ID.AVALANCHE) { + if ((await getOrNull("JEWEL")) == null) { + const receipt = await execute( + "SynapseERC20Factory", + { from: deployer, log: true }, + "deploy", + ( + await get("SynapseERC20") + ).address, + "JEWEL", + "JEWEL", + "18", + deployer, + // ( + // await get("DevMultisig") + // ).address, + ) + + const newTokenEvent = receipt?.events?.find( + (e: any) => e["event"] == "SynapseERC20Created", + ) + const tokenAddress = newTokenEvent["args"]["contractAddress"] + log(`deployed JEWEL token at ${tokenAddress}`) + + await save("JEWEL", { + abi: (await get("SynapseERC20")).abi, // Generic ERC20 ABI + address: tokenAddress, + }) + + await execute( + "JEWEL", + { from: deployer, log: true }, + "grantRole", + "0x9f2df0fed2c77648de5860a4cc508cd0818c85b8b8a1ab4ceeef8d981c8956a6", + ( + await get("SynapseBridge") + ).address, + ) + + + await execute( + "JEWEL", + { from: deployer, log: true }, + "grantRole", + "0x0000000000000000000000000000000000000000000000000000000000000000", + ( + await get("DevMultisig") + ).address, + ) + + await execute( + "JEWEL", + { from: deployer, log: true }, + "renounceRole", + "0x0000000000000000000000000000000000000000000000000000000000000000", + deployer, + ) + + } + } +} + +export default func +func.tags = ["JEWEL"] diff --git a/deploy/060_deploy_UST.ts b/deploy/060_deploy_UST.ts index 0d3b3b7e2..52d1d732a 100644 --- a/deploy/060_deploy_UST.ts +++ b/deploy/060_deploy_UST.ts @@ -8,7 +8,7 @@ const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) { const { deploy, get, execute, getOrNull, log, save } = deployments const { deployer } = await getNamedAccounts() - if ((includes([CHAIN_ID.FANTOM, CHAIN_ID.ARBITRUM, CHAIN_ID.AVALANCHE, CHAIN_ID.POLYGON, CHAIN_ID.MOONBEAM, CHAIN_ID.BSC, CHAIN_ID.MOONRIVER, CHAIN_ID.MAINNET, CHAIN_ID.BOBA, CHAIN_ID.OPTIMISM, CHAIN_ID.AURORA, CHAIN_ID.HARMONY, CHAIN_ID.CRONOS, CHAIN_ID.METIS], await getChainId()))) { + if ((includes([CHAIN_ID.FANTOM, CHAIN_ID.ARBITRUM, CHAIN_ID.AVALANCHE, CHAIN_ID.POLYGON, CHAIN_ID.MOONBEAM, CHAIN_ID.BSC, CHAIN_ID.MOONRIVER, CHAIN_ID.MAINNET, CHAIN_ID.BOBA, CHAIN_ID.OPTIMISM, CHAIN_ID.AURORA, CHAIN_ID.HARMONY, CHAIN_ID.CRONOS, CHAIN_ID.METIS, CHAIN_ID.DFK], await getChainId()))) { if ((await getOrNull("UST")) == null) { const receipt = await execute( "SynapseERC20Factory", diff --git a/deploy/060_deploy_synJEWEL.ts b/deploy/060_deploy_synJEWEL.ts new file mode 100644 index 000000000..a54425927 --- /dev/null +++ b/deploy/060_deploy_synJEWEL.ts @@ -0,0 +1,73 @@ +import { HardhatRuntimeEnvironment } from "hardhat/types" +import { DeployFunction } from "hardhat-deploy/types" +import { CHAIN_ID } from "../utils/network" + +const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) { + const { deployments, getNamedAccounts, getChainId } = hre + const { get, execute, getOrNull, log, save } = deployments + const { deployer } = await getNamedAccounts() + + if (await getChainId() == CHAIN_ID.HARMONY) { + if ((await getOrNull("synJEWEL")) == null) { + const receipt = await execute( + "SynapseERC20Factory", + { from: deployer, log: true }, + "deploy", + ( + await get("SynapseERC20") + ).address, + "synJEWEL", + "synJEWEL", + "18", + deployer, + // ( + // await get("DevMultisig") + // ).address, + ) + + const newTokenEvent = receipt?.events?.find( + (e: any) => e["event"] == "SynapseERC20Created", + ) + const tokenAddress = newTokenEvent["args"]["contractAddress"] + log(`deployed synJEWEL token at ${tokenAddress}`) + + await save("synJEWEL", { + abi: (await get("SynapseERC20")).abi, // Generic ERC20 ABI + address: tokenAddress, + }) + + await execute( + "synJEWEL", + { from: deployer, log: true }, + "grantRole", + "0x9f2df0fed2c77648de5860a4cc508cd0818c85b8b8a1ab4ceeef8d981c8956a6", + ( + await get("SynapseBridge") + ).address, + ) + + + await execute( + "synJEWEL", + { from: deployer, log: true }, + "grantRole", + "0x0000000000000000000000000000000000000000000000000000000000000000", + ( + await get("DevMultisig") + ).address, + ) + + await execute( + "synJEWEL", + { from: deployer, log: true }, + "renounceRole", + "0x0000000000000000000000000000000000000000000000000000000000000000", + deployer, + ) + + } + } +} + +export default func +func.tags = ["synJEWEL"] diff --git a/deploy/060_deploy_xJEWEL.ts b/deploy/060_deploy_xJEWEL.ts new file mode 100644 index 000000000..dc1219e03 --- /dev/null +++ b/deploy/060_deploy_xJEWEL.ts @@ -0,0 +1,71 @@ +import { HardhatRuntimeEnvironment } from "hardhat/types" +import { DeployFunction } from "hardhat-deploy/types" +import { CHAIN_ID } from "../utils/network" + +const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) { + const { deployments, getNamedAccounts, getChainId } = hre + const { get, execute, getOrNull, log, save } = deployments + const { deployer } = await getNamedAccounts() + + if (await getChainId() == CHAIN_ID.DFK) { + if ((await getOrNull("xJEWEL")) == null) { + const receipt = await execute( + "SynapseERC20Factory", + { from: deployer, log: true }, + "deploy", + ( + await get("SynapseERC20") + ).address, + "xJEWEL", + "xJEWEL", + "18", + deployer, + // ( + // await get("DevMultisig") + // ).address, + ) + + const newTokenEvent = receipt?.events?.find( + (e: any) => e["event"] == "SynapseERC20Created", + ) + const tokenAddress = newTokenEvent["args"]["contractAddress"] + log(`deployed xJEWEL token at ${tokenAddress}`) + + await save("xJEWEL", { + abi: (await get("SynapseERC20")).abi, // Generic ERC20 ABI + address: tokenAddress, + }) + + await execute( + "xJEWEL", + { from: deployer, log: true }, + "grantRole", + "0x9f2df0fed2c77648de5860a4cc508cd0818c85b8b8a1ab4ceeef8d981c8956a6", + ( + await get("SynapseBridge") + ).address, + ) + + await execute( + "xJEWEL", + { from: deployer, log: true }, + "grantRole", + "0x0000000000000000000000000000000000000000000000000000000000000000", + ( + await get("DevMultisig") + ).address, + ) + + await execute( + "xJEWEL", + { from: deployer, log: true }, + "renounceRole", + "0x0000000000000000000000000000000000000000000000000000000000000000", + deployer, + ) + } + } +} + +export default func +func.tags = ["xJEWEL"] diff --git a/deploy/061_deploy_VST.ts b/deploy/061_deploy_VST.ts new file mode 100644 index 000000000..2f1db9fd7 --- /dev/null +++ b/deploy/061_deploy_VST.ts @@ -0,0 +1,72 @@ +import { HardhatRuntimeEnvironment } from "hardhat/types" +import { DeployFunction } from "hardhat-deploy/types" +import { CHAIN_ID } from "../utils/network" +import {includes} from "lodash"; + +const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) { + const { deployments, getNamedAccounts, getChainId } = hre + const { deploy, get, execute, getOrNull, log, save } = deployments + const { deployer } = await getNamedAccounts() + + if ((includes([CHAIN_ID.MAINNET], await getChainId()))) { + if ((await getOrNull("VSTA")) == null) { + const receipt = await execute( + "SynapseERC20Factory", + { from: deployer, log: true }, + "deploy", + ( + await get("SynapseERC20") + ).address, + "Vesta", + "VSTA", + "18", + deployer, + // ( + // await get("DevMultisig") + // ).address, + ) + + const newTokenEvent = receipt?.events?.find( + (e: any) => e["event"] == "SynapseERC20Created", + ) + const tokenAddress = newTokenEvent["args"]["contractAddress"] + log(`deployed VSTA token at ${tokenAddress}`) + + await save("VSTA", { + abi: (await get("SynapseERC20")).abi, // Generic ERC20 ABI + address: tokenAddress, + }) + + await execute( + "VSTA", + { from: deployer, log: true }, + "grantRole", + "0x9f2df0fed2c77648de5860a4cc508cd0818c85b8b8a1ab4ceeef8d981c8956a6", + ( + await get("SynapseBridge") + ).address, + ) + + await execute( + "VSTA", + { from: deployer, log: true }, + "grantRole", + "0x0000000000000000000000000000000000000000000000000000000000000000", + ( + await get("DevMultisig") + ).address, + ) + + await execute( + "VSTA", + { from: deployer, log: true }, + "renounceRole", + "0x0000000000000000000000000000000000000000000000000000000000000000", + deployer, + ) + } + } +} + +export default func +func.tags = ["VSTA"] diff --git a/deploy/amm/002_deploy_LPToken.ts b/deploy/amm/002_deploy_LPToken.ts index af20344f1..86fc8bd31 100644 --- a/deploy/amm/002_deploy_LPToken.ts +++ b/deploy/amm/002_deploy_LPToken.ts @@ -1,11 +1,14 @@ import { HardhatRuntimeEnvironment } from "hardhat/types" import { DeployFunction } from "hardhat-deploy/types" +import {includes} from "lodash"; +import { CHAIN_ID } from "../../utils/network" const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) { - const { deployments, getNamedAccounts } = hre + const { deployments, getNamedAccounts, getChainId } = hre const { deploy, execute, getOrNull } = deployments const { libraryDeployer } = await getNamedAccounts() + if (!(includes([CHAIN_ID.DFK], await getChainId()))) { let LPToken = await getOrNull("LPToken") if (!LPToken) { await deploy("LPToken", { @@ -23,5 +26,6 @@ const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) { ) } } +} export default func func.tags = ["LPToken"] diff --git a/deploy/amm/003_deploy_AmplificationUtils.ts b/deploy/amm/003_deploy_AmplificationUtils.ts index e7eef6f4b..38a40c564 100644 --- a/deploy/amm/003_deploy_AmplificationUtils.ts +++ b/deploy/amm/003_deploy_AmplificationUtils.ts @@ -1,16 +1,19 @@ import { HardhatRuntimeEnvironment } from "hardhat/types" import { DeployFunction } from "hardhat-deploy/types" +import {includes} from "lodash"; +import { CHAIN_ID } from "../../utils/network" const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) { - const { deployments, getNamedAccounts } = hre + const { deployments, getNamedAccounts, getChainId } = hre const { deploy } = deployments const { libraryDeployer } = await getNamedAccounts() - + if (!(includes([CHAIN_ID.DFK], await getChainId()))) { await deploy("AmplificationUtils", { from: libraryDeployer, log: true, skipIfAlreadyDeployed: true, }) } +} export default func func.tags = ["AmplificationUtils"] diff --git a/deploy/amm/004_deploy_SwapUtils.ts b/deploy/amm/004_deploy_SwapUtils.ts index 9e05e024b..e50aeeae0 100644 --- a/deploy/amm/004_deploy_SwapUtils.ts +++ b/deploy/amm/004_deploy_SwapUtils.ts @@ -1,16 +1,20 @@ import { HardhatRuntimeEnvironment } from "hardhat/types" import { DeployFunction } from "hardhat-deploy/types" +import {includes} from "lodash"; +import { CHAIN_ID } from "../../utils/network" const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) { - const { deployments, getNamedAccounts } = hre + const { deployments, getNamedAccounts, getChainId } = hre const { deploy, get } = deployments const { libraryDeployer } = await getNamedAccounts() + if (!(includes([CHAIN_ID.DFK], await getChainId()))) { await deploy("SwapUtils", { from: libraryDeployer, log: true, skipIfAlreadyDeployed: true, }) + } } export default func func.tags = ["SwapUtils"] diff --git a/deploy/amm/005_deploy_SwapDeployer.ts b/deploy/amm/005_deploy_SwapDeployer.ts index e50321ee0..5141e95a5 100644 --- a/deploy/amm/005_deploy_SwapDeployer.ts +++ b/deploy/amm/005_deploy_SwapDeployer.ts @@ -1,11 +1,14 @@ import { HardhatRuntimeEnvironment } from "hardhat/types" import { DeployFunction } from "hardhat-deploy/types" +import {includes} from "lodash"; +import { CHAIN_ID } from "../../utils/network" + const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) { const { deployments, getNamedAccounts, getChainId } = hre const { deploy, execute, read, get, getOrNull } = deployments const { deployer } = await getNamedAccounts() - + if (!(includes([CHAIN_ID.DFK], await getChainId()))) { if ((await getOrNull("SwapDeployer")) == null) { await deploy("SwapDeployer", { from: deployer, @@ -25,6 +28,7 @@ const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) { ) } } + } } export default func func.tags = ["SwapDeployer"] diff --git a/deploy/amm/006_deploy_Swap.ts b/deploy/amm/006_deploy_Swap.ts index cab28cdd8..2a77cdd54 100644 --- a/deploy/amm/006_deploy_Swap.ts +++ b/deploy/amm/006_deploy_Swap.ts @@ -1,11 +1,13 @@ import { HardhatRuntimeEnvironment } from "hardhat/types" import { DeployFunction } from "hardhat-deploy/types" +import {includes} from "lodash"; +import { CHAIN_ID } from "../../utils/network" const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) { - const { deployments, getNamedAccounts } = hre + const { deployments, getNamedAccounts, getChainId } = hre const { deploy, get } = deployments const { libraryDeployer } = await getNamedAccounts() - + if (!(includes([CHAIN_ID.DFK], await getChainId()))) { await deploy("Swap", { from: libraryDeployer, log: true, @@ -16,6 +18,7 @@ const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) { skipIfAlreadyDeployed: true, }) } +} export default func func.tags = ["Swap"] func.dependencies = ["AmplificationUtils", "SwapUtils"] diff --git a/deploy/amm/006_deploy_SwapFlashLoan.ts b/deploy/amm/006_deploy_SwapFlashLoan.ts index b0c7c1d08..46893064e 100644 --- a/deploy/amm/006_deploy_SwapFlashLoan.ts +++ b/deploy/amm/006_deploy_SwapFlashLoan.ts @@ -1,10 +1,13 @@ import { HardhatRuntimeEnvironment } from "hardhat/types" import { DeployFunction } from "hardhat-deploy/types" +import {includes} from "lodash"; +import { CHAIN_ID } from "../../utils/network" const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) { - const { deployments, getNamedAccounts } = hre + const { deployments, getNamedAccounts, getChainId } = hre const { deploy, get } = deployments const { libraryDeployer } = await getNamedAccounts() + if (!(includes([CHAIN_ID.DFK], await getChainId()))) { await deploy("SwapFlashLoan", { from: libraryDeployer, @@ -16,6 +19,7 @@ const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) { skipIfAlreadyDeployed: true, }) } +} export default func func.tags = ["SwapFlashLoan"] func.dependencies = ["AmplificationUtils", "SwapUtils"] diff --git a/deploy/amm/100_deploy_nUSDV2Pool.ts b/deploy/amm/100_deploy_nUSDV2Pool.ts index dd9380c5e..851b3376b 100644 --- a/deploy/amm/100_deploy_nUSDV2Pool.ts +++ b/deploy/amm/100_deploy_nUSDV2Pool.ts @@ -9,7 +9,7 @@ const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) { // Manually check if the pool is already deployed let nUSDPoolV2 = await getOrNull("nUSDPoolV2") - if (nUSDPoolV2 || (await getChainId()) === CHAIN_ID.OPTIMISM || (await getChainId()) === CHAIN_ID.MAINNET || (await getChainId()) === CHAIN_ID.MOONBEAM || (await getChainId()) === CHAIN_ID.METIS || (await getChainId()) === CHAIN_ID.CRONOS) { + if (nUSDPoolV2 || (await getChainId()) === CHAIN_ID.OPTIMISM || (await getChainId()) === CHAIN_ID.MAINNET || (await getChainId()) === CHAIN_ID.MOONBEAM || (await getChainId()) === CHAIN_ID.METIS || (await getChainId()) === CHAIN_ID.CRONOS || (await getChainId()) === CHAIN_ID.DFK ) { // log(`reusing "nUSDPoolV2" at ${nUSDPoolV2}`) } else { // Constructor arguments diff --git a/deploy/amm/100_deploy_nUSDV3Pool.ts b/deploy/amm/100_deploy_nUSDV3Pool.ts index 5d9ba53e8..c9744fb2e 100644 --- a/deploy/amm/100_deploy_nUSDV3Pool.ts +++ b/deploy/amm/100_deploy_nUSDV3Pool.ts @@ -10,7 +10,7 @@ const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) { // Manually check if the pool is already deployed let nUSDPoolV3 = await getOrNull("nUSDPoolV3") - if (nUSDPoolV3 || includes([CHAIN_ID.OPTIMISM, CHAIN_ID.MAINNET, CHAIN_ID.MOONBEAM, CHAIN_ID.CRONOS], await getChainId())) { + if (nUSDPoolV3 || includes([CHAIN_ID.MAINNET, CHAIN_ID.MOONBEAM, CHAIN_ID.DFK], await getChainId())) { // log(`reusing "nUSDPoolV3" at ${nUSDPoolV3}`) } else { // Constructor arguments @@ -73,7 +73,19 @@ const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) { INITIAL_A = 200 } - if (await getChainId() === CHAIN_ID.METIS) { + + if (await getChainId() === CHAIN_ID.CRONOS) { + TOKEN_ADDRESSES = [ + (await get("nUSD")).address, + (await get("DAI")).address, + (await get("USDC")).address, + (await get("USDT")).address, + ] + TOKEN_DECIMALS = [18, 18, 6, 6] + INITIAL_A = 600 + } + + if (await getChainId() === CHAIN_ID.OPTIMISM) { TOKEN_ADDRESSES = [ (await get("nUSD")).address, (await get("USDC")).address, @@ -83,7 +95,6 @@ const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) { } - // if (await getChainId() === CHAIN_ID.OPTIMISM) { // TOKEN_ADDRESSES = [ // (await get("nUSD")).address, diff --git a/deploy/avalanche/011_deploy_AvaxRevertedSwap.ts b/deploy/avalanche/011_deploy_AvaxRevertedSwap.ts new file mode 100644 index 000000000..f7ba0dbf1 --- /dev/null +++ b/deploy/avalanche/011_deploy_AvaxRevertedSwap.ts @@ -0,0 +1,20 @@ +import { DeployFunction } from "hardhat-deploy/types" +import { HardhatRuntimeEnvironment } from "hardhat/types" +import { CHAIN_ID } from "../../utils/network" + + +const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) { + const { deployments, getNamedAccounts, getChainId } = hre + const { deploy, get, read, execute, log } = deployments + const { deployer } = await getNamedAccounts() + + if ((await getChainId()) === CHAIN_ID.AVALANCHE) { + await deploy("AvaxJewelSwap", { + from: deployer, + log: true, + skipIfAlreadyDeployed: true, + }) +} +} +export default func +func.tags = ["AvaxJewelMigration"] diff --git a/deploy/avalanche/011_deploy_JewelMigration.ts b/deploy/avalanche/011_deploy_JewelMigration.ts new file mode 100644 index 000000000..f80e0cb57 --- /dev/null +++ b/deploy/avalanche/011_deploy_JewelMigration.ts @@ -0,0 +1,34 @@ +import { DeployFunction } from "hardhat-deploy/types" +import { HardhatRuntimeEnvironment } from "hardhat/types" +import { CHAIN_ID } from "../../utils/network" + + +const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) { + const { deployments, getNamedAccounts, getChainId } = hre + const { deploy, get, read, execute, log } = deployments + const { deployer } = await getNamedAccounts() + + if ((await getChainId()) === CHAIN_ID.AVALANCHE) { + await deploy("AvaxJewelMigration", { + from: deployer, + log: true, + skipIfAlreadyDeployed: true, + }) + + const currentOwner = await read("AvaxJewelMigration", "owner") + + if (currentOwner == deployer) { + log( + `transferring the ownership of "AvaxJewelMigration" to the multisig: ${(await get("DevMultisig")).address}`, + ) + await execute( + "AvaxJewelMigration", + { from: deployer, log: true }, + "transferOwnership", + (await get("DevMultisig")).address, + ) + } +} +} +export default func +func.tags = ["AvaxJewelMigration"] diff --git a/deploy/boba/012_deploy_nETHPool.ts b/deploy/boba/012_deploy_nETHPool.ts index f6078c49c..1b6fe3408 100644 --- a/deploy/boba/012_deploy_nETHPool.ts +++ b/deploy/boba/012_deploy_nETHPool.ts @@ -12,7 +12,7 @@ const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) { let ETHPool = await getOrNull("ETHPool") if (ETHPool) { log(`reusing "ETHPool" at ${ETHPool.address}`) - } else if ((includes([CHAIN_ID.BOBA, CHAIN_ID.HARDHAT, CHAIN_ID.METIS], await getChainId()))) { + } else if ((includes([CHAIN_ID.BOBA, CHAIN_ID.HARDHAT, CHAIN_ID.DFK, CHAIN_ID.CRONOS], await getChainId()))) { log(`Not BOBA or Hardhat`) } else { // Constructor arguments diff --git a/deploy/fantom/012_deploy_nETHPool.ts b/deploy/fantom/012_deploy_nETHPool.ts index 8cb4d367f..a6645b8a5 100644 --- a/deploy/fantom/012_deploy_nETHPool.ts +++ b/deploy/fantom/012_deploy_nETHPool.ts @@ -12,7 +12,7 @@ const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) { let ETHPool = await getOrNull("ETHPool") if (ETHPool) { log(`reusing "ETHPool" at ${ETHPool.address}`) - } else if ((includes([CHAIN_ID.FANTOM, CHAIN_ID.HARDHAT, CHAIN_ID.METIS], await getChainId()))) { + } else if ((includes([CHAIN_ID.FANTOM, CHAIN_ID.HARDHAT, CHAIN_ID.METIS, CHAIN_ID.DFK, CHAIN_ID.CRONOS], await getChainId()))) { log(`Not Fantom or Hardhat`) } else { // Constructor arguments diff --git a/deploy/harmony/012_deploy_AVAXPool.ts b/deploy/harmony/012_deploy_AVAXPool.ts new file mode 100644 index 000000000..d787f9ccc --- /dev/null +++ b/deploy/harmony/012_deploy_AVAXPool.ts @@ -0,0 +1,93 @@ +import { HardhatRuntimeEnvironment } from "hardhat/types" +import { DeployFunction } from "hardhat-deploy/types" +import { CHAIN_ID } from "../../utils/network" +import {includes} from "lodash"; + +const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) { + const { deployments, getNamedAccounts, getChainId } = hre + const { execute, get, getOrNull, log, read, save } = deployments + const { deployer } = await getNamedAccounts() + + // Manually check if the pool is already deployed + let BridgedAVAXPool = await getOrNull("BridgedAVAXPool") + if (BridgedAVAXPool) { + log(`reusing "BridgedAVAXPool" at ${BridgedAVAXPool.address}`) + } else if ((includes([CHAIN_ID.HARMONY], await getChainId()))) { + // Constructor arguments + const TOKEN_ADDRESSES = [ + (await get("AVAX")).address, + (await get("multiAVAX")).address + ] + const TOKEN_DECIMALS = [18, 18] + const LP_TOKEN_NAME = "AVAX-LP" + const LP_TOKEN_SYMBOL = "AVAX-LP" + const INITIAL_A = 800 + const SWAP_FEE = 4e6 // 4bps + const ADMIN_FEE = 9000000000 + + const receipt = await execute( + "SwapDeployer", + { from: deployer, log: true }, + "deploy", + ( + await get("SwapFlashLoan") + ).address, + TOKEN_ADDRESSES, + TOKEN_DECIMALS, + LP_TOKEN_NAME, + LP_TOKEN_SYMBOL, + INITIAL_A, + SWAP_FEE, + ADMIN_FEE, + ( + await get("LPToken") + ).address, + ) + + const newPoolEvent = receipt?.events?.find( + (e: any) => e["event"] == "NewSwapPool", + ) + const usdSwapAddress = newPoolEvent["args"]["swapAddress"] + log( + `deployed ETH pool clone (targeting "SwapFlashLoan") at ${usdSwapAddress}`, + ) + await save("BridgedAVAXPool", { + abi: (await get("SwapFlashLoan")).abi, + address: usdSwapAddress, + }) + + const lpTokenAddress = (await read("BridgedAVAXPool", "swapStorage")).lpToken + log(`ETH pool LP Token at ${lpTokenAddress}`) + + await save("BridgedAVAXPoolLPToken", { + abi: (await get("DAI")).abi, // Generic ERC20 ABI + address: lpTokenAddress, + }) + + const currentOwner = await read("BridgedAVAXPool", "owner") + + if (currentOwner == deployer) { + log( + `transferring the ownership of "BridgedAVAXPool" to the multisig: ${(await get("DevMultisig")).address}`, + ) + await execute( + "BridgedAVAXPool", + { from: deployer, log: true }, + "transferOwnership", + (await get("DevMultisig")).address, + ) + } else if (currentOwner == (await get("DevMultisig")).address){ + log( + `"BridgedAVAXPool" is already owned by the multisig: ${(await get("DevMultisig")).address}`, + ) + } + } +} +export default func +func.tags = ["BridgedAVAXPool"] +func.dependencies = [ + "SwapUtils", + "SwapDeployer", + "SwapFlashLoan", + "USDPoolTokens", +] diff --git a/deploy/harmony/012_deploy_JewelBridgeSwap.ts b/deploy/harmony/012_deploy_JewelBridgeSwap.ts new file mode 100644 index 000000000..3230e82d8 --- /dev/null +++ b/deploy/harmony/012_deploy_JewelBridgeSwap.ts @@ -0,0 +1,21 @@ +import { HardhatRuntimeEnvironment } from 'hardhat/types' +import { DeployFunction } from 'hardhat-deploy/types' +import { CHAIN_ID } from "../../utils/network" +import {includes} from "lodash"; + +const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) { + const { deployments, getNamedAccounts, getChainId } = hre + const { deploy, get } = deployments + const { deployer } = await getNamedAccounts() + if ((includes([CHAIN_ID.HARMONY], await getChainId()))) { + await deploy('JewelBridgeSwap', { + from: deployer, + log: true, + skipIfAlreadyDeployed: true, + args: ["0x72Cb10C6bfA5624dD07Ef608027E366bd690048F", + (await get('synJEWEL')).address], + }) + } +} +export default func +func.tags = ['JewelBridgeSwap'] diff --git a/deploy/harmony/012_deploy_nETHPool.ts b/deploy/harmony/012_deploy_nETHPool.ts index fbc81ec5a..5a3a72ec6 100644 --- a/deploy/harmony/012_deploy_nETHPool.ts +++ b/deploy/harmony/012_deploy_nETHPool.ts @@ -12,7 +12,7 @@ const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) { let ETHPool = await getOrNull("ETHPool") if (ETHPool) { log(`reusing "ETHPool" at ${ETHPool.address}`) - } else if ((includes([CHAIN_ID.HARMONY, CHAIN_ID.HARDHAT, CHAIN_ID.METIS], await getChainId()))) { + } else if ((includes([CHAIN_ID.HARMONY, CHAIN_ID.HARDHAT, CHAIN_ID.METIS, CHAIN_ID.DFK, CHAIN_ID.CRONOS], await getChainId()))) { log(`Not BOBA or Hardhat`) } else { // Constructor arguments diff --git a/deploy/mainnet/006_BridgeNerveZap.ts b/deploy/mainnet/006_BridgeNerveZap.ts index 369bc542f..f1afb696f 100644 --- a/deploy/mainnet/006_BridgeNerveZap.ts +++ b/deploy/mainnet/006_BridgeNerveZap.ts @@ -19,6 +19,20 @@ const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) { gasLimit: 5000000 }) } + + if ((await getChainId()) === CHAIN_ID.DFK) { + await deploy('L1BridgeZap', { + from: deployer, + log: true, + skipIfAlreadyDeployed: true, + args: [ + (await get('WJEWEL')).address, + "0x0000000000000000000000000000000000000000", + (await get('SynapseBridge')).address, + ], + gasLimit: 5000000 + }) + } } export default func func.tags = ['NerveBridgeZap'] diff --git a/deploy/optimism/000_deploy_DummyWethProxy.ts b/deploy/optimism/000_deploy_DummyWethProxy.ts index 833902d8b..1c9a62181 100644 --- a/deploy/optimism/000_deploy_DummyWethProxy.ts +++ b/deploy/optimism/000_deploy_DummyWethProxy.ts @@ -7,17 +7,17 @@ const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) { const { deploy, get } = deployments const { deployer } = await getNamedAccounts() - if ((await getChainId()) === CHAIN_ID.OPTIMISM) { - await deploy("DummyWethProxy", { - from: deployer, - log: true, - skipIfAlreadyDeployed: true, - proxy: { - owner: deployer, - proxyContract: "OpenZeppelinTransparentProxy", - }, - }) -} +// if ((await getChainId()) === CHAIN_ID.OPTIMISM) { +// await deploy("DummyWethProxy", { +// from: deployer, +// log: true, +// skipIfAlreadyDeployed: true, +// proxy: { +// owner: deployer, +// proxyContract: "OpenZeppelinTransparentProxy", +// }, +// }) +// } } export default func func.tags = ["DummyWeth"] diff --git a/deploy/optimism/201_deploy_nETH.ts b/deploy/optimism/201_deploy_nETH.ts index cc3675afd..3234f5e10 100644 --- a/deploy/optimism/201_deploy_nETH.ts +++ b/deploy/optimism/201_deploy_nETH.ts @@ -6,29 +6,29 @@ const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) { const { deploy, get, getOrNull, execute, log } = deployments const { deployer } = await getNamedAccounts() - let nETH = await getOrNull("nETH"); - if (nETH) { - log(`reusing 'nETH' at ${nETH.address}`) - } else { - await deploy('nETH', { - contract: 'SynapseERC20', - from: deployer, - log: true, - skipIfAlreadyDeployed: true, - }) + // let nETH = await getOrNull("nETH"); + // if (nETH) { + // log(`reusing 'nETH' at ${nETH.address}`) + // } else { + // await deploy('nETH', { + // contract: 'SynapseERC20', + // from: deployer, + // log: true, + // skipIfAlreadyDeployed: true, + // }) - await execute( - "nETH", - { from: deployer, log: true }, - "initialize", - "nETH", - "nETH", - "18", - ( - await get("DevMultisig") - ).address, - ) - } + // await execute( + // "nETH", + // { from: deployer, log: true }, + // "initialize", + // "nETH", + // "nETH", + // "18", + // ( + // await get("DevMultisig") + // ).address, + // ) + // } } export default func func.tags = ['SynapseERC20'] diff --git a/deployments/avalanche/AvaxJewelMigration.json b/deployments/avalanche/AvaxJewelMigration.json new file mode 100644 index 000000000..406d02bca --- /dev/null +++ b/deployments/avalanche/AvaxJewelMigration.json @@ -0,0 +1,233 @@ +{ + "address": "0x82d4aCF0DA013Ee3649C7eAdF5Db9093A7EFa7B0", + "abi": [ + { + "inputs": [], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "previousOwner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "OwnershipTransferred", + "type": "event" + }, + { + "inputs": [], + "name": "LEGACY_TOKEN", + "outputs": [ + { + "internalType": "contract IERC20", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "NEW_TOKEN", + "outputs": [ + { + "internalType": "contract IERC20Mintable", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "SYNAPSE_BRIDGE", + "outputs": [ + { + "internalType": "contract ISynapseBridge", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "migrate", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "chainId", + "type": "uint256" + } + ], + "name": "migrateAndBridge", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "redeemLegacy", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "renounceOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } + ], + "transactionHash": "0x0fad31cc9c9b99ea56672bd879e1c6843fe63c8c4e10a6aefd19f7ab80e3f8e5", + "receipt": { + "to": null, + "from": "0x0AF91FA049A7e1894F480bFE5bBa20142C6c29a9", + "contractAddress": "0x82d4aCF0DA013Ee3649C7eAdF5Db9093A7EFa7B0", + "transactionIndex": 0, + "gasUsed": "964694", + "logsBloom": "0x000000000000000000000000000000000080000000000000008000000000000000000000000008000000000000000000000000000000000000000000012008000000000000000400000008000200000000010000000000000000100000000000000000000200000000000000000008000000000000000000000000000000004000000000000000000000000000c0000000000000000000100000000000000010020000000000000000000080000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000020000010000000000000000000000000000000000000000000000000008000000000", + "blockHash": "0xea87d8adf3c8a86a9957bc7e85d8c6e2836d9aed45679d9c5f08970ac86eb346", + "transactionHash": "0x0fad31cc9c9b99ea56672bd879e1c6843fe63c8c4e10a6aefd19f7ab80e3f8e5", + "logs": [ + { + "transactionIndex": 0, + "blockNumber": 12754121, + "transactionHash": "0x0fad31cc9c9b99ea56672bd879e1c6843fe63c8c4e10a6aefd19f7ab80e3f8e5", + "address": "0x82d4aCF0DA013Ee3649C7eAdF5Db9093A7EFa7B0", + "topics": [ + "0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000af91fa049a7e1894f480bfe5bba20142c6c29a9" + ], + "data": "0x", + "logIndex": 0, + "blockHash": "0xea87d8adf3c8a86a9957bc7e85d8c6e2836d9aed45679d9c5f08970ac86eb346" + }, + { + "transactionIndex": 0, + "blockNumber": 12754121, + "transactionHash": "0x0fad31cc9c9b99ea56672bd879e1c6843fe63c8c4e10a6aefd19f7ab80e3f8e5", + "address": "0x997Ddaa07d716995DE90577C123Db411584E5E46", + "topics": [ + "0x8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925", + "0x00000000000000000000000082d4acf0da013ee3649c7eadf5db9093a7efa7b0", + "0x000000000000000000000000c05e61d0e7a63d27546389b7ad62fdff5a91aace" + ], + "data": "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + "logIndex": 1, + "blockHash": "0xea87d8adf3c8a86a9957bc7e85d8c6e2836d9aed45679d9c5f08970ac86eb346" + } + ], + "blockNumber": 12754121, + "cumulativeGasUsed": "964694", + "status": 1, + "byzantium": true + }, + "args": [], + "solcInputHash": "4f6ac5a071c626013e79b035fadd0c21", + "metadata": "{\"compiler\":{\"version\":\"0.6.12+commit.27d51765\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"previousOwner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"LEGACY_TOKEN\",\"outputs\":[{\"internalType\":\"contract IERC20\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"NEW_TOKEN\",\"outputs\":[{\"internalType\":\"contract IERC20Mintable\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"SYNAPSE_BRIDGE\",\"outputs\":[{\"internalType\":\"contract ISynapseBridge\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"migrate\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"chainId\",\"type\":\"uint256\"}],\"name\":\"migrateAndBridge\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"redeemLegacy\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"renounceOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{\"owner()\":{\"details\":\"Returns the address of the current owner.\"},\"renounceOwnership()\":{\"details\":\"Leaves the contract without owner. It will not be possible to call `onlyOwner` functions anymore. Can only be called by the current owner. NOTE: Renouncing ownership will leave the contract without an owner, thereby removing any functionality that is only available to the owner.\"},\"transferOwnership(address)\":{\"details\":\"Transfers ownership of the contract to a new account (`newOwner`). Can only be called by the current owner.\"}},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/bridge/wrappers/AvaxJewelMigration.sol\":\"AvaxJewelMigration\"},\"evmVersion\":\"istanbul\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":10000},\"remappings\":[]},\"sources\":{\"@openzeppelin/contracts/access/Ownable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity >=0.6.0 <0.8.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 () internal {\\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\",\"keccak256\":\"0x15e2d5bd4c28a88548074c54d220e8086f638a71ed07e6b3ba5a70066fcf458d\",\"license\":\"MIT\"},\"@openzeppelin/contracts/math/SafeMath.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity >=0.6.0 <0.8.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\",\"keccak256\":\"0xcc78a17dd88fa5a2edc60c8489e2f405c0913b377216a5b26b35656b2d0dab52\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/ERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity >=0.6.0 <0.8.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_) public {\\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\",\"keccak256\":\"0xca0c2396dbeb3503b51abf4248ebf77a1461edad513c01529df51850a012bee3\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/ERC20Burnable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity >=0.6.0 <0.8.0;\\n\\nimport \\\"../../utils/Context.sol\\\";\\nimport \\\"./ERC20.sol\\\";\\n\\n/**\\n * @dev Extension of {ERC20} that allows token holders to destroy both their own\\n * tokens and those that they have an allowance for, in a way that can be\\n * recognized off-chain (via event analysis).\\n */\\nabstract contract ERC20Burnable is Context, ERC20 {\\n using SafeMath for uint256;\\n\\n /**\\n * @dev Destroys `amount` tokens from the caller.\\n *\\n * See {ERC20-_burn}.\\n */\\n function burn(uint256 amount) public virtual {\\n _burn(_msgSender(), amount);\\n }\\n\\n /**\\n * @dev Destroys `amount` tokens from `account`, deducting from the caller's\\n * allowance.\\n *\\n * See {ERC20-_burn} and {ERC20-allowance}.\\n *\\n * Requirements:\\n *\\n * - the caller must have allowance for ``accounts``'s tokens of at least\\n * `amount`.\\n */\\n function burnFrom(address account, uint256 amount) public virtual {\\n uint256 decreasedAllowance = allowance(account, _msgSender()).sub(amount, \\\"ERC20: burn amount exceeds allowance\\\");\\n\\n _approve(account, _msgSender(), decreasedAllowance);\\n _burn(account, amount);\\n }\\n}\\n\",\"keccak256\":\"0x9c0eb3b0e11d2480d49991dc384f1e5f9c9b9967cc81944d50916a9b9c6c4984\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/IERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity >=0.6.0 <0.8.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\",\"keccak256\":\"0x5f02220344881ce43204ae4a6281145a67bc52c2bb1290a791857df3d19d78f5\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/SafeERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity >=0.6.0 <0.8.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\",\"keccak256\":\"0xf12dfbe97e6276980b83d2830bb0eb75e0cf4f3e626c2471137f82158ae6a0fc\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/Address.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity >=0.6.2 <0.8.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\",\"keccak256\":\"0x28911e614500ae7c607a432a709d35da25f3bc5ddc8bd12b278b66358070c0ea\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/Context.sol\":{\"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\",\"keccak256\":\"0x8d3cb350f04ff49cfb10aef08d87f19dcbaecc8027b0bed12f3275cd12f38cf0\",\"license\":\"MIT\"},\"contracts/bridge/interfaces/ISynapseBridge.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity 0.6.12;\\n\\nimport '@openzeppelin/contracts/token/ERC20/SafeERC20.sol';\\nimport '@openzeppelin/contracts/token/ERC20/ERC20Burnable.sol';\\n\\ninterface ISynapseBridge {\\n using SafeERC20 for IERC20;\\n\\n function deposit(\\n address to,\\n uint256 chainId,\\n IERC20 token,\\n uint256 amount\\n ) external;\\n\\n function depositAndSwap(\\n address to,\\n uint256 chainId,\\n IERC20 token,\\n uint256 amount,\\n uint8 tokenIndexFrom,\\n uint8 tokenIndexTo,\\n uint256 minDy,\\n uint256 deadline\\n ) external;\\n\\n function redeem(\\n address to,\\n uint256 chainId,\\n IERC20 token,\\n uint256 amount\\n ) external;\\n\\n\\n function redeemv2(\\n bytes32 to,\\n uint256 chainId,\\n IERC20 token,\\n uint256 amount\\n ) external;\\n\\n\\n function redeemAndSwap(\\n address to,\\n uint256 chainId,\\n IERC20 token,\\n uint256 amount,\\n uint8 tokenIndexFrom,\\n uint8 tokenIndexTo,\\n uint256 minDy,\\n uint256 deadline\\n ) external;\\n\\n function redeemAndRemove(\\n address to,\\n uint256 chainId,\\n IERC20 token,\\n uint256 amount,\\n uint8 liqTokenIndex,\\n uint256 liqMinAmount,\\n uint256 liqDeadline\\n ) external;\\n}\\n\",\"keccak256\":\"0x9ae06bbed7d464faceb9c63e929171f422b5eaee1f6d653742ab97862bc6609a\",\"license\":\"MIT\"},\"contracts/bridge/wrappers/AvaxJewelMigration.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity 0.6.12;\\n\\nimport \\\"@openzeppelin/contracts/token/ERC20/ERC20.sol\\\";\\nimport \\\"@openzeppelin/contracts/token/ERC20/SafeERC20.sol\\\";\\nimport \\\"@openzeppelin/contracts/access/Ownable.sol\\\";\\n\\nimport \\\"../interfaces/ISynapseBridge.sol\\\";\\n\\ninterface IERC20Mintable is IERC20 {\\n function mint(address to, uint256 amount) external;\\n}\\n\\ncontract AvaxJewelMigration is Ownable {\\n using SafeERC20 for IERC20;\\n using SafeERC20 for IERC20Mintable;\\n\\n ISynapseBridge public constant SYNAPSE_BRIDGE =\\n ISynapseBridge(0xC05e61d0E7a63D27546389B7aD62FdFf5A91aACE);\\n // MULTICHAIN JEWEL\\n IERC20 public constant LEGACY_TOKEN =\\n IERC20(0x4f60a160D8C2DDdaAfe16FCC57566dB84D674BD6);\\n // SYNAPSE JEWEL\\n IERC20Mintable public constant NEW_TOKEN =\\n IERC20Mintable(0x997Ddaa07d716995DE90577C123Db411584E5E46);\\n uint256 private constant MAX_UINT256 = 2**256 - 1;\\n\\n constructor() public {\\n NEW_TOKEN.safeApprove(address(SYNAPSE_BRIDGE), MAX_UINT256);\\n }\\n\\n function migrate(uint256 amount) external {\\n _migrate(amount, msg.sender);\\n }\\n\\n function migrateAndBridge(\\n uint256 amount,\\n address to,\\n uint256 chainId\\n ) external {\\n // First, mint new tokens to this contract, as Bridge burns tokens\\n // from msg.sender, which would be AvaxJewelMigration\\n _migrate(amount, address(this));\\n // Initiate bridging and specify `to` as receiver on destination chain\\n SYNAPSE_BRIDGE.redeem(to, chainId, NEW_TOKEN, amount);\\n }\\n\\n /// @notice Pull old tokens from user and mint new ones to account\\n function _migrate(uint256 amount, address account) internal {\\n require(amount != 0, \\\"Amount must be greater than zero\\\");\\n LEGACY_TOKEN.safeTransferFrom(msg.sender, address(this), amount);\\n NEW_TOKEN.mint(account, amount);\\n }\\n\\n function redeemLegacy() external onlyOwner {\\n uint256 legacyBalance = LEGACY_TOKEN.balanceOf(address(this));\\n LEGACY_TOKEN.safeTransfer(owner(), legacyBalance);\\n }\\n}\\n\",\"keccak256\":\"0x16f6ed85175db27d3c1043e7a8e3c0aad693dccf44d5fa456f3ce0876fe64eae\",\"license\":\"MIT\"}},\"version\":1}", + "bytecode": "0x60806040523480156200001157600080fd5b5060006200001e620000b1565b600080546001600160a01b0319166001600160a01b0383169081178255604051929350917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908290a350620000ab73997ddaa07d716995de90577c123db411584e5e4673c05e61d0e7a63d27546389b7ad62fdff5a91aace600019620000b5602090811b620006f617901c565b620004c8565b3390565b8015806200013f575060408051636eb1769f60e11b81523060048201526001600160a01b03848116602483015291519185169163dd62ed3e91604480820192602092909190829003018186803b1580156200010f57600080fd5b505afa15801562000124573d6000803e3d6000fd5b505050506040513d60208110156200013b57600080fd5b5051155b6200017c5760405162461bcd60e51b81526004018080602001828103825260368152602001806200145b6036913960400191505060405180910390fd5b604080516001600160a01b038416602482015260448082018490528251808303909101815260649091019091526020810180516001600160e01b0390811663095ea7b360e01b17909152620001d4918591620001d916565b505050565b606062000235826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b03166200029560201b62000889179092919060201c565b805190915015620001d4578080602001905160208110156200025657600080fd5b5051620001d45760405162461bcd60e51b815260040180806020018281038252602a81526020018062001431602a913960400191505060405180910390fd5b6060620002a68484600085620002b0565b90505b9392505050565b606082471015620002f35760405162461bcd60e51b81526004018080602001828103825260268152602001806200140b6026913960400191505060405180910390fd5b620002fe8562000418565b62000350576040805162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000604482015290519081900360640190fd5b60006060866001600160a01b031685876040518082805190602001908083835b60208310620003915780518252601f19909201916020918201910162000370565b6001836020036101000a03801982511681845116808217855250505050505090500191505060006040518083038185875af1925050503d8060008114620003f5576040519150601f19603f3d011682016040523d82523d6000602084013e620003fa565b606091505b5090925090506200040d8282866200041e565b979650505050505050565b3b151590565b606083156200042f575081620002a9565b825115620004405782518084602001fd5b8160405162461bcd60e51b81526004018080602001828103825283818151815260200191508051906020019080838360005b838110156200048c57818101518382015260200162000472565b50505050905090810190601f168015620004ba5780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b610f3380620004d86000396000f3fe608060405234801561001057600080fd5b50600436106100a35760003560e01c806385489e7c11610076578063ccd946191161005b578063ccd9461914610118578063f2fde38b14610157578063f8b57f421461018a576100a3565b806385489e7c146101085780638da5cb5b14610110576100a3565b8063359b6cab146100a8578063454b0608146100d9578063715018a6146100f857806374e8484514610100575b600080fd5b6100b0610192565b6040805173ffffffffffffffffffffffffffffffffffffffff9092168252519081900360200190f35b6100f6600480360360208110156100ef57600080fd5b50356101aa565b005b6100f66101b7565b6100b06102ce565b6100b06102e6565b6100b06102fe565b6100f66004803603606081101561012e57600080fd5b5080359073ffffffffffffffffffffffffffffffffffffffff602082013516906040013561031a565b6100f66004803603602081101561016d57600080fd5b503573ffffffffffffffffffffffffffffffffffffffff166103ea565b6100f661058b565b73997ddaa07d716995de90577c123db411584e5e4681565b6101b481336108a2565b50565b6101bf6109d2565b73ffffffffffffffffffffffffffffffffffffffff166101dd6102fe565b73ffffffffffffffffffffffffffffffffffffffff161461025f57604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b6000805460405173ffffffffffffffffffffffffffffffffffffffff909116907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908390a3600080547fffffffffffffffffffffffff0000000000000000000000000000000000000000169055565b73c05e61d0e7a63d27546389b7ad62fdff5a91aace81565b734f60a160d8c2dddaafe16fcc57566db84d674bd681565b60005473ffffffffffffffffffffffffffffffffffffffff1690565b61032483306108a2565b604080517ff3f094a100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff841660048201526024810183905273997ddaa07d716995de90577c123db411584e5e46604482015260648101859052905173c05e61d0e7a63d27546389b7ad62fdff5a91aace9163f3f094a191608480830192600092919082900301818387803b1580156103cd57600080fd5b505af11580156103e1573d6000803e3d6000fd5b50505050505050565b6103f26109d2565b73ffffffffffffffffffffffffffffffffffffffff166104106102fe565b73ffffffffffffffffffffffffffffffffffffffff161461049257604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b73ffffffffffffffffffffffffffffffffffffffff81166104fe576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526026815260200180610e526026913960400191505060405180910390fd5b6000805460405173ffffffffffffffffffffffffffffffffffffffff808516939216917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a3600080547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff92909216919091179055565b6105936109d2565b73ffffffffffffffffffffffffffffffffffffffff166105b16102fe565b73ffffffffffffffffffffffffffffffffffffffff161461063357604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b604080517f70a082310000000000000000000000000000000000000000000000000000000081523060048201529051600091734f60a160d8c2dddaafe16fcc57566db84d674bd6916370a0823191602480820192602092909190829003018186803b1580156106a157600080fd5b505afa1580156106b5573d6000803e3d6000fd5b505050506040513d60208110156106cb57600080fd5b505190506101b46106da6102fe565b734f60a160d8c2dddaafe16fcc57566db84d674bd690836109d6565b8015806107a25750604080517fdd62ed3e00000000000000000000000000000000000000000000000000000000815230600482015273ffffffffffffffffffffffffffffffffffffffff848116602483015291519185169163dd62ed3e91604480820192602092909190829003018186803b15801561077457600080fd5b505afa158015610788573d6000803e3d6000fd5b505050506040513d602081101561079e57600080fd5b5051155b6107f7576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526036815260200180610ec86036913960400191505060405180910390fd5b6040805173ffffffffffffffffffffffffffffffffffffffff8416602482015260448082018490528251808303909101815260649091019091526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f095ea7b300000000000000000000000000000000000000000000000000000000179052610884908490610a5f565b505050565b60606108988484600085610b37565b90505b9392505050565b8161090e57604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f416d6f756e74206d7573742062652067726561746572207468616e207a65726f604482015290519081900360640190fd5b61092e734f60a160d8c2dddaafe16fcc57566db84d674bd6333085610cf2565b604080517f40c10f1900000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8316600482015260248101849052905173997ddaa07d716995de90577c123db411584e5e46916340c10f1991604480830192600092919082900301818387803b1580156109b657600080fd5b505af11580156109ca573d6000803e3d6000fd5b505050505050565b3390565b6040805173ffffffffffffffffffffffffffffffffffffffff8416602482015260448082018490528251808303909101815260649091019091526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fa9059cbb000000000000000000000000000000000000000000000000000000001790526108849084905b6060610ac1826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff166108899092919063ffffffff16565b80519091501561088457808060200190516020811015610ae057600080fd5b5051610884576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602a815260200180610e9e602a913960400191505060405180910390fd5b606082471015610b92576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526026815260200180610e786026913960400191505060405180910390fd5b610b9b85610d8d565b610c0657604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000604482015290519081900360640190fd5b600060608673ffffffffffffffffffffffffffffffffffffffff1685876040518082805190602001908083835b60208310610c7057805182527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe09092019160209182019101610c33565b6001836020036101000a03801982511681845116808217855250505050505090500191505060006040518083038185875af1925050503d8060008114610cd2576040519150601f19603f3d011682016040523d82523d6000602084013e610cd7565b606091505b5091509150610ce7828286610d93565b979650505050505050565b6040805173ffffffffffffffffffffffffffffffffffffffff80861660248301528416604482015260648082018490528251808303909101815260849091019091526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f23b872dd00000000000000000000000000000000000000000000000000000000179052610d87908590610a5f565b50505050565b3b151590565b60608315610da257508161089b565b825115610db25782518084602001fd5b816040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825283818151815260200191508051906020019080838360005b83811015610e16578181015183820152602001610dfe565b50505050905090810190601f168015610e435780820380516001836020036101000a031916815260200191505b509250505060405180910390fdfe4f776e61626c653a206e6577206f776e657220697320746865207a65726f2061646472657373416464726573733a20696e73756666696369656e742062616c616e636520666f722063616c6c5361666545524332303a204552433230206f7065726174696f6e20646964206e6f7420737563636565645361666545524332303a20617070726f76652066726f6d206e6f6e2d7a65726f20746f206e6f6e2d7a65726f20616c6c6f77616e6365a2646970667358221220ace7ac8b2adba2c0efdc6de6bdc684a70f7043f71b935aeac313d84d2a899c8964736f6c634300060c0033416464726573733a20696e73756666696369656e742062616c616e636520666f722063616c6c5361666545524332303a204552433230206f7065726174696f6e20646964206e6f7420737563636565645361666545524332303a20617070726f76652066726f6d206e6f6e2d7a65726f20746f206e6f6e2d7a65726f20616c6c6f77616e6365", + "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106100a35760003560e01c806385489e7c11610076578063ccd946191161005b578063ccd9461914610118578063f2fde38b14610157578063f8b57f421461018a576100a3565b806385489e7c146101085780638da5cb5b14610110576100a3565b8063359b6cab146100a8578063454b0608146100d9578063715018a6146100f857806374e8484514610100575b600080fd5b6100b0610192565b6040805173ffffffffffffffffffffffffffffffffffffffff9092168252519081900360200190f35b6100f6600480360360208110156100ef57600080fd5b50356101aa565b005b6100f66101b7565b6100b06102ce565b6100b06102e6565b6100b06102fe565b6100f66004803603606081101561012e57600080fd5b5080359073ffffffffffffffffffffffffffffffffffffffff602082013516906040013561031a565b6100f66004803603602081101561016d57600080fd5b503573ffffffffffffffffffffffffffffffffffffffff166103ea565b6100f661058b565b73997ddaa07d716995de90577c123db411584e5e4681565b6101b481336108a2565b50565b6101bf6109d2565b73ffffffffffffffffffffffffffffffffffffffff166101dd6102fe565b73ffffffffffffffffffffffffffffffffffffffff161461025f57604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b6000805460405173ffffffffffffffffffffffffffffffffffffffff909116907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908390a3600080547fffffffffffffffffffffffff0000000000000000000000000000000000000000169055565b73c05e61d0e7a63d27546389b7ad62fdff5a91aace81565b734f60a160d8c2dddaafe16fcc57566db84d674bd681565b60005473ffffffffffffffffffffffffffffffffffffffff1690565b61032483306108a2565b604080517ff3f094a100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff841660048201526024810183905273997ddaa07d716995de90577c123db411584e5e46604482015260648101859052905173c05e61d0e7a63d27546389b7ad62fdff5a91aace9163f3f094a191608480830192600092919082900301818387803b1580156103cd57600080fd5b505af11580156103e1573d6000803e3d6000fd5b50505050505050565b6103f26109d2565b73ffffffffffffffffffffffffffffffffffffffff166104106102fe565b73ffffffffffffffffffffffffffffffffffffffff161461049257604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b73ffffffffffffffffffffffffffffffffffffffff81166104fe576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526026815260200180610e526026913960400191505060405180910390fd5b6000805460405173ffffffffffffffffffffffffffffffffffffffff808516939216917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a3600080547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff92909216919091179055565b6105936109d2565b73ffffffffffffffffffffffffffffffffffffffff166105b16102fe565b73ffffffffffffffffffffffffffffffffffffffff161461063357604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b604080517f70a082310000000000000000000000000000000000000000000000000000000081523060048201529051600091734f60a160d8c2dddaafe16fcc57566db84d674bd6916370a0823191602480820192602092909190829003018186803b1580156106a157600080fd5b505afa1580156106b5573d6000803e3d6000fd5b505050506040513d60208110156106cb57600080fd5b505190506101b46106da6102fe565b734f60a160d8c2dddaafe16fcc57566db84d674bd690836109d6565b8015806107a25750604080517fdd62ed3e00000000000000000000000000000000000000000000000000000000815230600482015273ffffffffffffffffffffffffffffffffffffffff848116602483015291519185169163dd62ed3e91604480820192602092909190829003018186803b15801561077457600080fd5b505afa158015610788573d6000803e3d6000fd5b505050506040513d602081101561079e57600080fd5b5051155b6107f7576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526036815260200180610ec86036913960400191505060405180910390fd5b6040805173ffffffffffffffffffffffffffffffffffffffff8416602482015260448082018490528251808303909101815260649091019091526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f095ea7b300000000000000000000000000000000000000000000000000000000179052610884908490610a5f565b505050565b60606108988484600085610b37565b90505b9392505050565b8161090e57604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f416d6f756e74206d7573742062652067726561746572207468616e207a65726f604482015290519081900360640190fd5b61092e734f60a160d8c2dddaafe16fcc57566db84d674bd6333085610cf2565b604080517f40c10f1900000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8316600482015260248101849052905173997ddaa07d716995de90577c123db411584e5e46916340c10f1991604480830192600092919082900301818387803b1580156109b657600080fd5b505af11580156109ca573d6000803e3d6000fd5b505050505050565b3390565b6040805173ffffffffffffffffffffffffffffffffffffffff8416602482015260448082018490528251808303909101815260649091019091526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fa9059cbb000000000000000000000000000000000000000000000000000000001790526108849084905b6060610ac1826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff166108899092919063ffffffff16565b80519091501561088457808060200190516020811015610ae057600080fd5b5051610884576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602a815260200180610e9e602a913960400191505060405180910390fd5b606082471015610b92576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526026815260200180610e786026913960400191505060405180910390fd5b610b9b85610d8d565b610c0657604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000604482015290519081900360640190fd5b600060608673ffffffffffffffffffffffffffffffffffffffff1685876040518082805190602001908083835b60208310610c7057805182527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe09092019160209182019101610c33565b6001836020036101000a03801982511681845116808217855250505050505090500191505060006040518083038185875af1925050503d8060008114610cd2576040519150601f19603f3d011682016040523d82523d6000602084013e610cd7565b606091505b5091509150610ce7828286610d93565b979650505050505050565b6040805173ffffffffffffffffffffffffffffffffffffffff80861660248301528416604482015260648082018490528251808303909101815260849091019091526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f23b872dd00000000000000000000000000000000000000000000000000000000179052610d87908590610a5f565b50505050565b3b151590565b60608315610da257508161089b565b825115610db25782518084602001fd5b816040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825283818151815260200191508051906020019080838360005b83811015610e16578181015183820152602001610dfe565b50505050905090810190601f168015610e435780820380516001836020036101000a031916815260200191505b509250505060405180910390fdfe4f776e61626c653a206e6577206f776e657220697320746865207a65726f2061646472657373416464726573733a20696e73756666696369656e742062616c616e636520666f722063616c6c5361666545524332303a204552433230206f7065726174696f6e20646964206e6f7420737563636565645361666545524332303a20617070726f76652066726f6d206e6f6e2d7a65726f20746f206e6f6e2d7a65726f20616c6c6f77616e6365a2646970667358221220ace7ac8b2adba2c0efdc6de6bdc684a70f7043f71b935aeac313d84d2a899c8964736f6c634300060c0033", + "devdoc": { + "kind": "dev", + "methods": { + "owner()": { + "details": "Returns the address of the current owner." + }, + "renounceOwnership()": { + "details": "Leaves the contract without owner. It will not be possible to call `onlyOwner` functions anymore. Can only be called by the current owner. NOTE: Renouncing ownership will leave the contract without an owner, thereby removing any functionality that is only available to the owner." + }, + "transferOwnership(address)": { + "details": "Transfers ownership of the contract to a new account (`newOwner`). Can only be called by the current owner." + } + }, + "version": 1 + }, + "userdoc": { + "kind": "user", + "methods": {}, + "version": 1 + }, + "storageLayout": { + "storage": [ + { + "astId": 3330, + "contract": "contracts/bridge/wrappers/AvaxJewelMigration.sol:AvaxJewelMigration", + "label": "_owner", + "offset": 0, + "slot": "0", + "type": "t_address" + } + ], + "types": { + "t_address": { + "encoding": "inplace", + "label": "address", + "numberOfBytes": "20" + } + } + } +} \ No newline at end of file diff --git a/deployments/avalanche/AvaxJewelSwap.json b/deployments/avalanche/AvaxJewelSwap.json new file mode 100644 index 000000000..8ffb9d791 --- /dev/null +++ b/deployments/avalanche/AvaxJewelSwap.json @@ -0,0 +1,108 @@ +{ + "address": "0xa6Fa14A446B1b86619De3c27D10eeaAd84a0FcCd", + "abi": [ + { + "inputs": [ + { + "internalType": "uint8", + "name": "tokenIndexFrom", + "type": "uint8" + }, + { + "internalType": "uint8", + "name": "tokenIndexTo", + "type": "uint8" + }, + { + "internalType": "uint256", + "name": "dx", + "type": "uint256" + } + ], + "name": "calculateSwap", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint8", + "name": "tokenIndexFrom", + "type": "uint8" + }, + { + "internalType": "uint8", + "name": "tokenIndexTo", + "type": "uint8" + }, + { + "internalType": "uint256", + "name": "dx", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "minDy", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" + } + ], + "name": "swap", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + } + ], + "transactionHash": "0x871bb8b0daddd98c4d0bf453fcdaad6ff0bdf6f615af8f60ec519ad2fc8606be", + "receipt": { + "to": null, + "from": "0x0AF91FA049A7e1894F480bFE5bBa20142C6c29a9", + "contractAddress": "0xa6Fa14A446B1b86619De3c27D10eeaAd84a0FcCd", + "transactionIndex": 0, + "gasUsed": "129079", + "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "blockHash": "0xee7a6c980955caedd3eb0f68c0b85da588ea02c86194440c9c0476bfe003e316", + "transactionHash": "0x871bb8b0daddd98c4d0bf453fcdaad6ff0bdf6f615af8f60ec519ad2fc8606be", + "logs": [], + "blockNumber": 12926465, + "cumulativeGasUsed": "129079", + "status": 1, + "byzantium": true + }, + "args": [], + "solcInputHash": "176148eace03d1f556691bfef59d8130", + "metadata": "{\"compiler\":{\"version\":\"0.6.12+commit.27d51765\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"uint8\",\"name\":\"tokenIndexFrom\",\"type\":\"uint8\"},{\"internalType\":\"uint8\",\"name\":\"tokenIndexTo\",\"type\":\"uint8\"},{\"internalType\":\"uint256\",\"name\":\"dx\",\"type\":\"uint256\"}],\"name\":\"calculateSwap\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint8\",\"name\":\"tokenIndexFrom\",\"type\":\"uint8\"},{\"internalType\":\"uint8\",\"name\":\"tokenIndexTo\",\"type\":\"uint8\"},{\"internalType\":\"uint256\",\"name\":\"dx\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"minDy\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"deadline\",\"type\":\"uint256\"}],\"name\":\"swap\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/bridge/wrappers/AvaxJewelSwap.sol\":\"AvaxJewelSwap\"},\"evmVersion\":\"istanbul\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":10000},\"remappings\":[]},\"sources\":{\"contracts/bridge/wrappers/AvaxJewelSwap.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity 0.6.12;\\n\\ncontract AvaxJewelSwap {\\n function calculateSwap(\\n uint8 tokenIndexFrom,\\n uint8 tokenIndexTo,\\n uint256 dx\\n ) external view returns (uint256) {\\n return 0;\\n }\\n\\n function swap(\\n uint8 tokenIndexFrom,\\n uint8 tokenIndexTo,\\n uint256 dx,\\n uint256 minDy,\\n uint256 deadline\\n ) external returns (uint256) {\\n revert(\\\"There is no swap\\\");\\n }\\n}\\n\",\"keccak256\":\"0x7bd0bceec25b4fc104bbeac9100769edda876fdd6374bd7e6960906953236355\",\"license\":\"MIT\"}},\"version\":1}", + "bytecode": "0x608060405234801561001057600080fd5b50610161806100206000396000f3fe608060405234801561001057600080fd5b50600436106100365760003560e01c8063916955861461003b578063a95b089f14610089575b600080fd5b610077600480360360a081101561005157600080fd5b5060ff8135811691602081013590911690604081013590606081013590608001356100b9565b60408051918252519081900360200190f35b6100776004803603606081101561009f57600080fd5b5060ff813581169160208101359091169060400135610122565b604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601060248201527f5468657265206973206e6f2073776170000000000000000000000000000000006044820152905160009181900360640190fd5b6000939250505056fea2646970667358221220587701cd875f8b5f9906572337091506b89e9b0b6dc6cb7ecbdd7d115437221064736f6c634300060c0033", + "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106100365760003560e01c8063916955861461003b578063a95b089f14610089575b600080fd5b610077600480360360a081101561005157600080fd5b5060ff8135811691602081013590911690604081013590606081013590608001356100b9565b60408051918252519081900360200190f35b6100776004803603606081101561009f57600080fd5b5060ff813581169160208101359091169060400135610122565b604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601060248201527f5468657265206973206e6f2073776170000000000000000000000000000000006044820152905160009181900360640190fd5b6000939250505056fea2646970667358221220587701cd875f8b5f9906572337091506b89e9b0b6dc6cb7ecbdd7d115437221064736f6c634300060c0033", + "devdoc": { + "kind": "dev", + "methods": {}, + "version": 1 + }, + "userdoc": { + "kind": "user", + "methods": {}, + "version": 1 + }, + "storageLayout": { + "storage": [], + "types": null + } +} \ No newline at end of file diff --git a/deployments/avalanche/JEWEL.json b/deployments/avalanche/JEWEL.json new file mode 100644 index 000000000..b9288ef9e --- /dev/null +++ b/deployments/avalanche/JEWEL.json @@ -0,0 +1,668 @@ +{ + "address": "0x997Ddaa07d716995DE90577C123Db411584E5E46", + "abi": [ + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "Approval", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "bytes32", + "name": "previousAdminRole", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "bytes32", + "name": "newAdminRole", + "type": "bytes32" + } + ], + "name": "RoleAdminChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "sender", + "type": "address" + } + ], + "name": "RoleGranted", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "sender", + "type": "address" + } + ], + "name": "RoleRevoked", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "Transfer", + "type": "event" + }, + { + "inputs": [], + "name": "DEFAULT_ADMIN_ROLE", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "DOMAIN_SEPARATOR", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "MINTER_ROLE", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "address", + "name": "spender", + "type": "address" + } + ], + "name": "allowance", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "approve", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "balanceOf", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "burn", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "burnFrom", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "decimals", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "subtractedValue", + "type": "uint256" + } + ], + "name": "decreaseAllowance", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + } + ], + "name": "getRoleAdmin", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "internalType": "uint256", + "name": "index", + "type": "uint256" + } + ], + "name": "getRoleMember", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + } + ], + "name": "getRoleMemberCount", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "grantRole", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "hasRole", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "addedValue", + "type": "uint256" + } + ], + "name": "increaseAllowance", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "name", + "type": "string" + }, + { + "internalType": "string", + "name": "symbol", + "type": "string" + }, + { + "internalType": "uint8", + "name": "decimals", + "type": "uint8" + }, + { + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "initialize", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "mint", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "name", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "nonces", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" + }, + { + "internalType": "uint8", + "name": "v", + "type": "uint8" + }, + { + "internalType": "bytes32", + "name": "r", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "s", + "type": "bytes32" + } + ], + "name": "permit", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "renounceRole", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "revokeRole", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "symbol", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "totalSupply", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "recipient", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "transfer", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "internalType": "address", + "name": "recipient", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "transferFrom", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + } + ] +} \ No newline at end of file diff --git a/deployments/avalanche/L2BridgeZap.json b/deployments/avalanche/L2BridgeZap.json index 86c15b5f4..284cfecfa 100644 --- a/deployments/avalanche/L2BridgeZap.json +++ b/deployments/avalanche/L2BridgeZap.json @@ -1,5 +1,5 @@ { - "address": "0xE85429C97589AD793Ca11A8BC3477C03d27ED140", + "address": "0x0EF812f4c68DC84c22A4821EF30ba2ffAB9C2f3A", "abi": [ { "inputs": [ @@ -135,6 +135,49 @@ "stateMutability": "payable", "type": "function" }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "chainId", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "internalType": "uint8", + "name": "tokenIndexFrom", + "type": "uint8" + }, + { + "internalType": "uint8", + "name": "tokenIndexTo", + "type": "uint8" + }, + { + "internalType": "uint256", + "name": "minDy", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" + } + ], + "name": "depositETHAndSwap", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, { "inputs": [ { @@ -254,6 +297,34 @@ "stateMutability": "nonpayable", "type": "function" }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "to", + "type": "bytes32" + }, + { + "internalType": "uint256", + "name": "chainId", + "type": "uint256" + }, + { + "internalType": "contract IERC20", + "name": "token", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "redeemv2", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, { "inputs": [ { @@ -593,202 +664,202 @@ "type": "function" } ], - "transactionHash": "0x8e9e6541d1f6a57527e2a33d61fb9c492fd4a1b85625ec45659e60e087e35606", + "transactionHash": "0x98a45fc09b62d83547319f0a8fb1f294a0c240d441fd90f7ad569ab9b2ca395f", "receipt": { "to": null, "from": "0x0AF91FA049A7e1894F480bFE5bBa20142C6c29a9", - "contractAddress": "0xE85429C97589AD793Ca11A8BC3477C03d27ED140", - "transactionIndex": 12, - "gasUsed": "2778704", - "logsBloom": "0x00000000000000000000002000400000000000000000000020000080040000000004000240004800004000000000000000000000100000000000000001210000000080000000040000000000000000400000000000000100000000100000000000000000000000000030000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000040000000000020000000000000000000000000000000000000000000010000000002000000000000000000000000000000000400000000000000000000001000040000000000010040000000000000004000000020004000000000000000000000000000000", - "blockHash": "0xb0766d918876fa53b49649cfe172d4efb383e1c63dacccf3ab6acb61c5853f20", - "transactionHash": "0x8e9e6541d1f6a57527e2a33d61fb9c492fd4a1b85625ec45659e60e087e35606", + "contractAddress": "0x0EF812f4c68DC84c22A4821EF30ba2ffAB9C2f3A", + "transactionIndex": 0, + "gasUsed": "2971445", + "logsBloom": "0x00000000000000000000000000400200000000000000000020000080040000000004000240004800004000000000000000000000100000000000000001210000000080000000040000000000000000400000000000000100000000100000000000000000000000000020000000200000000000000000000000000000000000000000000000000000000000000000008000000000000000000000040000000000020000000000000000000000000000000000000000000010000000002000000000000000000000000000000000400000000000000000000001000040000000200010040000000000000004000000020004000000000000000000000000000000", + "blockHash": "0xa92a52bca8800e0494005d563ba5a7d8ddb32ec49641f480f46fba81be637821", + "transactionHash": "0x98a45fc09b62d83547319f0a8fb1f294a0c240d441fd90f7ad569ab9b2ca395f", "logs": [ { - "transactionIndex": 12, - "blockNumber": 9566786, - "transactionHash": "0x8e9e6541d1f6a57527e2a33d61fb9c492fd4a1b85625ec45659e60e087e35606", + "transactionIndex": 0, + "blockNumber": 12925828, + "transactionHash": "0x98a45fc09b62d83547319f0a8fb1f294a0c240d441fd90f7ad569ab9b2ca395f", "address": "0xB31f66AA3C1e785363F0875A1B74E27b85FD66c7", "topics": [ "0x8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925", - "0x000000000000000000000000e85429c97589ad793ca11a8bc3477c03d27ed140", + "0x0000000000000000000000000ef812f4c68dc84c22a4821ef30ba2ffab9c2f3a", "0x000000000000000000000000c05e61d0e7a63d27546389b7ad62fdff5a91aace" ], "data": "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", - "logIndex": 22, - "blockHash": "0xb0766d918876fa53b49649cfe172d4efb383e1c63dacccf3ab6acb61c5853f20" + "logIndex": 0, + "blockHash": "0xa92a52bca8800e0494005d563ba5a7d8ddb32ec49641f480f46fba81be637821" }, { - "transactionIndex": 12, - "blockNumber": 9566786, - "transactionHash": "0x8e9e6541d1f6a57527e2a33d61fb9c492fd4a1b85625ec45659e60e087e35606", + "transactionIndex": 0, + "blockNumber": 12925828, + "transactionHash": "0x98a45fc09b62d83547319f0a8fb1f294a0c240d441fd90f7ad569ab9b2ca395f", "address": "0x19E1ae0eE35c0404f835521146206595d37981ae", "topics": [ "0x8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925", - "0x000000000000000000000000e85429c97589ad793ca11a8bc3477c03d27ed140", + "0x0000000000000000000000000ef812f4c68dc84c22a4821ef30ba2ffab9c2f3a", "0x000000000000000000000000dd60483ace9b215a7c019a44be2f22aa9982652e" ], "data": "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", - "logIndex": 23, - "blockHash": "0xb0766d918876fa53b49649cfe172d4efb383e1c63dacccf3ab6acb61c5853f20" + "logIndex": 1, + "blockHash": "0xa92a52bca8800e0494005d563ba5a7d8ddb32ec49641f480f46fba81be637821" }, { - "transactionIndex": 12, - "blockNumber": 9566786, - "transactionHash": "0x8e9e6541d1f6a57527e2a33d61fb9c492fd4a1b85625ec45659e60e087e35606", + "transactionIndex": 0, + "blockNumber": 12925828, + "transactionHash": "0x98a45fc09b62d83547319f0a8fb1f294a0c240d441fd90f7ad569ab9b2ca395f", "address": "0x19E1ae0eE35c0404f835521146206595d37981ae", "topics": [ "0x8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925", - "0x000000000000000000000000e85429c97589ad793ca11a8bc3477c03d27ed140", + "0x0000000000000000000000000ef812f4c68dc84c22a4821ef30ba2ffab9c2f3a", "0x000000000000000000000000c05e61d0e7a63d27546389b7ad62fdff5a91aace" ], "data": "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", - "logIndex": 24, - "blockHash": "0xb0766d918876fa53b49649cfe172d4efb383e1c63dacccf3ab6acb61c5853f20" + "logIndex": 2, + "blockHash": "0xa92a52bca8800e0494005d563ba5a7d8ddb32ec49641f480f46fba81be637821" }, { - "transactionIndex": 12, - "blockNumber": 9566786, - "transactionHash": "0x8e9e6541d1f6a57527e2a33d61fb9c492fd4a1b85625ec45659e60e087e35606", + "transactionIndex": 0, + "blockNumber": 12925828, + "transactionHash": "0x98a45fc09b62d83547319f0a8fb1f294a0c240d441fd90f7ad569ab9b2ca395f", "address": "0x49D5c2BdFfac6CE2BFdB6640F4F80f226bc10bAB", "topics": [ "0x8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925", - "0x000000000000000000000000e85429c97589ad793ca11a8bc3477c03d27ed140", + "0x0000000000000000000000000ef812f4c68dc84c22a4821ef30ba2ffab9c2f3a", "0x000000000000000000000000dd60483ace9b215a7c019a44be2f22aa9982652e" ], "data": "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", - "logIndex": 25, - "blockHash": "0xb0766d918876fa53b49649cfe172d4efb383e1c63dacccf3ab6acb61c5853f20" + "logIndex": 3, + "blockHash": "0xa92a52bca8800e0494005d563ba5a7d8ddb32ec49641f480f46fba81be637821" }, { - "transactionIndex": 12, - "blockNumber": 9566786, - "transactionHash": "0x8e9e6541d1f6a57527e2a33d61fb9c492fd4a1b85625ec45659e60e087e35606", + "transactionIndex": 0, + "blockNumber": 12925828, + "transactionHash": "0x98a45fc09b62d83547319f0a8fb1f294a0c240d441fd90f7ad569ab9b2ca395f", "address": "0x49D5c2BdFfac6CE2BFdB6640F4F80f226bc10bAB", "topics": [ "0x8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925", - "0x000000000000000000000000e85429c97589ad793ca11a8bc3477c03d27ed140", + "0x0000000000000000000000000ef812f4c68dc84c22a4821ef30ba2ffab9c2f3a", "0x000000000000000000000000c05e61d0e7a63d27546389b7ad62fdff5a91aace" ], "data": "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", - "logIndex": 26, - "blockHash": "0xb0766d918876fa53b49649cfe172d4efb383e1c63dacccf3ab6acb61c5853f20" + "logIndex": 4, + "blockHash": "0xa92a52bca8800e0494005d563ba5a7d8ddb32ec49641f480f46fba81be637821" }, { - "transactionIndex": 12, - "blockNumber": 9566786, - "transactionHash": "0x8e9e6541d1f6a57527e2a33d61fb9c492fd4a1b85625ec45659e60e087e35606", + "transactionIndex": 0, + "blockNumber": 12925828, + "transactionHash": "0x98a45fc09b62d83547319f0a8fb1f294a0c240d441fd90f7ad569ab9b2ca395f", "address": "0xCFc37A6AB183dd4aED08C204D1c2773c0b1BDf46", "topics": [ "0x8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925", - "0x000000000000000000000000e85429c97589ad793ca11a8bc3477c03d27ed140", + "0x0000000000000000000000000ef812f4c68dc84c22a4821ef30ba2ffab9c2f3a", "0x000000000000000000000000ed2a7edd7413021d440b09d654f3b87712abab66" ], "data": "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", - "logIndex": 27, - "blockHash": "0xb0766d918876fa53b49649cfe172d4efb383e1c63dacccf3ab6acb61c5853f20" + "logIndex": 5, + "blockHash": "0xa92a52bca8800e0494005d563ba5a7d8ddb32ec49641f480f46fba81be637821" }, { - "transactionIndex": 12, - "blockNumber": 9566786, - "transactionHash": "0x8e9e6541d1f6a57527e2a33d61fb9c492fd4a1b85625ec45659e60e087e35606", + "transactionIndex": 0, + "blockNumber": 12925828, + "transactionHash": "0x98a45fc09b62d83547319f0a8fb1f294a0c240d441fd90f7ad569ab9b2ca395f", "address": "0xCFc37A6AB183dd4aED08C204D1c2773c0b1BDf46", "topics": [ "0x8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925", - "0x000000000000000000000000e85429c97589ad793ca11a8bc3477c03d27ed140", + "0x0000000000000000000000000ef812f4c68dc84c22a4821ef30ba2ffab9c2f3a", "0x000000000000000000000000c05e61d0e7a63d27546389b7ad62fdff5a91aace" ], "data": "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", - "logIndex": 28, - "blockHash": "0xb0766d918876fa53b49649cfe172d4efb383e1c63dacccf3ab6acb61c5853f20" + "logIndex": 6, + "blockHash": "0xa92a52bca8800e0494005d563ba5a7d8ddb32ec49641f480f46fba81be637821" }, { - "transactionIndex": 12, - "blockNumber": 9566786, - "transactionHash": "0x8e9e6541d1f6a57527e2a33d61fb9c492fd4a1b85625ec45659e60e087e35606", + "transactionIndex": 0, + "blockNumber": 12925828, + "transactionHash": "0x98a45fc09b62d83547319f0a8fb1f294a0c240d441fd90f7ad569ab9b2ca395f", "address": "0xd586E7F844cEa2F87f50152665BCbc2C279D8d70", "topics": [ "0x8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925", - "0x000000000000000000000000e85429c97589ad793ca11a8bc3477c03d27ed140", + "0x0000000000000000000000000ef812f4c68dc84c22a4821ef30ba2ffab9c2f3a", "0x000000000000000000000000ed2a7edd7413021d440b09d654f3b87712abab66" ], "data": "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", - "logIndex": 29, - "blockHash": "0xb0766d918876fa53b49649cfe172d4efb383e1c63dacccf3ab6acb61c5853f20" + "logIndex": 7, + "blockHash": "0xa92a52bca8800e0494005d563ba5a7d8ddb32ec49641f480f46fba81be637821" }, { - "transactionIndex": 12, - "blockNumber": 9566786, - "transactionHash": "0x8e9e6541d1f6a57527e2a33d61fb9c492fd4a1b85625ec45659e60e087e35606", + "transactionIndex": 0, + "blockNumber": 12925828, + "transactionHash": "0x98a45fc09b62d83547319f0a8fb1f294a0c240d441fd90f7ad569ab9b2ca395f", "address": "0xd586E7F844cEa2F87f50152665BCbc2C279D8d70", "topics": [ "0x8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925", - "0x000000000000000000000000e85429c97589ad793ca11a8bc3477c03d27ed140", + "0x0000000000000000000000000ef812f4c68dc84c22a4821ef30ba2ffab9c2f3a", "0x000000000000000000000000c05e61d0e7a63d27546389b7ad62fdff5a91aace" ], "data": "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", - "logIndex": 30, - "blockHash": "0xb0766d918876fa53b49649cfe172d4efb383e1c63dacccf3ab6acb61c5853f20" + "logIndex": 8, + "blockHash": "0xa92a52bca8800e0494005d563ba5a7d8ddb32ec49641f480f46fba81be637821" }, { - "transactionIndex": 12, - "blockNumber": 9566786, - "transactionHash": "0x8e9e6541d1f6a57527e2a33d61fb9c492fd4a1b85625ec45659e60e087e35606", + "transactionIndex": 0, + "blockNumber": 12925828, + "transactionHash": "0x98a45fc09b62d83547319f0a8fb1f294a0c240d441fd90f7ad569ab9b2ca395f", "address": "0xA7D7079b0FEaD91F3e65f86E8915Cb59c1a4C664", "topics": [ "0x8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925", - "0x000000000000000000000000e85429c97589ad793ca11a8bc3477c03d27ed140", + "0x0000000000000000000000000ef812f4c68dc84c22a4821ef30ba2ffab9c2f3a", "0x000000000000000000000000ed2a7edd7413021d440b09d654f3b87712abab66" ], "data": "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", - "logIndex": 31, - "blockHash": "0xb0766d918876fa53b49649cfe172d4efb383e1c63dacccf3ab6acb61c5853f20" + "logIndex": 9, + "blockHash": "0xa92a52bca8800e0494005d563ba5a7d8ddb32ec49641f480f46fba81be637821" }, { - "transactionIndex": 12, - "blockNumber": 9566786, - "transactionHash": "0x8e9e6541d1f6a57527e2a33d61fb9c492fd4a1b85625ec45659e60e087e35606", + "transactionIndex": 0, + "blockNumber": 12925828, + "transactionHash": "0x98a45fc09b62d83547319f0a8fb1f294a0c240d441fd90f7ad569ab9b2ca395f", "address": "0xA7D7079b0FEaD91F3e65f86E8915Cb59c1a4C664", "topics": [ "0x8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925", - "0x000000000000000000000000e85429c97589ad793ca11a8bc3477c03d27ed140", + "0x0000000000000000000000000ef812f4c68dc84c22a4821ef30ba2ffab9c2f3a", "0x000000000000000000000000c05e61d0e7a63d27546389b7ad62fdff5a91aace" ], "data": "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", - "logIndex": 32, - "blockHash": "0xb0766d918876fa53b49649cfe172d4efb383e1c63dacccf3ab6acb61c5853f20" + "logIndex": 10, + "blockHash": "0xa92a52bca8800e0494005d563ba5a7d8ddb32ec49641f480f46fba81be637821" }, { - "transactionIndex": 12, - "blockNumber": 9566786, - "transactionHash": "0x8e9e6541d1f6a57527e2a33d61fb9c492fd4a1b85625ec45659e60e087e35606", + "transactionIndex": 0, + "blockNumber": 12925828, + "transactionHash": "0x98a45fc09b62d83547319f0a8fb1f294a0c240d441fd90f7ad569ab9b2ca395f", "address": "0xc7198437980c041c805A1EDcbA50c1Ce5db95118", "topics": [ "0x8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925", - "0x000000000000000000000000e85429c97589ad793ca11a8bc3477c03d27ed140", + "0x0000000000000000000000000ef812f4c68dc84c22a4821ef30ba2ffab9c2f3a", "0x000000000000000000000000ed2a7edd7413021d440b09d654f3b87712abab66" ], "data": "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", - "logIndex": 33, - "blockHash": "0xb0766d918876fa53b49649cfe172d4efb383e1c63dacccf3ab6acb61c5853f20" + "logIndex": 11, + "blockHash": "0xa92a52bca8800e0494005d563ba5a7d8ddb32ec49641f480f46fba81be637821" }, { - "transactionIndex": 12, - "blockNumber": 9566786, - "transactionHash": "0x8e9e6541d1f6a57527e2a33d61fb9c492fd4a1b85625ec45659e60e087e35606", + "transactionIndex": 0, + "blockNumber": 12925828, + "transactionHash": "0x98a45fc09b62d83547319f0a8fb1f294a0c240d441fd90f7ad569ab9b2ca395f", "address": "0xc7198437980c041c805A1EDcbA50c1Ce5db95118", "topics": [ "0x8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925", - "0x000000000000000000000000e85429c97589ad793ca11a8bc3477c03d27ed140", + "0x0000000000000000000000000ef812f4c68dc84c22a4821ef30ba2ffab9c2f3a", "0x000000000000000000000000c05e61d0e7a63d27546389b7ad62fdff5a91aace" ], "data": "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", - "logIndex": 34, - "blockHash": "0xb0766d918876fa53b49649cfe172d4efb383e1c63dacccf3ab6acb61c5853f20" + "logIndex": 12, + "blockHash": "0xa92a52bca8800e0494005d563ba5a7d8ddb32ec49641f480f46fba81be637821" } ], - "blockNumber": 9566786, - "cumulativeGasUsed": "3752917", + "blockNumber": 12925828, + "cumulativeGasUsed": "2971445", "status": 1, "byzantium": true }, @@ -800,11 +871,10 @@ "0xCFc37A6AB183dd4aED08C204D1c2773c0b1BDf46", "0xC05e61d0E7a63D27546389B7aD62FdFf5A91aACE" ], - "numDeployments": 1, - "solcInputHash": "d2af276489d403c51a5684671159023d", - "metadata": "{\"compiler\":{\"version\":\"0.6.12+commit.27d51765\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address payable\",\"name\":\"_wethAddress\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_swapOne\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenOne\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_swapTwo\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenTwo\",\"type\":\"address\"},{\"internalType\":\"contract ISynapseBridge\",\"name\":\"_synapseBridge\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"WETH_ADDRESS\",\"outputs\":[{\"internalType\":\"address payable\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contract IERC20\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint8\",\"name\":\"tokenIndexFrom\",\"type\":\"uint8\"},{\"internalType\":\"uint8\",\"name\":\"tokenIndexTo\",\"type\":\"uint8\"},{\"internalType\":\"uint256\",\"name\":\"dx\",\"type\":\"uint256\"}],\"name\":\"calculateSwap\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"chainId\",\"type\":\"uint256\"},{\"internalType\":\"contract IERC20\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"deposit\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"chainId\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"depositETH\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"chainId\",\"type\":\"uint256\"},{\"internalType\":\"contract IERC20\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"redeem\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"chainId\",\"type\":\"uint256\"},{\"internalType\":\"contract IERC20\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"uint8\",\"name\":\"liqTokenIndex\",\"type\":\"uint8\"},{\"internalType\":\"uint256\",\"name\":\"liqMinAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"liqDeadline\",\"type\":\"uint256\"}],\"name\":\"redeemAndRemove\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"chainId\",\"type\":\"uint256\"},{\"internalType\":\"contract IERC20\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"uint8\",\"name\":\"tokenIndexFrom\",\"type\":\"uint8\"},{\"internalType\":\"uint8\",\"name\":\"tokenIndexTo\",\"type\":\"uint8\"},{\"internalType\":\"uint256\",\"name\":\"minDy\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"deadline\",\"type\":\"uint256\"}],\"name\":\"redeemAndSwap\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"chainId\",\"type\":\"uint256\"},{\"internalType\":\"contract IERC20\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint8\",\"name\":\"tokenIndexFrom\",\"type\":\"uint8\"},{\"internalType\":\"uint8\",\"name\":\"tokenIndexTo\",\"type\":\"uint8\"},{\"internalType\":\"uint256\",\"name\":\"dx\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"minDy\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"deadline\",\"type\":\"uint256\"}],\"name\":\"swapAndRedeem\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"chainId\",\"type\":\"uint256\"},{\"internalType\":\"contract IERC20\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint8\",\"name\":\"tokenIndexFrom\",\"type\":\"uint8\"},{\"internalType\":\"uint8\",\"name\":\"tokenIndexTo\",\"type\":\"uint8\"},{\"internalType\":\"uint256\",\"name\":\"dx\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"minDy\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"deadline\",\"type\":\"uint256\"},{\"internalType\":\"uint8\",\"name\":\"liqTokenIndex\",\"type\":\"uint8\"},{\"internalType\":\"uint256\",\"name\":\"liqMinAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"liqDeadline\",\"type\":\"uint256\"}],\"name\":\"swapAndRedeemAndRemove\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"chainId\",\"type\":\"uint256\"},{\"internalType\":\"contract IERC20\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint8\",\"name\":\"tokenIndexFrom\",\"type\":\"uint8\"},{\"internalType\":\"uint8\",\"name\":\"tokenIndexTo\",\"type\":\"uint8\"},{\"internalType\":\"uint256\",\"name\":\"dx\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"minDy\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"deadline\",\"type\":\"uint256\"},{\"internalType\":\"uint8\",\"name\":\"swapTokenIndexFrom\",\"type\":\"uint8\"},{\"internalType\":\"uint8\",\"name\":\"swapTokenIndexTo\",\"type\":\"uint8\"},{\"internalType\":\"uint256\",\"name\":\"swapMinDy\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"swapDeadline\",\"type\":\"uint256\"}],\"name\":\"swapAndRedeemAndSwap\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"chainId\",\"type\":\"uint256\"},{\"internalType\":\"contract IERC20\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint8\",\"name\":\"tokenIndexFrom\",\"type\":\"uint8\"},{\"internalType\":\"uint8\",\"name\":\"tokenIndexTo\",\"type\":\"uint8\"},{\"internalType\":\"uint256\",\"name\":\"dx\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"minDy\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"deadline\",\"type\":\"uint256\"}],\"name\":\"swapETHAndRedeem\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"chainId\",\"type\":\"uint256\"},{\"internalType\":\"contract IERC20\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint8\",\"name\":\"tokenIndexFrom\",\"type\":\"uint8\"},{\"internalType\":\"uint8\",\"name\":\"tokenIndexTo\",\"type\":\"uint8\"},{\"internalType\":\"uint256\",\"name\":\"dx\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"minDy\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"deadline\",\"type\":\"uint256\"},{\"internalType\":\"uint8\",\"name\":\"swapTokenIndexFrom\",\"type\":\"uint8\"},{\"internalType\":\"uint8\",\"name\":\"swapTokenIndexTo\",\"type\":\"uint8\"},{\"internalType\":\"uint256\",\"name\":\"swapMinDy\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"swapDeadline\",\"type\":\"uint256\"}],\"name\":\"swapETHAndRedeemAndSwap\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"swapMap\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"swapTokensMap\",\"outputs\":[{\"internalType\":\"contract IERC20\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{\"calculateSwap(address,uint8,uint8,uint256)\":{\"params\":{\"dx\":\"the amount of tokens the user wants to sell. If the token charges a fee on transfers, use the amount that gets transferred after the fee.\",\"tokenIndexFrom\":\"the token the user wants to sell\",\"tokenIndexTo\":\"the token the user wants to buy\"},\"returns\":{\"_0\":\"amount of tokens the user will receive\"}},\"deposit(address,uint256,address,uint256)\":{\"params\":{\"amount\":\"Amount in native token decimals to transfer cross-chain pre-fees*\",\"chainId\":\"which underlying chain to bridge assets onto\",\"to\":\"address on other chain to redeem underlying assets to\",\"token\":\"ERC20 compatible token to deposit into the bridge\"}},\"depositETH(address,uint256,uint256)\":{\"params\":{\"amount\":\"Amount in native token decimals to transfer cross-chain pre-fees*\",\"chainId\":\"which chain to bridge assets onto\",\"to\":\"address on other chain to bridge assets to\"}},\"redeem(address,uint256,address,uint256)\":{\"params\":{\"amount\":\"Amount in native token decimals to transfer cross-chain pre-fees*\",\"chainId\":\"which underlying chain to bridge assets onto\",\"to\":\"address on other chain to redeem underlying assets to\",\"token\":\"ERC20 compatible token to deposit into the bridge\"}},\"redeemAndRemove(address,uint256,address,uint256,uint8,uint256,uint256)\":{\"params\":{\"amount\":\"Amount of (typically) LP token to pass to the nodes to attempt to removeLiquidity() with to redeem for the underlying assets of the LP token\",\"chainId\":\"which underlying chain to bridge assets onto\",\"liqDeadline\":\"Specificies the deadline that the nodes are allowed to try to redeem/swap the LP token*\",\"liqMinAmount\":\"Specifies the minimum amount of the underlying asset needed for the nodes to execute the redeem/swap\",\"liqTokenIndex\":\"Specifies which of the underlying LP assets the nodes should attempt to redeem for\",\"to\":\"address on other chain to redeem underlying assets to\",\"token\":\"ERC20 compatible token to deposit into the bridge\"}},\"redeemAndSwap(address,uint256,address,uint256,uint8,uint8,uint256,uint256)\":{\"params\":{\"amount\":\"Amount in native token decimals to transfer cross-chain pre-fees\",\"chainId\":\"which underlying chain to bridge assets onto\",\"deadline\":\"latest timestamp to accept this transaction*\",\"minDy\":\"the min amount the user would like to receive, or revert to only minting the SynERC20 token crosschain.\",\"to\":\"address on other chain to redeem underlying assets to\",\"token\":\"ERC20 compatible token to deposit into the bridge\",\"tokenIndexFrom\":\"the token the user wants to swap from\",\"tokenIndexTo\":\"the token the user wants to swap to\"}}},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{\"calculateSwap(address,uint8,uint8,uint256)\":{\"notice\":\"Calculate amount of tokens you receive on swap\"},\"deposit(address,uint256,address,uint256)\":{\"notice\":\"wraps SynapseBridge redeem()\"},\"depositETH(address,uint256,uint256)\":{\"notice\":\"Wraps SynapseBridge deposit() function to make it compatible w/ ETH -> WETH conversions\"},\"redeem(address,uint256,address,uint256)\":{\"notice\":\"wraps SynapseBridge redeem()\"},\"redeemAndRemove(address,uint256,address,uint256,uint8,uint256,uint256)\":{\"notice\":\"Wraps redeemAndRemove on SynapseBridge Relays to nodes that (typically) a wrapped synAsset ERC20 token has been burned and the underlying needs to be redeeemed on the native chain. This function indicates to the nodes that they should attempt to redeem the LP token for the underlying assets (E.g \\\"swap\\\" out of the LP token)\"},\"redeemAndSwap(address,uint256,address,uint256,uint8,uint8,uint256,uint256)\":{\"notice\":\"Wraps redeemAndSwap on SynapseBridge.sol Relays to nodes that (typically) a wrapped synAsset ERC20 token has been burned and the underlying needs to be redeeemed on the native chain. This function indicates to the nodes that they should attempt to redeem the LP token for the underlying assets (E.g \\\"swap\\\" out of the LP token)\"}},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/bridge/wrappers/L2BridgeZap.sol\":\"L2BridgeZap\"},\"evmVersion\":\"istanbul\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":10000},\"remappings\":[]},\"sources\":{\"@openzeppelin/contracts/math/SafeMath.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity >=0.6.0 <0.8.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\",\"keccak256\":\"0xcc78a17dd88fa5a2edc60c8489e2f405c0913b377216a5b26b35656b2d0dab52\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/ERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity >=0.6.0 <0.8.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_) public {\\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\",\"keccak256\":\"0xca0c2396dbeb3503b51abf4248ebf77a1461edad513c01529df51850a012bee3\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/ERC20Burnable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity >=0.6.0 <0.8.0;\\n\\nimport \\\"../../utils/Context.sol\\\";\\nimport \\\"./ERC20.sol\\\";\\n\\n/**\\n * @dev Extension of {ERC20} that allows token holders to destroy both their own\\n * tokens and those that they have an allowance for, in a way that can be\\n * recognized off-chain (via event analysis).\\n */\\nabstract contract ERC20Burnable is Context, ERC20 {\\n using SafeMath for uint256;\\n\\n /**\\n * @dev Destroys `amount` tokens from the caller.\\n *\\n * See {ERC20-_burn}.\\n */\\n function burn(uint256 amount) public virtual {\\n _burn(_msgSender(), amount);\\n }\\n\\n /**\\n * @dev Destroys `amount` tokens from `account`, deducting from the caller's\\n * allowance.\\n *\\n * See {ERC20-_burn} and {ERC20-allowance}.\\n *\\n * Requirements:\\n *\\n * - the caller must have allowance for ``accounts``'s tokens of at least\\n * `amount`.\\n */\\n function burnFrom(address account, uint256 amount) public virtual {\\n uint256 decreasedAllowance = allowance(account, _msgSender()).sub(amount, \\\"ERC20: burn amount exceeds allowance\\\");\\n\\n _approve(account, _msgSender(), decreasedAllowance);\\n _burn(account, amount);\\n }\\n}\\n\",\"keccak256\":\"0x9c0eb3b0e11d2480d49991dc384f1e5f9c9b9967cc81944d50916a9b9c6c4984\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/IERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity >=0.6.0 <0.8.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\",\"keccak256\":\"0x5f02220344881ce43204ae4a6281145a67bc52c2bb1290a791857df3d19d78f5\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/SafeERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity >=0.6.0 <0.8.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\",\"keccak256\":\"0xf12dfbe97e6276980b83d2830bb0eb75e0cf4f3e626c2471137f82158ae6a0fc\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/Address.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity >=0.6.2 <0.8.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\",\"keccak256\":\"0x28911e614500ae7c607a432a709d35da25f3bc5ddc8bd12b278b66358070c0ea\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/Context.sol\":{\"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\",\"keccak256\":\"0x8d3cb350f04ff49cfb10aef08d87f19dcbaecc8027b0bed12f3275cd12f38cf0\",\"license\":\"MIT\"},\"contracts/bridge/interfaces/ISwap.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity 0.6.12;\\n\\nimport '@openzeppelin/contracts/token/ERC20/ERC20.sol';\\n\\ninterface ISwap {\\n // pool data view functions\\n function getA() external view returns (uint256);\\n\\n function getToken(uint8 index) external view returns (IERC20);\\n\\n function getTokenIndex(address tokenAddress) external view returns (uint8);\\n\\n function getTokenBalance(uint8 index) external view returns (uint256);\\n\\n function getVirtualPrice() external view returns (uint256);\\n\\n // min return calculation functions\\n function calculateSwap(\\n uint8 tokenIndexFrom,\\n uint8 tokenIndexTo,\\n uint256 dx\\n ) external view returns (uint256);\\n\\n function calculateTokenAmount(uint256[] calldata amounts, bool deposit)\\n external\\n view\\n returns (uint256);\\n\\n function calculateRemoveLiquidity(uint256 amount)\\n external\\n view\\n returns (uint256[] memory);\\n\\n function calculateRemoveLiquidityOneToken(\\n uint256 tokenAmount,\\n uint8 tokenIndex\\n ) external view returns (uint256 availableTokenAmount);\\n\\n // state modifying functions\\n function initialize(\\n IERC20[] memory pooledTokens,\\n uint8[] memory decimals,\\n string memory lpTokenName,\\n string memory lpTokenSymbol,\\n uint256 a,\\n uint256 fee,\\n uint256 adminFee,\\n address lpTokenTargetAddress\\n ) external;\\n\\n function swap(\\n uint8 tokenIndexFrom,\\n uint8 tokenIndexTo,\\n uint256 dx,\\n uint256 minDy,\\n uint256 deadline\\n ) external returns (uint256);\\n\\n function addLiquidity(\\n uint256[] calldata amounts,\\n uint256 minToMint,\\n uint256 deadline\\n ) external returns (uint256);\\n\\n function removeLiquidity(\\n uint256 amount,\\n uint256[] calldata minAmounts,\\n uint256 deadline\\n ) external returns (uint256[] memory);\\n\\n function removeLiquidityOneToken(\\n uint256 tokenAmount,\\n uint8 tokenIndex,\\n uint256 minAmount,\\n uint256 deadline\\n ) external returns (uint256);\\n\\n function removeLiquidityImbalance(\\n uint256[] calldata amounts,\\n uint256 maxBurnAmount,\\n uint256 deadline\\n ) external returns (uint256);\\n}\\n\",\"keccak256\":\"0xb51eb389637b2b595a09cd95ea4167a6d945719be1bc127eafae07c06abd8ca8\",\"license\":\"MIT\"},\"contracts/bridge/interfaces/ISynapseBridge.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity 0.6.12;\\n\\nimport '@openzeppelin/contracts/token/ERC20/SafeERC20.sol';\\nimport '@openzeppelin/contracts/token/ERC20/ERC20Burnable.sol';\\n\\ninterface ISynapseBridge {\\n using SafeERC20 for IERC20;\\n\\n function deposit(\\n address to,\\n uint256 chainId,\\n IERC20 token,\\n uint256 amount\\n ) external;\\n\\n function depositAndSwap(\\n address to,\\n uint256 chainId,\\n IERC20 token,\\n uint256 amount,\\n uint8 tokenIndexFrom,\\n uint8 tokenIndexTo,\\n uint256 minDy,\\n uint256 deadline\\n ) external;\\n\\n function redeem(\\n address to,\\n uint256 chainId,\\n IERC20 token,\\n uint256 amount\\n ) external;\\n\\n function redeemAndSwap(\\n address to,\\n uint256 chainId,\\n IERC20 token,\\n uint256 amount,\\n uint8 tokenIndexFrom,\\n uint8 tokenIndexTo,\\n uint256 minDy,\\n uint256 deadline\\n ) external;\\n\\n function redeemAndRemove(\\n address to,\\n uint256 chainId,\\n IERC20 token,\\n uint256 amount,\\n uint8 liqTokenIndex,\\n uint256 liqMinAmount,\\n uint256 liqDeadline\\n ) external;\\n}\\n\",\"keccak256\":\"0x481ef0dfbfdf319518480c86f83fe6caea352ced4aa05f26389285af5c7e4c19\",\"license\":\"MIT\"},\"contracts/bridge/interfaces/IWETH9.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity >=0.4.0;\\n\\ninterface IWETH9 {\\n function name() external view returns (string memory);\\n\\n function symbol() external view returns (string memory);\\n\\n function decimals() external view returns (uint8);\\n\\n function balanceOf(address) external view returns (uint256);\\n\\n function allowance(address, address) external view returns (uint256);\\n\\n receive() external payable;\\n\\n function deposit() external payable;\\n\\n function withdraw(uint256 wad) external;\\n\\n function totalSupply() external view returns (uint256);\\n\\n function approve(address guy, uint256 wad) external returns (bool);\\n\\n function transfer(address dst, uint256 wad) external returns (bool);\\n\\n function transferFrom(\\n address src,\\n address dst,\\n uint256 wad\\n ) external returns (bool);\\n}\",\"keccak256\":\"0x081ebde11dad2210d382564d40336f914d3d621750645f23707ca1a92139dbe2\",\"license\":\"MIT\"},\"contracts/bridge/wrappers/L2BridgeZap.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.6.12;\\n\\nimport \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\nimport \\\"@openzeppelin/contracts/token/ERC20/SafeERC20.sol\\\";\\nimport \\\"../interfaces/ISwap.sol\\\";\\nimport \\\"../interfaces/ISynapseBridge.sol\\\";\\nimport \\\"../interfaces/IWETH9.sol\\\";\\n\\ncontract L2BridgeZap {\\n using SafeERC20 for IERC20;\\n\\n ISynapseBridge synapseBridge;\\n address payable public immutable WETH_ADDRESS;\\n\\n mapping(address => address) public swapMap;\\n mapping(address => IERC20[]) public swapTokensMap;\\n\\n uint256 constant MAX_UINT256 = 2**256 - 1;\\n\\n constructor(\\n address payable _wethAddress,\\n address _swapOne,\\n address tokenOne,\\n address _swapTwo,\\n address tokenTwo,\\n ISynapseBridge _synapseBridge\\n ) public {\\n WETH_ADDRESS = _wethAddress;\\n synapseBridge = _synapseBridge;\\n swapMap[tokenOne] = _swapOne;\\n swapMap[tokenTwo] = _swapTwo;\\n IERC20(_wethAddress).safeIncreaseAllowance(address(_synapseBridge), MAX_UINT256);\\n if (address(_swapOne) != address(0)) {\\n {\\n uint8 i;\\n for (; i < 32; i++) {\\n try ISwap(_swapOne).getToken(i) returns (\\n IERC20 token\\n ) {\\n swapTokensMap[_swapOne].push(token);\\n token.safeApprove(address(_swapOne), MAX_UINT256);\\n token.safeApprove(address(synapseBridge), MAX_UINT256);\\n } catch {\\n break;\\n }\\n }\\n require(i > 1, \\\"swap must have at least 2 tokens\\\");\\n }\\n }\\n if (address(_swapTwo) != address(0)) {\\n {\\n uint8 i;\\n for (; i < 32; i++) {\\n try ISwap(_swapTwo).getToken(i) returns (\\n IERC20 token\\n ) {\\n swapTokensMap[_swapTwo].push(token);\\n token.safeApprove(address(_swapTwo), MAX_UINT256);\\n token.safeApprove(address(synapseBridge), MAX_UINT256);\\n } catch {\\n break;\\n }\\n }\\n require(i > 1, \\\"swap must have at least 2 tokens\\\");\\n }\\n }\\n }\\n\\n /**\\n * @notice Calculate amount of tokens you receive on swap\\n * @param tokenIndexFrom the token the user wants to sell\\n * @param tokenIndexTo the token the user wants to buy\\n * @param dx the amount of tokens the user wants to sell. If the token charges\\n * a fee on transfers, use the amount that gets transferred after the fee.\\n * @return amount of tokens the user will receive\\n */\\n function calculateSwap(\\n IERC20 token,\\n uint8 tokenIndexFrom,\\n uint8 tokenIndexTo,\\n uint256 dx\\n ) external view virtual returns (uint256) {\\n ISwap swap = ISwap(\\n swapMap[address(token)]\\n );\\n return swap.calculateSwap(tokenIndexFrom, tokenIndexTo, dx);\\n }\\n\\n function swapAndRedeem(\\n address to,\\n uint256 chainId,\\n IERC20 token,\\n uint8 tokenIndexFrom,\\n uint8 tokenIndexTo,\\n uint256 dx,\\n uint256 minDy,\\n uint256 deadline\\n ) external {\\n ISwap swap = ISwap(swapMap[address(token)]);\\n require(address(swap) != address(0), \\\"Swap is 0x00\\\");\\n IERC20[] memory tokens = swapTokensMap[address(swap)];\\n tokens[tokenIndexFrom].safeTransferFrom(\\n msg.sender,\\n address(this),\\n dx\\n );\\n // swap\\n\\n uint256 swappedAmount = swap.swap(\\n tokenIndexFrom,\\n tokenIndexTo,\\n dx,\\n minDy,\\n deadline\\n );\\n // deposit into bridge, gets nUSD\\n if (\\n token.allowance(address(this), address(synapseBridge)) <\\n swappedAmount\\n ) {\\n token.safeApprove(address(synapseBridge), MAX_UINT256);\\n }\\n synapseBridge.redeem(to, chainId, token, swappedAmount);\\n }\\n\\n function swapAndRedeemAndSwap(\\n address to,\\n uint256 chainId,\\n IERC20 token,\\n uint8 tokenIndexFrom,\\n uint8 tokenIndexTo,\\n uint256 dx,\\n uint256 minDy,\\n uint256 deadline,\\n uint8 swapTokenIndexFrom,\\n uint8 swapTokenIndexTo,\\n uint256 swapMinDy,\\n uint256 swapDeadline\\n ) external {\\n require(\\n address(swapMap[address(token)]) != address(0),\\n \\\"Swap is 0x00\\\"\\n );\\n IERC20[] memory tokens = swapTokensMap[\\n swapMap[address(token)]\\n ];\\n tokens[tokenIndexFrom].safeTransferFrom(\\n msg.sender,\\n address(this),\\n dx\\n );\\n // swap\\n\\n uint256 swappedAmount = ISwap(swapMap[address(token)]).swap(tokenIndexFrom, tokenIndexTo, dx, minDy, deadline);\\n // deposit into bridge, gets nUSD\\n if (\\n token.allowance(address(this), address(synapseBridge)) <\\n swappedAmount\\n ) {\\n token.safeApprove(address(synapseBridge), MAX_UINT256);\\n }\\n synapseBridge.redeemAndSwap(\\n to,\\n chainId,\\n token,\\n swappedAmount,\\n swapTokenIndexFrom,\\n swapTokenIndexTo,\\n swapMinDy,\\n swapDeadline\\n );\\n }\\n\\n function swapAndRedeemAndRemove(\\n address to,\\n uint256 chainId,\\n IERC20 token,\\n uint8 tokenIndexFrom,\\n uint8 tokenIndexTo,\\n uint256 dx,\\n uint256 minDy,\\n uint256 deadline,\\n uint8 liqTokenIndex,\\n uint256 liqMinAmount,\\n uint256 liqDeadline\\n ) external {\\n ISwap swap = ISwap(swapMap[address(token)]);\\n require(address(swap) != address(0), \\\"Swap is 0x00\\\");\\n IERC20[] memory tokens = swapTokensMap[address(swap)];\\n tokens[tokenIndexFrom].safeTransferFrom(\\n msg.sender,\\n address(this),\\n dx\\n );\\n // swap\\n\\n uint256 swappedAmount = swap.swap(\\n tokenIndexFrom,\\n tokenIndexTo,\\n dx,\\n minDy,\\n deadline\\n );\\n // deposit into bridge, gets nUSD\\n if (\\n token.allowance(address(this), address(synapseBridge)) <\\n swappedAmount\\n ) {\\n token.safeApprove(address(synapseBridge), MAX_UINT256);\\n }\\n synapseBridge.redeemAndRemove(\\n to,\\n chainId,\\n token,\\n swappedAmount,\\n liqTokenIndex,\\n liqMinAmount,\\n liqDeadline\\n );\\n }\\n\\n /**\\n * @notice wraps SynapseBridge redeem()\\n * @param to address on other chain to redeem underlying assets to\\n * @param chainId which underlying chain to bridge assets onto\\n * @param token ERC20 compatible token to deposit into the bridge\\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\\n **/\\n function redeem(\\n address to,\\n uint256 chainId,\\n IERC20 token,\\n uint256 amount\\n ) external {\\n token.safeTransferFrom(msg.sender, address(this), amount);\\n if (token.allowance(address(this), address(synapseBridge)) < amount) {\\n token.safeApprove(address(synapseBridge), MAX_UINT256);\\n }\\n synapseBridge.redeem(to, chainId, token, amount);\\n }\\n\\n /**\\n * @notice wraps SynapseBridge redeem()\\n * @param to address on other chain to redeem underlying assets to\\n * @param chainId which underlying chain to bridge assets onto\\n * @param token ERC20 compatible token to deposit into the bridge\\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\\n **/\\n function deposit(\\n address to,\\n uint256 chainId,\\n IERC20 token,\\n uint256 amount\\n ) external {\\n token.safeTransferFrom(msg.sender, address(this), amount);\\n if (token.allowance(address(this), address(synapseBridge)) < amount) {\\n token.safeApprove(address(synapseBridge), MAX_UINT256);\\n }\\n synapseBridge.deposit(to, chainId, token, amount);\\n }\\n\\n /**\\n * @notice Wraps SynapseBridge deposit() function to make it compatible w/ ETH -> WETH conversions\\n * @param to address on other chain to bridge assets to\\n * @param chainId which chain to bridge assets onto\\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\\n **/\\n function depositETH(\\n address to,\\n uint256 chainId,\\n uint256 amount\\n ) external payable {\\n require(msg.value > 0 && msg.value == amount, 'INCORRECT MSG VALUE');\\n IWETH9(WETH_ADDRESS).deposit{value: msg.value}();\\n synapseBridge.deposit(to, chainId, IERC20(WETH_ADDRESS), amount);\\n }\\n\\n\\n function swapETHAndRedeem(\\n address to,\\n uint256 chainId,\\n IERC20 token,\\n uint8 tokenIndexFrom,\\n uint8 tokenIndexTo,\\n uint256 dx,\\n uint256 minDy,\\n uint256 deadline\\n ) external payable {\\n require(WETH_ADDRESS != address(0), \\\"WETH 0\\\");\\n require(msg.value > 0 && msg.value == dx, \\\"INCORRECT MSG VALUE\\\");\\n ISwap swap = ISwap(swapMap[address(token)]);\\n require(address(swap) != address(0), \\\"Swap is 0x00\\\");\\n IWETH9(WETH_ADDRESS).deposit{value: msg.value}();\\n\\n // swap\\n uint256 swappedAmount = swap.swap(\\n tokenIndexFrom,\\n tokenIndexTo,\\n dx,\\n minDy,\\n deadline\\n );\\n synapseBridge.redeem(to, chainId, token, swappedAmount);\\n }\\n\\n\\n function swapETHAndRedeemAndSwap(\\n address to,\\n uint256 chainId,\\n IERC20 token,\\n uint8 tokenIndexFrom,\\n uint8 tokenIndexTo,\\n uint256 dx,\\n uint256 minDy,\\n uint256 deadline,\\n uint8 swapTokenIndexFrom,\\n uint8 swapTokenIndexTo,\\n uint256 swapMinDy,\\n uint256 swapDeadline\\n ) external payable {\\n require(WETH_ADDRESS != address(0), \\\"WETH 0\\\");\\n require(msg.value > 0 && msg.value == dx, \\\"INCORRECT MSG VALUE\\\");\\n ISwap swap = ISwap(swapMap[address(token)]);\\n require(address(swap) != address(0), \\\"Swap is 0x00\\\");\\n IWETH9(WETH_ADDRESS).deposit{value: msg.value}();\\n\\n // swap\\n uint256 swappedAmount = swap.swap(\\n tokenIndexFrom,\\n tokenIndexTo,\\n dx,\\n minDy,\\n deadline\\n );\\n synapseBridge.redeemAndSwap(to, chainId, token, swappedAmount,swapTokenIndexFrom,\\n swapTokenIndexTo,\\n swapMinDy,\\n swapDeadline);\\n }\\n\\n\\n /**\\n * @notice Wraps redeemAndSwap on SynapseBridge.sol\\n * Relays to nodes that (typically) a wrapped synAsset ERC20 token has been burned and the underlying needs to be redeeemed on the native chain. This function indicates to the nodes that they should attempt to redeem the LP token for the underlying assets (E.g \\\"swap\\\" out of the LP token)\\n * @param to address on other chain to redeem underlying assets to\\n * @param chainId which underlying chain to bridge assets onto\\n * @param token ERC20 compatible token to deposit into the bridge\\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\\n * @param tokenIndexFrom the token the user wants to swap from\\n * @param tokenIndexTo the token the user wants to swap to\\n * @param minDy the min amount the user would like to receive, or revert to only minting the SynERC20 token crosschain.\\n * @param deadline latest timestamp to accept this transaction\\n **/\\n function redeemAndSwap(\\n address to,\\n uint256 chainId,\\n IERC20 token,\\n uint256 amount,\\n uint8 tokenIndexFrom,\\n uint8 tokenIndexTo,\\n uint256 minDy,\\n uint256 deadline\\n ) external {\\n token.safeTransferFrom(msg.sender, address(this), amount);\\n if (token.allowance(address(this), address(synapseBridge)) < amount) {\\n token.safeApprove(address(synapseBridge), MAX_UINT256);\\n }\\n synapseBridge.redeemAndSwap(\\n to,\\n chainId,\\n token,\\n amount,\\n tokenIndexFrom,\\n tokenIndexTo,\\n minDy,\\n deadline\\n );\\n }\\n\\n /**\\n * @notice Wraps redeemAndRemove on SynapseBridge\\n * Relays to nodes that (typically) a wrapped synAsset ERC20 token has been burned and the underlying needs to be redeeemed on the native chain. This function indicates to the nodes that they should attempt to redeem the LP token for the underlying assets (E.g \\\"swap\\\" out of the LP token)\\n * @param to address on other chain to redeem underlying assets to\\n * @param chainId which underlying chain to bridge assets onto\\n * @param token ERC20 compatible token to deposit into the bridge\\n * @param amount Amount of (typically) LP token to pass to the nodes to attempt to removeLiquidity() with to redeem for the underlying assets of the LP token\\n * @param liqTokenIndex Specifies which of the underlying LP assets the nodes should attempt to redeem for\\n * @param liqMinAmount Specifies the minimum amount of the underlying asset needed for the nodes to execute the redeem/swap\\n * @param liqDeadline Specificies the deadline that the nodes are allowed to try to redeem/swap the LP token\\n **/\\n function redeemAndRemove(\\n address to,\\n uint256 chainId,\\n IERC20 token,\\n uint256 amount,\\n uint8 liqTokenIndex,\\n uint256 liqMinAmount,\\n uint256 liqDeadline\\n ) external {\\n token.safeTransferFrom(msg.sender, address(this), amount);\\n if (token.allowance(address(this), address(synapseBridge)) < amount) {\\n token.safeApprove(address(synapseBridge), MAX_UINT256);\\n }\\n synapseBridge.redeemAndRemove(\\n to,\\n chainId,\\n token,\\n amount,\\n liqTokenIndex,\\n liqMinAmount,\\n liqDeadline\\n );\\n }\\n}\\n\",\"keccak256\":\"0x3730787562624797d82b25975aae7fdc5ee119d79f8b3c26af1f5770a2b25be1\",\"license\":\"MIT\"}},\"version\":1}", - "bytecode": "0x60a06040523480156200001157600080fd5b5060405162002eeb38038062002eeb833981810160405260c08110156200003757600080fd5b50805160208083015160408085015160608087015160808089015160a0909901519288901b6001600160601b0319169052600080546001600160a01b03199081166001600160a01b0380861691909117835580861683526001895286832080548316828a16179055808b1683529590912080549091168583161790559596939591949193929091620000db91881690839060001990620003cf811b62001db317901c565b6001600160a01b038516156200024f5760005b60208160ff1610156200020557856001600160a01b03166382b86600826040518263ffffffff1660e01b8152600401808260ff16815260200191505060206040518083038186803b1580156200014357600080fd5b505afa9250505080156200016a57506040513d60208110156200016557600080fd5b505160015b620001755762000205565b6001600160a01b038781166000908152600260209081526040822080546001810182559083529181902090910180546001600160a01b0319169284169283179055620001d19190899060001990620004d8811b62001ed217901c565b600054620001fb906001600160a01b038381169116600019620004d8602090811b62001ed217901c565b50600101620000ee565b60018160ff16116200024d576040805162461bcd60e51b8152602060048201819052602482015260008051602062002e6b833981519152604482015290519081900360640190fd5b505b6001600160a01b03831615620003c35760005b60208160ff1610156200037957836001600160a01b03166382b86600826040518263ffffffff1660e01b8152600401808260ff16815260200191505060206040518083038186803b158015620002b757600080fd5b505afa925050508015620002de57506040513d6020811015620002d957600080fd5b505160015b620002e95762000379565b6001600160a01b038581166000908152600260209081526040822080546001810182559083529181902090910180546001600160a01b0319169284169283179055620003459190879060001990620004d8811b62001ed217901c565b6000546200036f906001600160a01b038381169116600019620004d8602090811b62001ed217901c565b5060010162000262565b60018160ff1611620003c1576040805162461bcd60e51b8152602060048201819052602482015260008051602062002e6b833981519152604482015290519081900360640190fd5b505b5050505050506200094b565b60006200047682856001600160a01b031663dd62ed3e30876040518363ffffffff1660e01b815260040180836001600160a01b03168152602001826001600160a01b031681526020019250505060206040518083038186803b1580156200043557600080fd5b505afa1580156200044a573d6000803e3d6000fd5b505050506040513d60208110156200046157600080fd5b505190620005fc602090811b6200203117901c565b604080516001600160a01b038616602482015260448082018490528251808303909101815260649091019091526020810180516001600160e01b0390811663095ea7b360e01b17909152919250620004d2918691906200065e16565b50505050565b80158062000562575060408051636eb1769f60e11b81523060048201526001600160a01b03848116602483015291519185169163dd62ed3e91604480820192602092909190829003018186803b1580156200053257600080fd5b505afa15801562000547573d6000803e3d6000fd5b505050506040513d60208110156200055e57600080fd5b5051155b6200059f5760405162461bcd60e51b815260040180806020018281038252603681526020018062002eb56036913960400191505060405180910390fd5b604080516001600160a01b038416602482015260448082018490528251808303909101815260649091019091526020810180516001600160e01b0390811663095ea7b360e01b17909152620005f79185916200065e16565b505050565b60008282018381101562000657576040805162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b9392505050565b6060620006ba826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b03166200071a60201b62002092179092919060201c565b805190915015620005f757808060200190516020811015620006db57600080fd5b5051620005f75760405162461bcd60e51b815260040180806020018281038252602a81526020018062002e8b602a913960400191505060405180910390fd5b60606200072b848460008562000733565b949350505050565b606082471015620007765760405162461bcd60e51b815260040180806020018281038252602681526020018062002e456026913960400191505060405180910390fd5b62000781856200089b565b620007d3576040805162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000604482015290519081900360640190fd5b60006060866001600160a01b031685876040518082805190602001908083835b60208310620008145780518252601f199092019160209182019101620007f3565b6001836020036101000a03801982511681845116808217855250505050505090500191505060006040518083038185875af1925050503d806000811462000878576040519150601f19603f3d011682016040523d82523d6000602084013e6200087d565b606091505b50909250905062000890828286620008a1565b979650505050505050565b3b151590565b60608315620008b257508162000657565b825115620008c35782518084602001fd5b8160405162461bcd60e51b81526004018080602001828103825283818151815260200191508051906020019080838360005b838110156200090f578181015183820152602001620008f5565b50505050905090810190601f1680156200093d5780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b60805160601c6124be62000987600039806105a05280610ac35280610c0b52806110d4528061121c5280611b405280611bf352506124be6000f3fe6080604052600436106100dd5760003560e01c8063798af7201161007f57806390d250741161005957806390d25074146104595780639f330727146104a0578063ce0b63ce14610525578063f3f094a114610557576100dd565b8063798af72014610361578063839ed90a146103bf57806385528f0b14610426576100dd565b8063393494b8116100bb578063393494b8146101ef5780633d5da164146102285780634a517a55146102a057806365749c9d14610307576100dd565b8063040141e5146100e2578063174dc9521461011357806336e712ed14610193575b600080fd5b3480156100ee57600080fd5b506100f761059e565b604080516001600160a01b039092168252519081900360200190f35b34801561011f57600080fd5b50610191600480360361016081101561013757600080fd5b506001600160a01b0381358116916020810135916040820135169060ff6060820135811691608081013582169160a08201359160c08101359160e082013591610100810135909116906101208101359061014001356105c2565b005b34801561019f57600080fd5b50610191600480360360e08110156101b657600080fd5b506001600160a01b0381358116916020810135916040820135169060608101359060ff6080820135169060a08101359060c0013561090b565b3480156101fb57600080fd5b506100f76004803603604081101561021257600080fd5b506001600160a01b038135169060200135610a8c565b610191600480360361018081101561023f57600080fd5b506001600160a01b0381358116916020810135916040820135169060ff6060820135811691608081013582169160a08201359160c08101359160e0820135916101008101358216916101208201351690610140810135906101600135610ac1565b3480156102ac57600080fd5b5061019160048036036101008110156102c457600080fd5b506001600160a01b0381358116916020810135916040820135169060ff606082013581169160808101359091169060a08101359060c08101359060e00135610dd1565b610191600480360361010081101561031e57600080fd5b506001600160a01b0381358116916020810135916040820135169060ff606082013581169160808101359091169060a08101359060c08101359060e001356110d2565b34801561036d57600080fd5b506103ad6004803603608081101561038457600080fd5b506001600160a01b038135169060ff6020820135811691604081013590911690606001356113de565b60408051918252519081900360200190f35b3480156103cb57600080fd5b5061019160048036036101008110156103e357600080fd5b506001600160a01b0381358116916020810135916040820135169060608101359060ff608082013581169160a08101359091169060c08101359060e00135611497565b34801561043257600080fd5b506100f76004803603602081101561044957600080fd5b50356001600160a01b0316611622565b34801561046557600080fd5b506101916004803603608081101561047c57600080fd5b506001600160a01b038135811691602081013591604082013516906060013561163d565b3480156104ac57600080fd5b5061019160048036036101808110156104c457600080fd5b506001600160a01b0381358116916020810135916040820135169060ff6060820135811691608081013582169160a08201359160c08101359160e08201359161010081013582169161012082013516906101408101359061016001356117a4565b6101916004803603606081101561053b57600080fd5b506001600160a01b038135169060208101359060400135611ade565b34801561056357600080fd5b506101916004803603608081101561057a57600080fd5b506001600160a01b0381358116916020810135916040820135169060600135611c6a565b7f000000000000000000000000000000000000000000000000000000000000000081565b6001600160a01b03808a16600090815260016020526040902054168061062f576040805162461bcd60e51b815260206004820152600c60248201527f5377617020697320307830300000000000000000000000000000000000000000604482015290519081900360640190fd5b6001600160a01b03811660009081526002602090815260409182902080548351818402810184019094528084526060939283018282801561069957602002820191906000526020600020905b81546001600160a01b0316815260019091019060200180831161067b575b505050505090506106d633308a848e60ff16815181106106b557fe5b60200260200101516001600160a01b03166120a9909392919063ffffffff16565b604080517f9169558600000000000000000000000000000000000000000000000000000000815260ff808d1660048301528b166024820152604481018a9052606481018990526084810188905290516000916001600160a01b0385169163916955869160a48082019260209290919082900301818787803b15801561075a57600080fd5b505af115801561076e573d6000803e3d6000fd5b505050506040513d602081101561078457600080fd5b5051600054604080517fdd62ed3e0000000000000000000000000000000000000000000000000000000081523060048201526001600160a01b03928316602482015290519293508392918f169163dd62ed3e91604480820192602092909190829003018186803b1580156107f757600080fd5b505afa15801561080b573d6000803e3d6000fd5b505050506040513d602081101561082157600080fd5b5051101561084557600054610845906001600160a01b038e81169116600019611ed2565b60008054906101000a90046001600160a01b03166001600160a01b03166336e712ed8f8f8f858b8b8b6040518863ffffffff1660e01b815260040180886001600160a01b03168152602001878152602001866001600160a01b031681526020018581526020018460ff168152602001838152602001828152602001975050505050505050600060405180830381600087803b1580156108e357600080fd5b505af11580156108f7573d6000803e3d6000fd5b505050505050505050505050505050505050565b6109206001600160a01b0386163330876120a9565b600054604080517fdd62ed3e0000000000000000000000000000000000000000000000000000000081523060048201526001600160a01b0392831660248201529051869288169163dd62ed3e916044808301926020929190829003018186803b15801561098c57600080fd5b505afa1580156109a0573d6000803e3d6000fd5b505050506040513d60208110156109b657600080fd5b505110156109da576000546109da906001600160a01b038781169116600019611ed2565b60008054604080517f36e712ed0000000000000000000000000000000000000000000000000000000081526001600160a01b038b81166004830152602482018b905289811660448301526064820189905260ff8816608483015260a4820187905260c48201869052915191909216926336e712ed9260e4808201939182900301818387803b158015610a6b57600080fd5b505af1158015610a7f573d6000803e3d6000fd5b5050505050505050505050565b60026020528160005260406000208181548110610aa557fe5b6000918252602090912001546001600160a01b03169150829050565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316610b3c576040805162461bcd60e51b815260206004820152600660248201527f5745544820300000000000000000000000000000000000000000000000000000604482015290519081900360640190fd5b600034118015610b4b57508634145b610b9c576040805162461bcd60e51b815260206004820152601360248201527f494e434f5252454354204d53472056414c554500000000000000000000000000604482015290519081900360640190fd5b6001600160a01b03808b166000908152600160205260409020541680610c09576040805162461bcd60e51b815260206004820152600c60248201527f5377617020697320307830300000000000000000000000000000000000000000604482015290519081900360640190fd5b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663d0e30db0346040518263ffffffff1660e01b81526004016000604051808303818588803b158015610c6457600080fd5b505af1158015610c78573d6000803e3d6000fd5b50505050506000816001600160a01b031663916955868c8c8c8c8c6040518663ffffffff1660e01b8152600401808660ff1681526020018560ff16815260200184815260200183815260200182815260200195505050505050602060405180830381600087803b158015610ceb57600080fd5b505af1158015610cff573d6000803e3d6000fd5b505050506040513d6020811015610d1557600080fd5b8101908080519060200190929190505050905060008054906101000a90046001600160a01b03166001600160a01b031663839ed90a8f8f8f858b8b8b8b6040518963ffffffff1660e01b815260040180896001600160a01b03168152602001888152602001876001600160a01b031681526020018681526020018560ff1681526020018460ff16815260200183815260200182815260200198505050505050505050600060405180830381600087803b1580156108e357600080fd5b6001600160a01b038087166000908152600160205260409020541680610e3e576040805162461bcd60e51b815260206004820152600c60248201527f5377617020697320307830300000000000000000000000000000000000000000604482015290519081900360640190fd5b6001600160a01b038116600090815260026020908152604091829020805483518184028101840190945280845260609392830182828015610ea857602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311610e8a575b50505050509050610ec4333087848b60ff16815181106106b557fe5b604080517f9169558600000000000000000000000000000000000000000000000000000000815260ff808a1660048301528816602482015260448101879052606481018690526084810185905290516000916001600160a01b0385169163916955869160a48082019260209290919082900301818787803b158015610f4857600080fd5b505af1158015610f5c573d6000803e3d6000fd5b505050506040513d6020811015610f7257600080fd5b5051600054604080517fdd62ed3e0000000000000000000000000000000000000000000000000000000081523060048201526001600160a01b03928316602482015290519293508392918c169163dd62ed3e91604480820192602092909190829003018186803b158015610fe557600080fd5b505afa158015610ff9573d6000803e3d6000fd5b505050506040513d602081101561100f57600080fd5b5051101561103357600054611033906001600160a01b038b81169116600019611ed2565b60008054604080517ff3f094a10000000000000000000000000000000000000000000000000000000081526001600160a01b038f81166004830152602482018f90528d81166044830152606482018690529151919092169263f3f094a1926084808201939182900301818387803b1580156110ad57600080fd5b505af11580156110c1573d6000803e3d6000fd5b505050505050505050505050505050565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031661114d576040805162461bcd60e51b815260206004820152600660248201527f5745544820300000000000000000000000000000000000000000000000000000604482015290519081900360640190fd5b60003411801561115c57508234145b6111ad576040805162461bcd60e51b815260206004820152601360248201527f494e434f5252454354204d53472056414c554500000000000000000000000000604482015290519081900360640190fd5b6001600160a01b03808716600090815260016020526040902054168061121a576040805162461bcd60e51b815260206004820152600c60248201527f5377617020697320307830300000000000000000000000000000000000000000604482015290519081900360640190fd5b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663d0e30db0346040518263ffffffff1660e01b81526004016000604051808303818588803b15801561127557600080fd5b505af1158015611289573d6000803e3d6000fd5b5050604080517f9169558600000000000000000000000000000000000000000000000000000000815260ff808c1660048301528a1660248201526044810189905260648101889052608481018790529051600094506001600160a01b03861693506391695586925060a480830192602092919082900301818787803b15801561131157600080fd5b505af1158015611325573d6000803e3d6000fd5b505050506040513d602081101561133b57600080fd5b505160008054604080517ff3f094a10000000000000000000000000000000000000000000000000000000081526001600160a01b038f81166004830152602482018f90528d8116604483015260648201869052915194955091169263f3f094a19260848084019391929182900301818387803b1580156113ba57600080fd5b505af11580156113ce573d6000803e3d6000fd5b5050505050505050505050505050565b6001600160a01b0380851660009081526001602090815260408083205481517fa95b089f00000000000000000000000000000000000000000000000000000000815260ff808a1660048301528816602482015260448101879052915193941692839263a95b089f9260648082019391829003018186803b15801561146157600080fd5b505afa158015611475573d6000803e3d6000fd5b505050506040513d602081101561148b57600080fd5b50519695505050505050565b6114ac6001600160a01b0387163330886120a9565b600054604080517fdd62ed3e0000000000000000000000000000000000000000000000000000000081523060048201526001600160a01b0392831660248201529051879289169163dd62ed3e916044808301926020929190829003018186803b15801561151857600080fd5b505afa15801561152c573d6000803e3d6000fd5b505050506040513d602081101561154257600080fd5b5051101561156657600054611566906001600160a01b038881169116600019611ed2565b60008054604080517f839ed90a0000000000000000000000000000000000000000000000000000000081526001600160a01b038c81166004830152602482018c90528a81166044830152606482018a905260ff808a166084840152881660a483015260c4820187905260e482018690529151919092169263839ed90a92610104808201939182900301818387803b15801561160057600080fd5b505af1158015611614573d6000803e3d6000fd5b505050505050505050505050565b6001602052600090815260409020546001600160a01b031681565b6116526001600160a01b0383163330846120a9565b600054604080517fdd62ed3e0000000000000000000000000000000000000000000000000000000081523060048201526001600160a01b0392831660248201529051839285169163dd62ed3e916044808301926020929190829003018186803b1580156116be57600080fd5b505afa1580156116d2573d6000803e3d6000fd5b505050506040513d60208110156116e857600080fd5b5051101561170c5760005461170c906001600160a01b038481169116600019611ed2565b60008054604080517f90d250740000000000000000000000000000000000000000000000000000000081526001600160a01b03888116600483015260248201889052868116604483015260648201869052915191909216926390d25074926084808201939182900301818387803b15801561178657600080fd5b505af115801561179a573d6000803e3d6000fd5b5050505050505050565b6001600160a01b038a811660009081526001602052604090205416611810576040805162461bcd60e51b815260206004820152600c60248201527f5377617020697320307830300000000000000000000000000000000000000000604482015290519081900360640190fd5b6001600160a01b03808b166000908152600160209081526040808320549093168252600281529082902080548351818402810184019094528084526060939283018282801561188857602002820191906000526020600020905b81546001600160a01b0316815260019091019060200180831161186a575b505050505090506118a433308a848e60ff16815181106106b557fe5b6000600160008d6001600160a01b03166001600160a01b0316815260200190815260200160002060009054906101000a90046001600160a01b03166001600160a01b031663916955868c8c8c8c8c6040518663ffffffff1660e01b8152600401808660ff1681526020018560ff16815260200184815260200183815260200182815260200195505050505050602060405180830381600087803b15801561194a57600080fd5b505af115801561195e573d6000803e3d6000fd5b505050506040513d602081101561197457600080fd5b5051600054604080517fdd62ed3e0000000000000000000000000000000000000000000000000000000081523060048201526001600160a01b03928316602482015290519293508392918f169163dd62ed3e91604480820192602092909190829003018186803b1580156119e757600080fd5b505afa1580156119fb573d6000803e3d6000fd5b505050506040513d6020811015611a1157600080fd5b50511015611a3557600054611a35906001600160a01b038e81169116600019611ed2565b60008054906101000a90046001600160a01b03166001600160a01b031663839ed90a8f8f8f858b8b8b8b6040518963ffffffff1660e01b815260040180896001600160a01b03168152602001888152602001876001600160a01b031681526020018681526020018560ff1681526020018460ff16815260200183815260200182815260200198505050505050505050600060405180830381600087803b1580156108e357600080fd5b600034118015611aed57508034145b611b3e576040805162461bcd60e51b815260206004820152601360248201527f494e434f5252454354204d53472056414c554500000000000000000000000000604482015290519081900360640190fd5b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663d0e30db0346040518263ffffffff1660e01b81526004016000604051808303818588803b158015611b9957600080fd5b505af1158015611bad573d6000803e3d6000fd5b505060008054604080517f90d250740000000000000000000000000000000000000000000000000000000081526001600160a01b038a81166004830152602482018a90527f0000000000000000000000000000000000000000000000000000000000000000811660448301526064820189905291519190921695506390d25074945060848083019450909182900301818387803b158015611c4d57600080fd5b505af1158015611c61573d6000803e3d6000fd5b50505050505050565b611c7f6001600160a01b0383163330846120a9565b600054604080517fdd62ed3e0000000000000000000000000000000000000000000000000000000081523060048201526001600160a01b0392831660248201529051839285169163dd62ed3e916044808301926020929190829003018186803b158015611ceb57600080fd5b505afa158015611cff573d6000803e3d6000fd5b505050506040513d6020811015611d1557600080fd5b50511015611d3957600054611d39906001600160a01b038481169116600019611ed2565b60008054604080517ff3f094a10000000000000000000000000000000000000000000000000000000081526001600160a01b038881166004830152602482018890528681166044830152606482018690529151919092169263f3f094a1926084808201939182900301818387803b15801561178657600080fd5b6000611e4982856001600160a01b031663dd62ed3e30876040518363ffffffff1660e01b815260040180836001600160a01b03168152602001826001600160a01b031681526020019250505060206040518083038186803b158015611e1757600080fd5b505afa158015611e2b573d6000803e3d6000fd5b505050506040513d6020811015611e4157600080fd5b505190612031565b604080516001600160a01b038616602482015260448082018490528251808303909101815260649091019091526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f095ea7b300000000000000000000000000000000000000000000000000000000179052909150611ecc90859061212d565b50505050565b801580611f715750604080517fdd62ed3e0000000000000000000000000000000000000000000000000000000081523060048201526001600160a01b03848116602483015291519185169163dd62ed3e91604480820192602092909190829003018186803b158015611f4357600080fd5b505afa158015611f57573d6000803e3d6000fd5b505050506040513d6020811015611f6d57600080fd5b5051155b611fac5760405162461bcd60e51b81526004018080602001828103825260368152602001806124536036913960400191505060405180910390fd5b604080516001600160a01b038416602482015260448082018490528251808303909101815260649091019091526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f095ea7b30000000000000000000000000000000000000000000000000000000017905261202c90849061212d565b505050565b60008282018381101561208b576040805162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b9392505050565b60606120a184846000856121de565b949350505050565b604080516001600160a01b0380861660248301528416604482015260648082018490528251808303909101815260849091019091526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f23b872dd00000000000000000000000000000000000000000000000000000000179052611ecc9085905b6060612182826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b03166120929092919063ffffffff16565b80519091501561202c578080602001905160208110156121a157600080fd5b505161202c5760405162461bcd60e51b815260040180806020018281038252602a815260200180612429602a913960400191505060405180910390fd5b60608247101561221f5760405162461bcd60e51b81526004018080602001828103825260268152602001806124036026913960400191505060405180910390fd5b61222885612358565b612279576040805162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000604482015290519081900360640190fd5b60006060866001600160a01b031685876040518082805190602001908083835b602083106122d657805182527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe09092019160209182019101612299565b6001836020036101000a03801982511681845116808217855250505050505090500191505060006040518083038185875af1925050503d8060008114612338576040519150601f19603f3d011682016040523d82523d6000602084013e61233d565b606091505b509150915061234d82828661235e565b979650505050505050565b3b151590565b6060831561236d57508161208b565b82511561237d5782518084602001fd5b8160405162461bcd60e51b81526004018080602001828103825283818151815260200191508051906020019080838360005b838110156123c75781810151838201526020016123af565b50505050905090810190601f1680156123f45780820380516001836020036101000a031916815260200191505b509250505060405180910390fdfe416464726573733a20696e73756666696369656e742062616c616e636520666f722063616c6c5361666545524332303a204552433230206f7065726174696f6e20646964206e6f7420737563636565645361666545524332303a20617070726f76652066726f6d206e6f6e2d7a65726f20746f206e6f6e2d7a65726f20616c6c6f77616e6365a2646970667358221220c3a0aff13da237814afa3ff1b73bbf46d53990c652612308c4004550c592b44a64736f6c634300060c0033416464726573733a20696e73756666696369656e742062616c616e636520666f722063616c6c73776170206d7573742068617665206174206c65617374203220746f6b656e735361666545524332303a204552433230206f7065726174696f6e20646964206e6f7420737563636565645361666545524332303a20617070726f76652066726f6d206e6f6e2d7a65726f20746f206e6f6e2d7a65726f20616c6c6f77616e6365", - "deployedBytecode": "0x6080604052600436106100dd5760003560e01c8063798af7201161007f57806390d250741161005957806390d25074146104595780639f330727146104a0578063ce0b63ce14610525578063f3f094a114610557576100dd565b8063798af72014610361578063839ed90a146103bf57806385528f0b14610426576100dd565b8063393494b8116100bb578063393494b8146101ef5780633d5da164146102285780634a517a55146102a057806365749c9d14610307576100dd565b8063040141e5146100e2578063174dc9521461011357806336e712ed14610193575b600080fd5b3480156100ee57600080fd5b506100f761059e565b604080516001600160a01b039092168252519081900360200190f35b34801561011f57600080fd5b50610191600480360361016081101561013757600080fd5b506001600160a01b0381358116916020810135916040820135169060ff6060820135811691608081013582169160a08201359160c08101359160e082013591610100810135909116906101208101359061014001356105c2565b005b34801561019f57600080fd5b50610191600480360360e08110156101b657600080fd5b506001600160a01b0381358116916020810135916040820135169060608101359060ff6080820135169060a08101359060c0013561090b565b3480156101fb57600080fd5b506100f76004803603604081101561021257600080fd5b506001600160a01b038135169060200135610a8c565b610191600480360361018081101561023f57600080fd5b506001600160a01b0381358116916020810135916040820135169060ff6060820135811691608081013582169160a08201359160c08101359160e0820135916101008101358216916101208201351690610140810135906101600135610ac1565b3480156102ac57600080fd5b5061019160048036036101008110156102c457600080fd5b506001600160a01b0381358116916020810135916040820135169060ff606082013581169160808101359091169060a08101359060c08101359060e00135610dd1565b610191600480360361010081101561031e57600080fd5b506001600160a01b0381358116916020810135916040820135169060ff606082013581169160808101359091169060a08101359060c08101359060e001356110d2565b34801561036d57600080fd5b506103ad6004803603608081101561038457600080fd5b506001600160a01b038135169060ff6020820135811691604081013590911690606001356113de565b60408051918252519081900360200190f35b3480156103cb57600080fd5b5061019160048036036101008110156103e357600080fd5b506001600160a01b0381358116916020810135916040820135169060608101359060ff608082013581169160a08101359091169060c08101359060e00135611497565b34801561043257600080fd5b506100f76004803603602081101561044957600080fd5b50356001600160a01b0316611622565b34801561046557600080fd5b506101916004803603608081101561047c57600080fd5b506001600160a01b038135811691602081013591604082013516906060013561163d565b3480156104ac57600080fd5b5061019160048036036101808110156104c457600080fd5b506001600160a01b0381358116916020810135916040820135169060ff6060820135811691608081013582169160a08201359160c08101359160e08201359161010081013582169161012082013516906101408101359061016001356117a4565b6101916004803603606081101561053b57600080fd5b506001600160a01b038135169060208101359060400135611ade565b34801561056357600080fd5b506101916004803603608081101561057a57600080fd5b506001600160a01b0381358116916020810135916040820135169060600135611c6a565b7f000000000000000000000000000000000000000000000000000000000000000081565b6001600160a01b03808a16600090815260016020526040902054168061062f576040805162461bcd60e51b815260206004820152600c60248201527f5377617020697320307830300000000000000000000000000000000000000000604482015290519081900360640190fd5b6001600160a01b03811660009081526002602090815260409182902080548351818402810184019094528084526060939283018282801561069957602002820191906000526020600020905b81546001600160a01b0316815260019091019060200180831161067b575b505050505090506106d633308a848e60ff16815181106106b557fe5b60200260200101516001600160a01b03166120a9909392919063ffffffff16565b604080517f9169558600000000000000000000000000000000000000000000000000000000815260ff808d1660048301528b166024820152604481018a9052606481018990526084810188905290516000916001600160a01b0385169163916955869160a48082019260209290919082900301818787803b15801561075a57600080fd5b505af115801561076e573d6000803e3d6000fd5b505050506040513d602081101561078457600080fd5b5051600054604080517fdd62ed3e0000000000000000000000000000000000000000000000000000000081523060048201526001600160a01b03928316602482015290519293508392918f169163dd62ed3e91604480820192602092909190829003018186803b1580156107f757600080fd5b505afa15801561080b573d6000803e3d6000fd5b505050506040513d602081101561082157600080fd5b5051101561084557600054610845906001600160a01b038e81169116600019611ed2565b60008054906101000a90046001600160a01b03166001600160a01b03166336e712ed8f8f8f858b8b8b6040518863ffffffff1660e01b815260040180886001600160a01b03168152602001878152602001866001600160a01b031681526020018581526020018460ff168152602001838152602001828152602001975050505050505050600060405180830381600087803b1580156108e357600080fd5b505af11580156108f7573d6000803e3d6000fd5b505050505050505050505050505050505050565b6109206001600160a01b0386163330876120a9565b600054604080517fdd62ed3e0000000000000000000000000000000000000000000000000000000081523060048201526001600160a01b0392831660248201529051869288169163dd62ed3e916044808301926020929190829003018186803b15801561098c57600080fd5b505afa1580156109a0573d6000803e3d6000fd5b505050506040513d60208110156109b657600080fd5b505110156109da576000546109da906001600160a01b038781169116600019611ed2565b60008054604080517f36e712ed0000000000000000000000000000000000000000000000000000000081526001600160a01b038b81166004830152602482018b905289811660448301526064820189905260ff8816608483015260a4820187905260c48201869052915191909216926336e712ed9260e4808201939182900301818387803b158015610a6b57600080fd5b505af1158015610a7f573d6000803e3d6000fd5b5050505050505050505050565b60026020528160005260406000208181548110610aa557fe5b6000918252602090912001546001600160a01b03169150829050565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316610b3c576040805162461bcd60e51b815260206004820152600660248201527f5745544820300000000000000000000000000000000000000000000000000000604482015290519081900360640190fd5b600034118015610b4b57508634145b610b9c576040805162461bcd60e51b815260206004820152601360248201527f494e434f5252454354204d53472056414c554500000000000000000000000000604482015290519081900360640190fd5b6001600160a01b03808b166000908152600160205260409020541680610c09576040805162461bcd60e51b815260206004820152600c60248201527f5377617020697320307830300000000000000000000000000000000000000000604482015290519081900360640190fd5b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663d0e30db0346040518263ffffffff1660e01b81526004016000604051808303818588803b158015610c6457600080fd5b505af1158015610c78573d6000803e3d6000fd5b50505050506000816001600160a01b031663916955868c8c8c8c8c6040518663ffffffff1660e01b8152600401808660ff1681526020018560ff16815260200184815260200183815260200182815260200195505050505050602060405180830381600087803b158015610ceb57600080fd5b505af1158015610cff573d6000803e3d6000fd5b505050506040513d6020811015610d1557600080fd5b8101908080519060200190929190505050905060008054906101000a90046001600160a01b03166001600160a01b031663839ed90a8f8f8f858b8b8b8b6040518963ffffffff1660e01b815260040180896001600160a01b03168152602001888152602001876001600160a01b031681526020018681526020018560ff1681526020018460ff16815260200183815260200182815260200198505050505050505050600060405180830381600087803b1580156108e357600080fd5b6001600160a01b038087166000908152600160205260409020541680610e3e576040805162461bcd60e51b815260206004820152600c60248201527f5377617020697320307830300000000000000000000000000000000000000000604482015290519081900360640190fd5b6001600160a01b038116600090815260026020908152604091829020805483518184028101840190945280845260609392830182828015610ea857602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311610e8a575b50505050509050610ec4333087848b60ff16815181106106b557fe5b604080517f9169558600000000000000000000000000000000000000000000000000000000815260ff808a1660048301528816602482015260448101879052606481018690526084810185905290516000916001600160a01b0385169163916955869160a48082019260209290919082900301818787803b158015610f4857600080fd5b505af1158015610f5c573d6000803e3d6000fd5b505050506040513d6020811015610f7257600080fd5b5051600054604080517fdd62ed3e0000000000000000000000000000000000000000000000000000000081523060048201526001600160a01b03928316602482015290519293508392918c169163dd62ed3e91604480820192602092909190829003018186803b158015610fe557600080fd5b505afa158015610ff9573d6000803e3d6000fd5b505050506040513d602081101561100f57600080fd5b5051101561103357600054611033906001600160a01b038b81169116600019611ed2565b60008054604080517ff3f094a10000000000000000000000000000000000000000000000000000000081526001600160a01b038f81166004830152602482018f90528d81166044830152606482018690529151919092169263f3f094a1926084808201939182900301818387803b1580156110ad57600080fd5b505af11580156110c1573d6000803e3d6000fd5b505050505050505050505050505050565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031661114d576040805162461bcd60e51b815260206004820152600660248201527f5745544820300000000000000000000000000000000000000000000000000000604482015290519081900360640190fd5b60003411801561115c57508234145b6111ad576040805162461bcd60e51b815260206004820152601360248201527f494e434f5252454354204d53472056414c554500000000000000000000000000604482015290519081900360640190fd5b6001600160a01b03808716600090815260016020526040902054168061121a576040805162461bcd60e51b815260206004820152600c60248201527f5377617020697320307830300000000000000000000000000000000000000000604482015290519081900360640190fd5b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663d0e30db0346040518263ffffffff1660e01b81526004016000604051808303818588803b15801561127557600080fd5b505af1158015611289573d6000803e3d6000fd5b5050604080517f9169558600000000000000000000000000000000000000000000000000000000815260ff808c1660048301528a1660248201526044810189905260648101889052608481018790529051600094506001600160a01b03861693506391695586925060a480830192602092919082900301818787803b15801561131157600080fd5b505af1158015611325573d6000803e3d6000fd5b505050506040513d602081101561133b57600080fd5b505160008054604080517ff3f094a10000000000000000000000000000000000000000000000000000000081526001600160a01b038f81166004830152602482018f90528d8116604483015260648201869052915194955091169263f3f094a19260848084019391929182900301818387803b1580156113ba57600080fd5b505af11580156113ce573d6000803e3d6000fd5b5050505050505050505050505050565b6001600160a01b0380851660009081526001602090815260408083205481517fa95b089f00000000000000000000000000000000000000000000000000000000815260ff808a1660048301528816602482015260448101879052915193941692839263a95b089f9260648082019391829003018186803b15801561146157600080fd5b505afa158015611475573d6000803e3d6000fd5b505050506040513d602081101561148b57600080fd5b50519695505050505050565b6114ac6001600160a01b0387163330886120a9565b600054604080517fdd62ed3e0000000000000000000000000000000000000000000000000000000081523060048201526001600160a01b0392831660248201529051879289169163dd62ed3e916044808301926020929190829003018186803b15801561151857600080fd5b505afa15801561152c573d6000803e3d6000fd5b505050506040513d602081101561154257600080fd5b5051101561156657600054611566906001600160a01b038881169116600019611ed2565b60008054604080517f839ed90a0000000000000000000000000000000000000000000000000000000081526001600160a01b038c81166004830152602482018c90528a81166044830152606482018a905260ff808a166084840152881660a483015260c4820187905260e482018690529151919092169263839ed90a92610104808201939182900301818387803b15801561160057600080fd5b505af1158015611614573d6000803e3d6000fd5b505050505050505050505050565b6001602052600090815260409020546001600160a01b031681565b6116526001600160a01b0383163330846120a9565b600054604080517fdd62ed3e0000000000000000000000000000000000000000000000000000000081523060048201526001600160a01b0392831660248201529051839285169163dd62ed3e916044808301926020929190829003018186803b1580156116be57600080fd5b505afa1580156116d2573d6000803e3d6000fd5b505050506040513d60208110156116e857600080fd5b5051101561170c5760005461170c906001600160a01b038481169116600019611ed2565b60008054604080517f90d250740000000000000000000000000000000000000000000000000000000081526001600160a01b03888116600483015260248201889052868116604483015260648201869052915191909216926390d25074926084808201939182900301818387803b15801561178657600080fd5b505af115801561179a573d6000803e3d6000fd5b5050505050505050565b6001600160a01b038a811660009081526001602052604090205416611810576040805162461bcd60e51b815260206004820152600c60248201527f5377617020697320307830300000000000000000000000000000000000000000604482015290519081900360640190fd5b6001600160a01b03808b166000908152600160209081526040808320549093168252600281529082902080548351818402810184019094528084526060939283018282801561188857602002820191906000526020600020905b81546001600160a01b0316815260019091019060200180831161186a575b505050505090506118a433308a848e60ff16815181106106b557fe5b6000600160008d6001600160a01b03166001600160a01b0316815260200190815260200160002060009054906101000a90046001600160a01b03166001600160a01b031663916955868c8c8c8c8c6040518663ffffffff1660e01b8152600401808660ff1681526020018560ff16815260200184815260200183815260200182815260200195505050505050602060405180830381600087803b15801561194a57600080fd5b505af115801561195e573d6000803e3d6000fd5b505050506040513d602081101561197457600080fd5b5051600054604080517fdd62ed3e0000000000000000000000000000000000000000000000000000000081523060048201526001600160a01b03928316602482015290519293508392918f169163dd62ed3e91604480820192602092909190829003018186803b1580156119e757600080fd5b505afa1580156119fb573d6000803e3d6000fd5b505050506040513d6020811015611a1157600080fd5b50511015611a3557600054611a35906001600160a01b038e81169116600019611ed2565b60008054906101000a90046001600160a01b03166001600160a01b031663839ed90a8f8f8f858b8b8b8b6040518963ffffffff1660e01b815260040180896001600160a01b03168152602001888152602001876001600160a01b031681526020018681526020018560ff1681526020018460ff16815260200183815260200182815260200198505050505050505050600060405180830381600087803b1580156108e357600080fd5b600034118015611aed57508034145b611b3e576040805162461bcd60e51b815260206004820152601360248201527f494e434f5252454354204d53472056414c554500000000000000000000000000604482015290519081900360640190fd5b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663d0e30db0346040518263ffffffff1660e01b81526004016000604051808303818588803b158015611b9957600080fd5b505af1158015611bad573d6000803e3d6000fd5b505060008054604080517f90d250740000000000000000000000000000000000000000000000000000000081526001600160a01b038a81166004830152602482018a90527f0000000000000000000000000000000000000000000000000000000000000000811660448301526064820189905291519190921695506390d25074945060848083019450909182900301818387803b158015611c4d57600080fd5b505af1158015611c61573d6000803e3d6000fd5b50505050505050565b611c7f6001600160a01b0383163330846120a9565b600054604080517fdd62ed3e0000000000000000000000000000000000000000000000000000000081523060048201526001600160a01b0392831660248201529051839285169163dd62ed3e916044808301926020929190829003018186803b158015611ceb57600080fd5b505afa158015611cff573d6000803e3d6000fd5b505050506040513d6020811015611d1557600080fd5b50511015611d3957600054611d39906001600160a01b038481169116600019611ed2565b60008054604080517ff3f094a10000000000000000000000000000000000000000000000000000000081526001600160a01b038881166004830152602482018890528681166044830152606482018690529151919092169263f3f094a1926084808201939182900301818387803b15801561178657600080fd5b6000611e4982856001600160a01b031663dd62ed3e30876040518363ffffffff1660e01b815260040180836001600160a01b03168152602001826001600160a01b031681526020019250505060206040518083038186803b158015611e1757600080fd5b505afa158015611e2b573d6000803e3d6000fd5b505050506040513d6020811015611e4157600080fd5b505190612031565b604080516001600160a01b038616602482015260448082018490528251808303909101815260649091019091526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f095ea7b300000000000000000000000000000000000000000000000000000000179052909150611ecc90859061212d565b50505050565b801580611f715750604080517fdd62ed3e0000000000000000000000000000000000000000000000000000000081523060048201526001600160a01b03848116602483015291519185169163dd62ed3e91604480820192602092909190829003018186803b158015611f4357600080fd5b505afa158015611f57573d6000803e3d6000fd5b505050506040513d6020811015611f6d57600080fd5b5051155b611fac5760405162461bcd60e51b81526004018080602001828103825260368152602001806124536036913960400191505060405180910390fd5b604080516001600160a01b038416602482015260448082018490528251808303909101815260649091019091526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f095ea7b30000000000000000000000000000000000000000000000000000000017905261202c90849061212d565b505050565b60008282018381101561208b576040805162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b9392505050565b60606120a184846000856121de565b949350505050565b604080516001600160a01b0380861660248301528416604482015260648082018490528251808303909101815260849091019091526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f23b872dd00000000000000000000000000000000000000000000000000000000179052611ecc9085905b6060612182826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b03166120929092919063ffffffff16565b80519091501561202c578080602001905160208110156121a157600080fd5b505161202c5760405162461bcd60e51b815260040180806020018281038252602a815260200180612429602a913960400191505060405180910390fd5b60608247101561221f5760405162461bcd60e51b81526004018080602001828103825260268152602001806124036026913960400191505060405180910390fd5b61222885612358565b612279576040805162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000604482015290519081900360640190fd5b60006060866001600160a01b031685876040518082805190602001908083835b602083106122d657805182527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe09092019160209182019101612299565b6001836020036101000a03801982511681845116808217855250505050505090500191505060006040518083038185875af1925050503d8060008114612338576040519150601f19603f3d011682016040523d82523d6000602084013e61233d565b606091505b509150915061234d82828661235e565b979650505050505050565b3b151590565b6060831561236d57508161208b565b82511561237d5782518084602001fd5b8160405162461bcd60e51b81526004018080602001828103825283818151815260200191508051906020019080838360005b838110156123c75781810151838201526020016123af565b50505050905090810190601f1680156123f45780820380516001836020036101000a031916815260200191505b509250505060405180910390fdfe416464726573733a20696e73756666696369656e742062616c616e636520666f722063616c6c5361666545524332303a204552433230206f7065726174696f6e20646964206e6f7420737563636565645361666545524332303a20617070726f76652066726f6d206e6f6e2d7a65726f20746f206e6f6e2d7a65726f20616c6c6f77616e6365a2646970667358221220c3a0aff13da237814afa3ff1b73bbf46d53990c652612308c4004550c592b44a64736f6c634300060c0033", + "solcInputHash": "4d8253a299fa09b105ed2b87dd0189d4", + "metadata": "{\"compiler\":{\"version\":\"0.6.12+commit.27d51765\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address payable\",\"name\":\"_wethAddress\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_swapOne\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenOne\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_swapTwo\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenTwo\",\"type\":\"address\"},{\"internalType\":\"contract ISynapseBridge\",\"name\":\"_synapseBridge\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"WETH_ADDRESS\",\"outputs\":[{\"internalType\":\"address payable\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contract IERC20\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint8\",\"name\":\"tokenIndexFrom\",\"type\":\"uint8\"},{\"internalType\":\"uint8\",\"name\":\"tokenIndexTo\",\"type\":\"uint8\"},{\"internalType\":\"uint256\",\"name\":\"dx\",\"type\":\"uint256\"}],\"name\":\"calculateSwap\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"chainId\",\"type\":\"uint256\"},{\"internalType\":\"contract IERC20\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"deposit\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"chainId\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"depositETH\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"chainId\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"uint8\",\"name\":\"tokenIndexFrom\",\"type\":\"uint8\"},{\"internalType\":\"uint8\",\"name\":\"tokenIndexTo\",\"type\":\"uint8\"},{\"internalType\":\"uint256\",\"name\":\"minDy\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"deadline\",\"type\":\"uint256\"}],\"name\":\"depositETHAndSwap\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"chainId\",\"type\":\"uint256\"},{\"internalType\":\"contract IERC20\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"redeem\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"chainId\",\"type\":\"uint256\"},{\"internalType\":\"contract IERC20\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"uint8\",\"name\":\"liqTokenIndex\",\"type\":\"uint8\"},{\"internalType\":\"uint256\",\"name\":\"liqMinAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"liqDeadline\",\"type\":\"uint256\"}],\"name\":\"redeemAndRemove\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"chainId\",\"type\":\"uint256\"},{\"internalType\":\"contract IERC20\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"uint8\",\"name\":\"tokenIndexFrom\",\"type\":\"uint8\"},{\"internalType\":\"uint8\",\"name\":\"tokenIndexTo\",\"type\":\"uint8\"},{\"internalType\":\"uint256\",\"name\":\"minDy\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"deadline\",\"type\":\"uint256\"}],\"name\":\"redeemAndSwap\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"to\",\"type\":\"bytes32\"},{\"internalType\":\"uint256\",\"name\":\"chainId\",\"type\":\"uint256\"},{\"internalType\":\"contract IERC20\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"redeemv2\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"chainId\",\"type\":\"uint256\"},{\"internalType\":\"contract IERC20\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint8\",\"name\":\"tokenIndexFrom\",\"type\":\"uint8\"},{\"internalType\":\"uint8\",\"name\":\"tokenIndexTo\",\"type\":\"uint8\"},{\"internalType\":\"uint256\",\"name\":\"dx\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"minDy\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"deadline\",\"type\":\"uint256\"}],\"name\":\"swapAndRedeem\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"chainId\",\"type\":\"uint256\"},{\"internalType\":\"contract IERC20\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint8\",\"name\":\"tokenIndexFrom\",\"type\":\"uint8\"},{\"internalType\":\"uint8\",\"name\":\"tokenIndexTo\",\"type\":\"uint8\"},{\"internalType\":\"uint256\",\"name\":\"dx\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"minDy\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"deadline\",\"type\":\"uint256\"},{\"internalType\":\"uint8\",\"name\":\"liqTokenIndex\",\"type\":\"uint8\"},{\"internalType\":\"uint256\",\"name\":\"liqMinAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"liqDeadline\",\"type\":\"uint256\"}],\"name\":\"swapAndRedeemAndRemove\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"chainId\",\"type\":\"uint256\"},{\"internalType\":\"contract IERC20\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint8\",\"name\":\"tokenIndexFrom\",\"type\":\"uint8\"},{\"internalType\":\"uint8\",\"name\":\"tokenIndexTo\",\"type\":\"uint8\"},{\"internalType\":\"uint256\",\"name\":\"dx\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"minDy\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"deadline\",\"type\":\"uint256\"},{\"internalType\":\"uint8\",\"name\":\"swapTokenIndexFrom\",\"type\":\"uint8\"},{\"internalType\":\"uint8\",\"name\":\"swapTokenIndexTo\",\"type\":\"uint8\"},{\"internalType\":\"uint256\",\"name\":\"swapMinDy\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"swapDeadline\",\"type\":\"uint256\"}],\"name\":\"swapAndRedeemAndSwap\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"chainId\",\"type\":\"uint256\"},{\"internalType\":\"contract IERC20\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint8\",\"name\":\"tokenIndexFrom\",\"type\":\"uint8\"},{\"internalType\":\"uint8\",\"name\":\"tokenIndexTo\",\"type\":\"uint8\"},{\"internalType\":\"uint256\",\"name\":\"dx\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"minDy\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"deadline\",\"type\":\"uint256\"}],\"name\":\"swapETHAndRedeem\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"chainId\",\"type\":\"uint256\"},{\"internalType\":\"contract IERC20\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint8\",\"name\":\"tokenIndexFrom\",\"type\":\"uint8\"},{\"internalType\":\"uint8\",\"name\":\"tokenIndexTo\",\"type\":\"uint8\"},{\"internalType\":\"uint256\",\"name\":\"dx\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"minDy\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"deadline\",\"type\":\"uint256\"},{\"internalType\":\"uint8\",\"name\":\"swapTokenIndexFrom\",\"type\":\"uint8\"},{\"internalType\":\"uint8\",\"name\":\"swapTokenIndexTo\",\"type\":\"uint8\"},{\"internalType\":\"uint256\",\"name\":\"swapMinDy\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"swapDeadline\",\"type\":\"uint256\"}],\"name\":\"swapETHAndRedeemAndSwap\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"swapMap\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"swapTokensMap\",\"outputs\":[{\"internalType\":\"contract IERC20\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{\"calculateSwap(address,uint8,uint8,uint256)\":{\"params\":{\"dx\":\"the amount of tokens the user wants to sell. If the token charges a fee on transfers, use the amount that gets transferred after the fee.\",\"tokenIndexFrom\":\"the token the user wants to sell\",\"tokenIndexTo\":\"the token the user wants to buy\"},\"returns\":{\"_0\":\"amount of tokens the user will receive\"}},\"deposit(address,uint256,address,uint256)\":{\"params\":{\"amount\":\"Amount in native token decimals to transfer cross-chain pre-fees*\",\"chainId\":\"which underlying chain to bridge assets onto\",\"to\":\"address on other chain to redeem underlying assets to\",\"token\":\"ERC20 compatible token to deposit into the bridge\"}},\"depositETH(address,uint256,uint256)\":{\"params\":{\"amount\":\"Amount in native token decimals to transfer cross-chain pre-fees*\",\"chainId\":\"which chain to bridge assets onto\",\"to\":\"address on other chain to bridge assets to\"}},\"depositETHAndSwap(address,uint256,uint256,uint8,uint8,uint256,uint256)\":{\"params\":{\"amount\":\"Amount in native token decimals to transfer cross-chain pre-fees\",\"chainId\":\"which chain to bridge assets onto\",\"deadline\":\"latest timestamp to accept this transaction*\",\"minDy\":\"the min amount the user would like to receive, or revert to only minting the SynERC20 token crosschain.\",\"to\":\"address on other chain to bridge assets to\",\"tokenIndexFrom\":\"the token the user wants to swap from\",\"tokenIndexTo\":\"the token the user wants to swap to\"}},\"redeem(address,uint256,address,uint256)\":{\"params\":{\"amount\":\"Amount in native token decimals to transfer cross-chain pre-fees*\",\"chainId\":\"which underlying chain to bridge assets onto\",\"to\":\"address on other chain to redeem underlying assets to\",\"token\":\"ERC20 compatible token to deposit into the bridge\"}},\"redeemAndRemove(address,uint256,address,uint256,uint8,uint256,uint256)\":{\"params\":{\"amount\":\"Amount of (typically) LP token to pass to the nodes to attempt to removeLiquidity() with to redeem for the underlying assets of the LP token\",\"chainId\":\"which underlying chain to bridge assets onto\",\"liqDeadline\":\"Specificies the deadline that the nodes are allowed to try to redeem/swap the LP token*\",\"liqMinAmount\":\"Specifies the minimum amount of the underlying asset needed for the nodes to execute the redeem/swap\",\"liqTokenIndex\":\"Specifies which of the underlying LP assets the nodes should attempt to redeem for\",\"to\":\"address on other chain to redeem underlying assets to\",\"token\":\"ERC20 compatible token to deposit into the bridge\"}},\"redeemAndSwap(address,uint256,address,uint256,uint8,uint8,uint256,uint256)\":{\"params\":{\"amount\":\"Amount in native token decimals to transfer cross-chain pre-fees\",\"chainId\":\"which underlying chain to bridge assets onto\",\"deadline\":\"latest timestamp to accept this transaction*\",\"minDy\":\"the min amount the user would like to receive, or revert to only minting the SynERC20 token crosschain.\",\"to\":\"address on other chain to redeem underlying assets to\",\"token\":\"ERC20 compatible token to deposit into the bridge\",\"tokenIndexFrom\":\"the token the user wants to swap from\",\"tokenIndexTo\":\"the token the user wants to swap to\"}},\"redeemv2(bytes32,uint256,address,uint256)\":{\"params\":{\"amount\":\"Amount in native token decimals to transfer cross-chain pre-fees*\",\"chainId\":\"which chain to bridge assets onto\",\"to\":\"address on other chain to bridge assets to\",\"token\":\"ERC20 compatible token to redeem into the bridge\"}}},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{\"calculateSwap(address,uint8,uint8,uint256)\":{\"notice\":\"Calculate amount of tokens you receive on swap\"},\"deposit(address,uint256,address,uint256)\":{\"notice\":\"wraps SynapseBridge redeem()\"},\"depositETH(address,uint256,uint256)\":{\"notice\":\"Wraps SynapseBridge deposit() function to make it compatible w/ ETH -> WETH conversions\"},\"depositETHAndSwap(address,uint256,uint256,uint8,uint8,uint256,uint256)\":{\"notice\":\"Wraps SynapseBridge depositAndSwap() function to make it compatible w/ ETH -> WETH conversions\"},\"redeem(address,uint256,address,uint256)\":{\"notice\":\"wraps SynapseBridge redeem()\"},\"redeemAndRemove(address,uint256,address,uint256,uint8,uint256,uint256)\":{\"notice\":\"Wraps redeemAndRemove on SynapseBridge Relays to nodes that (typically) a wrapped synAsset ERC20 token has been burned and the underlying needs to be redeeemed on the native chain. This function indicates to the nodes that they should attempt to redeem the LP token for the underlying assets (E.g \\\"swap\\\" out of the LP token)\"},\"redeemAndSwap(address,uint256,address,uint256,uint8,uint8,uint256,uint256)\":{\"notice\":\"Wraps redeemAndSwap on SynapseBridge.sol Relays to nodes that (typically) a wrapped synAsset ERC20 token has been burned and the underlying needs to be redeeemed on the native chain. This function indicates to the nodes that they should attempt to redeem the LP token for the underlying assets (E.g \\\"swap\\\" out of the LP token)\"},\"redeemv2(bytes32,uint256,address,uint256)\":{\"notice\":\"Wraps SynapseBridge redeemv2() function\"}},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/bridge/wrappers/L2BridgeZap.sol\":\"L2BridgeZap\"},\"evmVersion\":\"istanbul\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":10000},\"remappings\":[]},\"sources\":{\"@openzeppelin/contracts/math/SafeMath.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity >=0.6.0 <0.8.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\",\"keccak256\":\"0xcc78a17dd88fa5a2edc60c8489e2f405c0913b377216a5b26b35656b2d0dab52\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/ERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity >=0.6.0 <0.8.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_) public {\\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\",\"keccak256\":\"0xca0c2396dbeb3503b51abf4248ebf77a1461edad513c01529df51850a012bee3\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/ERC20Burnable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity >=0.6.0 <0.8.0;\\n\\nimport \\\"../../utils/Context.sol\\\";\\nimport \\\"./ERC20.sol\\\";\\n\\n/**\\n * @dev Extension of {ERC20} that allows token holders to destroy both their own\\n * tokens and those that they have an allowance for, in a way that can be\\n * recognized off-chain (via event analysis).\\n */\\nabstract contract ERC20Burnable is Context, ERC20 {\\n using SafeMath for uint256;\\n\\n /**\\n * @dev Destroys `amount` tokens from the caller.\\n *\\n * See {ERC20-_burn}.\\n */\\n function burn(uint256 amount) public virtual {\\n _burn(_msgSender(), amount);\\n }\\n\\n /**\\n * @dev Destroys `amount` tokens from `account`, deducting from the caller's\\n * allowance.\\n *\\n * See {ERC20-_burn} and {ERC20-allowance}.\\n *\\n * Requirements:\\n *\\n * - the caller must have allowance for ``accounts``'s tokens of at least\\n * `amount`.\\n */\\n function burnFrom(address account, uint256 amount) public virtual {\\n uint256 decreasedAllowance = allowance(account, _msgSender()).sub(amount, \\\"ERC20: burn amount exceeds allowance\\\");\\n\\n _approve(account, _msgSender(), decreasedAllowance);\\n _burn(account, amount);\\n }\\n}\\n\",\"keccak256\":\"0x9c0eb3b0e11d2480d49991dc384f1e5f9c9b9967cc81944d50916a9b9c6c4984\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/IERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity >=0.6.0 <0.8.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\",\"keccak256\":\"0x5f02220344881ce43204ae4a6281145a67bc52c2bb1290a791857df3d19d78f5\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/SafeERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity >=0.6.0 <0.8.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\",\"keccak256\":\"0xf12dfbe97e6276980b83d2830bb0eb75e0cf4f3e626c2471137f82158ae6a0fc\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/Address.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity >=0.6.2 <0.8.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\",\"keccak256\":\"0x28911e614500ae7c607a432a709d35da25f3bc5ddc8bd12b278b66358070c0ea\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/Context.sol\":{\"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\",\"keccak256\":\"0x8d3cb350f04ff49cfb10aef08d87f19dcbaecc8027b0bed12f3275cd12f38cf0\",\"license\":\"MIT\"},\"contracts/bridge/interfaces/ISwap.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity 0.6.12;\\n\\nimport '@openzeppelin/contracts/token/ERC20/ERC20.sol';\\n\\ninterface ISwap {\\n // pool data view functions\\n function getA() external view returns (uint256);\\n\\n function getToken(uint8 index) external view returns (IERC20);\\n\\n function getTokenIndex(address tokenAddress) external view returns (uint8);\\n\\n function getTokenBalance(uint8 index) external view returns (uint256);\\n\\n function getVirtualPrice() external view returns (uint256);\\n\\n // min return calculation functions\\n function calculateSwap(\\n uint8 tokenIndexFrom,\\n uint8 tokenIndexTo,\\n uint256 dx\\n ) external view returns (uint256);\\n\\n function calculateTokenAmount(uint256[] calldata amounts, bool deposit)\\n external\\n view\\n returns (uint256);\\n\\n function calculateRemoveLiquidity(uint256 amount)\\n external\\n view\\n returns (uint256[] memory);\\n\\n function calculateRemoveLiquidityOneToken(\\n uint256 tokenAmount,\\n uint8 tokenIndex\\n ) external view returns (uint256 availableTokenAmount);\\n\\n // state modifying functions\\n function initialize(\\n IERC20[] memory pooledTokens,\\n uint8[] memory decimals,\\n string memory lpTokenName,\\n string memory lpTokenSymbol,\\n uint256 a,\\n uint256 fee,\\n uint256 adminFee,\\n address lpTokenTargetAddress\\n ) external;\\n\\n function swap(\\n uint8 tokenIndexFrom,\\n uint8 tokenIndexTo,\\n uint256 dx,\\n uint256 minDy,\\n uint256 deadline\\n ) external returns (uint256);\\n\\n function addLiquidity(\\n uint256[] calldata amounts,\\n uint256 minToMint,\\n uint256 deadline\\n ) external returns (uint256);\\n\\n function removeLiquidity(\\n uint256 amount,\\n uint256[] calldata minAmounts,\\n uint256 deadline\\n ) external returns (uint256[] memory);\\n\\n function removeLiquidityOneToken(\\n uint256 tokenAmount,\\n uint8 tokenIndex,\\n uint256 minAmount,\\n uint256 deadline\\n ) external returns (uint256);\\n\\n function removeLiquidityImbalance(\\n uint256[] calldata amounts,\\n uint256 maxBurnAmount,\\n uint256 deadline\\n ) external returns (uint256);\\n}\\n\",\"keccak256\":\"0xb51eb389637b2b595a09cd95ea4167a6d945719be1bc127eafae07c06abd8ca8\",\"license\":\"MIT\"},\"contracts/bridge/interfaces/ISynapseBridge.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity 0.6.12;\\n\\nimport '@openzeppelin/contracts/token/ERC20/SafeERC20.sol';\\nimport '@openzeppelin/contracts/token/ERC20/ERC20Burnable.sol';\\n\\ninterface ISynapseBridge {\\n using SafeERC20 for IERC20;\\n\\n function deposit(\\n address to,\\n uint256 chainId,\\n IERC20 token,\\n uint256 amount\\n ) external;\\n\\n function depositAndSwap(\\n address to,\\n uint256 chainId,\\n IERC20 token,\\n uint256 amount,\\n uint8 tokenIndexFrom,\\n uint8 tokenIndexTo,\\n uint256 minDy,\\n uint256 deadline\\n ) external;\\n\\n function redeem(\\n address to,\\n uint256 chainId,\\n IERC20 token,\\n uint256 amount\\n ) external;\\n\\n\\n function redeemv2(\\n bytes32 to,\\n uint256 chainId,\\n IERC20 token,\\n uint256 amount\\n ) external;\\n\\n\\n function redeemAndSwap(\\n address to,\\n uint256 chainId,\\n IERC20 token,\\n uint256 amount,\\n uint8 tokenIndexFrom,\\n uint8 tokenIndexTo,\\n uint256 minDy,\\n uint256 deadline\\n ) external;\\n\\n function redeemAndRemove(\\n address to,\\n uint256 chainId,\\n IERC20 token,\\n uint256 amount,\\n uint8 liqTokenIndex,\\n uint256 liqMinAmount,\\n uint256 liqDeadline\\n ) external;\\n}\\n\",\"keccak256\":\"0x9ae06bbed7d464faceb9c63e929171f422b5eaee1f6d653742ab97862bc6609a\",\"license\":\"MIT\"},\"contracts/bridge/interfaces/IWETH9.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity >=0.4.0;\\n\\ninterface IWETH9 {\\n function name() external view returns (string memory);\\n\\n function symbol() external view returns (string memory);\\n\\n function decimals() external view returns (uint8);\\n\\n function balanceOf(address) external view returns (uint256);\\n\\n function allowance(address, address) external view returns (uint256);\\n\\n receive() external payable;\\n\\n function deposit() external payable;\\n\\n function withdraw(uint256 wad) external;\\n\\n function totalSupply() external view returns (uint256);\\n\\n function approve(address guy, uint256 wad) external returns (bool);\\n\\n function transfer(address dst, uint256 wad) external returns (bool);\\n\\n function transferFrom(\\n address src,\\n address dst,\\n uint256 wad\\n ) external returns (bool);\\n}\",\"keccak256\":\"0x081ebde11dad2210d382564d40336f914d3d621750645f23707ca1a92139dbe2\",\"license\":\"MIT\"},\"contracts/bridge/wrappers/L2BridgeZap.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.6.12;\\n\\nimport \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\nimport \\\"@openzeppelin/contracts/token/ERC20/SafeERC20.sol\\\";\\nimport \\\"../interfaces/ISwap.sol\\\";\\nimport \\\"../interfaces/ISynapseBridge.sol\\\";\\nimport \\\"../interfaces/IWETH9.sol\\\";\\n\\ncontract L2BridgeZap {\\n using SafeERC20 for IERC20;\\n\\n ISynapseBridge synapseBridge;\\n address payable public immutable WETH_ADDRESS;\\n\\n mapping(address => address) public swapMap;\\n mapping(address => IERC20[]) public swapTokensMap;\\n\\n uint256 constant MAX_UINT256 = 2**256 - 1;\\n\\n constructor(\\n address payable _wethAddress,\\n address _swapOne,\\n address tokenOne,\\n address _swapTwo,\\n address tokenTwo,\\n ISynapseBridge _synapseBridge\\n ) public {\\n WETH_ADDRESS = _wethAddress;\\n synapseBridge = _synapseBridge;\\n swapMap[tokenOne] = _swapOne;\\n swapMap[tokenTwo] = _swapTwo;\\n if (_wethAddress != address(0)) {\\n IERC20(_wethAddress).safeIncreaseAllowance(address(_synapseBridge), MAX_UINT256);\\n }\\n if (address(_swapOne) != address(0)) {\\n {\\n uint8 i;\\n for (; i < 32; i++) {\\n try ISwap(_swapOne).getToken(i) returns (\\n IERC20 token\\n ) {\\n swapTokensMap[_swapOne].push(token);\\n token.safeApprove(address(_swapOne), MAX_UINT256);\\n token.safeApprove(address(synapseBridge), MAX_UINT256);\\n } catch {\\n break;\\n }\\n }\\n require(i > 1, \\\"swap must have at least 2 tokens\\\");\\n }\\n }\\n if (address(_swapTwo) != address(0)) {\\n {\\n uint8 i;\\n for (; i < 32; i++) {\\n try ISwap(_swapTwo).getToken(i) returns (\\n IERC20 token\\n ) {\\n swapTokensMap[_swapTwo].push(token);\\n token.safeApprove(address(_swapTwo), MAX_UINT256);\\n token.safeApprove(address(synapseBridge), MAX_UINT256);\\n } catch {\\n break;\\n }\\n }\\n require(i > 1, \\\"swap must have at least 2 tokens\\\");\\n }\\n }\\n }\\n\\n /**\\n * @notice Calculate amount of tokens you receive on swap\\n * @param tokenIndexFrom the token the user wants to sell\\n * @param tokenIndexTo the token the user wants to buy\\n * @param dx the amount of tokens the user wants to sell. If the token charges\\n * a fee on transfers, use the amount that gets transferred after the fee.\\n * @return amount of tokens the user will receive\\n */\\n function calculateSwap(\\n IERC20 token,\\n uint8 tokenIndexFrom,\\n uint8 tokenIndexTo,\\n uint256 dx\\n ) external view virtual returns (uint256) {\\n ISwap swap = ISwap(\\n swapMap[address(token)]\\n );\\n return swap.calculateSwap(tokenIndexFrom, tokenIndexTo, dx);\\n }\\n\\n function swapAndRedeem(\\n address to,\\n uint256 chainId,\\n IERC20 token,\\n uint8 tokenIndexFrom,\\n uint8 tokenIndexTo,\\n uint256 dx,\\n uint256 minDy,\\n uint256 deadline\\n ) external {\\n ISwap swap = ISwap(swapMap[address(token)]);\\n require(address(swap) != address(0), \\\"Swap is 0x00\\\");\\n IERC20[] memory tokens = swapTokensMap[address(swap)];\\n tokens[tokenIndexFrom].safeTransferFrom(\\n msg.sender,\\n address(this),\\n dx\\n );\\n // swap\\n\\n uint256 swappedAmount = swap.swap(\\n tokenIndexFrom,\\n tokenIndexTo,\\n dx,\\n minDy,\\n deadline\\n );\\n // deposit into bridge, gets nUSD\\n if (\\n token.allowance(address(this), address(synapseBridge)) <\\n swappedAmount\\n ) {\\n token.safeApprove(address(synapseBridge), MAX_UINT256);\\n }\\n synapseBridge.redeem(to, chainId, token, swappedAmount);\\n }\\n\\n function swapAndRedeemAndSwap(\\n address to,\\n uint256 chainId,\\n IERC20 token,\\n uint8 tokenIndexFrom,\\n uint8 tokenIndexTo,\\n uint256 dx,\\n uint256 minDy,\\n uint256 deadline,\\n uint8 swapTokenIndexFrom,\\n uint8 swapTokenIndexTo,\\n uint256 swapMinDy,\\n uint256 swapDeadline\\n ) external {\\n require(\\n address(swapMap[address(token)]) != address(0),\\n \\\"Swap is 0x00\\\"\\n );\\n IERC20[] memory tokens = swapTokensMap[\\n swapMap[address(token)]\\n ];\\n tokens[tokenIndexFrom].safeTransferFrom(\\n msg.sender,\\n address(this),\\n dx\\n );\\n // swap\\n\\n uint256 swappedAmount = ISwap(swapMap[address(token)]).swap(tokenIndexFrom, tokenIndexTo, dx, minDy, deadline);\\n // deposit into bridge, gets nUSD\\n if (\\n token.allowance(address(this), address(synapseBridge)) <\\n swappedAmount\\n ) {\\n token.safeApprove(address(synapseBridge), MAX_UINT256);\\n }\\n synapseBridge.redeemAndSwap(\\n to,\\n chainId,\\n token,\\n swappedAmount,\\n swapTokenIndexFrom,\\n swapTokenIndexTo,\\n swapMinDy,\\n swapDeadline\\n );\\n }\\n\\n function swapAndRedeemAndRemove(\\n address to,\\n uint256 chainId,\\n IERC20 token,\\n uint8 tokenIndexFrom,\\n uint8 tokenIndexTo,\\n uint256 dx,\\n uint256 minDy,\\n uint256 deadline,\\n uint8 liqTokenIndex,\\n uint256 liqMinAmount,\\n uint256 liqDeadline\\n ) external {\\n ISwap swap = ISwap(swapMap[address(token)]);\\n require(address(swap) != address(0), \\\"Swap is 0x00\\\");\\n IERC20[] memory tokens = swapTokensMap[address(swap)];\\n tokens[tokenIndexFrom].safeTransferFrom(\\n msg.sender,\\n address(this),\\n dx\\n );\\n // swap\\n\\n uint256 swappedAmount = swap.swap(\\n tokenIndexFrom,\\n tokenIndexTo,\\n dx,\\n minDy,\\n deadline\\n );\\n // deposit into bridge, gets nUSD\\n if (\\n token.allowance(address(this), address(synapseBridge)) <\\n swappedAmount\\n ) {\\n token.safeApprove(address(synapseBridge), MAX_UINT256);\\n }\\n synapseBridge.redeemAndRemove(\\n to,\\n chainId,\\n token,\\n swappedAmount,\\n liqTokenIndex,\\n liqMinAmount,\\n liqDeadline\\n );\\n }\\n\\n /**\\n * @notice wraps SynapseBridge redeem()\\n * @param to address on other chain to redeem underlying assets to\\n * @param chainId which underlying chain to bridge assets onto\\n * @param token ERC20 compatible token to deposit into the bridge\\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\\n **/\\n function redeem(\\n address to,\\n uint256 chainId,\\n IERC20 token,\\n uint256 amount\\n ) external {\\n token.safeTransferFrom(msg.sender, address(this), amount);\\n if (token.allowance(address(this), address(synapseBridge)) < amount) {\\n token.safeApprove(address(synapseBridge), MAX_UINT256);\\n }\\n synapseBridge.redeem(to, chainId, token, amount);\\n }\\n\\n /**\\n * @notice wraps SynapseBridge redeem()\\n * @param to address on other chain to redeem underlying assets to\\n * @param chainId which underlying chain to bridge assets onto\\n * @param token ERC20 compatible token to deposit into the bridge\\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\\n **/\\n function deposit(\\n address to,\\n uint256 chainId,\\n IERC20 token,\\n uint256 amount\\n ) external {\\n token.safeTransferFrom(msg.sender, address(this), amount);\\n if (token.allowance(address(this), address(synapseBridge)) < amount) {\\n token.safeApprove(address(synapseBridge), MAX_UINT256);\\n }\\n synapseBridge.deposit(to, chainId, token, amount);\\n }\\n\\n /**\\n * @notice Wraps SynapseBridge deposit() function to make it compatible w/ ETH -> WETH conversions\\n * @param to address on other chain to bridge assets to\\n * @param chainId which chain to bridge assets onto\\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\\n **/\\n function depositETH(\\n address to,\\n uint256 chainId,\\n uint256 amount\\n ) external payable {\\n require(msg.value > 0 && msg.value == amount, 'INCORRECT MSG VALUE');\\n IWETH9(WETH_ADDRESS).deposit{value: msg.value}();\\n synapseBridge.deposit(to, chainId, IERC20(WETH_ADDRESS), amount);\\n }\\n\\n\\n /**\\n * @notice Wraps SynapseBridge depositAndSwap() function to make it compatible w/ ETH -> WETH conversions\\n * @param to address on other chain to bridge assets to\\n * @param chainId which chain to bridge assets onto\\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\\n * @param tokenIndexFrom the token the user wants to swap from\\n * @param tokenIndexTo the token the user wants to swap to\\n * @param minDy the min amount the user would like to receive, or revert to only minting the SynERC20 token crosschain.\\n * @param deadline latest timestamp to accept this transaction\\n **/\\n function depositETHAndSwap(\\n address to,\\n uint256 chainId,\\n uint256 amount,\\n uint8 tokenIndexFrom,\\n uint8 tokenIndexTo,\\n uint256 minDy,\\n uint256 deadline\\n ) external payable {\\n require(msg.value > 0 && msg.value == amount, 'INCORRECT MSG VALUE');\\n IWETH9(WETH_ADDRESS).deposit{value: msg.value}();\\n synapseBridge.depositAndSwap(to, chainId, IERC20(WETH_ADDRESS), amount, tokenIndexFrom, tokenIndexTo, minDy, deadline);\\n }\\n\\n\\n function swapETHAndRedeem(\\n address to,\\n uint256 chainId,\\n IERC20 token,\\n uint8 tokenIndexFrom,\\n uint8 tokenIndexTo,\\n uint256 dx,\\n uint256 minDy,\\n uint256 deadline\\n ) external payable {\\n require(WETH_ADDRESS != address(0), \\\"WETH 0\\\");\\n require(msg.value > 0 && msg.value == dx, \\\"INCORRECT MSG VALUE\\\");\\n ISwap swap = ISwap(swapMap[address(token)]);\\n require(address(swap) != address(0), \\\"Swap is 0x00\\\");\\n IWETH9(WETH_ADDRESS).deposit{value: msg.value}();\\n\\n // swap\\n uint256 swappedAmount = swap.swap(\\n tokenIndexFrom,\\n tokenIndexTo,\\n dx,\\n minDy,\\n deadline\\n );\\n synapseBridge.redeem(to, chainId, token, swappedAmount);\\n }\\n\\n\\n function swapETHAndRedeemAndSwap(\\n address to,\\n uint256 chainId,\\n IERC20 token,\\n uint8 tokenIndexFrom,\\n uint8 tokenIndexTo,\\n uint256 dx,\\n uint256 minDy,\\n uint256 deadline,\\n uint8 swapTokenIndexFrom,\\n uint8 swapTokenIndexTo,\\n uint256 swapMinDy,\\n uint256 swapDeadline\\n ) external payable {\\n require(WETH_ADDRESS != address(0), \\\"WETH 0\\\");\\n require(msg.value > 0 && msg.value == dx, \\\"INCORRECT MSG VALUE\\\");\\n ISwap swap = ISwap(swapMap[address(token)]);\\n require(address(swap) != address(0), \\\"Swap is 0x00\\\");\\n IWETH9(WETH_ADDRESS).deposit{value: msg.value}();\\n\\n // swap\\n uint256 swappedAmount = swap.swap(\\n tokenIndexFrom,\\n tokenIndexTo,\\n dx,\\n minDy,\\n deadline\\n );\\n synapseBridge.redeemAndSwap(to, chainId, token, swappedAmount,swapTokenIndexFrom,\\n swapTokenIndexTo,\\n swapMinDy,\\n swapDeadline);\\n }\\n\\n\\n /**\\n * @notice Wraps redeemAndSwap on SynapseBridge.sol\\n * Relays to nodes that (typically) a wrapped synAsset ERC20 token has been burned and the underlying needs to be redeeemed on the native chain. This function indicates to the nodes that they should attempt to redeem the LP token for the underlying assets (E.g \\\"swap\\\" out of the LP token)\\n * @param to address on other chain to redeem underlying assets to\\n * @param chainId which underlying chain to bridge assets onto\\n * @param token ERC20 compatible token to deposit into the bridge\\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\\n * @param tokenIndexFrom the token the user wants to swap from\\n * @param tokenIndexTo the token the user wants to swap to\\n * @param minDy the min amount the user would like to receive, or revert to only minting the SynERC20 token crosschain.\\n * @param deadline latest timestamp to accept this transaction\\n **/\\n function redeemAndSwap(\\n address to,\\n uint256 chainId,\\n IERC20 token,\\n uint256 amount,\\n uint8 tokenIndexFrom,\\n uint8 tokenIndexTo,\\n uint256 minDy,\\n uint256 deadline\\n ) external {\\n token.safeTransferFrom(msg.sender, address(this), amount);\\n if (token.allowance(address(this), address(synapseBridge)) < amount) {\\n token.safeApprove(address(synapseBridge), MAX_UINT256);\\n }\\n synapseBridge.redeemAndSwap(\\n to,\\n chainId,\\n token,\\n amount,\\n tokenIndexFrom,\\n tokenIndexTo,\\n minDy,\\n deadline\\n );\\n }\\n\\n /**\\n * @notice Wraps redeemAndRemove on SynapseBridge\\n * Relays to nodes that (typically) a wrapped synAsset ERC20 token has been burned and the underlying needs to be redeeemed on the native chain. This function indicates to the nodes that they should attempt to redeem the LP token for the underlying assets (E.g \\\"swap\\\" out of the LP token)\\n * @param to address on other chain to redeem underlying assets to\\n * @param chainId which underlying chain to bridge assets onto\\n * @param token ERC20 compatible token to deposit into the bridge\\n * @param amount Amount of (typically) LP token to pass to the nodes to attempt to removeLiquidity() with to redeem for the underlying assets of the LP token\\n * @param liqTokenIndex Specifies which of the underlying LP assets the nodes should attempt to redeem for\\n * @param liqMinAmount Specifies the minimum amount of the underlying asset needed for the nodes to execute the redeem/swap\\n * @param liqDeadline Specificies the deadline that the nodes are allowed to try to redeem/swap the LP token\\n **/\\n function redeemAndRemove(\\n address to,\\n uint256 chainId,\\n IERC20 token,\\n uint256 amount,\\n uint8 liqTokenIndex,\\n uint256 liqMinAmount,\\n uint256 liqDeadline\\n ) external {\\n token.safeTransferFrom(msg.sender, address(this), amount);\\n if (token.allowance(address(this), address(synapseBridge)) < amount) {\\n token.safeApprove(address(synapseBridge), MAX_UINT256);\\n }\\n synapseBridge.redeemAndRemove(\\n to,\\n chainId,\\n token,\\n amount,\\n liqTokenIndex,\\n liqMinAmount,\\n liqDeadline\\n );\\n }\\n\\n /**\\n * @notice Wraps SynapseBridge redeemv2() function\\n * @param to address on other chain to bridge assets to\\n * @param chainId which chain to bridge assets onto\\n * @param token ERC20 compatible token to redeem into the bridge\\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\\n **/\\n function redeemv2(\\n bytes32 to,\\n uint256 chainId,\\n IERC20 token,\\n uint256 amount\\n ) external {\\n token.safeTransferFrom(msg.sender, address(this), amount);\\n\\n if (token.allowance(address(this), address(synapseBridge)) < amount) {\\n token.safeApprove(address(synapseBridge), MAX_UINT256);\\n }\\n synapseBridge.redeemv2(to, chainId, token, amount);\\n }\\n}\\n\",\"keccak256\":\"0x2fa1a767186130b8c0c7ceb38017dee69239358b41061036e98d44f23032c4f0\",\"license\":\"MIT\"}},\"version\":1}", + "bytecode": "0x60a06040523480156200001157600080fd5b506040516200328938038062003289833981810160405260c08110156200003757600080fd5b50805160208083015160408085015160608087015160808089015160a0909901519288901b6001600160601b0319169052600080546001600160a01b03199081166001600160a01b038086169190911783558086168352600190985285822080548216898916179055878a168252949020805490941686821617909355949592949093919291861615620000ec57620000ec81600019886001600160a01b0316620003e060201b62002136179092919060201c565b6001600160a01b03851615620002605760005b60208160ff1610156200021657856001600160a01b03166382b86600826040518263ffffffff1660e01b8152600401808260ff16815260200191505060206040518083038186803b1580156200015457600080fd5b505afa9250505080156200017b57506040513d60208110156200017657600080fd5b505160015b620001865762000216565b6001600160a01b038781166000908152600260209081526040822080546001810182559083529181902090910180546001600160a01b0319169284169283179055620001e29190899060001990620004e9811b6200225517901c565b6000546200020c906001600160a01b038381169116600019620004e9602090811b6200225517901c565b50600101620000ff565b60018160ff16116200025e576040805162461bcd60e51b8152602060048201819052602482015260008051602062003209833981519152604482015290519081900360640190fd5b505b6001600160a01b03831615620003d45760005b60208160ff1610156200038a57836001600160a01b03166382b86600826040518263ffffffff1660e01b8152600401808260ff16815260200191505060206040518083038186803b158015620002c857600080fd5b505afa925050508015620002ef57506040513d6020811015620002ea57600080fd5b505160015b620002fa576200038a565b6001600160a01b038581166000908152600260209081526040822080546001810182559083529181902090910180546001600160a01b0319169284169283179055620003569190879060001990620004e9811b6200225517901c565b60005462000380906001600160a01b038381169116600019620004e9602090811b6200225517901c565b5060010162000273565b60018160ff1611620003d2576040805162461bcd60e51b8152602060048201819052602482015260008051602062003209833981519152604482015290519081900360640190fd5b505b5050505050506200095c565b60006200048782856001600160a01b031663dd62ed3e30876040518363ffffffff1660e01b815260040180836001600160a01b03168152602001826001600160a01b031681526020019250505060206040518083038186803b1580156200044657600080fd5b505afa1580156200045b573d6000803e3d6000fd5b505050506040513d60208110156200047257600080fd5b5051906200060d602090811b620023b417901c565b604080516001600160a01b038616602482015260448082018490528251808303909101815260649091019091526020810180516001600160e01b0390811663095ea7b360e01b17909152919250620004e3918691906200066f16565b50505050565b80158062000573575060408051636eb1769f60e11b81523060048201526001600160a01b03848116602483015291519185169163dd62ed3e91604480820192602092909190829003018186803b1580156200054357600080fd5b505afa15801562000558573d6000803e3d6000fd5b505050506040513d60208110156200056f57600080fd5b5051155b620005b05760405162461bcd60e51b8152600401808060200182810382526036815260200180620032536036913960400191505060405180910390fd5b604080516001600160a01b038416602482015260448082018490528251808303909101815260649091019091526020810180516001600160e01b0390811663095ea7b360e01b17909152620006089185916200066f16565b505050565b60008282018381101562000668576040805162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b9392505050565b6060620006cb826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b03166200072b60201b62002415179092919060201c565b8051909150156200060857808060200190516020811015620006ec57600080fd5b5051620006085760405162461bcd60e51b815260040180806020018281038252602a81526020018062003229602a913960400191505060405180910390fd5b60606200073c848460008562000744565b949350505050565b606082471015620007875760405162461bcd60e51b8152600401808060200182810382526026815260200180620031e36026913960400191505060405180910390fd5b6200079285620008ac565b620007e4576040805162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000604482015290519081900360640190fd5b60006060866001600160a01b031685876040518082805190602001908083835b60208310620008255780518252601f19909201916020918201910162000804565b6001836020036101000a03801982511681845116808217855250505050505090500191505060006040518083038185875af1925050503d806000811462000889576040519150601f19603f3d011682016040523d82523d6000602084013e6200088e565b606091505b509092509050620008a1828286620008b2565b979650505050505050565b3b151590565b60608315620008c357508162000668565b825115620008d45782518084602001fd5b8160405162461bcd60e51b81526004018080602001828103825283818151815260200191508051906020019080838360005b838110156200092057818101518382015260200162000906565b50505050905090810190601f1680156200094e5780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b60805160601c612841620009a26000398061064c5280610b6f5280610cb752806112e6528061142e5280611d345280611de75280611ec35280611f7652506128416000f3fe6080604052600436106100f35760003560e01c8063798af7201161008a5780639f330727116100595780639f330727146104fb578063a9fd8c5714610580578063ce0b63ce146105d1578063f3f094a114610603576100f3565b8063798af720146103bc578063839ed90a1461041a57806385528f0b1461048157806390d25074146104b4576100f3565b80633d5da164116100c65780633d5da1641461023e57806349b7cf84146102b65780634a517a55146102fb57806365749c9d14610362576100f3565b8063040141e5146100f8578063174dc9521461012957806336e712ed146101a9578063393494b814610205575b600080fd5b34801561010457600080fd5b5061010d61064a565b604080516001600160a01b039092168252519081900360200190f35b34801561013557600080fd5b506101a7600480360361016081101561014d57600080fd5b506001600160a01b0381358116916020810135916040820135169060ff6060820135811691608081013582169160a08201359160c08101359160e0820135916101008101359091169061012081013590610140013561066e565b005b3480156101b557600080fd5b506101a7600480360360e08110156101cc57600080fd5b506001600160a01b0381358116916020810135916040820135169060608101359060ff6080820135169060a08101359060c001356109b7565b34801561021157600080fd5b5061010d6004803603604081101561022857600080fd5b506001600160a01b038135169060200135610b38565b6101a7600480360361018081101561025557600080fd5b506001600160a01b0381358116916020810135916040820135169060ff6060820135811691608081013582169160a08201359160c08101359160e0820135916101008101358216916101208201351690610140810135906101600135610b6d565b3480156102c257600080fd5b506101a7600480360360808110156102d957600080fd5b508035906020810135906001600160a01b036040820135169060600135610e7d565b34801561030757600080fd5b506101a7600480360361010081101561031f57600080fd5b506001600160a01b0381358116916020810135916040820135169060ff606082013581169160808101359091169060a08101359060c08101359060e00135610fe3565b6101a7600480360361010081101561037957600080fd5b506001600160a01b0381358116916020810135916040820135169060ff606082013581169160808101359091169060a08101359060c08101359060e001356112e4565b3480156103c857600080fd5b50610408600480360360808110156103df57600080fd5b506001600160a01b038135169060ff6020820135811691604081013590911690606001356115f0565b60408051918252519081900360200190f35b34801561042657600080fd5b506101a7600480360361010081101561043e57600080fd5b506001600160a01b0381358116916020810135916040820135169060608101359060ff608082013581169160a08101359091169060c08101359060e001356116a9565b34801561048d57600080fd5b5061010d600480360360208110156104a457600080fd5b50356001600160a01b0316611834565b3480156104c057600080fd5b506101a7600480360360808110156104d757600080fd5b506001600160a01b038135811691602081013591604082013516906060013561184f565b34801561050757600080fd5b506101a7600480360361018081101561051f57600080fd5b506001600160a01b0381358116916020810135916040820135169060ff6060820135811691608081013582169160a08201359160c08101359160e0820135916101008101358216916101208201351690610140810135906101600135611998565b6101a7600480360360e081101561059657600080fd5b506001600160a01b038135169060208101359060408101359060ff606082013581169160808101359091169060a08101359060c00135611cd2565b6101a7600480360360608110156105e757600080fd5b506001600160a01b038135169060208101359060400135611e61565b34801561060f57600080fd5b506101a76004803603608081101561062657600080fd5b506001600160a01b0381358116916020810135916040820135169060600135611fed565b7f000000000000000000000000000000000000000000000000000000000000000081565b6001600160a01b03808a1660009081526001602052604090205416806106db576040805162461bcd60e51b815260206004820152600c60248201527f5377617020697320307830300000000000000000000000000000000000000000604482015290519081900360640190fd5b6001600160a01b03811660009081526002602090815260409182902080548351818402810184019094528084526060939283018282801561074557602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311610727575b5050505050905061078233308a848e60ff168151811061076157fe5b60200260200101516001600160a01b031661242c909392919063ffffffff16565b604080517f9169558600000000000000000000000000000000000000000000000000000000815260ff808d1660048301528b166024820152604481018a9052606481018990526084810188905290516000916001600160a01b0385169163916955869160a48082019260209290919082900301818787803b15801561080657600080fd5b505af115801561081a573d6000803e3d6000fd5b505050506040513d602081101561083057600080fd5b5051600054604080517fdd62ed3e0000000000000000000000000000000000000000000000000000000081523060048201526001600160a01b03928316602482015290519293508392918f169163dd62ed3e91604480820192602092909190829003018186803b1580156108a357600080fd5b505afa1580156108b7573d6000803e3d6000fd5b505050506040513d60208110156108cd57600080fd5b505110156108f1576000546108f1906001600160a01b038e81169116600019612255565b60008054906101000a90046001600160a01b03166001600160a01b03166336e712ed8f8f8f858b8b8b6040518863ffffffff1660e01b815260040180886001600160a01b03168152602001878152602001866001600160a01b031681526020018581526020018460ff168152602001838152602001828152602001975050505050505050600060405180830381600087803b15801561098f57600080fd5b505af11580156109a3573d6000803e3d6000fd5b505050505050505050505050505050505050565b6109cc6001600160a01b03861633308761242c565b600054604080517fdd62ed3e0000000000000000000000000000000000000000000000000000000081523060048201526001600160a01b0392831660248201529051869288169163dd62ed3e916044808301926020929190829003018186803b158015610a3857600080fd5b505afa158015610a4c573d6000803e3d6000fd5b505050506040513d6020811015610a6257600080fd5b50511015610a8657600054610a86906001600160a01b038781169116600019612255565b60008054604080517f36e712ed0000000000000000000000000000000000000000000000000000000081526001600160a01b038b81166004830152602482018b905289811660448301526064820189905260ff8816608483015260a4820187905260c48201869052915191909216926336e712ed9260e4808201939182900301818387803b158015610b1757600080fd5b505af1158015610b2b573d6000803e3d6000fd5b5050505050505050505050565b60026020528160005260406000208181548110610b5157fe5b6000918252602090912001546001600160a01b03169150829050565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316610be8576040805162461bcd60e51b815260206004820152600660248201527f5745544820300000000000000000000000000000000000000000000000000000604482015290519081900360640190fd5b600034118015610bf757508634145b610c48576040805162461bcd60e51b815260206004820152601360248201527f494e434f5252454354204d53472056414c554500000000000000000000000000604482015290519081900360640190fd5b6001600160a01b03808b166000908152600160205260409020541680610cb5576040805162461bcd60e51b815260206004820152600c60248201527f5377617020697320307830300000000000000000000000000000000000000000604482015290519081900360640190fd5b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663d0e30db0346040518263ffffffff1660e01b81526004016000604051808303818588803b158015610d1057600080fd5b505af1158015610d24573d6000803e3d6000fd5b50505050506000816001600160a01b031663916955868c8c8c8c8c6040518663ffffffff1660e01b8152600401808660ff1681526020018560ff16815260200184815260200183815260200182815260200195505050505050602060405180830381600087803b158015610d9757600080fd5b505af1158015610dab573d6000803e3d6000fd5b505050506040513d6020811015610dc157600080fd5b8101908080519060200190929190505050905060008054906101000a90046001600160a01b03166001600160a01b031663839ed90a8f8f8f858b8b8b8b6040518963ffffffff1660e01b815260040180896001600160a01b03168152602001888152602001876001600160a01b031681526020018681526020018560ff1681526020018460ff16815260200183815260200182815260200198505050505050505050600060405180830381600087803b15801561098f57600080fd5b610e926001600160a01b03831633308461242c565b600054604080517fdd62ed3e0000000000000000000000000000000000000000000000000000000081523060048201526001600160a01b0392831660248201529051839285169163dd62ed3e916044808301926020929190829003018186803b158015610efe57600080fd5b505afa158015610f12573d6000803e3d6000fd5b505050506040513d6020811015610f2857600080fd5b50511015610f4c57600054610f4c906001600160a01b038481169116600019612255565b60008054604080517f49b7cf8400000000000000000000000000000000000000000000000000000000815260048101889052602481018790526001600160a01b03868116604483015260648201869052915191909216926349b7cf84926084808201939182900301818387803b158015610fc557600080fd5b505af1158015610fd9573d6000803e3d6000fd5b5050505050505050565b6001600160a01b038087166000908152600160205260409020541680611050576040805162461bcd60e51b815260206004820152600c60248201527f5377617020697320307830300000000000000000000000000000000000000000604482015290519081900360640190fd5b6001600160a01b0381166000908152600260209081526040918290208054835181840281018401909452808452606093928301828280156110ba57602002820191906000526020600020905b81546001600160a01b0316815260019091019060200180831161109c575b505050505090506110d6333087848b60ff168151811061076157fe5b604080517f9169558600000000000000000000000000000000000000000000000000000000815260ff808a1660048301528816602482015260448101879052606481018690526084810185905290516000916001600160a01b0385169163916955869160a48082019260209290919082900301818787803b15801561115a57600080fd5b505af115801561116e573d6000803e3d6000fd5b505050506040513d602081101561118457600080fd5b5051600054604080517fdd62ed3e0000000000000000000000000000000000000000000000000000000081523060048201526001600160a01b03928316602482015290519293508392918c169163dd62ed3e91604480820192602092909190829003018186803b1580156111f757600080fd5b505afa15801561120b573d6000803e3d6000fd5b505050506040513d602081101561122157600080fd5b5051101561124557600054611245906001600160a01b038b81169116600019612255565b60008054604080517ff3f094a10000000000000000000000000000000000000000000000000000000081526001600160a01b038f81166004830152602482018f90528d81166044830152606482018690529151919092169263f3f094a1926084808201939182900301818387803b1580156112bf57600080fd5b505af11580156112d3573d6000803e3d6000fd5b505050505050505050505050505050565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031661135f576040805162461bcd60e51b815260206004820152600660248201527f5745544820300000000000000000000000000000000000000000000000000000604482015290519081900360640190fd5b60003411801561136e57508234145b6113bf576040805162461bcd60e51b815260206004820152601360248201527f494e434f5252454354204d53472056414c554500000000000000000000000000604482015290519081900360640190fd5b6001600160a01b03808716600090815260016020526040902054168061142c576040805162461bcd60e51b815260206004820152600c60248201527f5377617020697320307830300000000000000000000000000000000000000000604482015290519081900360640190fd5b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663d0e30db0346040518263ffffffff1660e01b81526004016000604051808303818588803b15801561148757600080fd5b505af115801561149b573d6000803e3d6000fd5b5050604080517f9169558600000000000000000000000000000000000000000000000000000000815260ff808c1660048301528a1660248201526044810189905260648101889052608481018790529051600094506001600160a01b03861693506391695586925060a480830192602092919082900301818787803b15801561152357600080fd5b505af1158015611537573d6000803e3d6000fd5b505050506040513d602081101561154d57600080fd5b505160008054604080517ff3f094a10000000000000000000000000000000000000000000000000000000081526001600160a01b038f81166004830152602482018f90528d8116604483015260648201869052915194955091169263f3f094a19260848084019391929182900301818387803b1580156115cc57600080fd5b505af11580156115e0573d6000803e3d6000fd5b5050505050505050505050505050565b6001600160a01b0380851660009081526001602090815260408083205481517fa95b089f00000000000000000000000000000000000000000000000000000000815260ff808a1660048301528816602482015260448101879052915193941692839263a95b089f9260648082019391829003018186803b15801561167357600080fd5b505afa158015611687573d6000803e3d6000fd5b505050506040513d602081101561169d57600080fd5b50519695505050505050565b6116be6001600160a01b03871633308861242c565b600054604080517fdd62ed3e0000000000000000000000000000000000000000000000000000000081523060048201526001600160a01b0392831660248201529051879289169163dd62ed3e916044808301926020929190829003018186803b15801561172a57600080fd5b505afa15801561173e573d6000803e3d6000fd5b505050506040513d602081101561175457600080fd5b5051101561177857600054611778906001600160a01b038881169116600019612255565b60008054604080517f839ed90a0000000000000000000000000000000000000000000000000000000081526001600160a01b038c81166004830152602482018c90528a81166044830152606482018a905260ff808a166084840152881660a483015260c4820187905260e482018690529151919092169263839ed90a92610104808201939182900301818387803b15801561181257600080fd5b505af1158015611826573d6000803e3d6000fd5b505050505050505050505050565b6001602052600090815260409020546001600160a01b031681565b6118646001600160a01b03831633308461242c565b600054604080517fdd62ed3e0000000000000000000000000000000000000000000000000000000081523060048201526001600160a01b0392831660248201529051839285169163dd62ed3e916044808301926020929190829003018186803b1580156118d057600080fd5b505afa1580156118e4573d6000803e3d6000fd5b505050506040513d60208110156118fa57600080fd5b5051101561191e5760005461191e906001600160a01b038481169116600019612255565b60008054604080517f90d250740000000000000000000000000000000000000000000000000000000081526001600160a01b03888116600483015260248201889052868116604483015260648201869052915191909216926390d25074926084808201939182900301818387803b158015610fc557600080fd5b6001600160a01b038a811660009081526001602052604090205416611a04576040805162461bcd60e51b815260206004820152600c60248201527f5377617020697320307830300000000000000000000000000000000000000000604482015290519081900360640190fd5b6001600160a01b03808b1660009081526001602090815260408083205490931682526002815290829020805483518184028101840190945280845260609392830182828015611a7c57602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311611a5e575b50505050509050611a9833308a848e60ff168151811061076157fe5b6000600160008d6001600160a01b03166001600160a01b0316815260200190815260200160002060009054906101000a90046001600160a01b03166001600160a01b031663916955868c8c8c8c8c6040518663ffffffff1660e01b8152600401808660ff1681526020018560ff16815260200184815260200183815260200182815260200195505050505050602060405180830381600087803b158015611b3e57600080fd5b505af1158015611b52573d6000803e3d6000fd5b505050506040513d6020811015611b6857600080fd5b5051600054604080517fdd62ed3e0000000000000000000000000000000000000000000000000000000081523060048201526001600160a01b03928316602482015290519293508392918f169163dd62ed3e91604480820192602092909190829003018186803b158015611bdb57600080fd5b505afa158015611bef573d6000803e3d6000fd5b505050506040513d6020811015611c0557600080fd5b50511015611c2957600054611c29906001600160a01b038e81169116600019612255565b60008054906101000a90046001600160a01b03166001600160a01b031663839ed90a8f8f8f858b8b8b8b6040518963ffffffff1660e01b815260040180896001600160a01b03168152602001888152602001876001600160a01b031681526020018681526020018560ff1681526020018460ff16815260200183815260200182815260200198505050505050505050600060405180830381600087803b15801561098f57600080fd5b600034118015611ce157508434145b611d32576040805162461bcd60e51b815260206004820152601360248201527f494e434f5252454354204d53472056414c554500000000000000000000000000604482015290519081900360640190fd5b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663d0e30db0346040518263ffffffff1660e01b81526004016000604051808303818588803b158015611d8d57600080fd5b505af1158015611da1573d6000803e3d6000fd5b505060008054604080517fa2a2af0b0000000000000000000000000000000000000000000000000000000081526001600160a01b038e81166004830152602482018e90527f000000000000000000000000000000000000000000000000000000000000000081166044830152606482018d905260ff808d1660848401528b1660a483015260c482018a905260e48201899052915191909216955063a2a2af0b94506101048083019450909182900301818387803b158015610b1757600080fd5b600034118015611e7057508034145b611ec1576040805162461bcd60e51b815260206004820152601360248201527f494e434f5252454354204d53472056414c554500000000000000000000000000604482015290519081900360640190fd5b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663d0e30db0346040518263ffffffff1660e01b81526004016000604051808303818588803b158015611f1c57600080fd5b505af1158015611f30573d6000803e3d6000fd5b505060008054604080517f90d250740000000000000000000000000000000000000000000000000000000081526001600160a01b038a81166004830152602482018a90527f0000000000000000000000000000000000000000000000000000000000000000811660448301526064820189905291519190921695506390d25074945060848083019450909182900301818387803b158015611fd057600080fd5b505af1158015611fe4573d6000803e3d6000fd5b50505050505050565b6120026001600160a01b03831633308461242c565b600054604080517fdd62ed3e0000000000000000000000000000000000000000000000000000000081523060048201526001600160a01b0392831660248201529051839285169163dd62ed3e916044808301926020929190829003018186803b15801561206e57600080fd5b505afa158015612082573d6000803e3d6000fd5b505050506040513d602081101561209857600080fd5b505110156120bc576000546120bc906001600160a01b038481169116600019612255565b60008054604080517ff3f094a10000000000000000000000000000000000000000000000000000000081526001600160a01b038881166004830152602482018890528681166044830152606482018690529151919092169263f3f094a1926084808201939182900301818387803b158015610fc557600080fd5b60006121cc82856001600160a01b031663dd62ed3e30876040518363ffffffff1660e01b815260040180836001600160a01b03168152602001826001600160a01b031681526020019250505060206040518083038186803b15801561219a57600080fd5b505afa1580156121ae573d6000803e3d6000fd5b505050506040513d60208110156121c457600080fd5b5051906123b4565b604080516001600160a01b038616602482015260448082018490528251808303909101815260649091019091526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f095ea7b30000000000000000000000000000000000000000000000000000000017905290915061224f9085906124b0565b50505050565b8015806122f45750604080517fdd62ed3e0000000000000000000000000000000000000000000000000000000081523060048201526001600160a01b03848116602483015291519185169163dd62ed3e91604480820192602092909190829003018186803b1580156122c657600080fd5b505afa1580156122da573d6000803e3d6000fd5b505050506040513d60208110156122f057600080fd5b5051155b61232f5760405162461bcd60e51b81526004018080602001828103825260368152602001806127d66036913960400191505060405180910390fd5b604080516001600160a01b038416602482015260448082018490528251808303909101815260649091019091526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f095ea7b3000000000000000000000000000000000000000000000000000000001790526123af9084906124b0565b505050565b60008282018381101561240e576040805162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b9392505050565b60606124248484600085612561565b949350505050565b604080516001600160a01b0380861660248301528416604482015260648082018490528251808303909101815260849091019091526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f23b872dd0000000000000000000000000000000000000000000000000000000017905261224f9085905b6060612505826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b03166124159092919063ffffffff16565b8051909150156123af5780806020019051602081101561252457600080fd5b50516123af5760405162461bcd60e51b815260040180806020018281038252602a8152602001806127ac602a913960400191505060405180910390fd5b6060824710156125a25760405162461bcd60e51b81526004018080602001828103825260268152602001806127866026913960400191505060405180910390fd5b6125ab856126db565b6125fc576040805162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000604482015290519081900360640190fd5b60006060866001600160a01b031685876040518082805190602001908083835b6020831061265957805182527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0909201916020918201910161261c565b6001836020036101000a03801982511681845116808217855250505050505090500191505060006040518083038185875af1925050503d80600081146126bb576040519150601f19603f3d011682016040523d82523d6000602084013e6126c0565b606091505b50915091506126d08282866126e1565b979650505050505050565b3b151590565b606083156126f057508161240e565b8251156127005782518084602001fd5b8160405162461bcd60e51b81526004018080602001828103825283818151815260200191508051906020019080838360005b8381101561274a578181015183820152602001612732565b50505050905090810190601f1680156127775780820380516001836020036101000a031916815260200191505b509250505060405180910390fdfe416464726573733a20696e73756666696369656e742062616c616e636520666f722063616c6c5361666545524332303a204552433230206f7065726174696f6e20646964206e6f7420737563636565645361666545524332303a20617070726f76652066726f6d206e6f6e2d7a65726f20746f206e6f6e2d7a65726f20616c6c6f77616e6365a264697066735822122043e7e9b36961500da4f30ed0906f6468518d581e0050085217f10a02e6afda8964736f6c634300060c0033416464726573733a20696e73756666696369656e742062616c616e636520666f722063616c6c73776170206d7573742068617665206174206c65617374203220746f6b656e735361666545524332303a204552433230206f7065726174696f6e20646964206e6f7420737563636565645361666545524332303a20617070726f76652066726f6d206e6f6e2d7a65726f20746f206e6f6e2d7a65726f20616c6c6f77616e6365", + "deployedBytecode": "0x6080604052600436106100f35760003560e01c8063798af7201161008a5780639f330727116100595780639f330727146104fb578063a9fd8c5714610580578063ce0b63ce146105d1578063f3f094a114610603576100f3565b8063798af720146103bc578063839ed90a1461041a57806385528f0b1461048157806390d25074146104b4576100f3565b80633d5da164116100c65780633d5da1641461023e57806349b7cf84146102b65780634a517a55146102fb57806365749c9d14610362576100f3565b8063040141e5146100f8578063174dc9521461012957806336e712ed146101a9578063393494b814610205575b600080fd5b34801561010457600080fd5b5061010d61064a565b604080516001600160a01b039092168252519081900360200190f35b34801561013557600080fd5b506101a7600480360361016081101561014d57600080fd5b506001600160a01b0381358116916020810135916040820135169060ff6060820135811691608081013582169160a08201359160c08101359160e0820135916101008101359091169061012081013590610140013561066e565b005b3480156101b557600080fd5b506101a7600480360360e08110156101cc57600080fd5b506001600160a01b0381358116916020810135916040820135169060608101359060ff6080820135169060a08101359060c001356109b7565b34801561021157600080fd5b5061010d6004803603604081101561022857600080fd5b506001600160a01b038135169060200135610b38565b6101a7600480360361018081101561025557600080fd5b506001600160a01b0381358116916020810135916040820135169060ff6060820135811691608081013582169160a08201359160c08101359160e0820135916101008101358216916101208201351690610140810135906101600135610b6d565b3480156102c257600080fd5b506101a7600480360360808110156102d957600080fd5b508035906020810135906001600160a01b036040820135169060600135610e7d565b34801561030757600080fd5b506101a7600480360361010081101561031f57600080fd5b506001600160a01b0381358116916020810135916040820135169060ff606082013581169160808101359091169060a08101359060c08101359060e00135610fe3565b6101a7600480360361010081101561037957600080fd5b506001600160a01b0381358116916020810135916040820135169060ff606082013581169160808101359091169060a08101359060c08101359060e001356112e4565b3480156103c857600080fd5b50610408600480360360808110156103df57600080fd5b506001600160a01b038135169060ff6020820135811691604081013590911690606001356115f0565b60408051918252519081900360200190f35b34801561042657600080fd5b506101a7600480360361010081101561043e57600080fd5b506001600160a01b0381358116916020810135916040820135169060608101359060ff608082013581169160a08101359091169060c08101359060e001356116a9565b34801561048d57600080fd5b5061010d600480360360208110156104a457600080fd5b50356001600160a01b0316611834565b3480156104c057600080fd5b506101a7600480360360808110156104d757600080fd5b506001600160a01b038135811691602081013591604082013516906060013561184f565b34801561050757600080fd5b506101a7600480360361018081101561051f57600080fd5b506001600160a01b0381358116916020810135916040820135169060ff6060820135811691608081013582169160a08201359160c08101359160e0820135916101008101358216916101208201351690610140810135906101600135611998565b6101a7600480360360e081101561059657600080fd5b506001600160a01b038135169060208101359060408101359060ff606082013581169160808101359091169060a08101359060c00135611cd2565b6101a7600480360360608110156105e757600080fd5b506001600160a01b038135169060208101359060400135611e61565b34801561060f57600080fd5b506101a76004803603608081101561062657600080fd5b506001600160a01b0381358116916020810135916040820135169060600135611fed565b7f000000000000000000000000000000000000000000000000000000000000000081565b6001600160a01b03808a1660009081526001602052604090205416806106db576040805162461bcd60e51b815260206004820152600c60248201527f5377617020697320307830300000000000000000000000000000000000000000604482015290519081900360640190fd5b6001600160a01b03811660009081526002602090815260409182902080548351818402810184019094528084526060939283018282801561074557602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311610727575b5050505050905061078233308a848e60ff168151811061076157fe5b60200260200101516001600160a01b031661242c909392919063ffffffff16565b604080517f9169558600000000000000000000000000000000000000000000000000000000815260ff808d1660048301528b166024820152604481018a9052606481018990526084810188905290516000916001600160a01b0385169163916955869160a48082019260209290919082900301818787803b15801561080657600080fd5b505af115801561081a573d6000803e3d6000fd5b505050506040513d602081101561083057600080fd5b5051600054604080517fdd62ed3e0000000000000000000000000000000000000000000000000000000081523060048201526001600160a01b03928316602482015290519293508392918f169163dd62ed3e91604480820192602092909190829003018186803b1580156108a357600080fd5b505afa1580156108b7573d6000803e3d6000fd5b505050506040513d60208110156108cd57600080fd5b505110156108f1576000546108f1906001600160a01b038e81169116600019612255565b60008054906101000a90046001600160a01b03166001600160a01b03166336e712ed8f8f8f858b8b8b6040518863ffffffff1660e01b815260040180886001600160a01b03168152602001878152602001866001600160a01b031681526020018581526020018460ff168152602001838152602001828152602001975050505050505050600060405180830381600087803b15801561098f57600080fd5b505af11580156109a3573d6000803e3d6000fd5b505050505050505050505050505050505050565b6109cc6001600160a01b03861633308761242c565b600054604080517fdd62ed3e0000000000000000000000000000000000000000000000000000000081523060048201526001600160a01b0392831660248201529051869288169163dd62ed3e916044808301926020929190829003018186803b158015610a3857600080fd5b505afa158015610a4c573d6000803e3d6000fd5b505050506040513d6020811015610a6257600080fd5b50511015610a8657600054610a86906001600160a01b038781169116600019612255565b60008054604080517f36e712ed0000000000000000000000000000000000000000000000000000000081526001600160a01b038b81166004830152602482018b905289811660448301526064820189905260ff8816608483015260a4820187905260c48201869052915191909216926336e712ed9260e4808201939182900301818387803b158015610b1757600080fd5b505af1158015610b2b573d6000803e3d6000fd5b5050505050505050505050565b60026020528160005260406000208181548110610b5157fe5b6000918252602090912001546001600160a01b03169150829050565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316610be8576040805162461bcd60e51b815260206004820152600660248201527f5745544820300000000000000000000000000000000000000000000000000000604482015290519081900360640190fd5b600034118015610bf757508634145b610c48576040805162461bcd60e51b815260206004820152601360248201527f494e434f5252454354204d53472056414c554500000000000000000000000000604482015290519081900360640190fd5b6001600160a01b03808b166000908152600160205260409020541680610cb5576040805162461bcd60e51b815260206004820152600c60248201527f5377617020697320307830300000000000000000000000000000000000000000604482015290519081900360640190fd5b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663d0e30db0346040518263ffffffff1660e01b81526004016000604051808303818588803b158015610d1057600080fd5b505af1158015610d24573d6000803e3d6000fd5b50505050506000816001600160a01b031663916955868c8c8c8c8c6040518663ffffffff1660e01b8152600401808660ff1681526020018560ff16815260200184815260200183815260200182815260200195505050505050602060405180830381600087803b158015610d9757600080fd5b505af1158015610dab573d6000803e3d6000fd5b505050506040513d6020811015610dc157600080fd5b8101908080519060200190929190505050905060008054906101000a90046001600160a01b03166001600160a01b031663839ed90a8f8f8f858b8b8b8b6040518963ffffffff1660e01b815260040180896001600160a01b03168152602001888152602001876001600160a01b031681526020018681526020018560ff1681526020018460ff16815260200183815260200182815260200198505050505050505050600060405180830381600087803b15801561098f57600080fd5b610e926001600160a01b03831633308461242c565b600054604080517fdd62ed3e0000000000000000000000000000000000000000000000000000000081523060048201526001600160a01b0392831660248201529051839285169163dd62ed3e916044808301926020929190829003018186803b158015610efe57600080fd5b505afa158015610f12573d6000803e3d6000fd5b505050506040513d6020811015610f2857600080fd5b50511015610f4c57600054610f4c906001600160a01b038481169116600019612255565b60008054604080517f49b7cf8400000000000000000000000000000000000000000000000000000000815260048101889052602481018790526001600160a01b03868116604483015260648201869052915191909216926349b7cf84926084808201939182900301818387803b158015610fc557600080fd5b505af1158015610fd9573d6000803e3d6000fd5b5050505050505050565b6001600160a01b038087166000908152600160205260409020541680611050576040805162461bcd60e51b815260206004820152600c60248201527f5377617020697320307830300000000000000000000000000000000000000000604482015290519081900360640190fd5b6001600160a01b0381166000908152600260209081526040918290208054835181840281018401909452808452606093928301828280156110ba57602002820191906000526020600020905b81546001600160a01b0316815260019091019060200180831161109c575b505050505090506110d6333087848b60ff168151811061076157fe5b604080517f9169558600000000000000000000000000000000000000000000000000000000815260ff808a1660048301528816602482015260448101879052606481018690526084810185905290516000916001600160a01b0385169163916955869160a48082019260209290919082900301818787803b15801561115a57600080fd5b505af115801561116e573d6000803e3d6000fd5b505050506040513d602081101561118457600080fd5b5051600054604080517fdd62ed3e0000000000000000000000000000000000000000000000000000000081523060048201526001600160a01b03928316602482015290519293508392918c169163dd62ed3e91604480820192602092909190829003018186803b1580156111f757600080fd5b505afa15801561120b573d6000803e3d6000fd5b505050506040513d602081101561122157600080fd5b5051101561124557600054611245906001600160a01b038b81169116600019612255565b60008054604080517ff3f094a10000000000000000000000000000000000000000000000000000000081526001600160a01b038f81166004830152602482018f90528d81166044830152606482018690529151919092169263f3f094a1926084808201939182900301818387803b1580156112bf57600080fd5b505af11580156112d3573d6000803e3d6000fd5b505050505050505050505050505050565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031661135f576040805162461bcd60e51b815260206004820152600660248201527f5745544820300000000000000000000000000000000000000000000000000000604482015290519081900360640190fd5b60003411801561136e57508234145b6113bf576040805162461bcd60e51b815260206004820152601360248201527f494e434f5252454354204d53472056414c554500000000000000000000000000604482015290519081900360640190fd5b6001600160a01b03808716600090815260016020526040902054168061142c576040805162461bcd60e51b815260206004820152600c60248201527f5377617020697320307830300000000000000000000000000000000000000000604482015290519081900360640190fd5b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663d0e30db0346040518263ffffffff1660e01b81526004016000604051808303818588803b15801561148757600080fd5b505af115801561149b573d6000803e3d6000fd5b5050604080517f9169558600000000000000000000000000000000000000000000000000000000815260ff808c1660048301528a1660248201526044810189905260648101889052608481018790529051600094506001600160a01b03861693506391695586925060a480830192602092919082900301818787803b15801561152357600080fd5b505af1158015611537573d6000803e3d6000fd5b505050506040513d602081101561154d57600080fd5b505160008054604080517ff3f094a10000000000000000000000000000000000000000000000000000000081526001600160a01b038f81166004830152602482018f90528d8116604483015260648201869052915194955091169263f3f094a19260848084019391929182900301818387803b1580156115cc57600080fd5b505af11580156115e0573d6000803e3d6000fd5b5050505050505050505050505050565b6001600160a01b0380851660009081526001602090815260408083205481517fa95b089f00000000000000000000000000000000000000000000000000000000815260ff808a1660048301528816602482015260448101879052915193941692839263a95b089f9260648082019391829003018186803b15801561167357600080fd5b505afa158015611687573d6000803e3d6000fd5b505050506040513d602081101561169d57600080fd5b50519695505050505050565b6116be6001600160a01b03871633308861242c565b600054604080517fdd62ed3e0000000000000000000000000000000000000000000000000000000081523060048201526001600160a01b0392831660248201529051879289169163dd62ed3e916044808301926020929190829003018186803b15801561172a57600080fd5b505afa15801561173e573d6000803e3d6000fd5b505050506040513d602081101561175457600080fd5b5051101561177857600054611778906001600160a01b038881169116600019612255565b60008054604080517f839ed90a0000000000000000000000000000000000000000000000000000000081526001600160a01b038c81166004830152602482018c90528a81166044830152606482018a905260ff808a166084840152881660a483015260c4820187905260e482018690529151919092169263839ed90a92610104808201939182900301818387803b15801561181257600080fd5b505af1158015611826573d6000803e3d6000fd5b505050505050505050505050565b6001602052600090815260409020546001600160a01b031681565b6118646001600160a01b03831633308461242c565b600054604080517fdd62ed3e0000000000000000000000000000000000000000000000000000000081523060048201526001600160a01b0392831660248201529051839285169163dd62ed3e916044808301926020929190829003018186803b1580156118d057600080fd5b505afa1580156118e4573d6000803e3d6000fd5b505050506040513d60208110156118fa57600080fd5b5051101561191e5760005461191e906001600160a01b038481169116600019612255565b60008054604080517f90d250740000000000000000000000000000000000000000000000000000000081526001600160a01b03888116600483015260248201889052868116604483015260648201869052915191909216926390d25074926084808201939182900301818387803b158015610fc557600080fd5b6001600160a01b038a811660009081526001602052604090205416611a04576040805162461bcd60e51b815260206004820152600c60248201527f5377617020697320307830300000000000000000000000000000000000000000604482015290519081900360640190fd5b6001600160a01b03808b1660009081526001602090815260408083205490931682526002815290829020805483518184028101840190945280845260609392830182828015611a7c57602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311611a5e575b50505050509050611a9833308a848e60ff168151811061076157fe5b6000600160008d6001600160a01b03166001600160a01b0316815260200190815260200160002060009054906101000a90046001600160a01b03166001600160a01b031663916955868c8c8c8c8c6040518663ffffffff1660e01b8152600401808660ff1681526020018560ff16815260200184815260200183815260200182815260200195505050505050602060405180830381600087803b158015611b3e57600080fd5b505af1158015611b52573d6000803e3d6000fd5b505050506040513d6020811015611b6857600080fd5b5051600054604080517fdd62ed3e0000000000000000000000000000000000000000000000000000000081523060048201526001600160a01b03928316602482015290519293508392918f169163dd62ed3e91604480820192602092909190829003018186803b158015611bdb57600080fd5b505afa158015611bef573d6000803e3d6000fd5b505050506040513d6020811015611c0557600080fd5b50511015611c2957600054611c29906001600160a01b038e81169116600019612255565b60008054906101000a90046001600160a01b03166001600160a01b031663839ed90a8f8f8f858b8b8b8b6040518963ffffffff1660e01b815260040180896001600160a01b03168152602001888152602001876001600160a01b031681526020018681526020018560ff1681526020018460ff16815260200183815260200182815260200198505050505050505050600060405180830381600087803b15801561098f57600080fd5b600034118015611ce157508434145b611d32576040805162461bcd60e51b815260206004820152601360248201527f494e434f5252454354204d53472056414c554500000000000000000000000000604482015290519081900360640190fd5b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663d0e30db0346040518263ffffffff1660e01b81526004016000604051808303818588803b158015611d8d57600080fd5b505af1158015611da1573d6000803e3d6000fd5b505060008054604080517fa2a2af0b0000000000000000000000000000000000000000000000000000000081526001600160a01b038e81166004830152602482018e90527f000000000000000000000000000000000000000000000000000000000000000081166044830152606482018d905260ff808d1660848401528b1660a483015260c482018a905260e48201899052915191909216955063a2a2af0b94506101048083019450909182900301818387803b158015610b1757600080fd5b600034118015611e7057508034145b611ec1576040805162461bcd60e51b815260206004820152601360248201527f494e434f5252454354204d53472056414c554500000000000000000000000000604482015290519081900360640190fd5b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663d0e30db0346040518263ffffffff1660e01b81526004016000604051808303818588803b158015611f1c57600080fd5b505af1158015611f30573d6000803e3d6000fd5b505060008054604080517f90d250740000000000000000000000000000000000000000000000000000000081526001600160a01b038a81166004830152602482018a90527f0000000000000000000000000000000000000000000000000000000000000000811660448301526064820189905291519190921695506390d25074945060848083019450909182900301818387803b158015611fd057600080fd5b505af1158015611fe4573d6000803e3d6000fd5b50505050505050565b6120026001600160a01b03831633308461242c565b600054604080517fdd62ed3e0000000000000000000000000000000000000000000000000000000081523060048201526001600160a01b0392831660248201529051839285169163dd62ed3e916044808301926020929190829003018186803b15801561206e57600080fd5b505afa158015612082573d6000803e3d6000fd5b505050506040513d602081101561209857600080fd5b505110156120bc576000546120bc906001600160a01b038481169116600019612255565b60008054604080517ff3f094a10000000000000000000000000000000000000000000000000000000081526001600160a01b038881166004830152602482018890528681166044830152606482018690529151919092169263f3f094a1926084808201939182900301818387803b158015610fc557600080fd5b60006121cc82856001600160a01b031663dd62ed3e30876040518363ffffffff1660e01b815260040180836001600160a01b03168152602001826001600160a01b031681526020019250505060206040518083038186803b15801561219a57600080fd5b505afa1580156121ae573d6000803e3d6000fd5b505050506040513d60208110156121c457600080fd5b5051906123b4565b604080516001600160a01b038616602482015260448082018490528251808303909101815260649091019091526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f095ea7b30000000000000000000000000000000000000000000000000000000017905290915061224f9085906124b0565b50505050565b8015806122f45750604080517fdd62ed3e0000000000000000000000000000000000000000000000000000000081523060048201526001600160a01b03848116602483015291519185169163dd62ed3e91604480820192602092909190829003018186803b1580156122c657600080fd5b505afa1580156122da573d6000803e3d6000fd5b505050506040513d60208110156122f057600080fd5b5051155b61232f5760405162461bcd60e51b81526004018080602001828103825260368152602001806127d66036913960400191505060405180910390fd5b604080516001600160a01b038416602482015260448082018490528251808303909101815260649091019091526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f095ea7b3000000000000000000000000000000000000000000000000000000001790526123af9084906124b0565b505050565b60008282018381101561240e576040805162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b9392505050565b60606124248484600085612561565b949350505050565b604080516001600160a01b0380861660248301528416604482015260648082018490528251808303909101815260849091019091526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f23b872dd0000000000000000000000000000000000000000000000000000000017905261224f9085905b6060612505826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b03166124159092919063ffffffff16565b8051909150156123af5780806020019051602081101561252457600080fd5b50516123af5760405162461bcd60e51b815260040180806020018281038252602a8152602001806127ac602a913960400191505060405180910390fd5b6060824710156125a25760405162461bcd60e51b81526004018080602001828103825260268152602001806127866026913960400191505060405180910390fd5b6125ab856126db565b6125fc576040805162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000604482015290519081900360640190fd5b60006060866001600160a01b031685876040518082805190602001908083835b6020831061265957805182527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0909201916020918201910161261c565b6001836020036101000a03801982511681845116808217855250505050505090500191505060006040518083038185875af1925050503d80600081146126bb576040519150601f19603f3d011682016040523d82523d6000602084013e6126c0565b606091505b50915091506126d08282866126e1565b979650505050505050565b3b151590565b606083156126f057508161240e565b8251156127005782518084602001fd5b8160405162461bcd60e51b81526004018080602001828103825283818151815260200191508051906020019080838360005b8381101561274a578181015183820152602001612732565b50505050905090810190601f1680156127775780820380516001836020036101000a031916815260200191505b509250505060405180910390fdfe416464726573733a20696e73756666696369656e742062616c616e636520666f722063616c6c5361666545524332303a204552433230206f7065726174696f6e20646964206e6f7420737563636565645361666545524332303a20617070726f76652066726f6d206e6f6e2d7a65726f20746f206e6f6e2d7a65726f20616c6c6f77616e6365a264697066735822122043e7e9b36961500da4f30ed0906f6468518d581e0050085217f10a02e6afda8964736f6c634300060c0033", "devdoc": { "kind": "dev", "methods": { @@ -833,6 +903,17 @@ "to": "address on other chain to bridge assets to" } }, + "depositETHAndSwap(address,uint256,uint256,uint8,uint8,uint256,uint256)": { + "params": { + "amount": "Amount in native token decimals to transfer cross-chain pre-fees", + "chainId": "which chain to bridge assets onto", + "deadline": "latest timestamp to accept this transaction*", + "minDy": "the min amount the user would like to receive, or revert to only minting the SynERC20 token crosschain.", + "to": "address on other chain to bridge assets to", + "tokenIndexFrom": "the token the user wants to swap from", + "tokenIndexTo": "the token the user wants to swap to" + } + }, "redeem(address,uint256,address,uint256)": { "params": { "amount": "Amount in native token decimals to transfer cross-chain pre-fees*", @@ -863,6 +944,14 @@ "tokenIndexFrom": "the token the user wants to swap from", "tokenIndexTo": "the token the user wants to swap to" } + }, + "redeemv2(bytes32,uint256,address,uint256)": { + "params": { + "amount": "Amount in native token decimals to transfer cross-chain pre-fees*", + "chainId": "which chain to bridge assets onto", + "to": "address on other chain to bridge assets to", + "token": "ERC20 compatible token to redeem into the bridge" + } } }, "version": 1 @@ -879,6 +968,9 @@ "depositETH(address,uint256,uint256)": { "notice": "Wraps SynapseBridge deposit() function to make it compatible w/ ETH -> WETH conversions" }, + "depositETHAndSwap(address,uint256,uint256,uint8,uint8,uint256,uint256)": { + "notice": "Wraps SynapseBridge depositAndSwap() function to make it compatible w/ ETH -> WETH conversions" + }, "redeem(address,uint256,address,uint256)": { "notice": "wraps SynapseBridge redeem()" }, @@ -887,6 +979,9 @@ }, "redeemAndSwap(address,uint256,address,uint256,uint8,uint8,uint256,uint256)": { "notice": "Wraps redeemAndSwap on SynapseBridge.sol Relays to nodes that (typically) a wrapped synAsset ERC20 token has been burned and the underlying needs to be redeeemed on the native chain. This function indicates to the nodes that they should attempt to redeem the LP token for the underlying assets (E.g \"swap\" out of the LP token)" + }, + "redeemv2(bytes32,uint256,address,uint256)": { + "notice": "Wraps SynapseBridge redeemv2() function" } }, "version": 1 @@ -894,15 +989,15 @@ "storageLayout": { "storage": [ { - "astId": 28001, + "astId": 25496, "contract": "contracts/bridge/wrappers/L2BridgeZap.sol:L2BridgeZap", "label": "synapseBridge", "offset": 0, "slot": "0", - "type": "t_contract(ISynapseBridge)25574" + "type": "t_contract(ISynapseBridge)20970" }, { - "astId": 28007, + "astId": 25502, "contract": "contracts/bridge/wrappers/L2BridgeZap.sol:L2BridgeZap", "label": "swapMap", "offset": 0, @@ -910,7 +1005,7 @@ "type": "t_mapping(t_address,t_address)" }, { - "astId": 28012, + "astId": 25507, "contract": "contracts/bridge/wrappers/L2BridgeZap.sol:L2BridgeZap", "label": "swapTokensMap", "offset": 0, @@ -935,7 +1030,7 @@ "label": "contract IERC20", "numberOfBytes": "20" }, - "t_contract(ISynapseBridge)25574": { + "t_contract(ISynapseBridge)20970": { "encoding": "inplace", "label": "contract ISynapseBridge", "numberOfBytes": "20" diff --git a/deployments/avalanche/solcInputs/176148eace03d1f556691bfef59d8130.json b/deployments/avalanche/solcInputs/176148eace03d1f556691bfef59d8130.json new file mode 100644 index 000000000..81b979568 --- /dev/null +++ b/deployments/avalanche/solcInputs/176148eace03d1f556691bfef59d8130.json @@ -0,0 +1,37 @@ +{ + "language": "Solidity", + "sources": { + "contracts/bridge/wrappers/AvaxJewelSwap.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.6.12;\n\ncontract AvaxJewelSwap {\n function calculateSwap(\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx\n ) external view returns (uint256) {\n return 0;\n }\n\n function swap(\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx,\n uint256 minDy,\n uint256 deadline\n ) external returns (uint256) {\n revert(\"There is no swap\");\n }\n}\n" + } + }, + "settings": { + "optimizer": { + "enabled": true, + "runs": 10000 + }, + "outputSelection": { + "*": { + "*": [ + "abi", + "evm.bytecode", + "evm.deployedBytecode", + "evm.methodIdentifiers", + "metadata", + "devdoc", + "userdoc", + "storageLayout", + "evm.gasEstimates", + "devdoc", + "userdoc" + ], + "": [ + "ast" + ] + } + }, + "metadata": { + "useLiteralContent": true + } + } +} \ No newline at end of file diff --git a/deployments/avalanche/solcInputs/4d8253a299fa09b105ed2b87dd0189d4.json b/deployments/avalanche/solcInputs/4d8253a299fa09b105ed2b87dd0189d4.json new file mode 100644 index 000000000..98ef3113c --- /dev/null +++ b/deployments/avalanche/solcInputs/4d8253a299fa09b105ed2b87dd0189d4.json @@ -0,0 +1,304 @@ +{ + "language": "Solidity", + "sources": { + "contracts/amm/AaveSwap.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.6.12;\n\nimport \"./Swap.sol\";\n\n/**\n * @title AaveSwap - A StableSwap implementation in solidity, integrated with Aave.\n * @notice This contract is responsible for custody of closely pegged assets (eg. group of stablecoins)\n * and automatic market making system. Users become an LP (Liquidity Provider) by depositing their tokens\n * in desired ratios for an exchange of the pool token that represents their share of the pool.\n * Users can burn pool tokens and withdraw their share of token(s).\n *\n * Each time a swap between the pooled tokens happens, a set fee incurs which effectively gets\n * distributed to the LPs.\n *\n * In case of emergencies, admin can pause additional deposits, swaps, or single-asset withdraws - which\n * stops the ratio of the tokens in the pool from changing.\n * Users can always withdraw their tokens via multi-asset withdraws.\n *\n * @dev Most of the logic is stored as a library `SwapUtils` for the sake of reducing contract's\n * deployment size.\n */\n\ncontract AaveSwap is Swap {\n address internal AAVE_REWARDS;\n address internal AAVE_LENDING_POOL;\n address internal REWARD_TOKEN;\n address internal REWARD_RECEIVER;\n address[] internal AAVE_ASSETS;\n\n /**\n * @notice Initializes this Swap contract with the given parameters.\n * This will also clone a LPToken contract that represents users'\n * LP positions. The owner of LPToken will be this contract - which means\n * only this contract is allowed to mint/burn tokens.\n *\n * @param _pooledTokens an array of ERC20s this pool will accept\n * @param decimals the decimals to use for each pooled token,\n * eg 8 for WBTC. Cannot be larger than POOL_PRECISION_DECIMALS\n * @param lpTokenName the long-form name of the token to be deployed\n * @param lpTokenSymbol the short symbol for the token to be deployed\n * @param _a the amplification coefficient * n * (n - 1). See the\n * StableSwap paper for details\n * @param _fee default swap fee to be initialized with\n * @param _adminFee default adminFee to be initialized with\n * @param lpTokenTargetAddress the address of an existing LPToken contract to use as a target\n */\n function initialize(\n IERC20[] memory _pooledTokens,\n uint8[] memory decimals,\n string memory lpTokenName,\n string memory lpTokenSymbol,\n uint256 _a,\n uint256 _fee,\n uint256 _adminFee,\n address lpTokenTargetAddress\n ) public virtual override initializer {\n Swap.initialize(\n _pooledTokens,\n decimals,\n lpTokenName,\n lpTokenSymbol,\n _a,\n _fee,\n _adminFee,\n lpTokenTargetAddress\n );\n AAVE_REWARDS = 0x01D83Fe6A10D2f2B7AF17034343746188272cAc9;\n AAVE_LENDING_POOL = 0x4F01AeD16D97E3aB5ab2B501154DC9bb0F1A5A2C;\n REWARD_TOKEN = 0xB31f66AA3C1e785363F0875A1B74E27b85FD66c7;\n AAVE_ASSETS = [0x53f7c5869a859F0AeC3D334ee8B4Cf01E3492f21];\n REWARD_RECEIVER = msg.sender;\n }\n\n function setRewardReceiver(address _reward_receiver) external onlyOwner {\n REWARD_RECEIVER = _reward_receiver;\n }\n\n function claimAaveRewards() external {\n AAVE_REWARDS.call(\n abi.encodeWithSignature(\n \"claimRewards(address[],uint256,address)\",\n AAVE_ASSETS,\n type(uint256).max,\n REWARD_RECEIVER\n )\n );\n }\n}\n" + }, + "contracts/amm/Swap.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.6.12;\n\nimport \"@openzeppelin/contracts/math/SafeMath.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/SafeERC20.sol\";\nimport \"@openzeppelin/contracts/proxy/Clones.sol\";\nimport \"@openzeppelin/contracts-upgradeable/utils/ReentrancyGuardUpgradeable.sol\";\nimport \"./OwnerPausableUpgradeable.sol\";\nimport \"./SwapUtils.sol\";\nimport \"./AmplificationUtils.sol\";\n\n/**\n * @title Swap - A StableSwap implementation in solidity.\n * @notice This contract is responsible for custody of closely pegged assets (eg. group of stablecoins)\n * and automatic market making system. Users become an LP (Liquidity Provider) by depositing their tokens\n * in desired ratios for an exchange of the pool token that represents their share of the pool.\n * Users can burn pool tokens and withdraw their share of token(s).\n *\n * Each time a swap between the pooled tokens happens, a set fee incurs which effectively gets\n * distributed to the LPs.\n *\n * In case of emergencies, admin can pause additional deposits, swaps, or single-asset withdraws - which\n * stops the ratio of the tokens in the pool from changing.\n * Users can always withdraw their tokens via multi-asset withdraws.\n *\n * @dev Most of the logic is stored as a library `SwapUtils` for the sake of reducing contract's\n * deployment size.\n */\ncontract Swap is OwnerPausableUpgradeable, ReentrancyGuardUpgradeable {\n using SafeERC20 for IERC20;\n using SafeMath for uint256;\n using SwapUtils for SwapUtils.Swap;\n using AmplificationUtils for SwapUtils.Swap;\n\n // Struct storing data responsible for automatic market maker functionalities. In order to\n // access this data, this contract uses SwapUtils library. For more details, see SwapUtils.sol\n SwapUtils.Swap public swapStorage;\n\n // Maps token address to an index in the pool. Used to prevent duplicate tokens in the pool.\n // getTokenIndex function also relies on this mapping to retrieve token index.\n mapping(address => uint8) private tokenIndexes;\n\n /*** EVENTS ***/\n\n // events replicated from SwapUtils to make the ABI easier for dumb\n // clients\n event TokenSwap(\n address indexed buyer,\n uint256 tokensSold,\n uint256 tokensBought,\n uint128 soldId,\n uint128 boughtId\n );\n event AddLiquidity(\n address indexed provider,\n uint256[] tokenAmounts,\n uint256[] fees,\n uint256 invariant,\n uint256 lpTokenSupply\n );\n event RemoveLiquidity(\n address indexed provider,\n uint256[] tokenAmounts,\n uint256 lpTokenSupply\n );\n event RemoveLiquidityOne(\n address indexed provider,\n uint256 lpTokenAmount,\n uint256 lpTokenSupply,\n uint256 boughtId,\n uint256 tokensBought\n );\n event RemoveLiquidityImbalance(\n address indexed provider,\n uint256[] tokenAmounts,\n uint256[] fees,\n uint256 invariant,\n uint256 lpTokenSupply\n );\n event NewAdminFee(uint256 newAdminFee);\n event NewSwapFee(uint256 newSwapFee);\n event RampA(\n uint256 oldA,\n uint256 newA,\n uint256 initialTime,\n uint256 futureTime\n );\n event StopRampA(uint256 currentA, uint256 time);\n\n /**\n * @notice Initializes this Swap contract with the given parameters.\n * This will also clone a LPToken contract that represents users'\n * LP positions. The owner of LPToken will be this contract - which means\n * only this contract is allowed to mint/burn tokens.\n *\n * @param _pooledTokens an array of ERC20s this pool will accept\n * @param decimals the decimals to use for each pooled token,\n * eg 8 for WBTC. Cannot be larger than POOL_PRECISION_DECIMALS\n * @param lpTokenName the long-form name of the token to be deployed\n * @param lpTokenSymbol the short symbol for the token to be deployed\n * @param _a the amplification coefficient * n * (n - 1). See the\n * StableSwap paper for details\n * @param _fee default swap fee to be initialized with\n * @param _adminFee default adminFee to be initialized with\n * @param lpTokenTargetAddress the address of an existing LPToken contract to use as a target\n */\n function initialize(\n IERC20[] memory _pooledTokens,\n uint8[] memory decimals,\n string memory lpTokenName,\n string memory lpTokenSymbol,\n uint256 _a,\n uint256 _fee,\n uint256 _adminFee,\n address lpTokenTargetAddress\n ) public virtual initializer {\n __OwnerPausable_init();\n __ReentrancyGuard_init();\n // Check _pooledTokens and precisions parameter\n require(_pooledTokens.length > 1, \"_pooledTokens.length <= 1\");\n require(_pooledTokens.length <= 32, \"_pooledTokens.length > 32\");\n require(\n _pooledTokens.length == decimals.length,\n \"_pooledTokens decimals mismatch\"\n );\n\n uint256[] memory precisionMultipliers = new uint256[](decimals.length);\n\n for (uint8 i = 0; i < _pooledTokens.length; i++) {\n if (i > 0) {\n // Check if index is already used. Check if 0th element is a duplicate.\n require(\n tokenIndexes[address(_pooledTokens[i])] == 0 &&\n _pooledTokens[0] != _pooledTokens[i],\n \"Duplicate tokens\"\n );\n }\n require(\n address(_pooledTokens[i]) != address(0),\n \"The 0 address isn't an ERC-20\"\n );\n require(\n decimals[i] <= SwapUtils.POOL_PRECISION_DECIMALS,\n \"Token decimals exceeds max\"\n );\n precisionMultipliers[i] =\n 10 **\n uint256(SwapUtils.POOL_PRECISION_DECIMALS).sub(\n uint256(decimals[i])\n );\n tokenIndexes[address(_pooledTokens[i])] = i;\n }\n\n // Check _a, _fee, _adminFee parameters\n require(_a < AmplificationUtils.MAX_A, \"_a exceeds maximum\");\n require(_fee < SwapUtils.MAX_SWAP_FEE, \"_fee exceeds maximum\");\n require(\n _adminFee < SwapUtils.MAX_ADMIN_FEE,\n \"_adminFee exceeds maximum\"\n );\n\n // Clone and initialize a LPToken contract\n LPToken lpToken = LPToken(Clones.clone(lpTokenTargetAddress));\n require(\n lpToken.initialize(lpTokenName, lpTokenSymbol),\n \"could not init lpToken clone\"\n );\n\n // Initialize swapStorage struct\n swapStorage.lpToken = lpToken;\n swapStorage.pooledTokens = _pooledTokens;\n swapStorage.tokenPrecisionMultipliers = precisionMultipliers;\n swapStorage.balances = new uint256[](_pooledTokens.length);\n swapStorage.initialA = _a.mul(AmplificationUtils.A_PRECISION);\n swapStorage.futureA = _a.mul(AmplificationUtils.A_PRECISION);\n // swapStorage.initialATime = 0;\n // swapStorage.futureATime = 0;\n swapStorage.swapFee = _fee;\n swapStorage.adminFee = _adminFee;\n }\n\n /*** MODIFIERS ***/\n\n /**\n * @notice Modifier to check deadline against current timestamp\n * @param deadline latest timestamp to accept this transaction\n */\n modifier deadlineCheck(uint256 deadline) {\n require(block.timestamp <= deadline, \"Deadline not met\");\n _;\n }\n\n /*** VIEW FUNCTIONS ***/\n\n /**\n * @notice Return A, the amplification coefficient * n * (n - 1)\n * @dev See the StableSwap paper for details\n * @return A parameter\n */\n function getA() external view virtual returns (uint256) {\n return swapStorage.getA();\n }\n\n /**\n * @notice Return A in its raw precision form\n * @dev See the StableSwap paper for details\n * @return A parameter in its raw precision form\n */\n function getAPrecise() external view virtual returns (uint256) {\n return swapStorage.getAPrecise();\n }\n\n /**\n * @notice Return address of the pooled token at given index. Reverts if tokenIndex is out of range.\n * @param index the index of the token\n * @return address of the token at given index\n */\n function getToken(uint8 index) public view virtual returns (IERC20) {\n require(index < swapStorage.pooledTokens.length, \"Out of range\");\n return swapStorage.pooledTokens[index];\n }\n\n /**\n * @notice Return the index of the given token address. Reverts if no matching\n * token is found.\n * @param tokenAddress address of the token\n * @return the index of the given token address\n */\n function getTokenIndex(address tokenAddress)\n public\n view\n virtual\n returns (uint8)\n {\n uint8 index = tokenIndexes[tokenAddress];\n require(\n address(getToken(index)) == tokenAddress,\n \"Token does not exist\"\n );\n return index;\n }\n\n /**\n * @notice Return current balance of the pooled token at given index\n * @param index the index of the token\n * @return current balance of the pooled token at given index with token's native precision\n */\n function getTokenBalance(uint8 index)\n external\n view\n virtual\n returns (uint256)\n {\n require(index < swapStorage.pooledTokens.length, \"Index out of range\");\n return swapStorage.balances[index];\n }\n\n /**\n * @notice Get the virtual price, to help calculate profit\n * @return the virtual price, scaled to the POOL_PRECISION_DECIMALS\n */\n function getVirtualPrice() external view virtual returns (uint256) {\n return swapStorage.getVirtualPrice();\n }\n\n /**\n * @notice Calculate amount of tokens you receive on swap\n * @param tokenIndexFrom the token the user wants to sell\n * @param tokenIndexTo the token the user wants to buy\n * @param dx the amount of tokens the user wants to sell. If the token charges\n * a fee on transfers, use the amount that gets transferred after the fee.\n * @return amount of tokens the user will receive\n */\n function calculateSwap(\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx\n ) external view virtual returns (uint256) {\n return swapStorage.calculateSwap(tokenIndexFrom, tokenIndexTo, dx);\n }\n\n /**\n * @notice A simple method to calculate prices from deposits or\n * withdrawals, excluding fees but including slippage. This is\n * helpful as an input into the various \"min\" parameters on calls\n * to fight front-running\n *\n * @dev This shouldn't be used outside frontends for user estimates.\n *\n * @param amounts an array of token amounts to deposit or withdrawal,\n * corresponding to pooledTokens. The amount should be in each\n * pooled token's native precision. If a token charges a fee on transfers,\n * use the amount that gets transferred after the fee.\n * @param deposit whether this is a deposit or a withdrawal\n * @return token amount the user will receive\n */\n function calculateTokenAmount(uint256[] calldata amounts, bool deposit)\n external\n view\n virtual\n returns (uint256)\n {\n return swapStorage.calculateTokenAmount(amounts, deposit);\n }\n\n /**\n * @notice A simple method to calculate amount of each underlying\n * tokens that is returned upon burning given amount of LP tokens\n * @param amount the amount of LP tokens that would be burned on withdrawal\n * @return array of token balances that the user will receive\n */\n function calculateRemoveLiquidity(uint256 amount)\n external\n view\n virtual\n returns (uint256[] memory)\n {\n return swapStorage.calculateRemoveLiquidity(amount);\n }\n\n /**\n * @notice Calculate the amount of underlying token available to withdraw\n * when withdrawing via only single token\n * @param tokenAmount the amount of LP token to burn\n * @param tokenIndex index of which token will be withdrawn\n * @return availableTokenAmount calculated amount of underlying token\n * available to withdraw\n */\n function calculateRemoveLiquidityOneToken(\n uint256 tokenAmount,\n uint8 tokenIndex\n ) external view virtual returns (uint256 availableTokenAmount) {\n return swapStorage.calculateWithdrawOneToken(tokenAmount, tokenIndex);\n }\n\n /**\n * @notice This function reads the accumulated amount of admin fees of the token with given index\n * @param index Index of the pooled token\n * @return admin's token balance in the token's precision\n */\n function getAdminBalance(uint256 index)\n external\n view\n virtual\n returns (uint256)\n {\n return swapStorage.getAdminBalance(index);\n }\n\n /*** STATE MODIFYING FUNCTIONS ***/\n\n /**\n * @notice Swap two tokens using this pool\n * @param tokenIndexFrom the token the user wants to swap from\n * @param tokenIndexTo the token the user wants to swap to\n * @param dx the amount of tokens the user wants to swap from\n * @param minDy the min amount the user would like to receive, or revert.\n * @param deadline latest timestamp to accept this transaction\n */\n function swap(\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx,\n uint256 minDy,\n uint256 deadline\n )\n external\n virtual\n nonReentrant\n whenNotPaused\n deadlineCheck(deadline)\n returns (uint256)\n {\n return swapStorage.swap(tokenIndexFrom, tokenIndexTo, dx, minDy);\n }\n\n /**\n * @notice Add liquidity to the pool with the given amounts of tokens\n * @param amounts the amounts of each token to add, in their native precision\n * @param minToMint the minimum LP tokens adding this amount of liquidity\n * should mint, otherwise revert. Handy for front-running mitigation\n * @param deadline latest timestamp to accept this transaction\n * @return amount of LP token user minted and received\n */\n function addLiquidity(\n uint256[] calldata amounts,\n uint256 minToMint,\n uint256 deadline\n )\n external\n virtual\n nonReentrant\n whenNotPaused\n deadlineCheck(deadline)\n returns (uint256)\n {\n return swapStorage.addLiquidity(amounts, minToMint);\n }\n\n /**\n * @notice Burn LP tokens to remove liquidity from the pool. Withdraw fee that decays linearly\n * over period of 4 weeks since last deposit will apply.\n * @dev Liquidity can always be removed, even when the pool is paused.\n * @param amount the amount of LP tokens to burn\n * @param minAmounts the minimum amounts of each token in the pool\n * acceptable for this burn. Useful as a front-running mitigation\n * @param deadline latest timestamp to accept this transaction\n * @return amounts of tokens user received\n */\n function removeLiquidity(\n uint256 amount,\n uint256[] calldata minAmounts,\n uint256 deadline\n )\n external\n virtual\n nonReentrant\n deadlineCheck(deadline)\n returns (uint256[] memory)\n {\n return swapStorage.removeLiquidity(amount, minAmounts);\n }\n\n /**\n * @notice Remove liquidity from the pool all in one token. Withdraw fee that decays linearly\n * over period of 4 weeks since last deposit will apply.\n * @param tokenAmount the amount of the token you want to receive\n * @param tokenIndex the index of the token you want to receive\n * @param minAmount the minimum amount to withdraw, otherwise revert\n * @param deadline latest timestamp to accept this transaction\n * @return amount of chosen token user received\n */\n function removeLiquidityOneToken(\n uint256 tokenAmount,\n uint8 tokenIndex,\n uint256 minAmount,\n uint256 deadline\n )\n external\n virtual\n nonReentrant\n whenNotPaused\n deadlineCheck(deadline)\n returns (uint256)\n {\n return\n swapStorage.removeLiquidityOneToken(\n tokenAmount,\n tokenIndex,\n minAmount\n );\n }\n\n /**\n * @notice Remove liquidity from the pool, weighted differently than the\n * pool's current balances. Withdraw fee that decays linearly\n * over period of 4 weeks since last deposit will apply.\n * @param amounts how much of each token to withdraw\n * @param maxBurnAmount the max LP token provider is willing to pay to\n * remove liquidity. Useful as a front-running mitigation.\n * @param deadline latest timestamp to accept this transaction\n * @return amount of LP tokens burned\n */\n function removeLiquidityImbalance(\n uint256[] calldata amounts,\n uint256 maxBurnAmount,\n uint256 deadline\n )\n external\n virtual\n nonReentrant\n whenNotPaused\n deadlineCheck(deadline)\n returns (uint256)\n {\n return swapStorage.removeLiquidityImbalance(amounts, maxBurnAmount);\n }\n\n /*** ADMIN FUNCTIONS ***/\n\n /**\n * @notice Withdraw all admin fees to the contract owner\n */\n function withdrawAdminFees() external onlyOwner {\n swapStorage.withdrawAdminFees(owner());\n }\n\n /**\n * @notice Update the admin fee. Admin fee takes portion of the swap fee.\n * @param newAdminFee new admin fee to be applied on future transactions\n */\n function setAdminFee(uint256 newAdminFee) external onlyOwner {\n swapStorage.setAdminFee(newAdminFee);\n }\n\n /**\n * @notice Update the swap fee to be applied on swaps\n * @param newSwapFee new swap fee to be applied on future transactions\n */\n function setSwapFee(uint256 newSwapFee) external onlyOwner {\n swapStorage.setSwapFee(newSwapFee);\n }\n\n /**\n * @notice Start ramping up or down A parameter towards given futureA and futureTime\n * Checks if the change is too rapid, and commits the new A value only when it falls under\n * the limit range.\n * @param futureA the new A to ramp towards\n * @param futureTime timestamp when the new A should be reached\n */\n function rampA(uint256 futureA, uint256 futureTime) external onlyOwner {\n swapStorage.rampA(futureA, futureTime);\n }\n\n /**\n * @notice Stop ramping A immediately. Reverts if ramp A is already stopped.\n */\n function stopRampA() external onlyOwner {\n swapStorage.stopRampA();\n }\n}\n" + }, + "@openzeppelin/contracts/math/SafeMath.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <0.8.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" + }, + "@openzeppelin/contracts/token/ERC20/SafeERC20.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <0.8.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" + }, + "@openzeppelin/contracts/proxy/Clones.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <0.8.0;\n\n/**\n * @dev https://eips.ethereum.org/EIPS/eip-1167[EIP 1167] is a standard for\n * deploying minimal proxy contracts, also known as \"clones\".\n *\n * > To simply and cheaply clone contract functionality in an immutable way, this standard specifies\n * > a minimal bytecode implementation that delegates all calls to a known, fixed address.\n *\n * The library includes functions to deploy a proxy using either `create` (traditional deployment) or `create2`\n * (salted deterministic deployment). It also includes functions to predict the addresses of clones deployed using the\n * deterministic method.\n *\n * _Available since v3.4._\n */\nlibrary Clones {\n /**\n * @dev Deploys and returns the address of a clone that mimics the behaviour of `master`.\n *\n * This function uses the create opcode, which should never revert.\n */\n function clone(address master) internal returns (address instance) {\n // solhint-disable-next-line no-inline-assembly\n assembly {\n let ptr := mload(0x40)\n mstore(ptr, 0x3d602d80600a3d3981f3363d3d373d3d3d363d73000000000000000000000000)\n mstore(add(ptr, 0x14), shl(0x60, master))\n mstore(add(ptr, 0x28), 0x5af43d82803e903d91602b57fd5bf30000000000000000000000000000000000)\n instance := create(0, ptr, 0x37)\n }\n require(instance != address(0), \"ERC1167: create failed\");\n }\n\n /**\n * @dev Deploys and returns the address of a clone that mimics the behaviour of `master`.\n *\n * This function uses the create2 opcode and a `salt` to deterministically deploy\n * the clone. Using the same `master` and `salt` multiple time will revert, since\n * the clones cannot be deployed twice at the same address.\n */\n function cloneDeterministic(address master, bytes32 salt) internal returns (address instance) {\n // solhint-disable-next-line no-inline-assembly\n assembly {\n let ptr := mload(0x40)\n mstore(ptr, 0x3d602d80600a3d3981f3363d3d373d3d3d363d73000000000000000000000000)\n mstore(add(ptr, 0x14), shl(0x60, master))\n mstore(add(ptr, 0x28), 0x5af43d82803e903d91602b57fd5bf30000000000000000000000000000000000)\n instance := create2(0, ptr, 0x37, salt)\n }\n require(instance != address(0), \"ERC1167: create2 failed\");\n }\n\n /**\n * @dev Computes the address of a clone deployed using {Clones-cloneDeterministic}.\n */\n function predictDeterministicAddress(address master, bytes32 salt, address deployer) internal pure returns (address predicted) {\n // solhint-disable-next-line no-inline-assembly\n assembly {\n let ptr := mload(0x40)\n mstore(ptr, 0x3d602d80600a3d3981f3363d3d373d3d3d363d73000000000000000000000000)\n mstore(add(ptr, 0x14), shl(0x60, master))\n mstore(add(ptr, 0x28), 0x5af43d82803e903d91602b57fd5bf3ff00000000000000000000000000000000)\n mstore(add(ptr, 0x38), shl(0x60, deployer))\n mstore(add(ptr, 0x4c), salt)\n mstore(add(ptr, 0x6c), keccak256(ptr, 0x37))\n predicted := keccak256(add(ptr, 0x37), 0x55)\n }\n }\n\n /**\n * @dev Computes the address of a clone deployed using {Clones-cloneDeterministic}.\n */\n function predictDeterministicAddress(address master, bytes32 salt) internal view returns (address predicted) {\n return predictDeterministicAddress(master, salt, address(this));\n }\n}\n" + }, + "@openzeppelin/contracts-upgradeable/utils/ReentrancyGuardUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <0.8.0;\nimport \"../proxy/Initializable.sol\";\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 ReentrancyGuardUpgradeable is Initializable {\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 function __ReentrancyGuard_init() internal initializer {\n __ReentrancyGuard_init_unchained();\n }\n\n function __ReentrancyGuard_init_unchained() internal initializer {\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 uint256[49] private __gap;\n}\n" + }, + "contracts/amm/OwnerPausableUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.6.12;\n\nimport \"@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol\";\nimport \"@openzeppelin/contracts-upgradeable/utils/PausableUpgradeable.sol\";\n\n/**\n * @title OwnerPausable\n * @notice An ownable contract allows the owner to pause and unpause the\n * contract without a delay.\n * @dev Only methods using the provided modifiers will be paused.\n */\nabstract contract OwnerPausableUpgradeable is\n OwnableUpgradeable,\n PausableUpgradeable\n{\n function __OwnerPausable_init() internal initializer {\n __Context_init_unchained();\n __Ownable_init_unchained();\n __Pausable_init_unchained();\n }\n\n /**\n * @notice Pause the contract. Revert if already paused.\n */\n function pause() external onlyOwner {\n PausableUpgradeable._pause();\n }\n\n /**\n * @notice Unpause the contract. Revert if already unpaused.\n */\n function unpause() external onlyOwner {\n PausableUpgradeable._unpause();\n }\n}\n" + }, + "contracts/amm/SwapUtils.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.6.12;\n\nimport \"@openzeppelin/contracts/math/SafeMath.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/SafeERC20.sol\";\nimport \"./AmplificationUtils.sol\";\nimport \"./LPToken.sol\";\nimport \"./MathUtils.sol\";\n\n/**\n * @title SwapUtils library\n * @notice A library to be used within Swap.sol. Contains functions responsible for custody and AMM functionalities.\n * @dev Contracts relying on this library must initialize SwapUtils.Swap struct then use this library\n * for SwapUtils.Swap struct. Note that this library contains both functions called by users and admins.\n * Admin functions should be protected within contracts using this library.\n */\nlibrary SwapUtils {\n using SafeERC20 for IERC20;\n using SafeMath for uint256;\n using MathUtils for uint256;\n\n /*** EVENTS ***/\n\n event TokenSwap(\n address indexed buyer,\n uint256 tokensSold,\n uint256 tokensBought,\n uint128 soldId,\n uint128 boughtId\n );\n event AddLiquidity(\n address indexed provider,\n uint256[] tokenAmounts,\n uint256[] fees,\n uint256 invariant,\n uint256 lpTokenSupply\n );\n event RemoveLiquidity(\n address indexed provider,\n uint256[] tokenAmounts,\n uint256 lpTokenSupply\n );\n event RemoveLiquidityOne(\n address indexed provider,\n uint256 lpTokenAmount,\n uint256 lpTokenSupply,\n uint256 boughtId,\n uint256 tokensBought\n );\n event RemoveLiquidityImbalance(\n address indexed provider,\n uint256[] tokenAmounts,\n uint256[] fees,\n uint256 invariant,\n uint256 lpTokenSupply\n );\n event NewAdminFee(uint256 newAdminFee);\n event NewSwapFee(uint256 newSwapFee);\n\n struct Swap {\n // variables around the ramp management of A,\n // the amplification coefficient * n * (n - 1)\n // see https://www.curve.fi/stableswap-paper.pdf for details\n uint256 initialA;\n uint256 futureA;\n uint256 initialATime;\n uint256 futureATime;\n // fee calculation\n uint256 swapFee;\n uint256 adminFee;\n LPToken lpToken;\n // contract references for all tokens being pooled\n IERC20[] pooledTokens;\n // multipliers for each pooled token's precision to get to POOL_PRECISION_DECIMALS\n // for example, TBTC has 18 decimals, so the multiplier should be 1. WBTC\n // has 8, so the multiplier should be 10 ** 18 / 10 ** 8 => 10 ** 10\n uint256[] tokenPrecisionMultipliers;\n // the pool balance of each token, in the token's precision\n // the contract's actual token balance might differ\n uint256[] balances;\n }\n\n // Struct storing variables used in calculations in the\n // calculateWithdrawOneTokenDY function to avoid stack too deep errors\n struct CalculateWithdrawOneTokenDYInfo {\n uint256 d0;\n uint256 d1;\n uint256 newY;\n uint256 feePerToken;\n uint256 preciseA;\n }\n\n // Struct storing variables used in calculations in the\n // {add,remove}Liquidity functions to avoid stack too deep errors\n struct ManageLiquidityInfo {\n uint256 d0;\n uint256 d1;\n uint256 d2;\n uint256 preciseA;\n LPToken lpToken;\n uint256 totalSupply;\n uint256[] balances;\n uint256[] multipliers;\n }\n\n // the precision all pools tokens will be converted to\n uint8 public constant POOL_PRECISION_DECIMALS = 18;\n\n // the denominator used to calculate admin and LP fees. For example, an\n // LP fee might be something like tradeAmount.mul(fee).div(FEE_DENOMINATOR)\n uint256 private constant FEE_DENOMINATOR = 10**10;\n\n // Max swap fee is 1% or 100bps of each swap\n uint256 public constant MAX_SWAP_FEE = 10**8;\n\n // Max adminFee is 100% of the swapFee\n // adminFee does not add additional fee on top of swapFee\n // Instead it takes a certain % of the swapFee. Therefore it has no impact on the\n // users but only on the earnings of LPs\n uint256 public constant MAX_ADMIN_FEE = 10**10;\n\n // Constant value used as max loop limit\n uint256 private constant MAX_LOOP_LIMIT = 256;\n\n /*** VIEW & PURE FUNCTIONS ***/\n\n function _getAPrecise(Swap storage self) internal view returns (uint256) {\n return AmplificationUtils._getAPrecise(self);\n }\n\n /**\n * @notice Calculate the dy, the amount of selected token that user receives and\n * the fee of withdrawing in one token\n * @param tokenAmount the amount to withdraw in the pool's precision\n * @param tokenIndex which token will be withdrawn\n * @param self Swap struct to read from\n * @return the amount of token user will receive\n */\n function calculateWithdrawOneToken(\n Swap storage self,\n uint256 tokenAmount,\n uint8 tokenIndex\n ) external view returns (uint256) {\n (uint256 availableTokenAmount, ) = _calculateWithdrawOneToken(\n self,\n tokenAmount,\n tokenIndex,\n self.lpToken.totalSupply()\n );\n return availableTokenAmount;\n }\n\n function _calculateWithdrawOneToken(\n Swap storage self,\n uint256 tokenAmount,\n uint8 tokenIndex,\n uint256 totalSupply\n ) internal view returns (uint256, uint256) {\n uint256 dy;\n uint256 newY;\n uint256 currentY;\n\n (dy, newY, currentY) = calculateWithdrawOneTokenDY(\n self,\n tokenIndex,\n tokenAmount,\n totalSupply\n );\n\n // dy_0 (without fees)\n // dy, dy_0 - dy\n\n uint256 dySwapFee = currentY\n .sub(newY)\n .div(self.tokenPrecisionMultipliers[tokenIndex])\n .sub(dy);\n\n return (dy, dySwapFee);\n }\n\n /**\n * @notice Calculate the dy of withdrawing in one token\n * @param self Swap struct to read from\n * @param tokenIndex which token will be withdrawn\n * @param tokenAmount the amount to withdraw in the pools precision\n * @return the d and the new y after withdrawing one token\n */\n function calculateWithdrawOneTokenDY(\n Swap storage self,\n uint8 tokenIndex,\n uint256 tokenAmount,\n uint256 totalSupply\n )\n internal\n view\n returns (\n uint256,\n uint256,\n uint256\n )\n {\n // Get the current D, then solve the stableswap invariant\n // y_i for D - tokenAmount\n uint256[] memory xp = _xp(self);\n\n require(tokenIndex < xp.length, \"Token index out of range\");\n\n\n CalculateWithdrawOneTokenDYInfo memory v\n = CalculateWithdrawOneTokenDYInfo(0, 0, 0, 0, 0);\n v.preciseA = _getAPrecise(self);\n v.d0 = getD(xp, v.preciseA);\n v.d1 = v.d0.sub(tokenAmount.mul(v.d0).div(totalSupply));\n\n require(tokenAmount <= xp[tokenIndex], \"Withdraw exceeds available\");\n\n v.newY = getYD(v.preciseA, tokenIndex, xp, v.d1);\n\n uint256[] memory xpReduced = new uint256[](xp.length);\n\n v.feePerToken = _feePerToken(self.swapFee, xp.length);\n for (uint256 i = 0; i < xp.length; i++) {\n uint256 xpi = xp[i];\n // if i == tokenIndex, dxExpected = xp[i] * d1 / d0 - newY\n // else dxExpected = xp[i] - (xp[i] * d1 / d0)\n // xpReduced[i] -= dxExpected * fee / FEE_DENOMINATOR\n xpReduced[i] = xpi.sub(\n (\n (i == tokenIndex)\n ? xpi.mul(v.d1).div(v.d0).sub(v.newY)\n : xpi.sub(xpi.mul(v.d1).div(v.d0))\n )\n .mul(v.feePerToken)\n .div(FEE_DENOMINATOR)\n );\n }\n\n uint256 dy = xpReduced[tokenIndex].sub(\n getYD(v.preciseA, tokenIndex, xpReduced, v.d1)\n );\n dy = dy.sub(1).div(self.tokenPrecisionMultipliers[tokenIndex]);\n\n return (dy, v.newY, xp[tokenIndex]);\n }\n\n /**\n * @notice Calculate the price of a token in the pool with given\n * precision-adjusted balances and a particular D.\n *\n * @dev This is accomplished via solving the invariant iteratively.\n * See the StableSwap paper and Curve.fi implementation for further details.\n *\n * x_1**2 + x1 * (sum' - (A*n**n - 1) * D / (A * n**n)) = D ** (n + 1) / (n ** (2 * n) * prod' * A)\n * x_1**2 + b*x_1 = c\n * x_1 = (x_1**2 + c) / (2*x_1 + b)\n *\n * @param a the amplification coefficient * n * (n - 1). See the StableSwap paper for details.\n * @param tokenIndex Index of token we are calculating for.\n * @param xp a precision-adjusted set of pool balances. Array should be\n * the same cardinality as the pool.\n * @param d the stableswap invariant\n * @return the price of the token, in the same precision as in xp\n */\n function getYD(\n uint256 a,\n uint8 tokenIndex,\n uint256[] memory xp,\n uint256 d\n ) internal pure returns (uint256) {\n uint256 numTokens = xp.length;\n require(tokenIndex < numTokens, \"Token not found\");\n\n uint256 c = d;\n uint256 s;\n uint256 nA = a.mul(numTokens);\n\n for (uint256 i = 0; i < numTokens; i++) {\n if (i != tokenIndex) {\n s = s.add(xp[i]);\n c = c.mul(d).div(xp[i].mul(numTokens));\n // If we were to protect the division loss we would have to keep the denominator separate\n // and divide at the end. However this leads to overflow with large numTokens or/and D.\n // c = c * D * D * D * ... overflow!\n }\n }\n c = c.mul(d).mul(AmplificationUtils.A_PRECISION).div(nA.mul(numTokens));\n\n uint256 b = s.add(d.mul(AmplificationUtils.A_PRECISION).div(nA));\n uint256 yPrev;\n uint256 y = d;\n for (uint256 i = 0; i < MAX_LOOP_LIMIT; i++) {\n yPrev = y;\n y = y.mul(y).add(c).div(y.mul(2).add(b).sub(d));\n if (y.within1(yPrev)) {\n return y;\n }\n }\n revert(\"Approximation did not converge\");\n }\n\n /**\n * @notice Get D, the StableSwap invariant, based on a set of balances and a particular A.\n * @param xp a precision-adjusted set of pool balances. Array should be the same cardinality\n * as the pool.\n * @param a the amplification coefficient * n * (n - 1) in A_PRECISION.\n * See the StableSwap paper for details\n * @return the invariant, at the precision of the pool\n */\n function getD(uint256[] memory xp, uint256 a)\n internal\n pure\n returns (uint256)\n {\n uint256 numTokens = xp.length;\n uint256 s;\n for (uint256 i = 0; i < numTokens; i++) {\n s = s.add(xp[i]);\n }\n if (s == 0) {\n return 0;\n }\n\n uint256 prevD;\n uint256 d = s;\n uint256 nA = a.mul(numTokens);\n\n for (uint256 i = 0; i < MAX_LOOP_LIMIT; i++) {\n uint256 dP = d;\n for (uint256 j = 0; j < numTokens; j++) {\n dP = dP.mul(d).div(xp[j].mul(numTokens));\n // If we were to protect the division loss we would have to keep the denominator separate\n // and divide at the end. However this leads to overflow with large numTokens or/and D.\n // dP = dP * D * D * D * ... overflow!\n }\n prevD = d;\n d = nA\n .mul(s)\n .div(AmplificationUtils.A_PRECISION)\n .add(dP.mul(numTokens))\n .mul(d)\n .div(\n nA\n .sub(AmplificationUtils.A_PRECISION)\n .mul(d)\n .div(AmplificationUtils.A_PRECISION)\n .add(numTokens.add(1).mul(dP))\n );\n if (d.within1(prevD)) {\n return d;\n }\n }\n\n // Convergence should occur in 4 loops or less. If this is reached, there may be something wrong\n // with the pool. If this were to occur repeatedly, LPs should withdraw via `removeLiquidity()`\n // function which does not rely on D.\n revert(\"D does not converge\");\n }\n\n /**\n * @notice Given a set of balances and precision multipliers, return the\n * precision-adjusted balances.\n *\n * @param balances an array of token balances, in their native precisions.\n * These should generally correspond with pooled tokens.\n *\n * @param precisionMultipliers an array of multipliers, corresponding to\n * the amounts in the balances array. When multiplied together they\n * should yield amounts at the pool's precision.\n *\n * @return an array of amounts \"scaled\" to the pool's precision\n */\n function _xp(\n uint256[] memory balances,\n uint256[] memory precisionMultipliers\n ) internal pure returns (uint256[] memory) {\n uint256 numTokens = balances.length;\n require(\n numTokens == precisionMultipliers.length,\n \"Balances must match multipliers\"\n );\n uint256[] memory xp = new uint256[](numTokens);\n for (uint256 i = 0; i < numTokens; i++) {\n xp[i] = balances[i].mul(precisionMultipliers[i]);\n }\n return xp;\n }\n\n /**\n * @notice Return the precision-adjusted balances of all tokens in the pool\n * @param self Swap struct to read from\n * @return the pool balances \"scaled\" to the pool's precision, allowing\n * them to be more easily compared.\n */\n function _xp(Swap storage self) internal view returns (uint256[] memory) {\n return _xp(self.balances, self.tokenPrecisionMultipliers);\n }\n\n /**\n * @notice Get the virtual price, to help calculate profit\n * @param self Swap struct to read from\n * @return the virtual price, scaled to precision of POOL_PRECISION_DECIMALS\n */\n function getVirtualPrice(Swap storage self)\n external\n view\n returns (uint256)\n {\n uint256 d = getD(_xp(self), _getAPrecise(self));\n LPToken lpToken = self.lpToken;\n uint256 supply = lpToken.totalSupply();\n if (supply > 0) {\n return d.mul(10**uint256(POOL_PRECISION_DECIMALS)).div(supply);\n }\n return 0;\n }\n\n /**\n * @notice Calculate the new balances of the tokens given the indexes of the token\n * that is swapped from (FROM) and the token that is swapped to (TO).\n * This function is used as a helper function to calculate how much TO token\n * the user should receive on swap.\n *\n * @param preciseA precise form of amplification coefficient\n * @param tokenIndexFrom index of FROM token\n * @param tokenIndexTo index of TO token\n * @param x the new total amount of FROM token\n * @param xp balances of the tokens in the pool\n * @return the amount of TO token that should remain in the pool\n */\n function getY(\n uint256 preciseA,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 x,\n uint256[] memory xp\n ) internal pure returns (uint256) {\n uint256 numTokens = xp.length;\n require(\n tokenIndexFrom != tokenIndexTo,\n \"Can't compare token to itself\"\n );\n require(\n tokenIndexFrom < numTokens && tokenIndexTo < numTokens,\n \"Tokens must be in pool\"\n );\n\n uint256 d = getD(xp, preciseA);\n uint256 c = d;\n uint256 s;\n uint256 nA = numTokens.mul(preciseA);\n\n uint256 _x;\n for (uint256 i = 0; i < numTokens; i++) {\n if (i == tokenIndexFrom) {\n _x = x;\n } else if (i != tokenIndexTo) {\n _x = xp[i];\n } else {\n continue;\n }\n s = s.add(_x);\n c = c.mul(d).div(_x.mul(numTokens));\n // If we were to protect the division loss we would have to keep the denominator separate\n // and divide at the end. However this leads to overflow with large numTokens or/and D.\n // c = c * D * D * D * ... overflow!\n }\n c = c.mul(d).mul(AmplificationUtils.A_PRECISION).div(nA.mul(numTokens));\n uint256 b = s.add(d.mul(AmplificationUtils.A_PRECISION).div(nA));\n uint256 yPrev;\n uint256 y = d;\n\n // iterative approximation\n for (uint256 i = 0; i < MAX_LOOP_LIMIT; i++) {\n yPrev = y;\n y = y.mul(y).add(c).div(y.mul(2).add(b).sub(d));\n if (y.within1(yPrev)) {\n return y;\n }\n }\n revert(\"Approximation did not converge\");\n }\n\n /**\n * @notice Externally calculates a swap between two tokens.\n * @param self Swap struct to read from\n * @param tokenIndexFrom the token to sell\n * @param tokenIndexTo the token to buy\n * @param dx the number of tokens to sell. If the token charges a fee on transfers,\n * use the amount that gets transferred after the fee.\n * @return dy the number of tokens the user will get\n */\n function calculateSwap(\n Swap storage self,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx\n ) external view returns (uint256 dy) {\n (dy, ) = _calculateSwap(\n self,\n tokenIndexFrom,\n tokenIndexTo,\n dx,\n self.balances\n );\n }\n\n /**\n * @notice Internally calculates a swap between two tokens.\n *\n * @dev The caller is expected to transfer the actual amounts (dx and dy)\n * using the token contracts.\n *\n * @param self Swap struct to read from\n * @param tokenIndexFrom the token to sell\n * @param tokenIndexTo the token to buy\n * @param dx the number of tokens to sell. If the token charges a fee on transfers,\n * use the amount that gets transferred after the fee.\n * @return dy the number of tokens the user will get\n * @return dyFee the associated fee\n */\n function _calculateSwap(\n Swap storage self,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx,\n uint256[] memory balances\n ) internal view returns (uint256 dy, uint256 dyFee) {\n uint256[] memory multipliers = self.tokenPrecisionMultipliers;\n uint256[] memory xp = _xp(balances, multipliers);\n require(\n tokenIndexFrom < xp.length && tokenIndexTo < xp.length,\n \"Token index out of range\"\n );\n uint256 x = dx.mul(multipliers[tokenIndexFrom]).add(xp[tokenIndexFrom]);\n uint256 y = getY(\n _getAPrecise(self),\n tokenIndexFrom,\n tokenIndexTo,\n x,\n xp\n );\n dy = xp[tokenIndexTo].sub(y).sub(1);\n dyFee = dy.mul(self.swapFee).div(FEE_DENOMINATOR);\n dy = dy.sub(dyFee).div(multipliers[tokenIndexTo]);\n }\n\n /**\n * @notice A simple method to calculate amount of each underlying\n * tokens that is returned upon burning given amount of\n * LP tokens\n *\n * @param amount the amount of LP tokens that would to be burned on\n * withdrawal\n * @return array of amounts of tokens user will receive\n */\n function calculateRemoveLiquidity(Swap storage self, uint256 amount)\n external\n view\n returns (uint256[] memory)\n {\n return\n _calculateRemoveLiquidity(\n self.balances,\n amount,\n self.lpToken.totalSupply()\n );\n }\n\n function _calculateRemoveLiquidity(\n uint256[] memory balances,\n uint256 amount,\n uint256 totalSupply\n ) internal pure returns (uint256[] memory) {\n require(amount <= totalSupply, \"Cannot exceed total supply\");\n\n uint256[] memory amounts = new uint256[](balances.length);\n\n for (uint256 i = 0; i < balances.length; i++) {\n amounts[i] = balances[i].mul(amount).div(totalSupply);\n }\n return amounts;\n }\n\n /**\n * @notice A simple method to calculate prices from deposits or\n * withdrawals, excluding fees but including slippage. This is\n * helpful as an input into the various \"min\" parameters on calls\n * to fight front-running\n *\n * @dev This shouldn't be used outside frontends for user estimates.\n *\n * @param self Swap struct to read from\n * @param amounts an array of token amounts to deposit or withdrawal,\n * corresponding to pooledTokens. The amount should be in each\n * pooled token's native precision. If a token charges a fee on transfers,\n * use the amount that gets transferred after the fee.\n * @param deposit whether this is a deposit or a withdrawal\n * @return if deposit was true, total amount of lp token that will be minted and if\n * deposit was false, total amount of lp token that will be burned\n */\n function calculateTokenAmount(\n Swap storage self,\n uint256[] calldata amounts,\n bool deposit\n ) external view returns (uint256) {\n uint256 a = _getAPrecise(self);\n uint256[] memory balances = self.balances;\n uint256[] memory multipliers = self.tokenPrecisionMultipliers;\n\n uint256 d0 = getD(_xp(balances, multipliers), a);\n for (uint256 i = 0; i < balances.length; i++) {\n if (deposit) {\n balances[i] = balances[i].add(amounts[i]);\n } else {\n balances[i] = balances[i].sub(\n amounts[i],\n \"Cannot withdraw more than available\"\n );\n }\n }\n uint256 d1 = getD(_xp(balances, multipliers), a);\n uint256 totalSupply = self.lpToken.totalSupply();\n\n if (deposit) {\n return d1.sub(d0).mul(totalSupply).div(d0);\n } else {\n return d0.sub(d1).mul(totalSupply).div(d0);\n }\n }\n\n /**\n * @notice return accumulated amount of admin fees of the token with given index\n * @param self Swap struct to read from\n * @param index Index of the pooled token\n * @return admin balance in the token's precision\n */\n function getAdminBalance(Swap storage self, uint256 index)\n external\n view\n returns (uint256)\n {\n require(index < self.pooledTokens.length, \"Token index out of range\");\n return\n self.pooledTokens[index].balanceOf(address(this)).sub(\n self.balances[index]\n );\n }\n\n /**\n * @notice internal helper function to calculate fee per token multiplier used in\n * swap fee calculations\n * @param swapFee swap fee for the tokens\n * @param numTokens number of tokens pooled\n */\n function _feePerToken(uint256 swapFee, uint256 numTokens)\n internal\n pure\n returns (uint256)\n {\n return swapFee.mul(numTokens).div(numTokens.sub(1).mul(4));\n }\n\n /*** STATE MODIFYING FUNCTIONS ***/\n\n /**\n * @notice swap two tokens in the pool\n * @param self Swap struct to read from and write to\n * @param tokenIndexFrom the token the user wants to sell\n * @param tokenIndexTo the token the user wants to buy\n * @param dx the amount of tokens the user wants to sell\n * @param minDy the min amount the user would like to receive, or revert.\n * @return amount of token user received on swap\n */\n function swap(\n Swap storage self,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx,\n uint256 minDy\n ) external returns (uint256) {\n {\n IERC20 tokenFrom = self.pooledTokens[tokenIndexFrom];\n require(\n dx <= tokenFrom.balanceOf(msg.sender),\n \"Cannot swap more than you own\"\n );\n // Transfer tokens first to see if a fee was charged on transfer\n uint256 beforeBalance = tokenFrom.balanceOf(address(this));\n tokenFrom.safeTransferFrom(msg.sender, address(this), dx);\n\n // Use the actual transferred amount for AMM math\n dx = tokenFrom.balanceOf(address(this)).sub(beforeBalance);\n }\n\n uint256 dy;\n uint256 dyFee;\n uint256[] memory balances = self.balances;\n (dy, dyFee) = _calculateSwap(\n self,\n tokenIndexFrom,\n tokenIndexTo,\n dx,\n balances\n );\n require(dy >= minDy, \"Swap didn't result in min tokens\");\n\n uint256 dyAdminFee = dyFee.mul(self.adminFee).div(FEE_DENOMINATOR).div(\n self.tokenPrecisionMultipliers[tokenIndexTo]\n );\n\n self.balances[tokenIndexFrom] = balances[tokenIndexFrom].add(dx);\n self.balances[tokenIndexTo] = balances[tokenIndexTo].sub(dy).sub(\n dyAdminFee\n );\n\n self.pooledTokens[tokenIndexTo].safeTransfer(msg.sender, dy);\n\n emit TokenSwap(msg.sender, dx, dy, tokenIndexFrom, tokenIndexTo);\n\n return dy;\n }\n\n /**\n * @notice Add liquidity to the pool\n * @param self Swap struct to read from and write to\n * @param amounts the amounts of each token to add, in their native precision\n * @param minToMint the minimum LP tokens adding this amount of liquidity\n * should mint, otherwise revert. Handy for front-running mitigation\n * allowed addresses. If the pool is not in the guarded launch phase, this parameter will be ignored.\n * @return amount of LP token user received\n */\n function addLiquidity(\n Swap storage self,\n uint256[] memory amounts,\n uint256 minToMint\n ) external returns (uint256) {\n IERC20[] memory pooledTokens = self.pooledTokens;\n require(\n amounts.length == pooledTokens.length,\n \"Amounts must match pooled tokens\"\n );\n\n // current state\n ManageLiquidityInfo memory v = ManageLiquidityInfo(\n 0,\n 0,\n 0,\n _getAPrecise(self),\n self.lpToken,\n 0,\n self.balances,\n self.tokenPrecisionMultipliers\n );\n v.totalSupply = v.lpToken.totalSupply();\n\n if (v.totalSupply != 0) {\n v.d0 = getD(_xp(v.balances, v.multipliers), v.preciseA);\n }\n\n uint256[] memory newBalances = new uint256[](pooledTokens.length);\n\n for (uint256 i = 0; i < pooledTokens.length; i++) {\n require(\n v.totalSupply != 0 || amounts[i] > 0,\n \"Must supply all tokens in pool\"\n );\n\n // Transfer tokens first to see if a fee was charged on transfer\n if (amounts[i] != 0) {\n uint256 beforeBalance = pooledTokens[i].balanceOf(\n address(this)\n );\n pooledTokens[i].safeTransferFrom(\n msg.sender,\n address(this),\n amounts[i]\n );\n\n // Update the amounts[] with actual transfer amount\n amounts[i] = pooledTokens[i].balanceOf(address(this)).sub(\n beforeBalance\n );\n }\n\n newBalances[i] = v.balances[i].add(amounts[i]);\n }\n\n // invariant after change\n v.d1 = getD(_xp(newBalances, v.multipliers), v.preciseA);\n require(v.d1 > v.d0, \"D should increase\");\n\n // updated to reflect fees and calculate the user's LP tokens\n v.d2 = v.d1;\n uint256[] memory fees = new uint256[](pooledTokens.length);\n\n if (v.totalSupply != 0) {\n uint256 feePerToken = _feePerToken(\n self.swapFee,\n pooledTokens.length\n );\n for (uint256 i = 0; i < pooledTokens.length; i++) {\n uint256 idealBalance = v.d1.mul(v.balances[i]).div(v.d0);\n fees[i] = feePerToken\n .mul(idealBalance.difference(newBalances[i]))\n .div(FEE_DENOMINATOR);\n self.balances[i] = newBalances[i].sub(\n fees[i].mul(self.adminFee).div(FEE_DENOMINATOR)\n );\n newBalances[i] = newBalances[i].sub(fees[i]);\n }\n v.d2 = getD(_xp(newBalances, v.multipliers), v.preciseA);\n } else {\n // the initial depositor doesn't pay fees\n self.balances = newBalances;\n }\n\n uint256 toMint;\n if (v.totalSupply == 0) {\n toMint = v.d1;\n } else {\n toMint = v.d2.sub(v.d0).mul(v.totalSupply).div(v.d0);\n }\n\n require(toMint >= minToMint, \"Couldn't mint min requested\");\n\n // mint the user's LP tokens\n v.lpToken.mint(msg.sender, toMint);\n\n emit AddLiquidity(\n msg.sender,\n amounts,\n fees,\n v.d1,\n v.totalSupply.add(toMint)\n );\n\n return toMint;\n }\n\n /**\n * @notice Burn LP tokens to remove liquidity from the pool.\n * @dev Liquidity can always be removed, even when the pool is paused.\n * @param self Swap struct to read from and write to\n * @param amount the amount of LP tokens to burn\n * @param minAmounts the minimum amounts of each token in the pool\n * acceptable for this burn. Useful as a front-running mitigation\n * @return amounts of tokens the user received\n */\n function removeLiquidity(\n Swap storage self,\n uint256 amount,\n uint256[] calldata minAmounts\n ) external returns (uint256[] memory) {\n LPToken lpToken = self.lpToken;\n IERC20[] memory pooledTokens = self.pooledTokens;\n require(amount <= lpToken.balanceOf(msg.sender), \">LP.balanceOf\");\n require(\n minAmounts.length == pooledTokens.length,\n \"minAmounts must match poolTokens\"\n );\n\n uint256[] memory balances = self.balances;\n uint256 totalSupply = lpToken.totalSupply();\n\n uint256[] memory amounts = _calculateRemoveLiquidity(\n balances,\n amount,\n totalSupply\n );\n\n for (uint256 i = 0; i < amounts.length; i++) {\n require(amounts[i] >= minAmounts[i], \"amounts[i] < minAmounts[i]\");\n self.balances[i] = balances[i].sub(amounts[i]);\n pooledTokens[i].safeTransfer(msg.sender, amounts[i]);\n }\n\n lpToken.burnFrom(msg.sender, amount);\n\n emit RemoveLiquidity(msg.sender, amounts, totalSupply.sub(amount));\n\n return amounts;\n }\n\n /**\n * @notice Remove liquidity from the pool all in one token.\n * @param self Swap struct to read from and write to\n * @param tokenAmount the amount of the lp tokens to burn\n * @param tokenIndex the index of the token you want to receive\n * @param minAmount the minimum amount to withdraw, otherwise revert\n * @return amount chosen token that user received\n */\n function removeLiquidityOneToken(\n Swap storage self,\n uint256 tokenAmount,\n uint8 tokenIndex,\n uint256 minAmount\n ) external returns (uint256) {\n LPToken lpToken = self.lpToken;\n IERC20[] memory pooledTokens = self.pooledTokens;\n\n require(tokenAmount <= lpToken.balanceOf(msg.sender), \">LP.balanceOf\");\n require(tokenIndex < pooledTokens.length, \"Token not found\");\n\n uint256 totalSupply = lpToken.totalSupply();\n\n (uint256 dy, uint256 dyFee) = _calculateWithdrawOneToken(\n self,\n tokenAmount,\n tokenIndex,\n totalSupply\n );\n\n require(dy >= minAmount, \"dy < minAmount\");\n\n self.balances[tokenIndex] = self.balances[tokenIndex].sub(\n dy.add(dyFee.mul(self.adminFee).div(FEE_DENOMINATOR))\n );\n lpToken.burnFrom(msg.sender, tokenAmount);\n pooledTokens[tokenIndex].safeTransfer(msg.sender, dy);\n\n emit RemoveLiquidityOne(\n msg.sender,\n tokenAmount,\n totalSupply,\n tokenIndex,\n dy\n );\n\n return dy;\n }\n\n /**\n * @notice Remove liquidity from the pool, weighted differently than the\n * pool's current balances.\n *\n * @param self Swap struct to read from and write to\n * @param amounts how much of each token to withdraw\n * @param maxBurnAmount the max LP token provider is willing to pay to\n * remove liquidity. Useful as a front-running mitigation.\n * @return actual amount of LP tokens burned in the withdrawal\n */\n function removeLiquidityImbalance(\n Swap storage self,\n uint256[] memory amounts,\n uint256 maxBurnAmount\n ) public returns (uint256) {\n ManageLiquidityInfo memory v = ManageLiquidityInfo(\n 0,\n 0,\n 0,\n _getAPrecise(self),\n self.lpToken,\n 0,\n self.balances,\n self.tokenPrecisionMultipliers\n );\n v.totalSupply = v.lpToken.totalSupply();\n\n IERC20[] memory pooledTokens = self.pooledTokens;\n\n require(\n amounts.length == pooledTokens.length,\n \"Amounts should match pool tokens\"\n );\n\n require(\n maxBurnAmount <= v.lpToken.balanceOf(msg.sender) &&\n maxBurnAmount != 0,\n \">LP.balanceOf\"\n );\n\n uint256 feePerToken = _feePerToken(self.swapFee, pooledTokens.length);\n uint256[] memory fees = new uint256[](pooledTokens.length);\n {\n uint256[] memory balances1 = new uint256[](pooledTokens.length);\n v.d0 = getD(_xp(v.balances, v.multipliers), v.preciseA);\n for (uint256 i = 0; i < pooledTokens.length; i++) {\n balances1[i] = v.balances[i].sub(\n amounts[i],\n \"Cannot withdraw more than available\"\n );\n }\n v.d1 = getD(_xp(balances1, v.multipliers), v.preciseA);\n\n for (uint256 i = 0; i < pooledTokens.length; i++) {\n uint256 idealBalance = v.d1.mul(v.balances[i]).div(v.d0);\n uint256 difference = idealBalance.difference(balances1[i]);\n fees[i] = feePerToken.mul(difference).div(FEE_DENOMINATOR);\n self.balances[i] = balances1[i].sub(\n fees[i].mul(self.adminFee).div(FEE_DENOMINATOR)\n );\n balances1[i] = balances1[i].sub(fees[i]);\n }\n\n v.d2 = getD(_xp(balances1, v.multipliers), v.preciseA);\n }\n uint256 tokenAmount = v.d0.sub(v.d2).mul(v.totalSupply).div(v.d0);\n require(tokenAmount != 0, \"Burnt amount cannot be zero\");\n tokenAmount = tokenAmount.add(1);\n\n require(tokenAmount <= maxBurnAmount, \"tokenAmount > maxBurnAmount\");\n\n v.lpToken.burnFrom(msg.sender, tokenAmount);\n\n for (uint256 i = 0; i < pooledTokens.length; i++) {\n pooledTokens[i].safeTransfer(msg.sender, amounts[i]);\n }\n\n emit RemoveLiquidityImbalance(\n msg.sender,\n amounts,\n fees,\n v.d1,\n v.totalSupply.sub(tokenAmount)\n );\n\n return tokenAmount;\n }\n\n /**\n * @notice withdraw all admin fees to a given address\n * @param self Swap struct to withdraw fees from\n * @param to Address to send the fees to\n */\n function withdrawAdminFees(Swap storage self, address to) external {\n IERC20[] memory pooledTokens = self.pooledTokens;\n for (uint256 i = 0; i < pooledTokens.length; i++) {\n IERC20 token = pooledTokens[i];\n uint256 balance = token.balanceOf(address(this)).sub(\n self.balances[i]\n );\n if (balance != 0) {\n token.safeTransfer(to, balance);\n }\n }\n }\n\n /**\n * @notice Sets the admin fee\n * @dev adminFee cannot be higher than 100% of the swap fee\n * @param self Swap struct to update\n * @param newAdminFee new admin fee to be applied on future transactions\n */\n function setAdminFee(Swap storage self, uint256 newAdminFee) external {\n require(newAdminFee <= MAX_ADMIN_FEE, \"Fee is too high\");\n self.adminFee = newAdminFee;\n\n emit NewAdminFee(newAdminFee);\n }\n\n /**\n * @notice update the swap fee\n * @dev fee cannot be higher than 1% of each swap\n * @param self Swap struct to update\n * @param newSwapFee new swap fee to be applied on future transactions\n */\n function setSwapFee(Swap storage self, uint256 newSwapFee) external {\n require(newSwapFee <= MAX_SWAP_FEE, \"Fee is too high\");\n self.swapFee = newSwapFee;\n\n emit NewSwapFee(newSwapFee);\n }\n}\n" + }, + "contracts/amm/AmplificationUtils.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.6.12;\n\nimport \"@openzeppelin/contracts/token/ERC20/SafeERC20.sol\";\nimport \"./SwapUtils.sol\";\n\n/**\n * @title AmplificationUtils library\n * @notice A library to calculate and ramp the A parameter of a given `SwapUtils.Swap` struct.\n * This library assumes the struct is fully validated.\n */\nlibrary AmplificationUtils {\n using SafeMath for uint256;\n\n event RampA(\n uint256 oldA,\n uint256 newA,\n uint256 initialTime,\n uint256 futureTime\n );\n event StopRampA(uint256 currentA, uint256 time);\n\n // Constant values used in ramping A calculations\n uint256 public constant A_PRECISION = 100;\n uint256 public constant MAX_A = 10**6;\n uint256 private constant MAX_A_CHANGE = 2;\n uint256 private constant MIN_RAMP_TIME = 7 days;\n\n /**\n * @notice Return A, the amplification coefficient * n * (n - 1)\n * @dev See the StableSwap paper for details\n * @param self Swap struct to read from\n * @return A parameter\n */\n function getA(SwapUtils.Swap storage self) external view returns (uint256) {\n return _getAPrecise(self).div(A_PRECISION);\n }\n\n /**\n * @notice Return A in its raw precision\n * @dev See the StableSwap paper for details\n * @param self Swap struct to read from\n * @return A parameter in its raw precision form\n */\n function getAPrecise(SwapUtils.Swap storage self)\n external\n view\n returns (uint256)\n {\n return _getAPrecise(self);\n }\n\n /**\n * @notice Return A in its raw precision\n * @dev See the StableSwap paper for details\n * @param self Swap struct to read from\n * @return A parameter in its raw precision form\n */\n function _getAPrecise(SwapUtils.Swap storage self)\n internal\n view\n returns (uint256)\n {\n uint256 t1 = self.futureATime; // time when ramp is finished\n uint256 a1 = self.futureA; // final A value when ramp is finished\n\n if (block.timestamp < t1) {\n uint256 t0 = self.initialATime; // time when ramp is started\n uint256 a0 = self.initialA; // initial A value when ramp is started\n if (a1 > a0) {\n // a0 + (a1 - a0) * (block.timestamp - t0) / (t1 - t0)\n return\n a0.add(\n a1.sub(a0).mul(block.timestamp.sub(t0)).div(t1.sub(t0))\n );\n } else {\n // a0 - (a0 - a1) * (block.timestamp - t0) / (t1 - t0)\n return\n a0.sub(\n a0.sub(a1).mul(block.timestamp.sub(t0)).div(t1.sub(t0))\n );\n }\n } else {\n return a1;\n }\n }\n\n /**\n * @notice Start ramping up or down A parameter towards given futureA_ and futureTime_\n * Checks if the change is too rapid, and commits the new A value only when it falls under\n * the limit range.\n * @param self Swap struct to update\n * @param futureA_ the new A to ramp towards\n * @param futureTime_ timestamp when the new A should be reached\n */\n function rampA(\n SwapUtils.Swap storage self,\n uint256 futureA_,\n uint256 futureTime_\n ) external {\n require(\n block.timestamp >= self.initialATime.add(1 days),\n \"Wait 1 day before starting ramp\"\n );\n require(\n futureTime_ >= block.timestamp.add(MIN_RAMP_TIME),\n \"Insufficient ramp time\"\n );\n require(\n futureA_ > 0 && futureA_ < MAX_A,\n \"futureA_ must be > 0 and < MAX_A\"\n );\n\n uint256 initialAPrecise = _getAPrecise(self);\n uint256 futureAPrecise = futureA_.mul(A_PRECISION);\n\n if (futureAPrecise < initialAPrecise) {\n require(\n futureAPrecise.mul(MAX_A_CHANGE) >= initialAPrecise,\n \"futureA_ is too small\"\n );\n } else {\n require(\n futureAPrecise <= initialAPrecise.mul(MAX_A_CHANGE),\n \"futureA_ is too large\"\n );\n }\n\n self.initialA = initialAPrecise;\n self.futureA = futureAPrecise;\n self.initialATime = block.timestamp;\n self.futureATime = futureTime_;\n\n emit RampA(\n initialAPrecise,\n futureAPrecise,\n block.timestamp,\n futureTime_\n );\n }\n\n /**\n * @notice Stops ramping A immediately. Once this function is called, rampA()\n * cannot be called for another 24 hours\n * @param self Swap struct to update\n */\n function stopRampA(SwapUtils.Swap storage self) external {\n require(self.futureATime > block.timestamp, \"Ramp is already stopped\");\n\n uint256 currentA = _getAPrecise(self);\n self.initialA = currentA;\n self.futureA = currentA;\n self.initialATime = block.timestamp;\n self.futureATime = block.timestamp;\n\n emit StopRampA(currentA, block.timestamp);\n }\n}\n" + }, + "@openzeppelin/contracts/token/ERC20/IERC20.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <0.8.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" + }, + "@openzeppelin/contracts/utils/Address.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.2 <0.8.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" + }, + "@openzeppelin/contracts-upgradeable/proxy/Initializable.sol": { + "content": "// SPDX-License-Identifier: MIT\n\n// solhint-disable-next-line compiler-version\npragma solidity >=0.4.24 <0.8.0;\n\nimport \"../utils/AddressUpgradeable.sol\";\n\n/**\n * @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed\n * behind a proxy. Since a proxied contract can't have a constructor, it's common to move constructor logic to an\n * external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer\n * function so it can only be called once. The {initializer} modifier provided by this contract will have this effect.\n *\n * TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as\n * possible by providing the encoded function call as the `_data` argument to {UpgradeableProxy-constructor}.\n *\n * CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure\n * that all initializers are idempotent. This is not verified automatically as constructors are by Solidity.\n */\nabstract contract Initializable {\n\n /**\n * @dev Indicates that the contract has been initialized.\n */\n bool private _initialized;\n\n /**\n * @dev Indicates that the contract is in the process of being initialized.\n */\n bool private _initializing;\n\n /**\n * @dev Modifier to protect an initializer function from being invoked twice.\n */\n modifier initializer() {\n require(_initializing || _isConstructor() || !_initialized, \"Initializable: contract is already initialized\");\n\n bool isTopLevelCall = !_initializing;\n if (isTopLevelCall) {\n _initializing = true;\n _initialized = true;\n }\n\n _;\n\n if (isTopLevelCall) {\n _initializing = false;\n }\n }\n\n /// @dev Returns true if and only if the function is running in the constructor\n function _isConstructor() private view returns (bool) {\n return !AddressUpgradeable.isContract(address(this));\n }\n}\n" + }, + "@openzeppelin/contracts-upgradeable/utils/AddressUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.2 <0.8.0;\n\n/**\n * @dev Collection of functions related to the address type\n */\nlibrary AddressUpgradeable {\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 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" + }, + "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <0.8.0;\n\nimport \"../utils/ContextUpgradeable.sol\";\nimport \"../proxy/Initializable.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 OwnableUpgradeable is Initializable, ContextUpgradeable {\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 function __Ownable_init() internal initializer {\n __Context_init_unchained();\n __Ownable_init_unchained();\n }\n\n function __Ownable_init_unchained() internal initializer {\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 uint256[49] private __gap;\n}\n" + }, + "@openzeppelin/contracts-upgradeable/utils/PausableUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <0.8.0;\n\nimport \"./ContextUpgradeable.sol\";\nimport \"../proxy/Initializable.sol\";\n\n/**\n * @dev Contract module which allows children to implement an emergency stop\n * mechanism that can be triggered by an authorized account.\n *\n * This module is used through inheritance. It will make available the\n * modifiers `whenNotPaused` and `whenPaused`, which can be applied to\n * the functions of your contract. Note that they will not be pausable by\n * simply including this module, only once the modifiers are put in place.\n */\nabstract contract PausableUpgradeable is Initializable, ContextUpgradeable {\n /**\n * @dev Emitted when the pause is triggered by `account`.\n */\n event Paused(address account);\n\n /**\n * @dev Emitted when the pause is lifted by `account`.\n */\n event Unpaused(address account);\n\n bool private _paused;\n\n /**\n * @dev Initializes the contract in unpaused state.\n */\n function __Pausable_init() internal initializer {\n __Context_init_unchained();\n __Pausable_init_unchained();\n }\n\n function __Pausable_init_unchained() internal initializer {\n _paused = false;\n }\n\n /**\n * @dev Returns true if the contract is paused, and false otherwise.\n */\n function paused() public view virtual returns (bool) {\n return _paused;\n }\n\n /**\n * @dev Modifier to make a function callable only when the contract is not paused.\n *\n * Requirements:\n *\n * - The contract must not be paused.\n */\n modifier whenNotPaused() {\n require(!paused(), \"Pausable: paused\");\n _;\n }\n\n /**\n * @dev Modifier to make a function callable only when the contract is paused.\n *\n * Requirements:\n *\n * - The contract must be paused.\n */\n modifier whenPaused() {\n require(paused(), \"Pausable: not paused\");\n _;\n }\n\n /**\n * @dev Triggers stopped state.\n *\n * Requirements:\n *\n * - The contract must not be paused.\n */\n function _pause() internal virtual whenNotPaused {\n _paused = true;\n emit Paused(_msgSender());\n }\n\n /**\n * @dev Returns to normal state.\n *\n * Requirements:\n *\n * - The contract must be paused.\n */\n function _unpause() internal virtual whenPaused {\n _paused = false;\n emit Unpaused(_msgSender());\n }\n uint256[49] private __gap;\n}\n" + }, + "@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <0.8.0;\nimport \"../proxy/Initializable.sol\";\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 ContextUpgradeable is Initializable {\n function __Context_init() internal initializer {\n __Context_init_unchained();\n }\n\n function __Context_init_unchained() internal initializer {\n }\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 uint256[50] private __gap;\n}\n" + }, + "contracts/amm/LPToken.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.6.12;\n\nimport \"@openzeppelin/contracts-upgradeable/token/ERC20/ERC20BurnableUpgradeable.sol\";\nimport \"@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol\";\nimport \"./interfaces/ISwap.sol\";\n\n/**\n * @title Liquidity Provider Token\n * @notice This token is an ERC20 detailed token with added capability to be minted by the owner.\n * It is used to represent user's shares when providing liquidity to swap contracts.\n * @dev Only Swap contracts should initialize and own LPToken contracts.\n */\ncontract LPToken is ERC20BurnableUpgradeable, OwnableUpgradeable {\n using SafeMathUpgradeable for uint256;\n\n /**\n * @notice Initializes this LPToken contract with the given name and symbol\n * @dev The caller of this function will become the owner. A Swap contract should call this\n * in its initializer function.\n * @param name name of this token\n * @param symbol symbol of this token\n */\n function initialize(string memory name, string memory symbol)\n external\n initializer\n returns (bool)\n {\n __Context_init_unchained();\n __ERC20_init_unchained(name, symbol);\n __Ownable_init_unchained();\n return true;\n }\n\n /**\n * @notice Mints the given amount of LPToken to the recipient.\n * @dev only owner can call this mint function\n * @param recipient address of account to receive the tokens\n * @param amount amount of tokens to mint\n */\n function mint(address recipient, uint256 amount) external onlyOwner {\n require(amount != 0, \"LPToken: cannot mint 0\");\n _mint(recipient, amount);\n }\n\n /**\n * @dev Overrides ERC20._beforeTokenTransfer() which get called on every transfers including\n * minting and burning. * This assumes the owner is set to a Swap contract's address.\n */\n function _beforeTokenTransfer(\n address from,\n address to,\n uint256 amount\n ) internal virtual override(ERC20Upgradeable) {\n super._beforeTokenTransfer(from, to, amount);\n require(to != address(this), \"LPToken: cannot send to itself\");\n }\n}\n" + }, + "contracts/amm/MathUtils.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.6.12;\n\nimport \"@openzeppelin/contracts/math/SafeMath.sol\";\n\n/**\n * @title MathUtils library\n * @notice A library to be used in conjunction with SafeMath. Contains functions for calculating\n * differences between two uint256.\n */\nlibrary MathUtils {\n /**\n * @notice Compares a and b and returns true if the difference between a and b\n * is less than 1 or equal to each other.\n * @param a uint256 to compare with\n * @param b uint256 to compare with\n * @return True if the difference between a and b is less than 1 or equal,\n * otherwise return false\n */\n function within1(uint256 a, uint256 b) internal pure returns (bool) {\n return (difference(a, b) <= 1);\n }\n\n /**\n * @notice Calculates absolute difference between a and b\n * @param a uint256 to compare with\n * @param b uint256 to compare with\n * @return Difference between a and b\n */\n function difference(uint256 a, uint256 b) internal pure returns (uint256) {\n if (a > b) {\n return a - b;\n }\n return b - a;\n }\n}\n" + }, + "@openzeppelin/contracts-upgradeable/token/ERC20/ERC20BurnableUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <0.8.0;\n\nimport \"../../utils/ContextUpgradeable.sol\";\nimport \"./ERC20Upgradeable.sol\";\nimport \"../../proxy/Initializable.sol\";\n\n/**\n * @dev Extension of {ERC20} that allows token holders to destroy both their own\n * tokens and those that they have an allowance for, in a way that can be\n * recognized off-chain (via event analysis).\n */\nabstract contract ERC20BurnableUpgradeable is Initializable, ContextUpgradeable, ERC20Upgradeable {\n function __ERC20Burnable_init() internal initializer {\n __Context_init_unchained();\n __ERC20Burnable_init_unchained();\n }\n\n function __ERC20Burnable_init_unchained() internal initializer {\n }\n using SafeMathUpgradeable for uint256;\n\n /**\n * @dev Destroys `amount` tokens from the caller.\n *\n * See {ERC20-_burn}.\n */\n function burn(uint256 amount) public virtual {\n _burn(_msgSender(), amount);\n }\n\n /**\n * @dev Destroys `amount` tokens from `account`, deducting from the caller's\n * allowance.\n *\n * See {ERC20-_burn} and {ERC20-allowance}.\n *\n * Requirements:\n *\n * - the caller must have allowance for ``accounts``'s tokens of at least\n * `amount`.\n */\n function burnFrom(address account, uint256 amount) public virtual {\n uint256 decreasedAllowance = allowance(account, _msgSender()).sub(amount, \"ERC20: burn amount exceeds allowance\");\n\n _approve(account, _msgSender(), decreasedAllowance);\n _burn(account, amount);\n }\n uint256[50] private __gap;\n}\n" + }, + "contracts/amm/interfaces/ISwap.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.6.12;\n\nimport \"@openzeppelin/contracts/token/ERC20/ERC20.sol\";\n\ninterface ISwap {\n // pool data view functions\n function getA() external view returns (uint256);\n\n function getToken(uint8 index) external view returns (IERC20);\n\n function getTokenIndex(address tokenAddress) external view returns (uint8);\n\n function getTokenBalance(uint8 index) external view returns (uint256);\n\n function getVirtualPrice() external view returns (uint256);\n\n // min return calculation functions\n function calculateSwap(\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx\n ) external view returns (uint256);\n\n function calculateTokenAmount(uint256[] calldata amounts, bool deposit)\n external\n view\n returns (uint256);\n\n function calculateRemoveLiquidity(uint256 amount)\n external\n view\n returns (uint256[] memory);\n\n function calculateRemoveLiquidityOneToken(\n uint256 tokenAmount,\n uint8 tokenIndex\n ) external view returns (uint256 availableTokenAmount);\n\n // state modifying functions\n function initialize(\n IERC20[] memory pooledTokens,\n uint8[] memory decimals,\n string memory lpTokenName,\n string memory lpTokenSymbol,\n uint256 a,\n uint256 fee,\n uint256 adminFee,\n address lpTokenTargetAddress\n ) external;\n\n function swap(\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx,\n uint256 minDy,\n uint256 deadline\n ) external returns (uint256);\n\n function addLiquidity(\n uint256[] calldata amounts,\n uint256 minToMint,\n uint256 deadline\n ) external returns (uint256);\n\n function removeLiquidity(\n uint256 amount,\n uint256[] calldata minAmounts,\n uint256 deadline\n ) external returns (uint256[] memory);\n\n function removeLiquidityOneToken(\n uint256 tokenAmount,\n uint8 tokenIndex,\n uint256 minAmount,\n uint256 deadline\n ) external returns (uint256);\n\n function removeLiquidityImbalance(\n uint256[] calldata amounts,\n uint256 maxBurnAmount,\n uint256 deadline\n ) external returns (uint256);\n}\n" + }, + "@openzeppelin/contracts-upgradeable/token/ERC20/ERC20Upgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <0.8.0;\n\nimport \"../../utils/ContextUpgradeable.sol\";\nimport \"./IERC20Upgradeable.sol\";\nimport \"../../math/SafeMathUpgradeable.sol\";\nimport \"../../proxy/Initializable.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 ERC20Upgradeable is Initializable, ContextUpgradeable, IERC20Upgradeable {\n using SafeMathUpgradeable 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 function __ERC20_init(string memory name_, string memory symbol_) internal initializer {\n __Context_init_unchained();\n __ERC20_init_unchained(name_, symbol_);\n }\n\n function __ERC20_init_unchained(string memory name_, string memory symbol_) internal initializer {\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 uint256[44] private __gap;\n}\n" + }, + "@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <0.8.0;\n\n/**\n * @dev Interface of the ERC20 standard as defined in the EIP.\n */\ninterface IERC20Upgradeable {\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" + }, + "@openzeppelin/contracts-upgradeable/math/SafeMathUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <0.8.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 SafeMathUpgradeable {\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" + }, + "@openzeppelin/contracts/token/ERC20/ERC20.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <0.8.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_) public {\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" + }, + "@openzeppelin/contracts/utils/Context.sol": { + "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" + }, + "contracts/amm/SwapFlashLoan.sol": { + "content": "// SPDX-License-Identifier: MIT WITH AGPL-3.0-only\n\npragma solidity 0.6.12;\n\nimport \"./Swap.sol\";\nimport \"./interfaces/IFlashLoanReceiver.sol\";\n\n/**\n * @title Swap - A StableSwap implementation in solidity.\n * @notice This contract is responsible for custody of closely pegged assets (eg. group of stablecoins)\n * and automatic market making system. Users become an LP (Liquidity Provider) by depositing their tokens\n * in desired ratios for an exchange of the pool token that represents their share of the pool.\n * Users can burn pool tokens and withdraw their share of token(s).\n *\n * Each time a swap between the pooled tokens happens, a set fee incurs which effectively gets\n * distributed to the LPs.\n *\n * In case of emergencies, admin can pause additional deposits, swaps, or single-asset withdraws - which\n * stops the ratio of the tokens in the pool from changing.\n * Users can always withdraw their tokens via multi-asset withdraws.\n *\n * @dev Most of the logic is stored as a library `SwapUtils` for the sake of reducing contract's\n * deployment size.\n */\ncontract SwapFlashLoan is Swap {\n // Total fee that is charged on all flashloans in BPS. Borrowers must repay the amount plus the flash loan fee.\n // This fee is split between the protocol and the pool.\n uint256 public flashLoanFeeBPS;\n // Share of the flash loan fee that goes to the protocol in BPS. A portion of each flash loan fee is allocated\n // to the protocol rather than the pool.\n uint256 public protocolFeeShareBPS;\n // Max BPS for limiting flash loan fee settings.\n uint256 public constant MAX_BPS = 10000;\n\n /*** EVENTS ***/\n event FlashLoan(\n address indexed receiver,\n uint8 tokenIndex,\n uint256 amount,\n uint256 amountFee,\n uint256 protocolFee\n );\n\n /**\n * @notice Initializes this Swap contract with the given parameters.\n * This will also clone a LPToken contract that represents users'\n * LP positions. The owner of LPToken will be this contract - which means\n * only this contract is allowed to mint/burn tokens.\n *\n * @param _pooledTokens an array of ERC20s this pool will accept\n * @param decimals the decimals to use for each pooled token,\n * eg 8 for WBTC. Cannot be larger than POOL_PRECISION_DECIMALS\n * @param lpTokenName the long-form name of the token to be deployed\n * @param lpTokenSymbol the short symbol for the token to be deployed\n * @param _a the amplification coefficient * n * (n - 1). See the\n * StableSwap paper for details\n * @param _fee default swap fee to be initialized with\n * @param _adminFee default adminFee to be initialized with\n * @param lpTokenTargetAddress the address of an existing LPToken contract to use as a target\n */\n function initialize(\n IERC20[] memory _pooledTokens,\n uint8[] memory decimals,\n string memory lpTokenName,\n string memory lpTokenSymbol,\n uint256 _a,\n uint256 _fee,\n uint256 _adminFee,\n address lpTokenTargetAddress\n ) public virtual override initializer {\n Swap.initialize(\n _pooledTokens,\n decimals,\n lpTokenName,\n lpTokenSymbol,\n _a,\n _fee,\n _adminFee,\n lpTokenTargetAddress\n );\n flashLoanFeeBPS = 8; // 8 bps\n protocolFeeShareBPS = 0; // 0 bps\n }\n\n /*** STATE MODIFYING FUNCTIONS ***/\n\n /**\n * @notice Borrow the specified token from this pool for this transaction only. This function will call\n * `IFlashLoanReceiver(receiver).executeOperation` and the `receiver` must return the full amount of the token\n * and the associated fee by the end of the callback transaction. If the conditions are not met, this call\n * is reverted.\n * @param receiver the address of the receiver of the token. This address must implement the IFlashLoanReceiver\n * interface and the callback function `executeOperation`.\n * @param token the protocol fee in bps to be applied on the total flash loan fee\n * @param amount the total amount to borrow in this transaction\n * @param params optional data to pass along to the callback function\n */\n function flashLoan(\n address receiver,\n IERC20 token,\n uint256 amount,\n bytes memory params\n ) external nonReentrant {\n uint8 tokenIndex = getTokenIndex(address(token));\n uint256 availableLiquidityBefore = token.balanceOf(address(this));\n uint256 protocolBalanceBefore = availableLiquidityBefore.sub(\n swapStorage.balances[tokenIndex]\n );\n require(\n amount > 0 && availableLiquidityBefore >= amount,\n \"invalid amount\"\n );\n\n // Calculate the additional amount of tokens the pool should end up with\n uint256 amountFee = amount.mul(flashLoanFeeBPS).div(10000);\n // Calculate the portion of the fee that will go to the protocol\n uint256 protocolFee = amountFee.mul(protocolFeeShareBPS).div(10000);\n require(amountFee > 0, \"amount is small for a flashLoan\");\n\n // Transfer the requested amount of tokens\n token.safeTransfer(receiver, amount);\n\n // Execute callback function on receiver\n IFlashLoanReceiver(receiver).executeOperation(\n address(this),\n address(token),\n amount,\n amountFee,\n params\n );\n\n uint256 availableLiquidityAfter = token.balanceOf(address(this));\n require(\n availableLiquidityAfter >= availableLiquidityBefore.add(amountFee),\n \"flashLoan fee is not met\"\n );\n\n swapStorage.balances[tokenIndex] = availableLiquidityAfter\n .sub(protocolBalanceBefore)\n .sub(protocolFee);\n emit FlashLoan(receiver, tokenIndex, amount, amountFee, protocolFee);\n }\n\n /*** ADMIN FUNCTIONS ***/\n\n /**\n * @notice Updates the flash loan fee parameters. This function can only be called by the owner.\n * @param newFlashLoanFeeBPS the total fee in bps to be applied on future flash loans\n * @param newProtocolFeeShareBPS the protocol fee in bps to be applied on the total flash loan fee\n */\n function setFlashLoanFees(\n uint256 newFlashLoanFeeBPS,\n uint256 newProtocolFeeShareBPS\n ) external onlyOwner {\n require(\n newFlashLoanFeeBPS > 0 &&\n newFlashLoanFeeBPS <= MAX_BPS &&\n newProtocolFeeShareBPS <= MAX_BPS,\n \"fees are not in valid range\"\n );\n flashLoanFeeBPS = newFlashLoanFeeBPS;\n protocolFeeShareBPS = newProtocolFeeShareBPS;\n }\n}\n" + }, + "contracts/amm/interfaces/IFlashLoanReceiver.sol": { + "content": "// SPDX-License-Identifier: AGPL-3.0-only\n\npragma solidity 0.6.12;\n\n/**\n * @title IFlashLoanReceiver interface\n * @notice Interface for the Nerve fee IFlashLoanReceiver. Modified from Aave's IFlashLoanReceiver interface.\n * https://github.com/aave/aave-protocol/blob/4b4545fb583fd4f400507b10f3c3114f45b8a037/contracts/flashloan/interfaces/IFlashLoanReceiver.sol\n * @author Aave\n * @dev implement this interface to develop a flashloan-compatible flashLoanReceiver contract\n **/\ninterface IFlashLoanReceiver {\n function executeOperation(\n address pool,\n address token,\n uint256 amount,\n uint256 fee,\n bytes calldata params\n ) external;\n}\n" + }, + "contracts/amm/helper/FlashLoanBorrowerExample.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.6.12;\n\nimport \"@openzeppelin/contracts/math/SafeMath.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/SafeERC20.sol\";\nimport \"../interfaces/IFlashLoanReceiver.sol\";\nimport \"../interfaces/ISwapFlashLoan.sol\";\nimport \"hardhat/console.sol\";\n\ncontract FlashLoanBorrowerExample is IFlashLoanReceiver {\n using SafeMath for uint256;\n\n // Typical executeOperation function should do the 3 following actions\n // 1. Check if the flashLoan was successful\n // 2. Do actions with the borrowed tokens\n // 3. Repay the debt to the `pool`\n function executeOperation(\n address pool,\n address token,\n uint256 amount,\n uint256 fee,\n bytes calldata params\n ) external override {\n // 1. Check if the flashLoan was valid\n require(\n IERC20(token).balanceOf(address(this)) >= amount,\n \"flashloan is broken?\"\n );\n\n // 2. Do actions with the borrowed token\n bytes32 paramsHash = keccak256(params);\n if (paramsHash == keccak256(bytes(\"dontRepayDebt\"))) {\n return;\n } else if (paramsHash == keccak256(bytes(\"reentrancy_addLiquidity\"))) {\n ISwapFlashLoan(pool).addLiquidity(\n new uint256[](0),\n 0,\n block.timestamp\n );\n } else if (paramsHash == keccak256(bytes(\"reentrancy_swap\"))) {\n ISwapFlashLoan(pool).swap(1, 0, 1e6, 0, now);\n } else if (\n paramsHash == keccak256(bytes(\"reentrancy_removeLiquidity\"))\n ) {\n ISwapFlashLoan(pool).removeLiquidity(1e18, new uint256[](0), now);\n } else if (\n paramsHash == keccak256(bytes(\"reentrancy_removeLiquidityOneToken\"))\n ) {\n ISwapFlashLoan(pool).removeLiquidityOneToken(1e18, 0, 1e18, now);\n }\n\n // 3. Payback debt\n uint256 totalDebt = amount.add(fee);\n IERC20(token).transfer(pool, totalDebt);\n }\n\n function flashLoan(\n ISwapFlashLoan swap,\n IERC20 token,\n uint256 amount,\n bytes memory params\n ) external {\n swap.flashLoan(address(this), token, amount, params);\n }\n}\n" + }, + "contracts/amm/interfaces/ISwapFlashLoan.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.6.12;\n\nimport \"./ISwap.sol\";\n\ninterface ISwapFlashLoan is ISwap {\n function flashLoan(\n address receiver,\n IERC20 token,\n uint256 amount,\n bytes memory params\n ) external;\n}\n" + }, + "hardhat/console.sol": { + "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" + }, + "contracts/amm/helper/test/TestSwapReturnValues.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.6.12;\n\nimport \"../../interfaces/ISwap.sol\";\nimport \"hardhat/console.sol\";\n\ncontract TestSwapReturnValues {\n using SafeMath for uint256;\n\n ISwap public swap;\n IERC20 public lpToken;\n uint8 public n;\n\n uint256 public constant MAX_INT = 2**256 - 1;\n\n constructor(\n ISwap swapContract,\n IERC20 lpTokenContract,\n uint8 numOfTokens\n ) public {\n swap = swapContract;\n lpToken = lpTokenContract;\n n = numOfTokens;\n\n // Pre-approve tokens\n for (uint8 i; i < n; i++) {\n swap.getToken(i).approve(address(swap), MAX_INT);\n }\n lpToken.approve(address(swap), MAX_INT);\n }\n\n function test_swap(\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx,\n uint256 minDy\n ) public {\n uint256 balanceBefore =\n swap.getToken(tokenIndexTo).balanceOf(address(this));\n uint256 returnValue =\n swap.swap(tokenIndexFrom, tokenIndexTo, dx, minDy, block.timestamp);\n uint256 balanceAfter =\n swap.getToken(tokenIndexTo).balanceOf(address(this));\n\n console.log(\n \"swap: Expected %s, got %s\",\n balanceAfter.sub(balanceBefore),\n returnValue\n );\n\n require(\n returnValue == balanceAfter.sub(balanceBefore),\n \"swap()'s return value does not match received amount\"\n );\n }\n\n function test_addLiquidity(uint256[] calldata amounts, uint256 minToMint)\n public\n {\n uint256 balanceBefore = lpToken.balanceOf(address(this));\n uint256 returnValue = swap.addLiquidity(amounts, minToMint, MAX_INT);\n uint256 balanceAfter = lpToken.balanceOf(address(this));\n\n console.log(\n \"addLiquidity: Expected %s, got %s\",\n balanceAfter.sub(balanceBefore),\n returnValue\n );\n\n require(\n returnValue == balanceAfter.sub(balanceBefore),\n \"addLiquidity()'s return value does not match minted amount\"\n );\n }\n\n function test_removeLiquidity(uint256 amount, uint256[] memory minAmounts)\n public\n {\n uint256[] memory balanceBefore = new uint256[](n);\n uint256[] memory balanceAfter = new uint256[](n);\n\n for (uint8 i = 0; i < n; i++) {\n balanceBefore[i] = swap.getToken(i).balanceOf(address(this));\n }\n\n uint256[] memory returnValue =\n swap.removeLiquidity(amount, minAmounts, MAX_INT);\n\n for (uint8 i = 0; i < n; i++) {\n balanceAfter[i] = swap.getToken(i).balanceOf(address(this));\n console.log(\n \"removeLiquidity: Expected %s, got %s\",\n balanceAfter[i].sub(balanceBefore[i]),\n returnValue[i]\n );\n require(\n balanceAfter[i].sub(balanceBefore[i]) == returnValue[i],\n \"removeLiquidity()'s return value does not match received amounts of tokens\"\n );\n }\n }\n\n function test_removeLiquidityImbalance(\n uint256[] calldata amounts,\n uint256 maxBurnAmount\n ) public {\n uint256 balanceBefore = lpToken.balanceOf(address(this));\n uint256 returnValue =\n swap.removeLiquidityImbalance(amounts, maxBurnAmount, MAX_INT);\n uint256 balanceAfter = lpToken.balanceOf(address(this));\n\n console.log(\n \"removeLiquidityImbalance: Expected %s, got %s\",\n balanceBefore.sub(balanceAfter),\n returnValue\n );\n\n require(\n returnValue == balanceBefore.sub(balanceAfter),\n \"removeLiquidityImbalance()'s return value does not match burned lpToken amount\"\n );\n }\n\n function test_removeLiquidityOneToken(\n uint256 tokenAmount,\n uint8 tokenIndex,\n uint256 minAmount\n ) public {\n uint256 balanceBefore =\n swap.getToken(tokenIndex).balanceOf(address(this));\n uint256 returnValue =\n swap.removeLiquidityOneToken(\n tokenAmount,\n tokenIndex,\n minAmount,\n MAX_INT\n );\n uint256 balanceAfter =\n swap.getToken(tokenIndex).balanceOf(address(this));\n\n console.log(\n \"removeLiquidityOneToken: Expected %s, got %s\",\n balanceAfter.sub(balanceBefore),\n returnValue\n );\n\n require(\n returnValue == balanceAfter.sub(balanceBefore),\n \"removeLiquidityOneToken()'s return value does not match received token amount\"\n );\n }\n}\n" + }, + "contracts/amm/SwapDeployer.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.6.12;\n\nimport \"@openzeppelin/contracts/access/Ownable.sol\";\nimport \"@openzeppelin/contracts/proxy/Clones.sol\";\nimport \"./interfaces/ISwap.sol\";\n\ncontract SwapDeployer is Ownable {\n event NewSwapPool(\n address indexed deployer,\n address swapAddress,\n IERC20[] pooledTokens\n );\n\n constructor() public Ownable() {}\n\n function deploy(\n address swapAddress,\n IERC20[] memory _pooledTokens,\n uint8[] memory decimals,\n string memory lpTokenName,\n string memory lpTokenSymbol,\n uint256 _a,\n uint256 _fee,\n uint256 _adminFee,\n address lpTokenTargetAddress\n ) external returns (address) {\n address swapClone = Clones.clone(swapAddress);\n ISwap(swapClone).initialize(\n _pooledTokens,\n decimals,\n lpTokenName,\n lpTokenSymbol,\n _a,\n _fee,\n _adminFee,\n lpTokenTargetAddress\n );\n Ownable(swapClone).transferOwnership(owner());\n emit NewSwapPool(msg.sender, swapClone, _pooledTokens);\n return swapClone;\n }\n}\n" + }, + "@openzeppelin/contracts/access/Ownable.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <0.8.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 () internal {\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" + }, + "contracts/bridge/SynapseERC20Factory.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.6.12;\n\nimport \"@openzeppelin/contracts/access/Ownable.sol\";\nimport \"@openzeppelin/contracts/proxy/Clones.sol\";\nimport \"./interfaces/ISynapseERC20.sol\";\n\ncontract SynapseERC20Factory {\n constructor() public {}\n\n event SynapseERC20Created(address contractAddress);\n\n /**\n * @notice Deploys a new node\n * @param synapseERC20Address address of the synapseERC20Address contract to initialize with\n * @param name Token name\n * @param symbol Token symbol\n * @param decimals Token name\n * @param owner admin address to be initialized with\n * @return Address of the newest node management contract created\n **/\n function deploy(\n address synapseERC20Address,\n string memory name,\n string memory symbol,\n uint8 decimals,\n address owner\n ) external returns (address) {\n address synERC20Clone = Clones.clone(synapseERC20Address);\n ISynapseERC20(synERC20Clone).initialize(name, symbol, decimals, owner);\n\n emit SynapseERC20Created(synERC20Clone);\n\n return synERC20Clone;\n }\n}\n" + }, + "contracts/bridge/interfaces/ISynapseERC20.sol": { + "content": "// SPDX-License-Identifier: MIT\n\n\npragma solidity 0.6.12;\n\ninterface ISynapseERC20 { \n function initialize(\n string memory _name, string memory _symbol, uint8 _decimals, address owner) external;\n\n function mint(address to, uint256 amount) external;\n}\n\n" + }, + "contracts/bridge/wrappers/AvaxJewelMigration.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.6.12;\n\nimport '@openzeppelin/contracts/token/ERC20/ERC20.sol';\nimport \"@openzeppelin/contracts/token/ERC20/SafeERC20.sol\";\nimport \"@openzeppelin/contracts/access/Ownable.sol\";\n\nimport '../interfaces/ISynapseBridge.sol';\n\ninterface IERC20Mintable is IERC20 {\n function mint(address to, uint256 amount) external;\n}\n\ncontract AvaxJewelMigration is Ownable {\n using SafeERC20 for IERC20;\n using SafeERC20 for IERC20Mintable;\n\n\n ISynapseBridge constant synapseBridge = ISynapseBridge(0xC05e61d0E7a63D27546389B7aD62FdFf5A91aACE);\n // MULTICHAIN JEWEL \n IERC20 constant legacyToken = IERC20(0x4f60a160D8C2DDdaAfe16FCC57566dB84D674BD6);\n // SYNAPSE JEWEL\n IERC20 constant newToken = IERC20(0x997Ddaa07d716995DE90577C123Db411584E5E46);\n uint256 constant MAX_UINT256 = 2**256 - 1;\n\n constructor() public {\n newToken.safeApprove(address(synapseBridge), MAX_UINT256);\n }\n\n function migrate(uint256 amount) public {\n legacyToken.safeTransferFrom(msg.sender, address(this), amount);\n IERC20Mintable(address(newToken)).mint(msg.sender, amount);\n }\n\n function migrateAndBridge(uint256 amount, address to, uint256 chainId) external {\n migrate(amount);\n synapseBridge.redeem(to, chainId, newToken, amount);\n }\n\n function redeemLegacy() external onlyOwner {\n uint256 legacyBalance = legacyToken.balanceOf(address(this));\n legacyToken.safeTransfer(owner(), legacyBalance);\n }\n} " + }, + "contracts/bridge/interfaces/ISynapseBridge.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.6.12;\n\nimport '@openzeppelin/contracts/token/ERC20/SafeERC20.sol';\nimport '@openzeppelin/contracts/token/ERC20/ERC20Burnable.sol';\n\ninterface ISynapseBridge {\n using SafeERC20 for IERC20;\n\n function deposit(\n address to,\n uint256 chainId,\n IERC20 token,\n uint256 amount\n ) external;\n\n function depositAndSwap(\n address to,\n uint256 chainId,\n IERC20 token,\n uint256 amount,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 minDy,\n uint256 deadline\n ) external;\n\n function redeem(\n address to,\n uint256 chainId,\n IERC20 token,\n uint256 amount\n ) external;\n\n\n function redeemv2(\n bytes32 to,\n uint256 chainId,\n IERC20 token,\n uint256 amount\n ) external;\n\n\n function redeemAndSwap(\n address to,\n uint256 chainId,\n IERC20 token,\n uint256 amount,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 minDy,\n uint256 deadline\n ) external;\n\n function redeemAndRemove(\n address to,\n uint256 chainId,\n IERC20 token,\n uint256 amount,\n uint8 liqTokenIndex,\n uint256 liqMinAmount,\n uint256 liqDeadline\n ) external;\n}\n" + }, + "@openzeppelin/contracts/token/ERC20/ERC20Burnable.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <0.8.0;\n\nimport \"../../utils/Context.sol\";\nimport \"./ERC20.sol\";\n\n/**\n * @dev Extension of {ERC20} that allows token holders to destroy both their own\n * tokens and those that they have an allowance for, in a way that can be\n * recognized off-chain (via event analysis).\n */\nabstract contract ERC20Burnable is Context, ERC20 {\n using SafeMath for uint256;\n\n /**\n * @dev Destroys `amount` tokens from the caller.\n *\n * See {ERC20-_burn}.\n */\n function burn(uint256 amount) public virtual {\n _burn(_msgSender(), amount);\n }\n\n /**\n * @dev Destroys `amount` tokens from `account`, deducting from the caller's\n * allowance.\n *\n * See {ERC20-_burn} and {ERC20-allowance}.\n *\n * Requirements:\n *\n * - the caller must have allowance for ``accounts``'s tokens of at least\n * `amount`.\n */\n function burnFrom(address account, uint256 amount) public virtual {\n uint256 decreasedAllowance = allowance(account, _msgSender()).sub(amount, \"ERC20: burn amount exceeds allowance\");\n\n _approve(account, _msgSender(), decreasedAllowance);\n _burn(account, amount);\n }\n}\n" + }, + "contracts/bridge/wrappers/MoonriverBridgeZap.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.6.12;\n\nimport \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/SafeERC20.sol\";\nimport \"../interfaces/ISwap.sol\";\nimport \"../interfaces/ISynapseBridge.sol\";\nimport \"../interfaces/IWETH9.sol\";\n\ninterface IFrax {\n function exchangeCanonicalForOld(address bridge_token_address, uint256 token_amount) external returns (uint256);\n}\n\ncontract MoonriverBridgeZap {\n using SafeERC20 for IERC20;\n\n ISynapseBridge synapseBridge;\n address payable public immutable WETH_ADDRESS;\n IFrax private constant CANOLICAL_FRAX = IFrax(0x1A93B23281CC1CDE4C4741353F3064709A16197d);\n IERC20 private constant SYN_FRAX = IERC20(0xE96AC70907ffF3Efee79f502C985A7A21Bce407d);\n\n mapping(address => address) public swapMap;\n mapping(address => IERC20[]) public swapTokensMap;\n\n uint256 constant MAX_UINT256 = 2**256 - 1;\n\n constructor(\n address payable _wethAddress,\n address _swapOne,\n address tokenOne,\n address _swapTwo,\n address tokenTwo,\n ISynapseBridge _synapseBridge\n ) public {\n WETH_ADDRESS = _wethAddress;\n synapseBridge = _synapseBridge;\n swapMap[tokenOne] = _swapOne;\n swapMap[tokenTwo] = _swapTwo;\n IERC20(_wethAddress).safeIncreaseAllowance(address(_synapseBridge), MAX_UINT256);\n if (address(_swapOne) != address(0)) {\n {\n uint8 i;\n for (; i < 32; i++) {\n try ISwap(_swapOne).getToken(i) returns (\n IERC20 token\n ) {\n swapTokensMap[_swapOne].push(token);\n token.safeApprove(address(_swapOne), MAX_UINT256);\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n } catch {\n break;\n }\n }\n require(i > 1, \"swap must have at least 2 tokens\");\n }\n }\n if (address(_swapTwo) != address(0)) {\n {\n uint8 i;\n for (; i < 32; i++) {\n try ISwap(_swapTwo).getToken(i) returns (\n IERC20 token\n ) {\n swapTokensMap[_swapTwo].push(token);\n token.safeApprove(address(_swapTwo), MAX_UINT256);\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n } catch {\n break;\n }\n }\n require(i > 1, \"swap must have at least 2 tokens\");\n }\n }\n }\n\n /**\n * @notice Calculate amount of tokens you receive on swap\n * @param tokenIndexFrom the token the user wants to sell\n * @param tokenIndexTo the token the user wants to buy\n * @param dx the amount of tokens the user wants to sell. If the token charges\n * a fee on transfers, use the amount that gets transferred after the fee.\n * @return amount of tokens the user will receive\n */\n function calculateSwap(\n IERC20 token,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx\n ) external view virtual returns (uint256) {\n ISwap swap = ISwap(\n swapMap[address(token)]\n );\n return swap.calculateSwap(tokenIndexFrom, tokenIndexTo, dx);\n }\n\n function swapAndRedeem(\n address to,\n uint256 chainId,\n IERC20 token,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx,\n uint256 minDy,\n uint256 deadline\n ) external {\n ISwap swap = ISwap(swapMap[address(token)]);\n require(address(swap) != address(0), \"Swap is 0x00\");\n IERC20[] memory tokens = swapTokensMap[address(swap)];\n tokens[tokenIndexFrom].safeTransferFrom(\n msg.sender,\n address(this),\n dx\n );\n // swap\n\n uint256 swappedAmount = swap.swap(\n tokenIndexFrom,\n tokenIndexTo,\n dx,\n minDy,\n deadline\n );\n // deposit into bridge, gets nUSD\n if (\n token.allowance(address(this), address(synapseBridge)) <\n swappedAmount\n ) {\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n }\n synapseBridge.redeem(to, chainId, token, swappedAmount);\n }\n\n function swapAndRedeemAndSwap(\n address to,\n uint256 chainId,\n IERC20 token,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx,\n uint256 minDy,\n uint256 deadline,\n uint8 swapTokenIndexFrom,\n uint8 swapTokenIndexTo,\n uint256 swapMinDy,\n uint256 swapDeadline\n ) external {\n require(\n address(swapMap[address(token)]) != address(0),\n \"Swap is 0x00\"\n );\n IERC20[] memory tokens = swapTokensMap[\n swapMap[address(token)]\n ];\n tokens[tokenIndexFrom].safeTransferFrom(\n msg.sender,\n address(this),\n dx\n );\n // swap\n\n uint256 swappedAmount = ISwap(swapMap[address(token)]).swap(tokenIndexFrom, tokenIndexTo, dx, minDy, deadline);\n // deposit into bridge, gets nUSD\n if (\n token.allowance(address(this), address(synapseBridge)) <\n swappedAmount\n ) {\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n }\n synapseBridge.redeemAndSwap(\n to,\n chainId,\n token,\n swappedAmount,\n swapTokenIndexFrom,\n swapTokenIndexTo,\n swapMinDy,\n swapDeadline\n );\n }\n\n function swapAndRedeemAndRemove(\n address to,\n uint256 chainId,\n IERC20 token,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx,\n uint256 minDy,\n uint256 deadline,\n uint8 liqTokenIndex,\n uint256 liqMinAmount,\n uint256 liqDeadline\n ) external {\n ISwap swap = ISwap(swapMap[address(token)]);\n require(address(swap) != address(0), \"Swap is 0x00\");\n IERC20[] memory tokens = swapTokensMap[address(swap)];\n tokens[tokenIndexFrom].safeTransferFrom(\n msg.sender,\n address(this),\n dx\n );\n // swap\n\n uint256 swappedAmount = swap.swap(\n tokenIndexFrom,\n tokenIndexTo,\n dx,\n minDy,\n deadline\n );\n // deposit into bridge, gets nUSD\n if (\n token.allowance(address(this), address(synapseBridge)) <\n swappedAmount\n ) {\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n }\n synapseBridge.redeemAndRemove(\n to,\n chainId,\n token,\n swappedAmount,\n liqTokenIndex,\n liqMinAmount,\n liqDeadline\n );\n }\n\n /**\n * @notice wraps SynapseBridge redeem()\n * @param to address on other chain to redeem underlying assets to\n * @param chainId which underlying chain to bridge assets onto\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n **/\n function redeem(\n address to,\n uint256 chainId,\n IERC20 token,\n uint256 amount\n ) external {\n token.safeTransferFrom(msg.sender, address(this), amount);\n if (address(token) == address(CANOLICAL_FRAX)) {\n uint256 swappedAmount = CANOLICAL_FRAX.exchangeCanonicalForOld(address(SYN_FRAX), amount);\n if (SYN_FRAX.allowance(address(this), address(synapseBridge)) < amount) {\n SYN_FRAX.safeApprove(address(synapseBridge), MAX_UINT256);\n }\n synapseBridge.redeem(to, chainId, SYN_FRAX, swappedAmount);\n } else {\n if (token.allowance(address(this), address(synapseBridge)) < amount) {\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n }\n synapseBridge.redeem(to, chainId, token, amount);\n }\n }\n\n /**\n * @notice Wraps SynapseBridge redeemv2() function\n * @param to address on other chain to bridge assets to\n * @param chainId which chain to bridge assets onto\n * @param token ERC20 compatible token to redeem into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n **/\n function redeemv2(\n bytes32 to,\n uint256 chainId,\n IERC20 token,\n uint256 amount\n ) external {\n token.safeTransferFrom(msg.sender, address(this), amount);\n\n if (token.allowance(address(this), address(synapseBridge)) < amount) {\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n }\n synapseBridge.redeemv2(to, chainId, token, amount);\n }\n\n /**\n * @notice wraps SynapseBridge redeem()\n * @param to address on other chain to redeem underlying assets to\n * @param chainId which underlying chain to bridge assets onto\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n **/\n function deposit(\n address to,\n uint256 chainId,\n IERC20 token,\n uint256 amount\n ) external {\n token.safeTransferFrom(msg.sender, address(this), amount);\n if (token.allowance(address(this), address(synapseBridge)) < amount) {\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n }\n synapseBridge.deposit(to, chainId, token, amount);\n }\n\n /**\n * @notice Wraps SynapseBridge deposit() function to make it compatible w/ ETH -> WETH conversions\n * @param to address on other chain to bridge assets to\n * @param chainId which chain to bridge assets onto\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n **/\n function depositETH(\n address to,\n uint256 chainId,\n uint256 amount\n ) external payable {\n require(msg.value > 0 && msg.value == amount, 'INCORRECT MSG VALUE');\n IWETH9(WETH_ADDRESS).deposit{value: msg.value}();\n synapseBridge.deposit(to, chainId, IERC20(WETH_ADDRESS), amount);\n }\n\n\n\n function swapETHAndRedeem(\n address to,\n uint256 chainId,\n IERC20 token,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx,\n uint256 minDy,\n uint256 deadline\n ) external payable {\n require(WETH_ADDRESS != address(0), \"WETH 0\");\n require(msg.value > 0 && msg.value == dx, \"INCORRECT MSG VALUE\");\n ISwap swap = ISwap(swapMap[address(token)]);\n require(address(swap) != address(0), \"Swap is 0x00\");\n IWETH9(WETH_ADDRESS).deposit{value: msg.value}();\n\n // swap\n uint256 swappedAmount = swap.swap(\n tokenIndexFrom,\n tokenIndexTo,\n dx,\n minDy,\n deadline\n );\n synapseBridge.redeem(to, chainId, token, swappedAmount);\n }\n\n /**\n * @notice Wraps redeemAndSwap on SynapseBridge.sol\n * Relays to nodes that (typically) a wrapped synAsset ERC20 token has been burned and the underlying needs to be redeeemed on the native chain. This function indicates to the nodes that they should attempt to redeem the LP token for the underlying assets (E.g \"swap\" out of the LP token)\n * @param to address on other chain to redeem underlying assets to\n * @param chainId which underlying chain to bridge assets onto\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n * @param tokenIndexFrom the token the user wants to swap from\n * @param tokenIndexTo the token the user wants to swap to\n * @param minDy the min amount the user would like to receive, or revert to only minting the SynERC20 token crosschain.\n * @param deadline latest timestamp to accept this transaction\n **/\n function redeemAndSwap(\n address to,\n uint256 chainId,\n IERC20 token,\n uint256 amount,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 minDy,\n uint256 deadline\n ) external {\n token.safeTransferFrom(msg.sender, address(this), amount);\n if (token.allowance(address(this), address(synapseBridge)) < amount) {\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n }\n synapseBridge.redeemAndSwap(\n to,\n chainId,\n token,\n amount,\n tokenIndexFrom,\n tokenIndexTo,\n minDy,\n deadline\n );\n }\n\n /**\n * @notice Wraps redeemAndRemove on SynapseBridge\n * Relays to nodes that (typically) a wrapped synAsset ERC20 token has been burned and the underlying needs to be redeeemed on the native chain. This function indicates to the nodes that they should attempt to redeem the LP token for the underlying assets (E.g \"swap\" out of the LP token)\n * @param to address on other chain to redeem underlying assets to\n * @param chainId which underlying chain to bridge assets onto\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount of (typically) LP token to pass to the nodes to attempt to removeLiquidity() with to redeem for the underlying assets of the LP token\n * @param liqTokenIndex Specifies which of the underlying LP assets the nodes should attempt to redeem for\n * @param liqMinAmount Specifies the minimum amount of the underlying asset needed for the nodes to execute the redeem/swap\n * @param liqDeadline Specificies the deadline that the nodes are allowed to try to redeem/swap the LP token\n **/\n function redeemAndRemove(\n address to,\n uint256 chainId,\n IERC20 token,\n uint256 amount,\n uint8 liqTokenIndex,\n uint256 liqMinAmount,\n uint256 liqDeadline\n ) external {\n token.safeTransferFrom(msg.sender, address(this), amount);\n if (token.allowance(address(this), address(synapseBridge)) < amount) {\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n }\n synapseBridge.redeemAndRemove(\n to,\n chainId,\n token,\n amount,\n liqTokenIndex,\n liqMinAmount,\n liqDeadline\n );\n }\n}\n" + }, + "contracts/bridge/interfaces/ISwap.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.6.12;\n\nimport '@openzeppelin/contracts/token/ERC20/ERC20.sol';\n\ninterface ISwap {\n // pool data view functions\n function getA() external view returns (uint256);\n\n function getToken(uint8 index) external view returns (IERC20);\n\n function getTokenIndex(address tokenAddress) external view returns (uint8);\n\n function getTokenBalance(uint8 index) external view returns (uint256);\n\n function getVirtualPrice() external view returns (uint256);\n\n // min return calculation functions\n function calculateSwap(\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx\n ) external view returns (uint256);\n\n function calculateTokenAmount(uint256[] calldata amounts, bool deposit)\n external\n view\n returns (uint256);\n\n function calculateRemoveLiquidity(uint256 amount)\n external\n view\n returns (uint256[] memory);\n\n function calculateRemoveLiquidityOneToken(\n uint256 tokenAmount,\n uint8 tokenIndex\n ) external view returns (uint256 availableTokenAmount);\n\n // state modifying functions\n function initialize(\n IERC20[] memory pooledTokens,\n uint8[] memory decimals,\n string memory lpTokenName,\n string memory lpTokenSymbol,\n uint256 a,\n uint256 fee,\n uint256 adminFee,\n address lpTokenTargetAddress\n ) external;\n\n function swap(\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx,\n uint256 minDy,\n uint256 deadline\n ) external returns (uint256);\n\n function addLiquidity(\n uint256[] calldata amounts,\n uint256 minToMint,\n uint256 deadline\n ) external returns (uint256);\n\n function removeLiquidity(\n uint256 amount,\n uint256[] calldata minAmounts,\n uint256 deadline\n ) external returns (uint256[] memory);\n\n function removeLiquidityOneToken(\n uint256 tokenAmount,\n uint8 tokenIndex,\n uint256 minAmount,\n uint256 deadline\n ) external returns (uint256);\n\n function removeLiquidityImbalance(\n uint256[] calldata amounts,\n uint256 maxBurnAmount,\n uint256 deadline\n ) external returns (uint256);\n}\n" + }, + "contracts/bridge/interfaces/IWETH9.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.4.0;\n\ninterface IWETH9 {\n function name() external view returns (string memory);\n\n function symbol() external view returns (string memory);\n\n function decimals() external view returns (uint8);\n\n function balanceOf(address) external view returns (uint256);\n\n function allowance(address, address) external view returns (uint256);\n\n receive() external payable;\n\n function deposit() external payable;\n\n function withdraw(uint256 wad) external;\n\n function totalSupply() external view returns (uint256);\n\n function approve(address guy, uint256 wad) external returns (bool);\n\n function transfer(address dst, uint256 wad) external returns (bool);\n\n function transferFrom(\n address src,\n address dst,\n uint256 wad\n ) external returns (bool);\n}" + }, + "contracts/bridge/wrappers/L2BridgeZap.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.6.12;\n\nimport \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/SafeERC20.sol\";\nimport \"../interfaces/ISwap.sol\";\nimport \"../interfaces/ISynapseBridge.sol\";\nimport \"../interfaces/IWETH9.sol\";\n\ncontract L2BridgeZap {\n using SafeERC20 for IERC20;\n\n ISynapseBridge synapseBridge;\n address payable public immutable WETH_ADDRESS;\n\n mapping(address => address) public swapMap;\n mapping(address => IERC20[]) public swapTokensMap;\n\n uint256 constant MAX_UINT256 = 2**256 - 1;\n\n constructor(\n address payable _wethAddress,\n address _swapOne,\n address tokenOne,\n address _swapTwo,\n address tokenTwo,\n ISynapseBridge _synapseBridge\n ) public {\n WETH_ADDRESS = _wethAddress;\n synapseBridge = _synapseBridge;\n swapMap[tokenOne] = _swapOne;\n swapMap[tokenTwo] = _swapTwo;\n if (_wethAddress != address(0)) {\n IERC20(_wethAddress).safeIncreaseAllowance(address(_synapseBridge), MAX_UINT256);\n }\n if (address(_swapOne) != address(0)) {\n {\n uint8 i;\n for (; i < 32; i++) {\n try ISwap(_swapOne).getToken(i) returns (\n IERC20 token\n ) {\n swapTokensMap[_swapOne].push(token);\n token.safeApprove(address(_swapOne), MAX_UINT256);\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n } catch {\n break;\n }\n }\n require(i > 1, \"swap must have at least 2 tokens\");\n }\n }\n if (address(_swapTwo) != address(0)) {\n {\n uint8 i;\n for (; i < 32; i++) {\n try ISwap(_swapTwo).getToken(i) returns (\n IERC20 token\n ) {\n swapTokensMap[_swapTwo].push(token);\n token.safeApprove(address(_swapTwo), MAX_UINT256);\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n } catch {\n break;\n }\n }\n require(i > 1, \"swap must have at least 2 tokens\");\n }\n }\n }\n\n /**\n * @notice Calculate amount of tokens you receive on swap\n * @param tokenIndexFrom the token the user wants to sell\n * @param tokenIndexTo the token the user wants to buy\n * @param dx the amount of tokens the user wants to sell. If the token charges\n * a fee on transfers, use the amount that gets transferred after the fee.\n * @return amount of tokens the user will receive\n */\n function calculateSwap(\n IERC20 token,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx\n ) external view virtual returns (uint256) {\n ISwap swap = ISwap(\n swapMap[address(token)]\n );\n return swap.calculateSwap(tokenIndexFrom, tokenIndexTo, dx);\n }\n\n function swapAndRedeem(\n address to,\n uint256 chainId,\n IERC20 token,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx,\n uint256 minDy,\n uint256 deadline\n ) external {\n ISwap swap = ISwap(swapMap[address(token)]);\n require(address(swap) != address(0), \"Swap is 0x00\");\n IERC20[] memory tokens = swapTokensMap[address(swap)];\n tokens[tokenIndexFrom].safeTransferFrom(\n msg.sender,\n address(this),\n dx\n );\n // swap\n\n uint256 swappedAmount = swap.swap(\n tokenIndexFrom,\n tokenIndexTo,\n dx,\n minDy,\n deadline\n );\n // deposit into bridge, gets nUSD\n if (\n token.allowance(address(this), address(synapseBridge)) <\n swappedAmount\n ) {\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n }\n synapseBridge.redeem(to, chainId, token, swappedAmount);\n }\n\n function swapAndRedeemAndSwap(\n address to,\n uint256 chainId,\n IERC20 token,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx,\n uint256 minDy,\n uint256 deadline,\n uint8 swapTokenIndexFrom,\n uint8 swapTokenIndexTo,\n uint256 swapMinDy,\n uint256 swapDeadline\n ) external {\n require(\n address(swapMap[address(token)]) != address(0),\n \"Swap is 0x00\"\n );\n IERC20[] memory tokens = swapTokensMap[\n swapMap[address(token)]\n ];\n tokens[tokenIndexFrom].safeTransferFrom(\n msg.sender,\n address(this),\n dx\n );\n // swap\n\n uint256 swappedAmount = ISwap(swapMap[address(token)]).swap(tokenIndexFrom, tokenIndexTo, dx, minDy, deadline);\n // deposit into bridge, gets nUSD\n if (\n token.allowance(address(this), address(synapseBridge)) <\n swappedAmount\n ) {\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n }\n synapseBridge.redeemAndSwap(\n to,\n chainId,\n token,\n swappedAmount,\n swapTokenIndexFrom,\n swapTokenIndexTo,\n swapMinDy,\n swapDeadline\n );\n }\n\n function swapAndRedeemAndRemove(\n address to,\n uint256 chainId,\n IERC20 token,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx,\n uint256 minDy,\n uint256 deadline,\n uint8 liqTokenIndex,\n uint256 liqMinAmount,\n uint256 liqDeadline\n ) external {\n ISwap swap = ISwap(swapMap[address(token)]);\n require(address(swap) != address(0), \"Swap is 0x00\");\n IERC20[] memory tokens = swapTokensMap[address(swap)];\n tokens[tokenIndexFrom].safeTransferFrom(\n msg.sender,\n address(this),\n dx\n );\n // swap\n\n uint256 swappedAmount = swap.swap(\n tokenIndexFrom,\n tokenIndexTo,\n dx,\n minDy,\n deadline\n );\n // deposit into bridge, gets nUSD\n if (\n token.allowance(address(this), address(synapseBridge)) <\n swappedAmount\n ) {\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n }\n synapseBridge.redeemAndRemove(\n to,\n chainId,\n token,\n swappedAmount,\n liqTokenIndex,\n liqMinAmount,\n liqDeadline\n );\n }\n\n /**\n * @notice wraps SynapseBridge redeem()\n * @param to address on other chain to redeem underlying assets to\n * @param chainId which underlying chain to bridge assets onto\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n **/\n function redeem(\n address to,\n uint256 chainId,\n IERC20 token,\n uint256 amount\n ) external {\n token.safeTransferFrom(msg.sender, address(this), amount);\n if (token.allowance(address(this), address(synapseBridge)) < amount) {\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n }\n synapseBridge.redeem(to, chainId, token, amount);\n }\n\n /**\n * @notice wraps SynapseBridge redeem()\n * @param to address on other chain to redeem underlying assets to\n * @param chainId which underlying chain to bridge assets onto\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n **/\n function deposit(\n address to,\n uint256 chainId,\n IERC20 token,\n uint256 amount\n ) external {\n token.safeTransferFrom(msg.sender, address(this), amount);\n if (token.allowance(address(this), address(synapseBridge)) < amount) {\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n }\n synapseBridge.deposit(to, chainId, token, amount);\n }\n\n /**\n * @notice Wraps SynapseBridge deposit() function to make it compatible w/ ETH -> WETH conversions\n * @param to address on other chain to bridge assets to\n * @param chainId which chain to bridge assets onto\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n **/\n function depositETH(\n address to,\n uint256 chainId,\n uint256 amount\n ) external payable {\n require(msg.value > 0 && msg.value == amount, 'INCORRECT MSG VALUE');\n IWETH9(WETH_ADDRESS).deposit{value: msg.value}();\n synapseBridge.deposit(to, chainId, IERC20(WETH_ADDRESS), amount);\n }\n\n\n /**\n * @notice Wraps SynapseBridge depositAndSwap() function to make it compatible w/ ETH -> WETH conversions\n * @param to address on other chain to bridge assets to\n * @param chainId which chain to bridge assets onto\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n * @param tokenIndexFrom the token the user wants to swap from\n * @param tokenIndexTo the token the user wants to swap to\n * @param minDy the min amount the user would like to receive, or revert to only minting the SynERC20 token crosschain.\n * @param deadline latest timestamp to accept this transaction\n **/\n function depositETHAndSwap(\n address to,\n uint256 chainId,\n uint256 amount,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 minDy,\n uint256 deadline\n ) external payable {\n require(msg.value > 0 && msg.value == amount, 'INCORRECT MSG VALUE');\n IWETH9(WETH_ADDRESS).deposit{value: msg.value}();\n synapseBridge.depositAndSwap(to, chainId, IERC20(WETH_ADDRESS), amount, tokenIndexFrom, tokenIndexTo, minDy, deadline);\n }\n\n\n function swapETHAndRedeem(\n address to,\n uint256 chainId,\n IERC20 token,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx,\n uint256 minDy,\n uint256 deadline\n ) external payable {\n require(WETH_ADDRESS != address(0), \"WETH 0\");\n require(msg.value > 0 && msg.value == dx, \"INCORRECT MSG VALUE\");\n ISwap swap = ISwap(swapMap[address(token)]);\n require(address(swap) != address(0), \"Swap is 0x00\");\n IWETH9(WETH_ADDRESS).deposit{value: msg.value}();\n\n // swap\n uint256 swappedAmount = swap.swap(\n tokenIndexFrom,\n tokenIndexTo,\n dx,\n minDy,\n deadline\n );\n synapseBridge.redeem(to, chainId, token, swappedAmount);\n }\n\n\n function swapETHAndRedeemAndSwap(\n address to,\n uint256 chainId,\n IERC20 token,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx,\n uint256 minDy,\n uint256 deadline,\n uint8 swapTokenIndexFrom,\n uint8 swapTokenIndexTo,\n uint256 swapMinDy,\n uint256 swapDeadline\n ) external payable {\n require(WETH_ADDRESS != address(0), \"WETH 0\");\n require(msg.value > 0 && msg.value == dx, \"INCORRECT MSG VALUE\");\n ISwap swap = ISwap(swapMap[address(token)]);\n require(address(swap) != address(0), \"Swap is 0x00\");\n IWETH9(WETH_ADDRESS).deposit{value: msg.value}();\n\n // swap\n uint256 swappedAmount = swap.swap(\n tokenIndexFrom,\n tokenIndexTo,\n dx,\n minDy,\n deadline\n );\n synapseBridge.redeemAndSwap(to, chainId, token, swappedAmount,swapTokenIndexFrom,\n swapTokenIndexTo,\n swapMinDy,\n swapDeadline);\n }\n\n\n /**\n * @notice Wraps redeemAndSwap on SynapseBridge.sol\n * Relays to nodes that (typically) a wrapped synAsset ERC20 token has been burned and the underlying needs to be redeeemed on the native chain. This function indicates to the nodes that they should attempt to redeem the LP token for the underlying assets (E.g \"swap\" out of the LP token)\n * @param to address on other chain to redeem underlying assets to\n * @param chainId which underlying chain to bridge assets onto\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n * @param tokenIndexFrom the token the user wants to swap from\n * @param tokenIndexTo the token the user wants to swap to\n * @param minDy the min amount the user would like to receive, or revert to only minting the SynERC20 token crosschain.\n * @param deadline latest timestamp to accept this transaction\n **/\n function redeemAndSwap(\n address to,\n uint256 chainId,\n IERC20 token,\n uint256 amount,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 minDy,\n uint256 deadline\n ) external {\n token.safeTransferFrom(msg.sender, address(this), amount);\n if (token.allowance(address(this), address(synapseBridge)) < amount) {\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n }\n synapseBridge.redeemAndSwap(\n to,\n chainId,\n token,\n amount,\n tokenIndexFrom,\n tokenIndexTo,\n minDy,\n deadline\n );\n }\n\n /**\n * @notice Wraps redeemAndRemove on SynapseBridge\n * Relays to nodes that (typically) a wrapped synAsset ERC20 token has been burned and the underlying needs to be redeeemed on the native chain. This function indicates to the nodes that they should attempt to redeem the LP token for the underlying assets (E.g \"swap\" out of the LP token)\n * @param to address on other chain to redeem underlying assets to\n * @param chainId which underlying chain to bridge assets onto\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount of (typically) LP token to pass to the nodes to attempt to removeLiquidity() with to redeem for the underlying assets of the LP token\n * @param liqTokenIndex Specifies which of the underlying LP assets the nodes should attempt to redeem for\n * @param liqMinAmount Specifies the minimum amount of the underlying asset needed for the nodes to execute the redeem/swap\n * @param liqDeadline Specificies the deadline that the nodes are allowed to try to redeem/swap the LP token\n **/\n function redeemAndRemove(\n address to,\n uint256 chainId,\n IERC20 token,\n uint256 amount,\n uint8 liqTokenIndex,\n uint256 liqMinAmount,\n uint256 liqDeadline\n ) external {\n token.safeTransferFrom(msg.sender, address(this), amount);\n if (token.allowance(address(this), address(synapseBridge)) < amount) {\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n }\n synapseBridge.redeemAndRemove(\n to,\n chainId,\n token,\n amount,\n liqTokenIndex,\n liqMinAmount,\n liqDeadline\n );\n }\n\n /**\n * @notice Wraps SynapseBridge redeemv2() function\n * @param to address on other chain to bridge assets to\n * @param chainId which chain to bridge assets onto\n * @param token ERC20 compatible token to redeem into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n **/\n function redeemv2(\n bytes32 to,\n uint256 chainId,\n IERC20 token,\n uint256 amount\n ) external {\n token.safeTransferFrom(msg.sender, address(this), amount);\n\n if (token.allowance(address(this), address(synapseBridge)) < amount) {\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n }\n synapseBridge.redeemv2(to, chainId, token, amount);\n }\n}\n" + }, + "contracts/bridge/wrappers/L1BridgeZap.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.6.12;\n\nimport '@openzeppelin/contracts/token/ERC20/IERC20.sol';\nimport '@openzeppelin/contracts/token/ERC20/SafeERC20.sol';\nimport '../interfaces/ISwap.sol';\nimport '../interfaces/ISynapseBridge.sol';\nimport \"../interfaces/IWETH9.sol\";\n\n\n/**\n * @title L1BridgeZap\n * @notice This contract is responsible for handling user Zaps into the SynapseBridge contract, through the Synapse Swap contracts. It does so\n * It does so by combining the action of addLiquidity() to the base swap pool, and then calling either deposit() or depositAndSwap() on the bridge.\n * This is done in hopes of automating portions of the bridge user experience to users, while keeping the SynapseBridge contract logic small.\n *\n * @dev This contract should be deployed with a base Swap.sol address and a SynapseBridge.sol address, otherwise, it will not function.\n */\ncontract L1BridgeZap {\n using SafeERC20 for IERC20;\n\n uint256 constant MAX_UINT256 = 2**256 - 1;\n \n ISwap baseSwap;\n ISynapseBridge synapseBridge;\n IERC20[] public baseTokens;\n address payable public immutable WETH_ADDRESS;\n \n\n /**\n * @notice Constructs the contract, approves each token inside of baseSwap to be used by baseSwap (needed for addLiquidity())\n */\n constructor(address payable _wethAddress, ISwap _baseSwap, ISynapseBridge _synapseBridge) public {\n WETH_ADDRESS = _wethAddress;\n baseSwap = _baseSwap;\n synapseBridge = _synapseBridge;\n IERC20(_wethAddress).safeIncreaseAllowance(address(_synapseBridge), MAX_UINT256);\n if (address(_baseSwap) != address(0)) {\n {\n uint8 i;\n for (; i < 32; i++) {\n try _baseSwap.getToken(i) returns (IERC20 token) {\n baseTokens.push(token);\n token.safeIncreaseAllowance(address(_baseSwap), MAX_UINT256);\n } catch {\n break;\n }\n }\n require(i > 1, 'baseSwap must have at least 2 tokens');\n }\n }\n }\n \n /**\n * @notice Wraps SynapseBridge deposit() function to make it compatible w/ ETH -> WETH conversions\n * @param to address on other chain to bridge assets to\n * @param chainId which chain to bridge assets onto\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n **/\n function depositETH(\n address to,\n uint256 chainId,\n uint256 amount\n ) external payable {\n require(msg.value > 0 && msg.value == amount, 'INCORRECT MSG VALUE');\n IWETH9(WETH_ADDRESS).deposit{value: msg.value}();\n synapseBridge.deposit(to, chainId, IERC20(WETH_ADDRESS), amount);\n }\n\n /**\n * @notice Wraps SynapseBridge depositAndSwap() function to make it compatible w/ ETH -> WETH conversions\n * @param to address on other chain to bridge assets to\n * @param chainId which chain to bridge assets onto\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n * @param tokenIndexFrom the token the user wants to swap from\n * @param tokenIndexTo the token the user wants to swap to\n * @param minDy the min amount the user would like to receive, or revert to only minting the SynERC20 token crosschain.\n * @param deadline latest timestamp to accept this transaction\n **/\n function depositETHAndSwap(\n address to,\n uint256 chainId,\n uint256 amount,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 minDy,\n uint256 deadline\n ) external payable {\n require(msg.value > 0 && msg.value == amount, 'INCORRECT MSG VALUE');\n IWETH9(WETH_ADDRESS).deposit{value: msg.value}();\n synapseBridge.depositAndSwap(to, chainId, IERC20(WETH_ADDRESS), amount, tokenIndexFrom, tokenIndexTo, minDy, deadline);\n }\n\n\n /**\n * @notice A simple method to calculate prices from deposits or\n * withdrawals, excluding fees but including slippage. This is\n * helpful as an input into the various \"min\" parameters on calls\n * to fight front-running\n *\n * @dev This shouldn't be used outside frontends for user estimates.\n *\n * @param amounts an array of token amounts to deposit or withdrawal,\n * corresponding to pooledTokens. The amount should be in each\n * pooled token's native precision.\n * @param deposit whether this is a deposit or a withdrawal\n * @return token amount the user will receive\n */\n function calculateTokenAmount(uint256[] calldata amounts, bool deposit)\n external\n view\n virtual\n returns (uint256)\n {\n return baseSwap.calculateTokenAmount(amounts, deposit);\n }\n\n /**\n * @notice Calculate the amount of underlying token available to withdraw\n * when withdrawing via only single token\n * @param tokenAmount the amount of LP token to burn\n * @param tokenIndex index of which token will be withdrawn\n * @return availableTokenAmount calculated amount of underlying token\n * available to withdraw\n */\n function calculateRemoveLiquidityOneToken(\n uint256 tokenAmount,\n uint8 tokenIndex\n ) external view virtual returns (uint256 availableTokenAmount) {\n return baseSwap.calculateRemoveLiquidityOneToken(tokenAmount, tokenIndex);\n }\n\n\n /**\n * @notice Combines adding liquidity to the given Swap, and calls deposit() on the bridge using that LP token\n * @param to address on other chain to bridge assets to\n * @param chainId which chain to bridge assets onto\n * @param token ERC20 compatible token to deposit into the bridge\n * @param liquidityAmounts the amounts of each token to add, in their native precision\n * @param minToMint the minimum LP tokens adding this amount of liquidity\n * should mint, otherwise revert. Handy for front-running mitigation\n * @param deadline latest timestamp to accept this transaction\n **/\n function zapAndDeposit(\n address to,\n uint256 chainId,\n IERC20 token,\n uint256[] calldata liquidityAmounts,\n uint256 minToMint,\n uint256 deadline\n ) external {\n // add liquidity\n for (uint256 i = 0; i < baseTokens.length; i++) {\n if (liquidityAmounts[i] != 0) {\n baseTokens[i].safeTransferFrom(\n msg.sender,\n address(this),\n liquidityAmounts[i]\n );\n }\n }\n\n uint256 liqAdded = baseSwap.addLiquidity(\n liquidityAmounts,\n minToMint,\n deadline\n );\n // deposit into bridge, gets nUSD\n if (token.allowance(address(this), address(synapseBridge)) < liqAdded) {\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n }\n synapseBridge.deposit(to, chainId, token, liqAdded);\n }\n\n /**\n * @notice Combines adding liquidity to the given Swap, and calls depositAndSwap() on the bridge using that LP token\n * @param to address on other chain to bridge assets to\n * @param chainId which chain to bridge assets onto\n * @param token ERC20 compatible token to deposit into the bridge\n * @param liquidityAmounts the amounts of each token to add, in their native precision\n * @param minToMint the minimum LP tokens adding this amount of liquidity\n * should mint, otherwise revert. Handy for front-running mitigation\n * @param liqDeadline latest timestamp to accept this transaction\n * @param tokenIndexFrom the token the user wants to swap from\n * @param tokenIndexTo the token the user wants to swap to\n * @param minDy the min amount the user would like to receive, or revert to only minting the SynERC20 token crosschain.\n * @param swapDeadline latest timestamp to accept this transaction\n **/\n function zapAndDepositAndSwap(\n address to,\n uint256 chainId,\n IERC20 token,\n uint256[] calldata liquidityAmounts,\n uint256 minToMint,\n uint256 liqDeadline,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 minDy,\n uint256 swapDeadline\n ) external {\n // add liquidity\n for (uint256 i = 0; i < baseTokens.length; i++) {\n if (liquidityAmounts[i] != 0) {\n baseTokens[i].safeTransferFrom(\n msg.sender,\n address(this),\n liquidityAmounts[i]\n );\n }\n }\n\n uint256 liqAdded = baseSwap.addLiquidity(\n liquidityAmounts,\n minToMint,\n liqDeadline\n );\n // deposit into bridge, bridge attemps to swap into desired asset\n if (token.allowance(address(this), address(synapseBridge)) < liqAdded) {\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n }\n synapseBridge.depositAndSwap(\n to,\n chainId,\n token,\n liqAdded,\n tokenIndexFrom,\n tokenIndexTo,\n minDy,\n swapDeadline\n );\n }\n\n /**\n * @notice Wraps SynapseBridge deposit() function\n * @param to address on other chain to bridge assets to\n * @param chainId which chain to bridge assets onto\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n **/\n function deposit(\n address to,\n uint256 chainId,\n IERC20 token,\n uint256 amount\n ) external {\n token.safeTransferFrom(msg.sender, address(this), amount);\n\n if (token.allowance(address(this), address(synapseBridge)) < amount) {\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n }\n synapseBridge.deposit(to, chainId, token, amount);\n }\n \n /**\n * @notice Wraps SynapseBridge depositAndSwap() function\n * @param to address on other chain to bridge assets to\n * @param chainId which chain to bridge assets onto\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n * @param tokenIndexFrom the token the user wants to swap from\n * @param tokenIndexTo the token the user wants to swap to\n * @param minDy the min amount the user would like to receive, or revert to only minting the SynERC20 token crosschain.\n * @param deadline latest timestamp to accept this transaction\n **/\n function depositAndSwap(\n address to,\n uint256 chainId,\n IERC20 token,\n uint256 amount,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 minDy,\n uint256 deadline\n ) external {\n token.safeTransferFrom(msg.sender, address(this), amount);\n \n if (token.allowance(address(this), address(synapseBridge)) < amount) {\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n }\n synapseBridge.depositAndSwap(to, chainId, token, amount, tokenIndexFrom, tokenIndexTo, minDy, deadline);\n }\n\n\n /**\n * @notice Wraps SynapseBridge redeem() function\n * @param to address on other chain to bridge assets to\n * @param chainId which chain to bridge assets onto\n * @param token ERC20 compatible token to redeem into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n **/\n function redeem(\n address to,\n uint256 chainId,\n IERC20 token,\n uint256 amount\n ) external {\n token.safeTransferFrom(msg.sender, address(this), amount);\n\n if (token.allowance(address(this), address(synapseBridge)) < amount) {\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n }\n synapseBridge.redeem(to, chainId, token, amount);\n }\n\n /**\n * @notice Wraps SynapseBridge redeemv2() function\n * @param to address on other chain to bridge assets to\n * @param chainId which chain to bridge assets onto\n * @param token ERC20 compatible token to redeem into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n **/\n function redeemv2(\n bytes32 to,\n uint256 chainId,\n IERC20 token,\n uint256 amount\n ) external {\n token.safeTransferFrom(msg.sender, address(this), amount);\n\n if (token.allowance(address(this), address(synapseBridge)) < amount) {\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n }\n synapseBridge.redeemv2(to, chainId, token, amount);\n }\n\n}\n" + }, + "contracts/bridge/wrappers/MigratorBridgeZap.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.6.12;\n\nimport '@openzeppelin/contracts/token/ERC20/IERC20.sol';\nimport '@openzeppelin/contracts/token/ERC20/SafeERC20.sol';\nimport '@openzeppelin/contracts/math/SafeMath.sol';\n\nimport '../interfaces/ISynapseBridge.sol';\nimport '../interfaces/IERC20Migrator.sol';\n\ncontract MigratorBridgeZap {\n using SafeERC20 for IERC20;\n using SafeMath for uint256;\n \n ISynapseBridge constant synapseBridge = ISynapseBridge(0xd123f70AE324d34A9E76b67a27bf77593bA8749f);\n IERC20Migrator constant erc20Migrator = IERC20Migrator(0xf0284FB86adA5E4D82555C529677eEA3B2C3E022); \n IERC20 constant legacyToken = IERC20(0x42F6f551ae042cBe50C739158b4f0CAC0Edb9096);\n IERC20 constant newToken = IERC20(0xa4080f1778e69467E905B8d6F72f6e441f9e9484);\n uint256 constant MAX_UINT256 = 2**256 - 1;\n\n constructor() public {\n legacyToken.safeApprove(address(erc20Migrator), MAX_UINT256);\n newToken.safeApprove(address(synapseBridge), MAX_UINT256);\n }\n\n function migrate(uint256 amount) external {\n legacyToken.safeTransferFrom(msg.sender, address(this), amount);\n erc20Migrator.migrate(amount);\n newToken.safeTransfer(msg.sender, amount.mul(5).div(2));\n }\n\n function migrateAndBridge(uint256 amount, address to, uint256 chainId) external {\n legacyToken.safeTransferFrom(msg.sender, address(this), amount);\n erc20Migrator.migrate(amount);\n synapseBridge.redeem(to, chainId, newToken, amount.mul(5).div(2));\n }\n}" + }, + "contracts/bridge/interfaces/IERC20Migrator.sol": { + "content": "// SPDX-License-Identifier: MIT\n\n\npragma solidity 0.6.12;\n\ninterface IERC20Migrator { \n function migrate(uint256 amount) external;\n}\n\n" + }, + "contracts/bridge/wrappers/JewelBridgeSwap.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.6.12;\n\nimport '@openzeppelin/contracts/token/ERC20/ERC20.sol';\nimport \"@openzeppelin/contracts/token/ERC20/SafeERC20.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/ERC20Burnable.sol\";\nimport \"@openzeppelin/contracts/math/SafeMath.sol\";\n\ninterface IERC20Mintable is IERC20 {\n function mint(address to, uint256 amount) external;\n}\n\ncontract JewelBridgeSwap {\n using SafeERC20 for IERC20;\n using SafeERC20 for IERC20Mintable;\n using SafeMath for uint256;\n\n // Maps token address to an index in the pool. Used to prevent duplicate tokens in the pool.\n // getTokenIndex function also relies on this mapping to retrieve token index.\n mapping(address => uint8) private tokenIndexes;\n IERC20[2] pooledTokens;\n \n constructor(IERC20 tokenA, IERC20 mintableTokenB) public {\n pooledTokens[0] = tokenA;\n pooledTokens[1] = mintableTokenB;\n tokenIndexes[address(tokenA)] = 0;\n tokenIndexes[address(mintableTokenB)] = 1;\n }\n\n /**\n * @notice Return address of the pooled token at given index. Reverts if tokenIndex is out of range.\n * @param index the index of the token\n * @return address of the token at given index\n */\n function getToken(uint8 index) public view returns (IERC20) {\n require(index < pooledTokens.length, \"Out of range\");\n return pooledTokens[index];\n }\n\n /**\n * @notice Return the index of the given token address. Reverts if no matching\n * token is found.\n * @param tokenAddress address of the token\n * @return the index of the given token address\n */\n function getTokenIndex(address tokenAddress)\n public\n view\n returns (uint8)\n {\n uint8 index = tokenIndexes[tokenAddress];\n require(\n address(getToken(index)) == tokenAddress,\n \"Token does not exist\"\n );\n return index;\n }\n\n /**\n * @notice Calculate amount of tokens you receive on swap\n * @param tokenIndexFrom the token the user wants to sell\n * @param tokenIndexTo the token the user wants to buy\n * @param dx the amount of tokens the user wants to swap. \n * @return amount of tokens the user will receive\n */\n function calculateSwap(\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx\n ) external view returns (uint256) {\n return dx;\n }\n\n /**\n * @notice Swap two tokens using this pool\n * @param tokenIndexFrom the token the user wants to swap from\n * @param tokenIndexTo the token the user wants to swap to\n * @param dx the amount of tokens the user wants to swap from\n * @param minDy the min amount the user would like to receive, or revert.\n * @param deadline latest timestamp to accept this transaction\n */\n function swap(\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx,\n uint256 minDy,\n uint256 deadline\n )\n external\n returns (uint256)\n {\n {\n IERC20 tokenFrom = pooledTokens[tokenIndexFrom];\n require(\n dx <= tokenFrom.balanceOf(msg.sender),\n \"Cannot swap more than you own\"\n );\n // Transfer tokens first to see if a fee was charged on transfer\n uint256 beforeBalance = tokenFrom.balanceOf(address(this));\n tokenFrom.safeTransferFrom(msg.sender, address(this), dx);\n\n // Use the actual transferred amount for AMM math\n dx = tokenFrom.balanceOf(address(this)).sub(beforeBalance);\n }\n\n // redeem JEWEL for synJEWEL\n if (tokenIndexFrom == 0 && tokenIndexTo == 1) {\n IERC20Mintable(address(pooledTokens[tokenIndexTo])).mint(msg.sender, dx);\n return dx;\n // redeem synJEWEL for JEWEL\n } else if (tokenIndexFrom == 1 && tokenIndexTo == 0) {\n ERC20Burnable(address(pooledTokens[tokenIndexFrom])).burn(dx);\n pooledTokens[tokenIndexTo].safeTransfer(msg.sender, dx);\n return dx;\n } else {\n revert(\"Unsupported indexes\");\n }\n }\n}" + }, + "contracts/bridge/testing/SynapseToken.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity >=0.6.0 <0.8.0;\n\n\nimport \"@openzeppelin/contracts/token/ERC20/ERC20.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/ERC20Burnable.sol\";\nimport \"@openzeppelin/contracts/access/AccessControl.sol\";\nimport \"@openzeppelin/contracts/drafts/ERC20Permit.sol\";\n\ncontract Synapse is ERC20, ERC20Burnable, AccessControl, ERC20Permit {\n bytes32 public constant MINTER_ROLE = keccak256(\"MINTER_ROLE\");\n\n constructor() public ERC20(\"Synapse\", \"SYN\") ERC20Permit(\"Synapse\") {\n _setupRole(DEFAULT_ADMIN_ROLE, msg.sender);\n _setupRole(MINTER_ROLE, msg.sender);\n }\n\n function mint(address to, uint256 amount) external {\n require(hasRole(MINTER_ROLE, msg.sender));\n _mint(to, amount);\n }\n}" + }, + "@openzeppelin/contracts/access/AccessControl.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <0.8.0;\n\nimport \"../utils/EnumerableSet.sol\";\nimport \"../utils/Address.sol\";\nimport \"../utils/Context.sol\";\n\n/**\n * @dev Contract module that allows children to implement role-based access\n * control mechanisms.\n *\n * Roles are referred to by their `bytes32` identifier. These should be exposed\n * in the external API and be unique. The best way to achieve this is by\n * using `public constant` hash digests:\n *\n * ```\n * bytes32 public constant MY_ROLE = keccak256(\"MY_ROLE\");\n * ```\n *\n * Roles can be used to represent a set of permissions. To restrict access to a\n * function call, use {hasRole}:\n *\n * ```\n * function foo() public {\n * require(hasRole(MY_ROLE, msg.sender));\n * ...\n * }\n * ```\n *\n * Roles can be granted and revoked dynamically via the {grantRole} and\n * {revokeRole} functions. Each role has an associated admin role, and only\n * accounts that have a role's admin role can call {grantRole} and {revokeRole}.\n *\n * By default, the admin role for all roles is `DEFAULT_ADMIN_ROLE`, which means\n * that only accounts with this role will be able to grant or revoke other\n * roles. More complex role relationships can be created by using\n * {_setRoleAdmin}.\n *\n * WARNING: The `DEFAULT_ADMIN_ROLE` is also its own admin: it has permission to\n * grant and revoke this role. Extra precautions should be taken to secure\n * accounts that have been granted it.\n */\nabstract contract AccessControl is Context {\n using EnumerableSet for EnumerableSet.AddressSet;\n using Address for address;\n\n struct RoleData {\n EnumerableSet.AddressSet members;\n bytes32 adminRole;\n }\n\n mapping (bytes32 => RoleData) private _roles;\n\n bytes32 public constant DEFAULT_ADMIN_ROLE = 0x00;\n\n /**\n * @dev Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole`\n *\n * `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite\n * {RoleAdminChanged} not being emitted signaling this.\n *\n * _Available since v3.1._\n */\n event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole);\n\n /**\n * @dev Emitted when `account` is granted `role`.\n *\n * `sender` is the account that originated the contract call, an admin role\n * bearer except when using {_setupRole}.\n */\n event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender);\n\n /**\n * @dev Emitted when `account` is revoked `role`.\n *\n * `sender` is the account that originated the contract call:\n * - if using `revokeRole`, it is the admin role bearer\n * - if using `renounceRole`, it is the role bearer (i.e. `account`)\n */\n event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender);\n\n /**\n * @dev Returns `true` if `account` has been granted `role`.\n */\n function hasRole(bytes32 role, address account) public view returns (bool) {\n return _roles[role].members.contains(account);\n }\n\n /**\n * @dev Returns the number of accounts that have `role`. Can be used\n * together with {getRoleMember} to enumerate all bearers of a role.\n */\n function getRoleMemberCount(bytes32 role) public view returns (uint256) {\n return _roles[role].members.length();\n }\n\n /**\n * @dev Returns one of the accounts that have `role`. `index` must be a\n * value between 0 and {getRoleMemberCount}, non-inclusive.\n *\n * Role bearers are not sorted in any particular way, and their ordering may\n * change at any point.\n *\n * WARNING: When using {getRoleMember} and {getRoleMemberCount}, make sure\n * you perform all queries on the same block. See the following\n * https://forum.openzeppelin.com/t/iterating-over-elements-on-enumerableset-in-openzeppelin-contracts/2296[forum post]\n * for more information.\n */\n function getRoleMember(bytes32 role, uint256 index) public view returns (address) {\n return _roles[role].members.at(index);\n }\n\n /**\n * @dev Returns the admin role that controls `role`. See {grantRole} and\n * {revokeRole}.\n *\n * To change a role's admin, use {_setRoleAdmin}.\n */\n function getRoleAdmin(bytes32 role) public view returns (bytes32) {\n return _roles[role].adminRole;\n }\n\n /**\n * @dev Grants `role` to `account`.\n *\n * If `account` had not been already granted `role`, emits a {RoleGranted}\n * event.\n *\n * Requirements:\n *\n * - the caller must have ``role``'s admin role.\n */\n function grantRole(bytes32 role, address account) public virtual {\n require(hasRole(_roles[role].adminRole, _msgSender()), \"AccessControl: sender must be an admin to grant\");\n\n _grantRole(role, account);\n }\n\n /**\n * @dev Revokes `role` from `account`.\n *\n * If `account` had been granted `role`, emits a {RoleRevoked} event.\n *\n * Requirements:\n *\n * - the caller must have ``role``'s admin role.\n */\n function revokeRole(bytes32 role, address account) public virtual {\n require(hasRole(_roles[role].adminRole, _msgSender()), \"AccessControl: sender must be an admin to revoke\");\n\n _revokeRole(role, account);\n }\n\n /**\n * @dev Revokes `role` from the calling account.\n *\n * Roles are often managed via {grantRole} and {revokeRole}: this function's\n * purpose is to provide a mechanism for accounts to lose their privileges\n * if they are compromised (such as when a trusted device is misplaced).\n *\n * If the calling account had been granted `role`, emits a {RoleRevoked}\n * event.\n *\n * Requirements:\n *\n * - the caller must be `account`.\n */\n function renounceRole(bytes32 role, address account) public virtual {\n require(account == _msgSender(), \"AccessControl: can only renounce roles for self\");\n\n _revokeRole(role, account);\n }\n\n /**\n * @dev Grants `role` to `account`.\n *\n * If `account` had not been already granted `role`, emits a {RoleGranted}\n * event. Note that unlike {grantRole}, this function doesn't perform any\n * checks on the calling account.\n *\n * [WARNING]\n * ====\n * This function should only be called from the constructor when setting\n * up the initial roles for the system.\n *\n * Using this function in any other way is effectively circumventing the admin\n * system imposed by {AccessControl}.\n * ====\n */\n function _setupRole(bytes32 role, address account) internal virtual {\n _grantRole(role, account);\n }\n\n /**\n * @dev Sets `adminRole` as ``role``'s admin role.\n *\n * Emits a {RoleAdminChanged} event.\n */\n function _setRoleAdmin(bytes32 role, bytes32 adminRole) internal virtual {\n emit RoleAdminChanged(role, _roles[role].adminRole, adminRole);\n _roles[role].adminRole = adminRole;\n }\n\n function _grantRole(bytes32 role, address account) private {\n if (_roles[role].members.add(account)) {\n emit RoleGranted(role, account, _msgSender());\n }\n }\n\n function _revokeRole(bytes32 role, address account) private {\n if (_roles[role].members.remove(account)) {\n emit RoleRevoked(role, account, _msgSender());\n }\n }\n}\n" + }, + "@openzeppelin/contracts/drafts/ERC20Permit.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.5 <0.8.0;\n\nimport \"../token/ERC20/ERC20.sol\";\nimport \"./IERC20Permit.sol\";\nimport \"../cryptography/ECDSA.sol\";\nimport \"../utils/Counters.sol\";\nimport \"./EIP712.sol\";\n\n/**\n * @dev Implementation of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in\n * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612].\n *\n * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by\n * presenting a message signed by the account. By not relying on `{IERC20-approve}`, the token holder account doesn't\n * need to send a transaction, and thus is not required to hold Ether at all.\n *\n * _Available since v3.4._\n */\nabstract contract ERC20Permit is ERC20, IERC20Permit, EIP712 {\n using Counters for Counters.Counter;\n\n mapping (address => Counters.Counter) private _nonces;\n\n // solhint-disable-next-line var-name-mixedcase\n bytes32 private immutable _PERMIT_TYPEHASH = keccak256(\"Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)\");\n\n /**\n * @dev Initializes the {EIP712} domain separator using the `name` parameter, and setting `version` to `\"1\"`.\n *\n * It's a good idea to use the same `name` that is defined as the ERC20 token name.\n */\n constructor(string memory name) internal EIP712(name, \"1\") {\n }\n\n /**\n * @dev See {IERC20Permit-permit}.\n */\n function permit(address owner, address spender, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s) public virtual override {\n // solhint-disable-next-line not-rely-on-time\n require(block.timestamp <= deadline, \"ERC20Permit: expired deadline\");\n\n bytes32 structHash = keccak256(\n abi.encode(\n _PERMIT_TYPEHASH,\n owner,\n spender,\n value,\n _nonces[owner].current(),\n deadline\n )\n );\n\n bytes32 hash = _hashTypedDataV4(structHash);\n\n address signer = ECDSA.recover(hash, v, r, s);\n require(signer == owner, \"ERC20Permit: invalid signature\");\n\n _nonces[owner].increment();\n _approve(owner, spender, value);\n }\n\n /**\n * @dev See {IERC20Permit-nonces}.\n */\n function nonces(address owner) public view override returns (uint256) {\n return _nonces[owner].current();\n }\n\n /**\n * @dev See {IERC20Permit-DOMAIN_SEPARATOR}.\n */\n // solhint-disable-next-line func-name-mixedcase\n function DOMAIN_SEPARATOR() external view override returns (bytes32) {\n return _domainSeparatorV4();\n }\n}\n" + }, + "@openzeppelin/contracts/utils/EnumerableSet.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <0.8.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" + }, + "@openzeppelin/contracts/drafts/IERC20Permit.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <0.8.0;\n\n/**\n * @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in\n * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612].\n *\n * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by\n * presenting a message signed by the account. By not relying on `{IERC20-approve}`, the token holder account doesn't\n * need to send a transaction, and thus is not required to hold Ether at all.\n */\ninterface IERC20Permit {\n /**\n * @dev Sets `value` as the allowance of `spender` over `owner`'s tokens,\n * given `owner`'s signed approval.\n *\n * IMPORTANT: The same issues {IERC20-approve} has related to transaction\n * ordering also apply here.\n *\n * Emits an {Approval} event.\n *\n * Requirements:\n *\n * - `spender` cannot be the zero address.\n * - `deadline` must be a timestamp in the future.\n * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner`\n * over the EIP712-formatted function arguments.\n * - the signature must use ``owner``'s current nonce (see {nonces}).\n *\n * For more information on the signature format, see the\n * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP\n * section].\n */\n function permit(address owner, address spender, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s) external;\n\n /**\n * @dev Returns the current nonce for `owner`. This value must be\n * included whenever a signature is generated for {permit}.\n *\n * Every successful call to {permit} increases ``owner``'s nonce by one. This\n * prevents a signature from being used multiple times.\n */\n function nonces(address owner) external view returns (uint256);\n\n /**\n * @dev Returns the domain separator used in the encoding of the signature for `permit`, as defined by {EIP712}.\n */\n // solhint-disable-next-line func-name-mixedcase\n function DOMAIN_SEPARATOR() external view returns (bytes32);\n}\n" + }, + "@openzeppelin/contracts/cryptography/ECDSA.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <0.8.0;\n\n/**\n * @dev Elliptic Curve Digital Signature Algorithm (ECDSA) operations.\n *\n * These functions can be used to verify that a message was signed by the holder\n * of the private keys of a given address.\n */\nlibrary ECDSA {\n /**\n * @dev Returns the address that signed a hashed message (`hash`) with\n * `signature`. This address can then be used for verification purposes.\n *\n * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:\n * this function rejects them by requiring the `s` value to be in the lower\n * half order, and the `v` value to be either 27 or 28.\n *\n * IMPORTANT: `hash` _must_ be the result of a hash operation for the\n * verification to be secure: it is possible to craft signatures that\n * recover to arbitrary addresses for non-hashed data. A safe way to ensure\n * this is by receiving a hash of the original message (which may otherwise\n * be too long), and then calling {toEthSignedMessageHash} on it.\n */\n function recover(bytes32 hash, bytes memory signature) internal pure returns (address) {\n // Check the signature length\n if (signature.length != 65) {\n revert(\"ECDSA: invalid signature length\");\n }\n\n // Divide the signature in r, s and v variables\n bytes32 r;\n bytes32 s;\n uint8 v;\n\n // ecrecover takes the signature parameters, and the only way to get them\n // currently is to use assembly.\n // solhint-disable-next-line no-inline-assembly\n assembly {\n r := mload(add(signature, 0x20))\n s := mload(add(signature, 0x40))\n v := byte(0, mload(add(signature, 0x60)))\n }\n\n return recover(hash, v, r, s);\n }\n\n /**\n * @dev Overload of {ECDSA-recover-bytes32-bytes-} that receives the `v`,\n * `r` and `s` signature fields separately.\n */\n function recover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) internal pure returns (address) {\n // EIP-2 still allows signature malleability for ecrecover(). Remove this possibility and make the signature\n // unique. Appendix F in the Ethereum Yellow paper (https://ethereum.github.io/yellowpaper/paper.pdf), defines\n // the valid range for s in (281): 0 < s < secp256k1n ÷ 2 + 1, and for v in (282): v ∈ {27, 28}. Most\n // signatures from current libraries generate a unique signature with an s-value in the lower half order.\n //\n // If your library generates malleable signatures, such as s-values in the upper range, calculate a new s-value\n // with 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 - s1 and flip v from 27 to 28 or\n // vice versa. If your library also generates signatures with 0/1 for v instead 27/28, add 27 to v to accept\n // these malleable signatures as well.\n require(uint256(s) <= 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0, \"ECDSA: invalid signature 's' value\");\n require(v == 27 || v == 28, \"ECDSA: invalid signature 'v' value\");\n\n // If the signature is valid (and not malleable), return the signer address\n address signer = ecrecover(hash, v, r, s);\n require(signer != address(0), \"ECDSA: invalid signature\");\n\n return signer;\n }\n\n /**\n * @dev Returns an Ethereum Signed Message, created from a `hash`. This\n * replicates the behavior of the\n * https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_sign[`eth_sign`]\n * JSON-RPC method.\n *\n * See {recover}.\n */\n function toEthSignedMessageHash(bytes32 hash) internal pure returns (bytes32) {\n // 32 is the length in bytes of hash,\n // enforced by the type signature above\n return keccak256(abi.encodePacked(\"\\x19Ethereum Signed Message:\\n32\", hash));\n }\n}\n" + }, + "@openzeppelin/contracts/utils/Counters.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <0.8.0;\n\nimport \"../math/SafeMath.sol\";\n\n/**\n * @title Counters\n * @author Matt Condon (@shrugs)\n * @dev Provides counters that can only be incremented or decremented by one. This can be used e.g. to track the number\n * of elements in a mapping, issuing ERC721 ids, or counting request ids.\n *\n * Include with `using Counters for Counters.Counter;`\n * Since it is not possible to overflow a 256 bit integer with increments of one, `increment` can skip the {SafeMath}\n * overflow check, thereby saving gas. This does assume however correct usage, in that the underlying `_value` is never\n * directly accessed.\n */\nlibrary Counters {\n using SafeMath for uint256;\n\n struct Counter {\n // This variable should never be directly accessed by users of the library: interactions must be restricted to\n // the library's function. As of Solidity v0.5.2, this cannot be enforced, though there is a proposal to add\n // this feature: see https://github.com/ethereum/solidity/issues/4637\n uint256 _value; // default: 0\n }\n\n function current(Counter storage counter) internal view returns (uint256) {\n return counter._value;\n }\n\n function increment(Counter storage counter) internal {\n // The {SafeMath} overflow check can be skipped here, see the comment at the top\n counter._value += 1;\n }\n\n function decrement(Counter storage counter) internal {\n counter._value = counter._value.sub(1);\n }\n}\n" + }, + "@openzeppelin/contracts/drafts/EIP712.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <0.8.0;\n\n/**\n * @dev https://eips.ethereum.org/EIPS/eip-712[EIP 712] is a standard for hashing and signing of typed structured data.\n *\n * The encoding specified in the EIP is very generic, and such a generic implementation in Solidity is not feasible,\n * thus this contract does not implement the encoding itself. Protocols need to implement the type-specific encoding\n * they need in their contracts using a combination of `abi.encode` and `keccak256`.\n *\n * This contract implements the EIP 712 domain separator ({_domainSeparatorV4}) that is used as part of the encoding\n * scheme, and the final step of the encoding to obtain the message digest that is then signed via ECDSA\n * ({_hashTypedDataV4}).\n *\n * The implementation of the domain separator was designed to be as efficient as possible while still properly updating\n * the chain id to protect against replay attacks on an eventual fork of the chain.\n *\n * NOTE: This contract implements the version of the encoding known as \"v4\", as implemented by the JSON RPC method\n * https://docs.metamask.io/guide/signing-data.html[`eth_signTypedDataV4` in MetaMask].\n *\n * _Available since v3.4._\n */\nabstract contract EIP712 {\n /* solhint-disable var-name-mixedcase */\n // Cache the domain separator as an immutable value, but also store the chain id that it corresponds to, in order to\n // invalidate the cached domain separator if the chain id changes.\n bytes32 private immutable _CACHED_DOMAIN_SEPARATOR;\n uint256 private immutable _CACHED_CHAIN_ID;\n\n bytes32 private immutable _HASHED_NAME;\n bytes32 private immutable _HASHED_VERSION;\n bytes32 private immutable _TYPE_HASH;\n /* solhint-enable var-name-mixedcase */\n\n /**\n * @dev Initializes the domain separator and parameter caches.\n *\n * The meaning of `name` and `version` is specified in\n * https://eips.ethereum.org/EIPS/eip-712#definition-of-domainseparator[EIP 712]:\n *\n * - `name`: the user readable name of the signing domain, i.e. the name of the DApp or the protocol.\n * - `version`: the current major version of the signing domain.\n *\n * NOTE: These parameters cannot be changed except through a xref:learn::upgrading-smart-contracts.adoc[smart\n * contract upgrade].\n */\n constructor(string memory name, string memory version) internal {\n bytes32 hashedName = keccak256(bytes(name));\n bytes32 hashedVersion = keccak256(bytes(version));\n bytes32 typeHash = keccak256(\"EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)\");\n _HASHED_NAME = hashedName;\n _HASHED_VERSION = hashedVersion;\n _CACHED_CHAIN_ID = _getChainId();\n _CACHED_DOMAIN_SEPARATOR = _buildDomainSeparator(typeHash, hashedName, hashedVersion);\n _TYPE_HASH = typeHash;\n }\n\n /**\n * @dev Returns the domain separator for the current chain.\n */\n function _domainSeparatorV4() internal view virtual returns (bytes32) {\n if (_getChainId() == _CACHED_CHAIN_ID) {\n return _CACHED_DOMAIN_SEPARATOR;\n } else {\n return _buildDomainSeparator(_TYPE_HASH, _HASHED_NAME, _HASHED_VERSION);\n }\n }\n\n function _buildDomainSeparator(bytes32 typeHash, bytes32 name, bytes32 version) private view returns (bytes32) {\n return keccak256(\n abi.encode(\n typeHash,\n name,\n version,\n _getChainId(),\n address(this)\n )\n );\n }\n\n /**\n * @dev Given an already https://eips.ethereum.org/EIPS/eip-712#definition-of-hashstruct[hashed struct], this\n * function returns the hash of the fully encoded EIP712 message for this domain.\n *\n * This hash can be used together with {ECDSA-recover} to obtain the signer of a message. For example:\n *\n * ```solidity\n * bytes32 digest = _hashTypedDataV4(keccak256(abi.encode(\n * keccak256(\"Mail(address to,string contents)\"),\n * mailTo,\n * keccak256(bytes(mailContents))\n * )));\n * address signer = ECDSA.recover(digest, signature);\n * ```\n */\n function _hashTypedDataV4(bytes32 structHash) internal view virtual returns (bytes32) {\n return keccak256(abi.encodePacked(\"\\x19\\x01\", _domainSeparatorV4(), structHash));\n }\n\n function _getChainId() private view returns (uint256 chainId) {\n this; // silence state mutability warning without generating bytecode - see https://github.com/ethereum/solidity/issues/2691\n // solhint-disable-next-line no-inline-assembly\n assembly {\n chainId := chainid()\n }\n }\n}\n" + }, + "contracts/bridge/mocks/ERC20Mock.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.6.12;\n\nimport \"@openzeppelin/contracts/token/ERC20/ERC20.sol\";\n\ncontract ERC20Mock is ERC20 {\n constructor(\n string memory name,\n string memory symbol,\n uint256 supply\n ) public ERC20(name, symbol) {\n _mint(msg.sender, supply);\n }\n\n function mint(address to, uint256 amount) external {\n _mint(to, amount);\n }\n}" + }, + "contracts/bridge/interfaces/IMetaSwapDeposit.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.6.12;\nimport '@openzeppelin/contracts/token/ERC20/ERC20.sol';\n\n/**\n * @title IMetaSwapDeposit interface\n * @notice Interface for the meta swap contract.\n * @dev implement this interface to develop a a factory-patterned ECDSA node management contract\n **/\ninterface IMetaSwapDeposit {\n // min return calculation functions\n function calculateSwap(\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx\n ) external view returns (uint256);\n\n function swap(\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx,\n uint256 minDy,\n uint256 deadline\n ) external returns (uint256);\n\n function getToken(uint256 index) external view returns (IERC20);\n}\n" + }, + "contracts/amm/interfaces/IMetaSwapDeposit.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.6.12;\n\nimport \"@openzeppelin/contracts/token/ERC20/ERC20.sol\";\nimport \"./ISwap.sol\";\nimport \"./IMetaSwap.sol\";\n\ninterface IMetaSwapDeposit {\n function initialize(\n ISwap baseSwap_,\n IMetaSwap metaSwap_,\n IERC20 metaLPToken_\n ) external;\n}\n" + }, + "contracts/amm/interfaces/IMetaSwap.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.6.12;\n\nimport \"@openzeppelin/contracts/token/ERC20/ERC20.sol\";\n\ninterface IMetaSwap {\n // pool data view functions\n function getA() external view returns (uint256);\n\n function getToken(uint8 index) external view returns (IERC20);\n\n function getTokenIndex(address tokenAddress) external view returns (uint8);\n\n function getTokenBalance(uint8 index) external view returns (uint256);\n\n function getVirtualPrice() external view returns (uint256);\n\n function isGuarded() external view returns (bool);\n\n // min return calculation functions\n function calculateSwap(\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx\n ) external view returns (uint256);\n\n function calculateSwapUnderlying(\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx\n ) external view returns (uint256);\n\n function calculateTokenAmount(uint256[] calldata amounts, bool deposit)\n external\n view\n returns (uint256);\n\n function calculateRemoveLiquidity(uint256 amount)\n external\n view\n returns (uint256[] memory);\n\n function calculateRemoveLiquidityOneToken(\n uint256 tokenAmount,\n uint8 tokenIndex\n ) external view returns (uint256 availableTokenAmount);\n\n // state modifying functions\n function initializeMetaSwap(\n IERC20[] memory pooledTokens,\n uint8[] memory decimals,\n string memory lpTokenName,\n string memory lpTokenSymbol,\n uint256 a,\n uint256 fee,\n uint256 adminFee,\n address lpTokenTargetAddress,\n address baseSwap\n ) external;\n\n function swap(\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx,\n uint256 minDy,\n uint256 deadline\n ) external returns (uint256);\n\n function swapUnderlying(\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx,\n uint256 minDy,\n uint256 deadline\n ) external returns (uint256);\n\n function addLiquidity(\n uint256[] calldata amounts,\n uint256 minToMint,\n uint256 deadline\n ) external returns (uint256);\n\n function removeLiquidity(\n uint256 amount,\n uint256[] calldata minAmounts,\n uint256 deadline\n ) external returns (uint256[] memory);\n\n function removeLiquidityOneToken(\n uint256 tokenAmount,\n uint8 tokenIndex,\n uint256 minAmount,\n uint256 deadline\n ) external returns (uint256);\n\n function removeLiquidityImbalance(\n uint256[] calldata amounts,\n uint256 maxBurnAmount,\n uint256 deadline\n ) external returns (uint256);\n\n function swapStorage()\n external\n view\n returns (\n uint256 initialA,\n uint256 futureA,\n uint256 initialATime,\n uint256 futureATime,\n uint256 swapFee,\n uint256 adminFee,\n address lpToken\n );\n}\n" + }, + "contracts/amm/helper/GenericERC20.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.6.12;\n\nimport \"@openzeppelin/contracts/token/ERC20/ERC20.sol\";\nimport \"@openzeppelin/contracts/access/Ownable.sol\";\n\n/**\n * @title Generic ERC20 token\n * @notice This contract simulates a generic ERC20 token that is mintable and burnable.\n */\ncontract GenericERC20 is ERC20, Ownable {\n /**\n * @notice Deploy this contract with given name, symbol, and decimals\n * @dev the caller of this constructor will become the owner of this contract\n * @param name_ name of this token\n * @param symbol_ symbol of this token\n * @param decimals_ number of decimals this token will be based on\n */\n constructor(\n string memory name_,\n string memory symbol_,\n uint8 decimals_\n ) public ERC20(name_, symbol_) {\n _setupDecimals(decimals_);\n }\n\n /**\n * @notice Mints given amount of tokens to recipient\n * @dev only owner can call this mint function\n * @param recipient address of account to receive the tokens\n * @param amount amount of tokens to mint\n */\n function mint(address recipient, uint256 amount) external onlyOwner {\n require(amount != 0, \"amount == 0\");\n _mint(recipient, amount);\n }\n}\n" + }, + "contracts/bridge/wrappers/HarmonyBridgeZap.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.6.12;\n\nimport \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/SafeERC20.sol\";\nimport \"../interfaces/ISwap.sol\";\nimport \"../interfaces/ISynapseBridge.sol\";\nimport \"../interfaces/IWETH9.sol\";\n\ninterface IFrax {\n function exchangeCanonicalForOld(address bridge_token_address, uint256 token_amount) external returns (uint256);\n}\n\ncontract HarmonyBridgeZap {\n using SafeERC20 for IERC20;\n\n ISynapseBridge synapseBridge;\n address payable public immutable WETH_ADDRESS;\n IFrax private constant CANOLICAL_FRAX = IFrax(0xFa7191D292d5633f702B0bd7E3E3BcCC0e633200);\n IERC20 private constant SYN_FRAX = IERC20(0x1852F70512298d56e9c8FDd905e02581E04ddb2a);\n\n mapping(address => address) public swapMap;\n mapping(address => IERC20[]) public swapTokensMap;\n\n uint256 constant MAX_UINT256 = 2**256 - 1;\n\n constructor(\n address payable _wethAddress,\n address _swapOne,\n address tokenOne,\n address _swapTwo,\n address tokenTwo,\n address _swapThree,\n address tokenThree,\n address _swapFour,\n address tokenFour,\n ISynapseBridge _synapseBridge\n ) public {\n WETH_ADDRESS = _wethAddress;\n synapseBridge = _synapseBridge;\n swapMap[tokenOne] = _swapOne;\n swapMap[tokenTwo] = _swapTwo;\n swapMap[tokenThree] = _swapThree;\n swapMap[tokenFour] = _swapFour;\n\n if (address(_swapOne) != address(0)) {\n {\n uint8 i;\n for (; i < 32; i++) {\n try ISwap(_swapOne).getToken(i) returns (\n IERC20 token\n ) {\n swapTokensMap[_swapOne].push(token);\n token.safeApprove(address(_swapOne), MAX_UINT256);\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n } catch {\n break;\n }\n }\n require(i > 1, \"swap must have at least 2 tokens\");\n }\n }\n if (address(_swapTwo) != address(0)) {\n {\n uint8 i;\n for (; i < 32; i++) {\n try ISwap(_swapTwo).getToken(i) returns (\n IERC20 token\n ) {\n swapTokensMap[_swapTwo].push(token);\n token.safeApprove(address(_swapTwo), MAX_UINT256);\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n } catch {\n break;\n }\n }\n require(i > 1, \"swap must have at least 2 tokens\");\n }\n }\n\n if (address(_swapThree) != address(0)) {\n {\n uint8 i;\n for (; i < 32; i++) {\n try ISwap(_swapThree).getToken(i) returns (\n IERC20 token\n ) {\n swapTokensMap[_swapThree].push(token);\n token.safeApprove(address(_swapThree), MAX_UINT256);\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n } catch {\n break;\n }\n }\n require(i > 1, \"swap must have at least 2 tokens\");\n }\n }\n\n if (address(_swapFour) != address(0)) {\n {\n uint8 i;\n for (; i < 32; i++) {\n try ISwap(_swapFour).getToken(i) returns (\n IERC20 token\n ) {\n swapTokensMap[_swapFour].push(token);\n token.safeApprove(address(_swapFour), MAX_UINT256);\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n } catch {\n break;\n }\n }\n require(i > 1, \"swap must have at least 2 tokens\");\n }\n }\n }\n\n /**\n * @notice Calculate amount of tokens you receive on swap\n * @param tokenIndexFrom the token the user wants to sell\n * @param tokenIndexTo the token the user wants to buy\n * @param dx the amount of tokens the user wants to sell. If the token charges\n * a fee on transfers, use the amount that gets transferred after the fee.\n * @return amount of tokens the user will receive\n */\n function calculateSwap(\n IERC20 token,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx\n ) external view virtual returns (uint256) {\n ISwap swap = ISwap(\n swapMap[address(token)]\n );\n return swap.calculateSwap(tokenIndexFrom, tokenIndexTo, dx);\n }\n\n function swapAndRedeem(\n address to,\n uint256 chainId,\n IERC20 token,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx,\n uint256 minDy,\n uint256 deadline\n ) external {\n ISwap swap = ISwap(swapMap[address(token)]);\n require(address(swap) != address(0), \"Swap is 0x00\");\n IERC20[] memory tokens = swapTokensMap[address(swap)];\n tokens[tokenIndexFrom].safeTransferFrom(\n msg.sender,\n address(this),\n dx\n );\n // swap\n\n uint256 swappedAmount = swap.swap(\n tokenIndexFrom,\n tokenIndexTo,\n dx,\n minDy,\n deadline\n );\n // deposit into bridge, gets nUSD\n if (\n token.allowance(address(this), address(synapseBridge)) <\n swappedAmount\n ) {\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n }\n synapseBridge.redeem(to, chainId, token, swappedAmount);\n }\n\n function swapAndRedeemAndSwap(\n address to,\n uint256 chainId,\n IERC20 token,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx,\n uint256 minDy,\n uint256 deadline,\n uint8 swapTokenIndexFrom,\n uint8 swapTokenIndexTo,\n uint256 swapMinDy,\n uint256 swapDeadline\n ) external {\n require(\n address(swapMap[address(token)]) != address(0),\n \"Swap is 0x00\"\n );\n IERC20[] memory tokens = swapTokensMap[\n swapMap[address(token)]\n ];\n tokens[tokenIndexFrom].safeTransferFrom(\n msg.sender,\n address(this),\n dx\n );\n // swap\n\n uint256 swappedAmount = ISwap(swapMap[address(token)]).swap(tokenIndexFrom, tokenIndexTo, dx, minDy, deadline);\n // deposit into bridge, gets nUSD\n if (\n token.allowance(address(this), address(synapseBridge)) <\n swappedAmount\n ) {\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n }\n synapseBridge.redeemAndSwap(\n to,\n chainId,\n token,\n swappedAmount,\n swapTokenIndexFrom,\n swapTokenIndexTo,\n swapMinDy,\n swapDeadline\n );\n }\n\n function swapAndRedeemAndRemove(\n address to,\n uint256 chainId,\n IERC20 token,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx,\n uint256 minDy,\n uint256 deadline,\n uint8 liqTokenIndex,\n uint256 liqMinAmount,\n uint256 liqDeadline\n ) external {\n ISwap swap = ISwap(swapMap[address(token)]);\n require(address(swap) != address(0), \"Swap is 0x00\");\n IERC20[] memory tokens = swapTokensMap[address(swap)];\n tokens[tokenIndexFrom].safeTransferFrom(\n msg.sender,\n address(this),\n dx\n );\n // swap\n\n uint256 swappedAmount = swap.swap(\n tokenIndexFrom,\n tokenIndexTo,\n dx,\n minDy,\n deadline\n );\n // deposit into bridge, gets nUSD\n if (\n token.allowance(address(this), address(synapseBridge)) <\n swappedAmount\n ) {\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n }\n synapseBridge.redeemAndRemove(\n to,\n chainId,\n token,\n swappedAmount,\n liqTokenIndex,\n liqMinAmount,\n liqDeadline\n );\n }\n\n /**\n * @notice wraps SynapseBridge redeem()\n * @param to address on other chain to redeem underlying assets to\n * @param chainId which underlying chain to bridge assets onto\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n **/\n function redeem(\n address to,\n uint256 chainId,\n IERC20 token,\n uint256 amount\n ) external {\n token.safeTransferFrom(msg.sender, address(this), amount);\n if (address(token) == address(CANOLICAL_FRAX)) {\n uint256 swappedAmount = CANOLICAL_FRAX.exchangeCanonicalForOld(address(SYN_FRAX), amount);\n if (SYN_FRAX.allowance(address(this), address(synapseBridge)) < amount) {\n SYN_FRAX.safeApprove(address(synapseBridge), MAX_UINT256);\n }\n synapseBridge.redeem(to, chainId, SYN_FRAX, swappedAmount);\n } else {\n if (token.allowance(address(this), address(synapseBridge)) < amount) {\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n }\n synapseBridge.redeem(to, chainId, token, amount);\n }\n \n }\n\n /**\n * @notice Wraps SynapseBridge redeemv2() function\n * @param to address on other chain to bridge assets to\n * @param chainId which chain to bridge assets onto\n * @param token ERC20 compatible token to redeem into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n **/\n function redeemv2(\n bytes32 to,\n uint256 chainId,\n IERC20 token,\n uint256 amount\n ) external {\n token.safeTransferFrom(msg.sender, address(this), amount);\n\n if (token.allowance(address(this), address(synapseBridge)) < amount) {\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n }\n synapseBridge.redeemv2(to, chainId, token, amount);\n }\n\n /**\n * @notice wraps SynapseBridge redeem()\n * @param to address on other chain to redeem underlying assets to\n * @param chainId which underlying chain to bridge assets onto\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n **/\n function deposit(\n address to,\n uint256 chainId,\n IERC20 token,\n uint256 amount\n ) external {\n token.safeTransferFrom(msg.sender, address(this), amount);\n if (token.allowance(address(this), address(synapseBridge)) < amount) {\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n }\n synapseBridge.deposit(to, chainId, token, amount);\n }\n\n function swapETHAndRedeem(\n address to,\n uint256 chainId,\n IERC20 token,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx,\n uint256 minDy,\n uint256 deadline\n ) external payable {\n require(WETH_ADDRESS != address(0), \"WETH 0\");\n require(msg.value > 0 && msg.value == dx, \"INCORRECT MSG VALUE\");\n ISwap swap = ISwap(swapMap[address(token)]);\n require(address(swap) != address(0), \"Swap is 0x00\");\n IWETH9(WETH_ADDRESS).deposit{value: msg.value}();\n\n // swap\n uint256 swappedAmount = swap.swap(\n tokenIndexFrom,\n tokenIndexTo,\n dx,\n minDy,\n deadline\n );\n synapseBridge.redeem(to, chainId, token, swappedAmount);\n }\n\n /**\n * @notice Wraps redeemAndSwap on SynapseBridge.sol\n * Relays to nodes that (typically) a wrapped synAsset ERC20 token has been burned and the underlying needs to be redeeemed on the native chain. This function indicates to the nodes that they should attempt to redeem the LP token for the underlying assets (E.g \"swap\" out of the LP token)\n * @param to address on other chain to redeem underlying assets to\n * @param chainId which underlying chain to bridge assets onto\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n * @param tokenIndexFrom the token the user wants to swap from\n * @param tokenIndexTo the token the user wants to swap to\n * @param minDy the min amount the user would like to receive, or revert to only minting the SynERC20 token crosschain.\n * @param deadline latest timestamp to accept this transaction\n **/\n function redeemAndSwap(\n address to,\n uint256 chainId,\n IERC20 token,\n uint256 amount,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 minDy,\n uint256 deadline\n ) external {\n token.safeTransferFrom(msg.sender, address(this), amount);\n if (token.allowance(address(this), address(synapseBridge)) < amount) {\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n }\n synapseBridge.redeemAndSwap(\n to,\n chainId,\n token,\n amount,\n tokenIndexFrom,\n tokenIndexTo,\n minDy,\n deadline\n );\n }\n\n /**\n * @notice Wraps redeemAndRemove on SynapseBridge\n * Relays to nodes that (typically) a wrapped synAsset ERC20 token has been burned and the underlying needs to be redeeemed on the native chain. This function indicates to the nodes that they should attempt to redeem the LP token for the underlying assets (E.g \"swap\" out of the LP token)\n * @param to address on other chain to redeem underlying assets to\n * @param chainId which underlying chain to bridge assets onto\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount of (typically) LP token to pass to the nodes to attempt to removeLiquidity() with to redeem for the underlying assets of the LP token\n * @param liqTokenIndex Specifies which of the underlying LP assets the nodes should attempt to redeem for\n * @param liqMinAmount Specifies the minimum amount of the underlying asset needed for the nodes to execute the redeem/swap\n * @param liqDeadline Specificies the deadline that the nodes are allowed to try to redeem/swap the LP token\n **/\n function redeemAndRemove(\n address to,\n uint256 chainId,\n IERC20 token,\n uint256 amount,\n uint8 liqTokenIndex,\n uint256 liqMinAmount,\n uint256 liqDeadline\n ) external {\n token.safeTransferFrom(msg.sender, address(this), amount);\n if (token.allowance(address(this), address(synapseBridge)) < amount) {\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n }\n synapseBridge.redeemAndRemove(\n to,\n chainId,\n token,\n amount,\n liqTokenIndex,\n liqMinAmount,\n liqDeadline\n );\n }\n}\n" + }, + "contracts/bridge/wrappers/AvalancheBridgeZap.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.6.12;\n\nimport \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/SafeERC20.sol\";\nimport \"../interfaces/ISwap.sol\";\nimport \"../interfaces/ISynapseBridge.sol\";\nimport \"../interfaces/IWETH9.sol\";\n\ncontract AvalancheBridgeZap {\n using SafeERC20 for IERC20;\n\n ISynapseBridge synapseBridge;\n address payable public immutable WETH_ADDRESS;\n\n mapping(address => address) public swapMap;\n mapping(address => IERC20[]) public swapTokensMap;\n\n uint256 constant MAX_UINT256 = 2**256 - 1;\n\n constructor(\n address payable _wethAddress,\n address _swapOne,\n address tokenOne,\n address _swapTwo,\n address tokenTwo,\n ISynapseBridge _synapseBridge\n ) public {\n WETH_ADDRESS = _wethAddress;\n synapseBridge = _synapseBridge;\n swapMap[tokenOne] = _swapOne;\n swapMap[tokenTwo] = _swapTwo;\n if (_wethAddress != address(0)) {\n IERC20(_wethAddress).safeIncreaseAllowance(address(_synapseBridge), MAX_UINT256);\n }\n if (address(_swapOne) != address(0)) {\n {\n uint8 i;\n for (; i < 32; i++) {\n try ISwap(_swapOne).getToken(i) returns (\n IERC20 token\n ) {\n swapTokensMap[_swapOne].push(token);\n token.safeApprove(address(_swapOne), MAX_UINT256);\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n } catch {\n break;\n }\n }\n require(i > 1, \"swap must have at least 2 tokens\");\n }\n }\n if (address(_swapTwo) != address(0)) {\n {\n uint8 i;\n for (; i < 32; i++) {\n try ISwap(_swapTwo).getToken(i) returns (\n IERC20 token\n ) {\n swapTokensMap[_swapTwo].push(token);\n token.safeApprove(address(_swapTwo), MAX_UINT256);\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n } catch {\n break;\n }\n }\n require(i > 1, \"swap must have at least 2 tokens\");\n }\n }\n }\n\n /**\n * @notice Calculate amount of tokens you receive on swap\n * @param tokenIndexFrom the token the user wants to sell\n * @param tokenIndexTo the token the user wants to buy\n * @param dx the amount of tokens the user wants to sell. If the token charges\n * a fee on transfers, use the amount that gets transferred after the fee.\n * @return amount of tokens the user will receive\n */\n function calculateSwap(\n IERC20 token,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx\n ) external view virtual returns (uint256) {\n ISwap swap = ISwap(\n swapMap[address(token)]\n );\n return swap.calculateSwap(tokenIndexFrom, tokenIndexTo, dx);\n }\n\n function swapAndRedeem(\n address to,\n uint256 chainId,\n IERC20 token,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx,\n uint256 minDy,\n uint256 deadline\n ) external {\n ISwap swap = ISwap(swapMap[address(token)]);\n require(address(swap) != address(0), \"Swap is 0x00\");\n IERC20[] memory tokens = swapTokensMap[address(swap)];\n tokens[tokenIndexFrom].safeTransferFrom(\n msg.sender,\n address(this),\n dx\n );\n // swap\n\n uint256 swappedAmount = swap.swap(\n tokenIndexFrom,\n tokenIndexTo,\n dx,\n minDy,\n deadline\n );\n // deposit into bridge, gets nUSD\n if (\n token.allowance(address(this), address(synapseBridge)) <\n swappedAmount\n ) {\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n }\n synapseBridge.redeem(to, chainId, token, swappedAmount);\n }\n\n function swapAndRedeemAndSwap(\n address to,\n uint256 chainId,\n IERC20 token,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx,\n uint256 minDy,\n uint256 deadline,\n uint8 swapTokenIndexFrom,\n uint8 swapTokenIndexTo,\n uint256 swapMinDy,\n uint256 swapDeadline\n ) external {\n require(\n address(swapMap[address(token)]) != address(0),\n \"Swap is 0x00\"\n );\n IERC20[] memory tokens = swapTokensMap[\n swapMap[address(token)]\n ];\n tokens[tokenIndexFrom].safeTransferFrom(\n msg.sender,\n address(this),\n dx\n );\n // swap\n\n uint256 swappedAmount = ISwap(swapMap[address(token)]).swap(tokenIndexFrom, tokenIndexTo, dx, minDy, deadline);\n // deposit into bridge, gets nUSD\n if (\n token.allowance(address(this), address(synapseBridge)) <\n swappedAmount\n ) {\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n }\n synapseBridge.redeemAndSwap(\n to,\n chainId,\n token,\n swappedAmount,\n swapTokenIndexFrom,\n swapTokenIndexTo,\n swapMinDy,\n swapDeadline\n );\n }\n\n function swapAndRedeemAndRemove(\n address to,\n uint256 chainId,\n IERC20 token,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx,\n uint256 minDy,\n uint256 deadline,\n uint8 liqTokenIndex,\n uint256 liqMinAmount,\n uint256 liqDeadline\n ) external {\n ISwap swap = ISwap(swapMap[address(token)]);\n require(address(swap) != address(0), \"Swap is 0x00\");\n IERC20[] memory tokens = swapTokensMap[address(swap)];\n tokens[tokenIndexFrom].safeTransferFrom(\n msg.sender,\n address(this),\n dx\n );\n // swap\n\n uint256 swappedAmount = swap.swap(\n tokenIndexFrom,\n tokenIndexTo,\n dx,\n minDy,\n deadline\n );\n // deposit into bridge, gets nUSD\n if (\n token.allowance(address(this), address(synapseBridge)) <\n swappedAmount\n ) {\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n }\n synapseBridge.redeemAndRemove(\n to,\n chainId,\n token,\n swappedAmount,\n liqTokenIndex,\n liqMinAmount,\n liqDeadline\n );\n }\n\n /**\n * @notice wraps SynapseBridge redeem()\n * @param to address on other chain to redeem underlying assets to\n * @param chainId which underlying chain to bridge assets onto\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n **/\n function redeem(\n address to,\n uint256 chainId,\n IERC20 token,\n uint256 amount\n ) external {\n token.safeTransferFrom(msg.sender, address(this), amount);\n if (token.allowance(address(this), address(synapseBridge)) < amount) {\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n }\n synapseBridge.redeem(to, chainId, token, amount);\n }\n\n /**\n * @notice wraps SynapseBridge redeem()\n * @param to address on other chain to redeem underlying assets to\n * @param chainId which underlying chain to bridge assets onto\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n **/\n function deposit(\n address to,\n uint256 chainId,\n IERC20 token,\n uint256 amount\n ) external {\n token.safeTransferFrom(msg.sender, address(this), amount);\n if (token.allowance(address(this), address(synapseBridge)) < amount) {\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n }\n synapseBridge.deposit(to, chainId, token, amount);\n }\n\n /**\n * @notice Wraps SynapseBridge deposit() function to make it compatible w/ ETH -> WETH conversions\n * @param to address on other chain to bridge assets to\n * @param chainId which chain to bridge assets onto\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n **/\n function depositETH(\n address to,\n uint256 chainId,\n uint256 amount\n ) external payable {\n require(msg.value > 0 && msg.value == amount, 'INCORRECT MSG VALUE');\n IWETH9(WETH_ADDRESS).deposit{value: msg.value}();\n synapseBridge.deposit(to, chainId, IERC20(WETH_ADDRESS), amount);\n }\n\n\n function swapETHAndRedeem(\n address to,\n uint256 chainId,\n IERC20 token,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx,\n uint256 minDy,\n uint256 deadline\n ) external payable {\n require(WETH_ADDRESS != address(0), \"WETH 0\");\n require(msg.value > 0 && msg.value == dx, \"INCORRECT MSG VALUE\");\n ISwap swap = ISwap(swapMap[address(token)]);\n require(address(swap) != address(0), \"Swap is 0x00\");\n IWETH9(WETH_ADDRESS).deposit{value: msg.value}();\n\n // swap\n uint256 swappedAmount = swap.swap(\n tokenIndexFrom,\n tokenIndexTo,\n dx,\n minDy,\n deadline\n );\n synapseBridge.redeem(to, chainId, token, swappedAmount);\n }\n\n\n function swapETHAndRedeemAndSwap(\n address to,\n uint256 chainId,\n IERC20 token,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx,\n uint256 minDy,\n uint256 deadline,\n uint8 swapTokenIndexFrom,\n uint8 swapTokenIndexTo,\n uint256 swapMinDy,\n uint256 swapDeadline\n ) external payable {\n require(WETH_ADDRESS != address(0), \"WETH 0\");\n require(msg.value > 0 && msg.value == dx, \"INCORRECT MSG VALUE\");\n ISwap swap = ISwap(swapMap[address(token)]);\n require(address(swap) != address(0), \"Swap is 0x00\");\n IWETH9(WETH_ADDRESS).deposit{value: msg.value}();\n\n // swap\n uint256 swappedAmount = swap.swap(\n tokenIndexFrom,\n tokenIndexTo,\n dx,\n minDy,\n deadline\n );\n synapseBridge.redeemAndSwap(to, chainId, token, swappedAmount,swapTokenIndexFrom,\n swapTokenIndexTo,\n swapMinDy,\n swapDeadline);\n }\n\n\n /**\n * @notice Wraps redeemAndSwap on SynapseBridge.sol\n * Relays to nodes that (typically) a wrapped synAsset ERC20 token has been burned and the underlying needs to be redeeemed on the native chain. This function indicates to the nodes that they should attempt to redeem the LP token for the underlying assets (E.g \"swap\" out of the LP token)\n * @param to address on other chain to redeem underlying assets to\n * @param chainId which underlying chain to bridge assets onto\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n * @param tokenIndexFrom the token the user wants to swap from\n * @param tokenIndexTo the token the user wants to swap to\n * @param minDy the min amount the user would like to receive, or revert to only minting the SynERC20 token crosschain.\n * @param deadline latest timestamp to accept this transaction\n **/\n function redeemAndSwap(\n address to,\n uint256 chainId,\n IERC20 token,\n uint256 amount,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 minDy,\n uint256 deadline\n ) external {\n token.safeTransferFrom(msg.sender, address(this), amount);\n if (token.allowance(address(this), address(synapseBridge)) < amount) {\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n }\n synapseBridge.redeemAndSwap(\n to,\n chainId,\n token,\n amount,\n tokenIndexFrom,\n tokenIndexTo,\n minDy,\n deadline\n );\n }\n\n /**\n * @notice Wraps redeemAndRemove on SynapseBridge\n * Relays to nodes that (typically) a wrapped synAsset ERC20 token has been burned and the underlying needs to be redeeemed on the native chain. This function indicates to the nodes that they should attempt to redeem the LP token for the underlying assets (E.g \"swap\" out of the LP token)\n * @param to address on other chain to redeem underlying assets to\n * @param chainId which underlying chain to bridge assets onto\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount of (typically) LP token to pass to the nodes to attempt to removeLiquidity() with to redeem for the underlying assets of the LP token\n * @param liqTokenIndex Specifies which of the underlying LP assets the nodes should attempt to redeem for\n * @param liqMinAmount Specifies the minimum amount of the underlying asset needed for the nodes to execute the redeem/swap\n * @param liqDeadline Specificies the deadline that the nodes are allowed to try to redeem/swap the LP token\n **/\n function redeemAndRemove(\n address to,\n uint256 chainId,\n IERC20 token,\n uint256 amount,\n uint8 liqTokenIndex,\n uint256 liqMinAmount,\n uint256 liqDeadline\n ) external {\n token.safeTransferFrom(msg.sender, address(this), amount);\n if (token.allowance(address(this), address(synapseBridge)) < amount) {\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n }\n synapseBridge.redeemAndRemove(\n to,\n chainId,\n token,\n amount,\n liqTokenIndex,\n liqMinAmount,\n liqDeadline\n );\n }\n\n /**\n * @notice Wraps SynapseBridge redeemv2() function\n * @param to address on other chain to bridge assets to\n * @param chainId which chain to bridge assets onto\n * @param token ERC20 compatible token to redeem into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n **/\n function redeemv2(\n bytes32 to,\n uint256 chainId,\n IERC20 token,\n uint256 amount\n ) external {\n token.safeTransferFrom(msg.sender, address(this), amount);\n\n if (token.allowance(address(this), address(synapseBridge)) < amount) {\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n }\n synapseBridge.redeemv2(to, chainId, token, amount);\n }\n}\n" + }, + "contracts/bridge/SynapseBridge.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.6.12;\n\nimport \"@openzeppelin/contracts-upgradeable/proxy/Initializable.sol\";\nimport \"@openzeppelin/contracts-upgradeable/access/AccessControlUpgradeable.sol\";\nimport \"@openzeppelin/contracts-upgradeable/utils/ReentrancyGuardUpgradeable.sol\";\nimport \"@openzeppelin/contracts-upgradeable/utils/PausableUpgradeable.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/SafeERC20.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/ERC20Burnable.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport \"@openzeppelin/contracts/math/SafeMath.sol\";\n\nimport \"./interfaces/ISwap.sol\";\nimport \"./interfaces/IWETH9.sol\";\n\ninterface IERC20Mintable is IERC20 {\n function mint(address to, uint256 amount) external;\n}\n\ncontract SynapseBridge is\n Initializable,\n AccessControlUpgradeable,\n ReentrancyGuardUpgradeable,\n PausableUpgradeable\n{\n using SafeERC20 for IERC20;\n using SafeERC20 for IERC20Mintable;\n using SafeMath for uint256;\n\n bytes32 public constant NODEGROUP_ROLE = keccak256(\"NODEGROUP_ROLE\");\n bytes32 public constant GOVERNANCE_ROLE = keccak256(\"GOVERNANCE_ROLE\");\n\n mapping(address => uint256) private fees;\n\n uint256 public startBlockNumber;\n uint256 public constant bridgeVersion = 6;\n uint256 public chainGasAmount;\n address payable public WETH_ADDRESS;\n\n mapping(bytes32 => bool) private kappaMap;\n\n receive() external payable {}\n\n function initialize() external initializer {\n startBlockNumber = block.number;\n _setupRole(DEFAULT_ADMIN_ROLE, msg.sender);\n __AccessControl_init();\n }\n\n function setChainGasAmount(uint256 amount) external {\n require(hasRole(GOVERNANCE_ROLE, msg.sender), \"Not governance\");\n chainGasAmount = amount;\n }\n\n function setWethAddress(address payable _wethAddress) external {\n require(hasRole(DEFAULT_ADMIN_ROLE, msg.sender), \"Not admin\");\n WETH_ADDRESS = _wethAddress;\n }\n\n function addKappas(bytes32[] calldata kappas) external {\n require(hasRole(GOVERNANCE_ROLE, msg.sender), \"Not governance\");\n for (uint256 i = 0; i < kappas.length; ++i) {\n kappaMap[kappas[i]] = true;\n }\n }\n\n event TokenDeposit(\n address indexed to,\n uint256 chainId,\n IERC20 token,\n uint256 amount\n );\n event TokenRedeem(\n address indexed to,\n uint256 chainId,\n IERC20 token,\n uint256 amount\n );\n event TokenWithdraw(\n address indexed to,\n IERC20 token,\n uint256 amount,\n uint256 fee,\n bytes32 indexed kappa\n );\n event TokenMint(\n address indexed to,\n IERC20Mintable token,\n uint256 amount,\n uint256 fee,\n bytes32 indexed kappa\n );\n event TokenDepositAndSwap(\n address indexed to,\n uint256 chainId,\n IERC20 token,\n uint256 amount,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 minDy,\n uint256 deadline\n );\n event TokenMintAndSwap(\n address indexed to,\n IERC20Mintable token,\n uint256 amount,\n uint256 fee,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 minDy,\n uint256 deadline,\n bool swapSuccess,\n bytes32 indexed kappa\n );\n event TokenRedeemAndSwap(\n address indexed to,\n uint256 chainId,\n IERC20 token,\n uint256 amount,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 minDy,\n uint256 deadline\n );\n event TokenRedeemAndRemove(\n address indexed to,\n uint256 chainId,\n IERC20 token,\n uint256 amount,\n uint8 swapTokenIndex,\n uint256 swapMinAmount,\n uint256 swapDeadline\n );\n event TokenWithdrawAndRemove(\n address indexed to,\n IERC20 token,\n uint256 amount,\n uint256 fee,\n uint8 swapTokenIndex,\n uint256 swapMinAmount,\n uint256 swapDeadline,\n bool swapSuccess,\n bytes32 indexed kappa\n );\n\n // v2 events\n event TokenRedeemV2(\n bytes32 indexed to,\n uint256 chainId,\n IERC20 token,\n uint256 amount\n );\n\n // VIEW FUNCTIONS ***/\n function getFeeBalance(address tokenAddress)\n external\n view\n returns (uint256)\n {\n return fees[tokenAddress];\n }\n\n function kappaExists(bytes32 kappa) external view returns (bool) {\n return kappaMap[kappa];\n }\n\n // FEE FUNCTIONS ***/\n /**\n * * @notice withdraw specified ERC20 token fees to a given address\n * * @param token ERC20 token in which fees acccumulated to transfer\n * * @param to Address to send the fees to\n */\n function withdrawFees(IERC20 token, address to) external whenNotPaused {\n require(hasRole(GOVERNANCE_ROLE, msg.sender), \"Not governance\");\n require(to != address(0), \"Address is 0x000\");\n if (fees[address(token)] != 0) {\n token.safeTransfer(to, fees[address(token)]);\n fees[address(token)] = 0;\n }\n }\n\n // PAUSABLE FUNCTIONS ***/\n function pause() external {\n require(hasRole(GOVERNANCE_ROLE, msg.sender), \"Not governance\");\n _pause();\n }\n\n function unpause() external {\n require(hasRole(GOVERNANCE_ROLE, msg.sender), \"Not governance\");\n _unpause();\n }\n\n /**\n * @notice Relays to nodes to transfers an ERC20 token cross-chain\n * @param to address on other chain to bridge assets to\n * @param chainId which chain to bridge assets onto\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n **/\n function deposit(\n address to,\n uint256 chainId,\n IERC20 token,\n uint256 amount\n ) external nonReentrant whenNotPaused {\n emit TokenDeposit(to, chainId, token, amount);\n token.safeTransferFrom(msg.sender, address(this), amount);\n }\n\n /**\n * @notice Relays to nodes that (typically) a wrapped synAsset ERC20 token has been burned and the underlying needs to be redeeemed on the native chain\n * @param to address on other chain to redeem underlying assets to\n * @param chainId which underlying chain to bridge assets onto\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n **/\n function redeem(\n address to,\n uint256 chainId,\n ERC20Burnable token,\n uint256 amount\n ) external nonReentrant whenNotPaused {\n emit TokenRedeem(to, chainId, token, amount);\n token.burnFrom(msg.sender, amount);\n }\n\n /**\n * @notice Function to be called by the node group to withdraw the underlying assets from the contract\n * @param to address on chain to send underlying assets to\n * @param token ERC20 compatible token to withdraw from the bridge\n * @param amount Amount in native token decimals to withdraw\n * @param fee Amount in native token decimals to save to the contract as fees\n * @param kappa kappa\n **/\n function withdraw(\n address to,\n IERC20 token,\n uint256 amount,\n uint256 fee,\n bytes32 kappa\n ) external nonReentrant whenNotPaused {\n require(\n hasRole(NODEGROUP_ROLE, msg.sender),\n \"Caller is not a node group\"\n );\n require(amount > fee, \"Amount must be greater than fee\");\n require(!kappaMap[kappa], \"Kappa is already present\");\n kappaMap[kappa] = true;\n fees[address(token)] = fees[address(token)].add(fee);\n if (address(token) == WETH_ADDRESS && WETH_ADDRESS != address(0)) {\n IWETH9(WETH_ADDRESS).withdraw(amount.sub(fee));\n (bool success, ) = to.call{value: amount.sub(fee)}(\"\");\n require(success, \"ETH_TRANSFER_FAILED\");\n emit TokenWithdraw(to, token, amount, fee, kappa);\n } else {\n emit TokenWithdraw(to, token, amount, fee, kappa);\n token.safeTransfer(to, amount.sub(fee));\n }\n }\n\n /**\n * @notice Nodes call this function to mint a SynERC20 (or any asset that the bridge is given minter access to). This is called by the nodes after a TokenDeposit event is emitted.\n * @dev This means the SynapseBridge.sol contract must have minter access to the token attempting to be minted\n * @param to address on other chain to redeem underlying assets to\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain post-fees\n * @param fee Amount in native token decimals to save to the contract as fees\n * @param kappa kappa\n **/\n function mint(\n address payable to,\n IERC20Mintable token,\n uint256 amount,\n uint256 fee,\n bytes32 kappa\n ) external nonReentrant whenNotPaused {\n require(\n hasRole(NODEGROUP_ROLE, msg.sender),\n \"Caller is not a node group\"\n );\n require(amount > fee, \"Amount must be greater than fee\");\n require(!kappaMap[kappa], \"Kappa is already present\");\n kappaMap[kappa] = true;\n fees[address(token)] = fees[address(token)].add(fee);\n emit TokenMint(to, token, amount.sub(fee), fee, kappa);\n token.mint(address(this), amount);\n IERC20(token).safeTransfer(to, amount.sub(fee));\n if (chainGasAmount != 0 && address(this).balance > chainGasAmount) {\n to.call.value(chainGasAmount)(\"\");\n }\n }\n\n /**\n * @notice Relays to nodes to both transfer an ERC20 token cross-chain, and then have the nodes execute a swap through a liquidity pool on behalf of the user.\n * @param to address on other chain to bridge assets to\n * @param chainId which chain to bridge assets onto\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n * @param tokenIndexFrom the token the user wants to swap from\n * @param tokenIndexTo the token the user wants to swap to\n * @param minDy the min amount the user would like to receive, or revert to only minting the SynERC20 token crosschain.\n * @param deadline latest timestamp to accept this transaction\n **/\n function depositAndSwap(\n address to,\n uint256 chainId,\n IERC20 token,\n uint256 amount,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 minDy,\n uint256 deadline\n ) external nonReentrant whenNotPaused {\n emit TokenDepositAndSwap(\n to,\n chainId,\n token,\n amount,\n tokenIndexFrom,\n tokenIndexTo,\n minDy,\n deadline\n );\n token.safeTransferFrom(msg.sender, address(this), amount);\n }\n\n /**\n * @notice Relays to nodes that (typically) a wrapped synAsset ERC20 token has been burned and the underlying needs to be redeeemed on the native chain. This function indicates to the nodes that they should attempt to redeem the LP token for the underlying assets (E.g \"swap\" out of the LP token)\n * @param to address on other chain to redeem underlying assets to\n * @param chainId which underlying chain to bridge assets onto\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n * @param tokenIndexFrom the token the user wants to swap from\n * @param tokenIndexTo the token the user wants to swap to\n * @param minDy the min amount the user would like to receive, or revert to only minting the SynERC20 token crosschain.\n * @param deadline latest timestamp to accept this transaction\n **/\n function redeemAndSwap(\n address to,\n uint256 chainId,\n ERC20Burnable token,\n uint256 amount,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 minDy,\n uint256 deadline\n ) external nonReentrant whenNotPaused {\n emit TokenRedeemAndSwap(\n to,\n chainId,\n token,\n amount,\n tokenIndexFrom,\n tokenIndexTo,\n minDy,\n deadline\n );\n token.burnFrom(msg.sender, amount);\n }\n\n /**\n * @notice Relays to nodes that (typically) a wrapped synAsset ERC20 token has been burned and the underlying needs to be redeeemed on the native chain. This function indicates to the nodes that they should attempt to redeem the LP token for the underlying assets (E.g \"swap\" out of the LP token)\n * @param to address on other chain to redeem underlying assets to\n * @param chainId which underlying chain to bridge assets onto\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n * @param swapTokenIndex Specifies which of the underlying LP assets the nodes should attempt to redeem for\n * @param swapMinAmount Specifies the minimum amount of the underlying asset needed for the nodes to execute the redeem/swap\n * @param swapDeadline Specificies the deadline that the nodes are allowed to try to redeem/swap the LP token\n **/\n function redeemAndRemove(\n address to,\n uint256 chainId,\n ERC20Burnable token,\n uint256 amount,\n uint8 swapTokenIndex,\n uint256 swapMinAmount,\n uint256 swapDeadline\n ) external nonReentrant whenNotPaused {\n emit TokenRedeemAndRemove(\n to,\n chainId,\n token,\n amount,\n swapTokenIndex,\n swapMinAmount,\n swapDeadline\n );\n token.burnFrom(msg.sender, amount);\n }\n\n /**\n * @notice Nodes call this function to mint a SynERC20 (or any asset that the bridge is given minter access to), and then attempt to swap the SynERC20 into the desired destination asset. This is called by the nodes after a TokenDepositAndSwap event is emitted.\n * @dev This means the BridgeDeposit.sol contract must have minter access to the token attempting to be minted\n * @param to address on other chain to redeem underlying assets to\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain post-fees\n * @param fee Amount in native token decimals to save to the contract as fees\n * @param pool Destination chain's pool to use to swap SynERC20 -> Asset. The nodes determine this by using PoolConfig.sol.\n * @param tokenIndexFrom Index of the SynERC20 asset in the pool\n * @param tokenIndexTo Index of the desired final asset\n * @param minDy Minumum amount (in final asset decimals) that must be swapped for, otherwise the user will receive the SynERC20.\n * @param deadline Epoch time of the deadline that the swap is allowed to be executed.\n * @param kappa kappa\n **/\n function mintAndSwap(\n address payable to,\n IERC20Mintable token,\n uint256 amount,\n uint256 fee,\n ISwap pool,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 minDy,\n uint256 deadline,\n bytes32 kappa\n ) external nonReentrant whenNotPaused {\n require(\n hasRole(NODEGROUP_ROLE, msg.sender),\n \"Caller is not a node group\"\n );\n require(amount > fee, \"Amount must be greater than fee\");\n require(!kappaMap[kappa], \"Kappa is already present\");\n kappaMap[kappa] = true;\n fees[address(token)] = fees[address(token)].add(fee);\n // Transfer gas airdrop\n if (chainGasAmount != 0 && address(this).balance > chainGasAmount) {\n to.call.value(chainGasAmount)(\"\");\n }\n // first check to make sure more will be given than min amount required\n uint256 expectedOutput = ISwap(pool).calculateSwap(\n tokenIndexFrom,\n tokenIndexTo,\n amount.sub(fee)\n );\n\n if (expectedOutput >= minDy) {\n // proceed with swap\n token.mint(address(this), amount);\n token.safeIncreaseAllowance(address(pool), amount);\n try\n ISwap(pool).swap(\n tokenIndexFrom,\n tokenIndexTo,\n amount.sub(fee),\n minDy,\n deadline\n )\n returns (uint256 finalSwappedAmount) {\n // Swap succeeded, transfer swapped asset\n IERC20 swappedTokenTo = ISwap(pool).getToken(tokenIndexTo);\n if (\n address(swappedTokenTo) == WETH_ADDRESS &&\n WETH_ADDRESS != address(0)\n ) {\n IWETH9(WETH_ADDRESS).withdraw(finalSwappedAmount);\n (bool success, ) = to.call{value: finalSwappedAmount}(\"\");\n require(success, \"ETH_TRANSFER_FAILED\");\n emit TokenMintAndSwap(\n to,\n token,\n finalSwappedAmount,\n fee,\n tokenIndexFrom,\n tokenIndexTo,\n minDy,\n deadline,\n true,\n kappa\n );\n } else {\n swappedTokenTo.safeTransfer(to, finalSwappedAmount);\n emit TokenMintAndSwap(\n to,\n token,\n finalSwappedAmount,\n fee,\n tokenIndexFrom,\n tokenIndexTo,\n minDy,\n deadline,\n true,\n kappa\n );\n }\n } catch {\n IERC20(token).safeTransfer(to, amount.sub(fee));\n emit TokenMintAndSwap(\n to,\n token,\n amount.sub(fee),\n fee,\n tokenIndexFrom,\n tokenIndexTo,\n minDy,\n deadline,\n false,\n kappa\n );\n }\n } else {\n token.mint(address(this), amount);\n IERC20(token).safeTransfer(to, amount.sub(fee));\n emit TokenMintAndSwap(\n to,\n token,\n amount.sub(fee),\n fee,\n tokenIndexFrom,\n tokenIndexTo,\n minDy,\n deadline,\n false,\n kappa\n );\n }\n }\n\n /**\n * @notice Function to be called by the node group to withdraw the underlying assets from the contract\n * @param to address on chain to send underlying assets to\n * @param token ERC20 compatible token to withdraw from the bridge\n * @param amount Amount in native token decimals to withdraw\n * @param fee Amount in native token decimals to save to the contract as fees\n * @param pool Destination chain's pool to use to swap SynERC20 -> Asset. The nodes determine this by using PoolConfig.sol.\n * @param swapTokenIndex Specifies which of the underlying LP assets the nodes should attempt to redeem for\n * @param swapMinAmount Specifies the minimum amount of the underlying asset needed for the nodes to execute the redeem/swap\n * @param swapDeadline Specificies the deadline that the nodes are allowed to try to redeem/swap the LP token\n * @param kappa kappa\n **/\n function withdrawAndRemove(\n address to,\n IERC20 token,\n uint256 amount,\n uint256 fee,\n ISwap pool,\n uint8 swapTokenIndex,\n uint256 swapMinAmount,\n uint256 swapDeadline,\n bytes32 kappa\n ) external nonReentrant whenNotPaused {\n require(\n hasRole(NODEGROUP_ROLE, msg.sender),\n \"Caller is not a node group\"\n );\n require(amount > fee, \"Amount must be greater than fee\");\n require(!kappaMap[kappa], \"Kappa is already present\");\n kappaMap[kappa] = true;\n fees[address(token)] = fees[address(token)].add(fee);\n // first check to make sure more will be given than min amount required\n uint256 expectedOutput = ISwap(pool).calculateRemoveLiquidityOneToken(\n amount.sub(fee),\n swapTokenIndex\n );\n\n if (expectedOutput >= swapMinAmount) {\n token.safeIncreaseAllowance(address(pool), amount.sub(fee));\n try\n ISwap(pool).removeLiquidityOneToken(\n amount.sub(fee),\n swapTokenIndex,\n swapMinAmount,\n swapDeadline\n )\n returns (uint256 finalSwappedAmount) {\n // Swap succeeded, transfer swapped asset\n IERC20 swappedTokenTo = ISwap(pool).getToken(swapTokenIndex);\n swappedTokenTo.safeTransfer(to, finalSwappedAmount);\n emit TokenWithdrawAndRemove(\n to,\n token,\n finalSwappedAmount,\n fee,\n swapTokenIndex,\n swapMinAmount,\n swapDeadline,\n true,\n kappa\n );\n } catch {\n IERC20(token).safeTransfer(to, amount.sub(fee));\n emit TokenWithdrawAndRemove(\n to,\n token,\n amount.sub(fee),\n fee,\n swapTokenIndex,\n swapMinAmount,\n swapDeadline,\n false,\n kappa\n );\n }\n } else {\n token.safeTransfer(to, amount.sub(fee));\n emit TokenWithdrawAndRemove(\n to,\n token,\n amount.sub(fee),\n fee,\n swapTokenIndex,\n swapMinAmount,\n swapDeadline,\n false,\n kappa\n );\n }\n }\n\n // BRIDGE FUNCTIONS TO HANDLE DIFF ADDRESSES\n /**\n * @notice Relays to nodes that (typically) a wrapped synAsset ERC20 token has been burned and the underlying needs to be redeeemed on the native chain\n * @param to address on other chain to redeem underlying assets to\n * @param chainId which underlying chain to bridge assets onto\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n **/\n function redeemV2(\n bytes32 to,\n uint256 chainId,\n ERC20Burnable token,\n uint256 amount\n ) external nonReentrant whenNotPaused {\n emit TokenRedeemV2(to, chainId, token, amount);\n token.burnFrom(msg.sender, amount);\n }\n}\n" + }, + "@openzeppelin/contracts-upgradeable/access/AccessControlUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <0.8.0;\n\nimport \"../utils/EnumerableSetUpgradeable.sol\";\nimport \"../utils/AddressUpgradeable.sol\";\nimport \"../utils/ContextUpgradeable.sol\";\nimport \"../proxy/Initializable.sol\";\n\n/**\n * @dev Contract module that allows children to implement role-based access\n * control mechanisms.\n *\n * Roles are referred to by their `bytes32` identifier. These should be exposed\n * in the external API and be unique. The best way to achieve this is by\n * using `public constant` hash digests:\n *\n * ```\n * bytes32 public constant MY_ROLE = keccak256(\"MY_ROLE\");\n * ```\n *\n * Roles can be used to represent a set of permissions. To restrict access to a\n * function call, use {hasRole}:\n *\n * ```\n * function foo() public {\n * require(hasRole(MY_ROLE, msg.sender));\n * ...\n * }\n * ```\n *\n * Roles can be granted and revoked dynamically via the {grantRole} and\n * {revokeRole} functions. Each role has an associated admin role, and only\n * accounts that have a role's admin role can call {grantRole} and {revokeRole}.\n *\n * By default, the admin role for all roles is `DEFAULT_ADMIN_ROLE`, which means\n * that only accounts with this role will be able to grant or revoke other\n * roles. More complex role relationships can be created by using\n * {_setRoleAdmin}.\n *\n * WARNING: The `DEFAULT_ADMIN_ROLE` is also its own admin: it has permission to\n * grant and revoke this role. Extra precautions should be taken to secure\n * accounts that have been granted it.\n */\nabstract contract AccessControlUpgradeable is Initializable, ContextUpgradeable {\n function __AccessControl_init() internal initializer {\n __Context_init_unchained();\n __AccessControl_init_unchained();\n }\n\n function __AccessControl_init_unchained() internal initializer {\n }\n using EnumerableSetUpgradeable for EnumerableSetUpgradeable.AddressSet;\n using AddressUpgradeable for address;\n\n struct RoleData {\n EnumerableSetUpgradeable.AddressSet members;\n bytes32 adminRole;\n }\n\n mapping (bytes32 => RoleData) private _roles;\n\n bytes32 public constant DEFAULT_ADMIN_ROLE = 0x00;\n\n /**\n * @dev Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole`\n *\n * `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite\n * {RoleAdminChanged} not being emitted signaling this.\n *\n * _Available since v3.1._\n */\n event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole);\n\n /**\n * @dev Emitted when `account` is granted `role`.\n *\n * `sender` is the account that originated the contract call, an admin role\n * bearer except when using {_setupRole}.\n */\n event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender);\n\n /**\n * @dev Emitted when `account` is revoked `role`.\n *\n * `sender` is the account that originated the contract call:\n * - if using `revokeRole`, it is the admin role bearer\n * - if using `renounceRole`, it is the role bearer (i.e. `account`)\n */\n event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender);\n\n /**\n * @dev Returns `true` if `account` has been granted `role`.\n */\n function hasRole(bytes32 role, address account) public view returns (bool) {\n return _roles[role].members.contains(account);\n }\n\n /**\n * @dev Returns the number of accounts that have `role`. Can be used\n * together with {getRoleMember} to enumerate all bearers of a role.\n */\n function getRoleMemberCount(bytes32 role) public view returns (uint256) {\n return _roles[role].members.length();\n }\n\n /**\n * @dev Returns one of the accounts that have `role`. `index` must be a\n * value between 0 and {getRoleMemberCount}, non-inclusive.\n *\n * Role bearers are not sorted in any particular way, and their ordering may\n * change at any point.\n *\n * WARNING: When using {getRoleMember} and {getRoleMemberCount}, make sure\n * you perform all queries on the same block. See the following\n * https://forum.openzeppelin.com/t/iterating-over-elements-on-enumerableset-in-openzeppelin-contracts/2296[forum post]\n * for more information.\n */\n function getRoleMember(bytes32 role, uint256 index) public view returns (address) {\n return _roles[role].members.at(index);\n }\n\n /**\n * @dev Returns the admin role that controls `role`. See {grantRole} and\n * {revokeRole}.\n *\n * To change a role's admin, use {_setRoleAdmin}.\n */\n function getRoleAdmin(bytes32 role) public view returns (bytes32) {\n return _roles[role].adminRole;\n }\n\n /**\n * @dev Grants `role` to `account`.\n *\n * If `account` had not been already granted `role`, emits a {RoleGranted}\n * event.\n *\n * Requirements:\n *\n * - the caller must have ``role``'s admin role.\n */\n function grantRole(bytes32 role, address account) public virtual {\n require(hasRole(_roles[role].adminRole, _msgSender()), \"AccessControl: sender must be an admin to grant\");\n\n _grantRole(role, account);\n }\n\n /**\n * @dev Revokes `role` from `account`.\n *\n * If `account` had been granted `role`, emits a {RoleRevoked} event.\n *\n * Requirements:\n *\n * - the caller must have ``role``'s admin role.\n */\n function revokeRole(bytes32 role, address account) public virtual {\n require(hasRole(_roles[role].adminRole, _msgSender()), \"AccessControl: sender must be an admin to revoke\");\n\n _revokeRole(role, account);\n }\n\n /**\n * @dev Revokes `role` from the calling account.\n *\n * Roles are often managed via {grantRole} and {revokeRole}: this function's\n * purpose is to provide a mechanism for accounts to lose their privileges\n * if they are compromised (such as when a trusted device is misplaced).\n *\n * If the calling account had been granted `role`, emits a {RoleRevoked}\n * event.\n *\n * Requirements:\n *\n * - the caller must be `account`.\n */\n function renounceRole(bytes32 role, address account) public virtual {\n require(account == _msgSender(), \"AccessControl: can only renounce roles for self\");\n\n _revokeRole(role, account);\n }\n\n /**\n * @dev Grants `role` to `account`.\n *\n * If `account` had not been already granted `role`, emits a {RoleGranted}\n * event. Note that unlike {grantRole}, this function doesn't perform any\n * checks on the calling account.\n *\n * [WARNING]\n * ====\n * This function should only be called from the constructor when setting\n * up the initial roles for the system.\n *\n * Using this function in any other way is effectively circumventing the admin\n * system imposed by {AccessControl}.\n * ====\n */\n function _setupRole(bytes32 role, address account) internal virtual {\n _grantRole(role, account);\n }\n\n /**\n * @dev Sets `adminRole` as ``role``'s admin role.\n *\n * Emits a {RoleAdminChanged} event.\n */\n function _setRoleAdmin(bytes32 role, bytes32 adminRole) internal virtual {\n emit RoleAdminChanged(role, _roles[role].adminRole, adminRole);\n _roles[role].adminRole = adminRole;\n }\n\n function _grantRole(bytes32 role, address account) private {\n if (_roles[role].members.add(account)) {\n emit RoleGranted(role, account, _msgSender());\n }\n }\n\n function _revokeRole(bytes32 role, address account) private {\n if (_roles[role].members.remove(account)) {\n emit RoleRevoked(role, account, _msgSender());\n }\n }\n uint256[49] private __gap;\n}\n" + }, + "@openzeppelin/contracts-upgradeable/utils/EnumerableSetUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <0.8.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 EnumerableSetUpgradeable {\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" + }, + "contracts/bridge/MoonriverSynapseBridge.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.6.12;\n\nimport \"@openzeppelin/contracts-upgradeable/proxy/Initializable.sol\";\nimport \"@openzeppelin/contracts-upgradeable/access/AccessControlUpgradeable.sol\";\nimport \"@openzeppelin/contracts-upgradeable/utils/ReentrancyGuardUpgradeable.sol\";\nimport \"@openzeppelin/contracts-upgradeable/utils/PausableUpgradeable.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/SafeERC20.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/ERC20Burnable.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport \"@openzeppelin/contracts/math/SafeMath.sol\";\n\nimport \"./interfaces/ISwap.sol\";\nimport \"./interfaces/IWETH9.sol\";\n\ninterface IERC20Mintable is IERC20 {\n function mint(address to, uint256 amount) external;\n}\n\ninterface IFrax {\n function exchangeOldForCanonical(\n address bridge_token_address,\n uint256 token_amount\n ) external returns (uint256);\n}\n\ncontract MRSynapseBridge is\n Initializable,\n AccessControlUpgradeable,\n ReentrancyGuardUpgradeable,\n PausableUpgradeable\n{\n using SafeERC20 for IERC20;\n using SafeERC20 for IERC20Mintable;\n using SafeMath for uint256;\n\n bytes32 public constant NODEGROUP_ROLE = keccak256(\"NODEGROUP_ROLE\");\n bytes32 public constant GOVERNANCE_ROLE = keccak256(\"GOVERNANCE_ROLE\");\n\n mapping(address => uint256) private fees;\n\n uint256 public startBlockNumber;\n uint256 public constant bridgeVersion = 6;\n uint256 public chainGasAmount;\n address payable public WETH_ADDRESS;\n\n mapping(bytes32 => bool) private kappaMap;\n\n receive() external payable {}\n\n function initialize() external initializer {\n startBlockNumber = block.number;\n _setupRole(DEFAULT_ADMIN_ROLE, msg.sender);\n __AccessControl_init();\n }\n\n function setChainGasAmount(uint256 amount) external {\n require(hasRole(GOVERNANCE_ROLE, msg.sender), \"Not governance\");\n chainGasAmount = amount;\n }\n\n function setWethAddress(address payable _wethAddress) external {\n require(hasRole(DEFAULT_ADMIN_ROLE, msg.sender), \"Not admin\");\n WETH_ADDRESS = _wethAddress;\n }\n\n function addKappas(bytes32[] calldata kappas) external {\n require(hasRole(GOVERNANCE_ROLE, msg.sender), \"Not governance\");\n for (uint256 i = 0; i < kappas.length; ++i) {\n kappaMap[kappas[i]] = true;\n }\n }\n\n event TokenDeposit(\n address indexed to,\n uint256 chainId,\n IERC20 token,\n uint256 amount\n );\n event TokenRedeem(\n address indexed to,\n uint256 chainId,\n IERC20 token,\n uint256 amount\n );\n event TokenWithdraw(\n address indexed to,\n IERC20 token,\n uint256 amount,\n uint256 fee,\n bytes32 indexed kappa\n );\n event TokenMint(\n address indexed to,\n IERC20Mintable token,\n uint256 amount,\n uint256 fee,\n bytes32 indexed kappa\n );\n event TokenDepositAndSwap(\n address indexed to,\n uint256 chainId,\n IERC20 token,\n uint256 amount,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 minDy,\n uint256 deadline\n );\n event TokenMintAndSwap(\n address indexed to,\n IERC20Mintable token,\n uint256 amount,\n uint256 fee,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 minDy,\n uint256 deadline,\n bool swapSuccess,\n bytes32 indexed kappa\n );\n event TokenRedeemAndSwap(\n address indexed to,\n uint256 chainId,\n IERC20 token,\n uint256 amount,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 minDy,\n uint256 deadline\n );\n event TokenRedeemAndRemove(\n address indexed to,\n uint256 chainId,\n IERC20 token,\n uint256 amount,\n uint8 swapTokenIndex,\n uint256 swapMinAmount,\n uint256 swapDeadline\n );\n event TokenWithdrawAndRemove(\n address indexed to,\n IERC20 token,\n uint256 amount,\n uint256 fee,\n uint8 swapTokenIndex,\n uint256 swapMinAmount,\n uint256 swapDeadline,\n bool swapSuccess,\n bytes32 indexed kappa\n );\n\n // v2 events\n event TokenRedeemV2(\n bytes32 indexed to,\n uint256 chainId,\n IERC20 token,\n uint256 amount\n );\n\n // VIEW FUNCTIONS ***/\n function getFeeBalance(address tokenAddress)\n external\n view\n returns (uint256)\n {\n return fees[tokenAddress];\n }\n\n function kappaExists(bytes32 kappa) external view returns (bool) {\n return kappaMap[kappa];\n }\n\n // FEE FUNCTIONS ***/\n /**\n * * @notice withdraw specified ERC20 token fees to a given address\n * * @param token ERC20 token in which fees acccumulated to transfer\n * * @param to Address to send the fees to\n */\n function withdrawFees(IERC20 token, address to) external whenNotPaused {\n require(hasRole(GOVERNANCE_ROLE, msg.sender), \"Not governance\");\n require(to != address(0), \"Address is 0x000\");\n if (fees[address(token)] != 0) {\n token.safeTransfer(to, fees[address(token)]);\n fees[address(token)] = 0;\n }\n }\n\n // PAUSABLE FUNCTIONS ***/\n function pause() external {\n require(hasRole(GOVERNANCE_ROLE, msg.sender), \"Not governance\");\n _pause();\n }\n\n function unpause() external {\n require(hasRole(GOVERNANCE_ROLE, msg.sender), \"Not governance\");\n _unpause();\n }\n\n /**\n * @notice Relays to nodes to transfers an ERC20 token cross-chain\n * @param to address on other chain to bridge assets to\n * @param chainId which chain to bridge assets onto\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n **/\n function deposit(\n address to,\n uint256 chainId,\n IERC20 token,\n uint256 amount\n ) external nonReentrant whenNotPaused {\n emit TokenDeposit(to, chainId, token, amount);\n token.safeTransferFrom(msg.sender, address(this), amount);\n }\n\n /**\n * @notice Relays to nodes that (typically) a wrapped synAsset ERC20 token has been burned and the underlying needs to be redeeemed on the native chain\n * @param to address on other chain to redeem underlying assets to\n * @param chainId which underlying chain to bridge assets onto\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n **/\n function redeem(\n address to,\n uint256 chainId,\n ERC20Burnable token,\n uint256 amount\n ) external nonReentrant whenNotPaused {\n emit TokenRedeem(to, chainId, token, amount);\n token.burnFrom(msg.sender, amount);\n }\n\n /**\n * @notice Function to be called by the node group to withdraw the underlying assets from the contract\n * @param to address on chain to send underlying assets to\n * @param token ERC20 compatible token to withdraw from the bridge\n * @param amount Amount in native token decimals to withdraw\n * @param fee Amount in native token decimals to save to the contract as fees\n * @param kappa kappa\n **/\n function withdraw(\n address to,\n IERC20 token,\n uint256 amount,\n uint256 fee,\n bytes32 kappa\n ) external nonReentrant whenNotPaused {\n require(\n hasRole(NODEGROUP_ROLE, msg.sender),\n \"Caller is not a node group\"\n );\n require(amount > fee, \"Amount must be greater than fee\");\n require(!kappaMap[kappa], \"Kappa is already present\");\n kappaMap[kappa] = true;\n fees[address(token)] = fees[address(token)].add(fee);\n if (address(token) == WETH_ADDRESS && WETH_ADDRESS != address(0)) {\n IWETH9(WETH_ADDRESS).withdraw(amount.sub(fee));\n (bool success, ) = to.call{value: amount.sub(fee)}(\"\");\n require(success, \"ETH_TRANSFER_FAILED\");\n emit TokenWithdraw(to, token, amount, fee, kappa);\n } else {\n emit TokenWithdraw(to, token, amount, fee, kappa);\n token.safeTransfer(to, amount.sub(fee));\n }\n }\n\n /**\n * @notice Nodes call this function to mint a SynERC20 (or any asset that the bridge is given minter access to). This is called by the nodes after a TokenDeposit event is emitted.\n * @dev This means the SynapseBridge.sol contract must have minter access to the token attempting to be minted\n * @param to address on other chain to redeem underlying assets to\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain post-fees\n * @param fee Amount in native token decimals to save to the contract as fees\n * @param kappa kappa\n **/\n function mint(\n address payable to,\n IERC20Mintable token,\n uint256 amount,\n uint256 fee,\n bytes32 kappa\n ) external nonReentrant whenNotPaused {\n require(\n hasRole(NODEGROUP_ROLE, msg.sender),\n \"Caller is not a node group\"\n );\n require(amount > fee, \"Amount must be greater than fee\");\n require(!kappaMap[kappa], \"Kappa is already present\");\n kappaMap[kappa] = true;\n fees[address(token)] = fees[address(token)].add(fee);\n emit TokenMint(to, token, amount.sub(fee), fee, kappa);\n token.mint(address(this), amount);\n // checks if synFRAX\n if (address(token) == 0xE96AC70907ffF3Efee79f502C985A7A21Bce407d) {\n token.safeIncreaseAllowance(\n 0x1A93B23281CC1CDE4C4741353F3064709A16197d,\n amount.sub(fee)\n );\n try\n IFrax(0x1A93B23281CC1CDE4C4741353F3064709A16197d)\n .exchangeOldForCanonical(address(token), amount.sub(fee))\n returns (uint256 canolical_tokens_out) {\n IERC20(0x1A93B23281CC1CDE4C4741353F3064709A16197d).safeTransfer(\n to,\n canolical_tokens_out\n );\n } catch {\n IERC20(token).safeTransfer(to, amount.sub(fee));\n }\n } else {\n IERC20(token).safeTransfer(to, amount.sub(fee));\n }\n if (chainGasAmount != 0 && address(this).balance > chainGasAmount) {\n to.call.value(chainGasAmount)(\"\");\n }\n }\n\n /**\n * @notice Relays to nodes to both transfer an ERC20 token cross-chain, and then have the nodes execute a swap through a liquidity pool on behalf of the user.\n * @param to address on other chain to bridge assets to\n * @param chainId which chain to bridge assets onto\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n * @param tokenIndexFrom the token the user wants to swap from\n * @param tokenIndexTo the token the user wants to swap to\n * @param minDy the min amount the user would like to receive, or revert to only minting the SynERC20 token crosschain.\n * @param deadline latest timestamp to accept this transaction\n **/\n function depositAndSwap(\n address to,\n uint256 chainId,\n IERC20 token,\n uint256 amount,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 minDy,\n uint256 deadline\n ) external nonReentrant whenNotPaused {\n emit TokenDepositAndSwap(\n to,\n chainId,\n token,\n amount,\n tokenIndexFrom,\n tokenIndexTo,\n minDy,\n deadline\n );\n token.safeTransferFrom(msg.sender, address(this), amount);\n }\n\n /**\n * @notice Relays to nodes that (typically) a wrapped synAsset ERC20 token has been burned and the underlying needs to be redeeemed on the native chain. This function indicates to the nodes that they should attempt to redeem the LP token for the underlying assets (E.g \"swap\" out of the LP token)\n * @param to address on other chain to redeem underlying assets to\n * @param chainId which underlying chain to bridge assets onto\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n * @param tokenIndexFrom the token the user wants to swap from\n * @param tokenIndexTo the token the user wants to swap to\n * @param minDy the min amount the user would like to receive, or revert to only minting the SynERC20 token crosschain.\n * @param deadline latest timestamp to accept this transaction\n **/\n function redeemAndSwap(\n address to,\n uint256 chainId,\n ERC20Burnable token,\n uint256 amount,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 minDy,\n uint256 deadline\n ) external nonReentrant whenNotPaused {\n emit TokenRedeemAndSwap(\n to,\n chainId,\n token,\n amount,\n tokenIndexFrom,\n tokenIndexTo,\n minDy,\n deadline\n );\n token.burnFrom(msg.sender, amount);\n }\n\n /**\n * @notice Relays to nodes that (typically) a wrapped synAsset ERC20 token has been burned and the underlying needs to be redeeemed on the native chain. This function indicates to the nodes that they should attempt to redeem the LP token for the underlying assets (E.g \"swap\" out of the LP token)\n * @param to address on other chain to redeem underlying assets to\n * @param chainId which underlying chain to bridge assets onto\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n * @param swapTokenIndex Specifies which of the underlying LP assets the nodes should attempt to redeem for\n * @param swapMinAmount Specifies the minimum amount of the underlying asset needed for the nodes to execute the redeem/swap\n * @param swapDeadline Specificies the deadline that the nodes are allowed to try to redeem/swap the LP token\n **/\n function redeemAndRemove(\n address to,\n uint256 chainId,\n ERC20Burnable token,\n uint256 amount,\n uint8 swapTokenIndex,\n uint256 swapMinAmount,\n uint256 swapDeadline\n ) external nonReentrant whenNotPaused {\n emit TokenRedeemAndRemove(\n to,\n chainId,\n token,\n amount,\n swapTokenIndex,\n swapMinAmount,\n swapDeadline\n );\n token.burnFrom(msg.sender, amount);\n }\n\n /**\n * @notice Nodes call this function to mint a SynERC20 (or any asset that the bridge is given minter access to), and then attempt to swap the SynERC20 into the desired destination asset. This is called by the nodes after a TokenDepositAndSwap event is emitted.\n * @dev This means the BridgeDeposit.sol contract must have minter access to the token attempting to be minted\n * @param to address on other chain to redeem underlying assets to\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain post-fees\n * @param fee Amount in native token decimals to save to the contract as fees\n * @param pool Destination chain's pool to use to swap SynERC20 -> Asset. The nodes determine this by using PoolConfig.sol.\n * @param tokenIndexFrom Index of the SynERC20 asset in the pool\n * @param tokenIndexTo Index of the desired final asset\n * @param minDy Minumum amount (in final asset decimals) that must be swapped for, otherwise the user will receive the SynERC20.\n * @param deadline Epoch time of the deadline that the swap is allowed to be executed.\n * @param kappa kappa\n **/\n function mintAndSwap(\n address payable to,\n IERC20Mintable token,\n uint256 amount,\n uint256 fee,\n ISwap pool,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 minDy,\n uint256 deadline,\n bytes32 kappa\n ) external nonReentrant whenNotPaused {\n require(\n hasRole(NODEGROUP_ROLE, msg.sender),\n \"Caller is not a node group\"\n );\n require(amount > fee, \"Amount must be greater than fee\");\n require(!kappaMap[kappa], \"Kappa is already present\");\n kappaMap[kappa] = true;\n fees[address(token)] = fees[address(token)].add(fee);\n // Transfer gas airdrop\n if (chainGasAmount != 0 && address(this).balance > chainGasAmount) {\n to.call.value(chainGasAmount)(\"\");\n }\n // first check to make sure more will be given than min amount required\n uint256 expectedOutput = ISwap(pool).calculateSwap(\n tokenIndexFrom,\n tokenIndexTo,\n amount.sub(fee)\n );\n\n if (expectedOutput >= minDy) {\n // proceed with swap\n token.mint(address(this), amount);\n token.safeIncreaseAllowance(address(pool), amount);\n try\n ISwap(pool).swap(\n tokenIndexFrom,\n tokenIndexTo,\n amount.sub(fee),\n minDy,\n deadline\n )\n returns (uint256 finalSwappedAmount) {\n // Swap succeeded, transfer swapped asset\n IERC20 swappedTokenTo = ISwap(pool).getToken(tokenIndexTo);\n if (\n address(swappedTokenTo) == WETH_ADDRESS &&\n WETH_ADDRESS != address(0)\n ) {\n IWETH9(WETH_ADDRESS).withdraw(finalSwappedAmount);\n (bool success, ) = to.call{value: finalSwappedAmount}(\"\");\n require(success, \"ETH_TRANSFER_FAILED\");\n emit TokenMintAndSwap(\n to,\n token,\n finalSwappedAmount,\n fee,\n tokenIndexFrom,\n tokenIndexTo,\n minDy,\n deadline,\n true,\n kappa\n );\n } else {\n swappedTokenTo.safeTransfer(to, finalSwappedAmount);\n emit TokenMintAndSwap(\n to,\n token,\n finalSwappedAmount,\n fee,\n tokenIndexFrom,\n tokenIndexTo,\n minDy,\n deadline,\n true,\n kappa\n );\n }\n } catch {\n IERC20(token).safeTransfer(to, amount.sub(fee));\n emit TokenMintAndSwap(\n to,\n token,\n amount.sub(fee),\n fee,\n tokenIndexFrom,\n tokenIndexTo,\n minDy,\n deadline,\n false,\n kappa\n );\n }\n } else {\n token.mint(address(this), amount);\n IERC20(token).safeTransfer(to, amount.sub(fee));\n emit TokenMintAndSwap(\n to,\n token,\n amount.sub(fee),\n fee,\n tokenIndexFrom,\n tokenIndexTo,\n minDy,\n deadline,\n false,\n kappa\n );\n }\n }\n\n /**\n * @notice Function to be called by the node group to withdraw the underlying assets from the contract\n * @param to address on chain to send underlying assets to\n * @param token ERC20 compatible token to withdraw from the bridge\n * @param amount Amount in native token decimals to withdraw\n * @param fee Amount in native token decimals to save to the contract as fees\n * @param pool Destination chain's pool to use to swap SynERC20 -> Asset. The nodes determine this by using PoolConfig.sol.\n * @param swapTokenIndex Specifies which of the underlying LP assets the nodes should attempt to redeem for\n * @param swapMinAmount Specifies the minimum amount of the underlying asset needed for the nodes to execute the redeem/swap\n * @param swapDeadline Specificies the deadline that the nodes are allowed to try to redeem/swap the LP token\n * @param kappa kappa\n **/\n function withdrawAndRemove(\n address to,\n IERC20 token,\n uint256 amount,\n uint256 fee,\n ISwap pool,\n uint8 swapTokenIndex,\n uint256 swapMinAmount,\n uint256 swapDeadline,\n bytes32 kappa\n ) external nonReentrant whenNotPaused {\n require(\n hasRole(NODEGROUP_ROLE, msg.sender),\n \"Caller is not a node group\"\n );\n require(amount > fee, \"Amount must be greater than fee\");\n require(!kappaMap[kappa], \"Kappa is already present\");\n kappaMap[kappa] = true;\n fees[address(token)] = fees[address(token)].add(fee);\n // first check to make sure more will be given than min amount required\n uint256 expectedOutput = ISwap(pool).calculateRemoveLiquidityOneToken(\n amount.sub(fee),\n swapTokenIndex\n );\n\n if (expectedOutput >= swapMinAmount) {\n token.safeIncreaseAllowance(address(pool), amount.sub(fee));\n try\n ISwap(pool).removeLiquidityOneToken(\n amount.sub(fee),\n swapTokenIndex,\n swapMinAmount,\n swapDeadline\n )\n returns (uint256 finalSwappedAmount) {\n // Swap succeeded, transfer swapped asset\n IERC20 swappedTokenTo = ISwap(pool).getToken(swapTokenIndex);\n swappedTokenTo.safeTransfer(to, finalSwappedAmount);\n emit TokenWithdrawAndRemove(\n to,\n token,\n finalSwappedAmount,\n fee,\n swapTokenIndex,\n swapMinAmount,\n swapDeadline,\n true,\n kappa\n );\n } catch {\n IERC20(token).safeTransfer(to, amount.sub(fee));\n emit TokenWithdrawAndRemove(\n to,\n token,\n amount.sub(fee),\n fee,\n swapTokenIndex,\n swapMinAmount,\n swapDeadline,\n false,\n kappa\n );\n }\n } else {\n token.safeTransfer(to, amount.sub(fee));\n emit TokenWithdrawAndRemove(\n to,\n token,\n amount.sub(fee),\n fee,\n swapTokenIndex,\n swapMinAmount,\n swapDeadline,\n false,\n kappa\n );\n }\n }\n\n // BRIDGE FUNCTIONS TO HANDLE DIFF ADDRESSES\n /**\n * @notice Relays to nodes that (typically) a wrapped synAsset ERC20 token has been burned and the underlying needs to be redeeemed on the native chain\n * @param to address on other chain to redeem underlying assets to\n * @param chainId which underlying chain to bridge assets onto\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n **/\n function redeemV2(\n bytes32 to,\n uint256 chainId,\n ERC20Burnable token,\n uint256 amount\n ) external nonReentrant whenNotPaused {\n emit TokenRedeemV2(to, chainId, token, amount);\n token.burnFrom(msg.sender, amount);\n }\n}\n" + }, + "contracts/bridge/HarmonySynapseBridge.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.6.12;\n\nimport \"@openzeppelin/contracts-upgradeable/proxy/Initializable.sol\";\nimport \"@openzeppelin/contracts-upgradeable/access/AccessControlUpgradeable.sol\";\nimport \"@openzeppelin/contracts-upgradeable/utils/ReentrancyGuardUpgradeable.sol\";\nimport \"@openzeppelin/contracts-upgradeable/utils/PausableUpgradeable.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/SafeERC20.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/ERC20Burnable.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport \"@openzeppelin/contracts/math/SafeMath.sol\";\n\nimport \"./interfaces/ISwap.sol\";\nimport \"./interfaces/IWETH9.sol\";\n\ninterface IERC20Mintable is IERC20 {\n function mint(address to, uint256 amount) external;\n}\n\ninterface IFrax {\n function exchangeOldForCanonical(\n address bridge_token_address,\n uint256 token_amount\n ) external returns (uint256);\n}\n\ncontract HarmonySynapseBridge is\n Initializable,\n AccessControlUpgradeable,\n ReentrancyGuardUpgradeable,\n PausableUpgradeable\n{\n using SafeERC20 for IERC20;\n using SafeERC20 for IERC20Mintable;\n using SafeMath for uint256;\n\n bytes32 public constant NODEGROUP_ROLE = keccak256(\"NODEGROUP_ROLE\");\n bytes32 public constant GOVERNANCE_ROLE = keccak256(\"GOVERNANCE_ROLE\");\n\n mapping(address => uint256) private fees;\n\n uint256 public startBlockNumber;\n uint256 public constant bridgeVersion = 6;\n uint256 public chainGasAmount;\n address payable public WETH_ADDRESS;\n\n mapping(bytes32 => bool) private kappaMap;\n\n receive() external payable {}\n\n function initialize() external initializer {\n startBlockNumber = block.number;\n _setupRole(DEFAULT_ADMIN_ROLE, msg.sender);\n __AccessControl_init();\n }\n\n function setChainGasAmount(uint256 amount) external {\n require(hasRole(GOVERNANCE_ROLE, msg.sender), \"Not governance\");\n chainGasAmount = amount;\n }\n\n function setWethAddress(address payable _wethAddress) external {\n require(hasRole(DEFAULT_ADMIN_ROLE, msg.sender), \"Not admin\");\n WETH_ADDRESS = _wethAddress;\n }\n\n function addKappas(bytes32[] calldata kappas) external {\n require(hasRole(GOVERNANCE_ROLE, msg.sender), \"Not governance\");\n for (uint256 i = 0; i < kappas.length; ++i) {\n kappaMap[kappas[i]] = true;\n }\n }\n\n event TokenDeposit(\n address indexed to,\n uint256 chainId,\n IERC20 token,\n uint256 amount\n );\n event TokenRedeem(\n address indexed to,\n uint256 chainId,\n IERC20 token,\n uint256 amount\n );\n event TokenWithdraw(\n address indexed to,\n IERC20 token,\n uint256 amount,\n uint256 fee,\n bytes32 indexed kappa\n );\n event TokenMint(\n address indexed to,\n IERC20Mintable token,\n uint256 amount,\n uint256 fee,\n bytes32 indexed kappa\n );\n event TokenDepositAndSwap(\n address indexed to,\n uint256 chainId,\n IERC20 token,\n uint256 amount,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 minDy,\n uint256 deadline\n );\n event TokenMintAndSwap(\n address indexed to,\n IERC20Mintable token,\n uint256 amount,\n uint256 fee,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 minDy,\n uint256 deadline,\n bool swapSuccess,\n bytes32 indexed kappa\n );\n event TokenRedeemAndSwap(\n address indexed to,\n uint256 chainId,\n IERC20 token,\n uint256 amount,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 minDy,\n uint256 deadline\n );\n event TokenRedeemAndRemove(\n address indexed to,\n uint256 chainId,\n IERC20 token,\n uint256 amount,\n uint8 swapTokenIndex,\n uint256 swapMinAmount,\n uint256 swapDeadline\n );\n event TokenWithdrawAndRemove(\n address indexed to,\n IERC20 token,\n uint256 amount,\n uint256 fee,\n uint8 swapTokenIndex,\n uint256 swapMinAmount,\n uint256 swapDeadline,\n bool swapSuccess,\n bytes32 indexed kappa\n );\n\n // v2 events\n event TokenRedeemV2(\n bytes32 indexed to,\n uint256 chainId,\n IERC20 token,\n uint256 amount\n );\n\n // VIEW FUNCTIONS ***/\n function getFeeBalance(address tokenAddress)\n external\n view\n returns (uint256)\n {\n return fees[tokenAddress];\n }\n\n function kappaExists(bytes32 kappa) external view returns (bool) {\n return kappaMap[kappa];\n }\n\n // FEE FUNCTIONS ***/\n /**\n * * @notice withdraw specified ERC20 token fees to a given address\n * * @param token ERC20 token in which fees acccumulated to transfer\n * * @param to Address to send the fees to\n */\n function withdrawFees(IERC20 token, address to) external whenNotPaused {\n require(hasRole(GOVERNANCE_ROLE, msg.sender), \"Not governance\");\n require(to != address(0), \"Address is 0x000\");\n if (fees[address(token)] != 0) {\n token.safeTransfer(to, fees[address(token)]);\n fees[address(token)] = 0;\n }\n }\n\n // PAUSABLE FUNCTIONS ***/\n function pause() external {\n require(hasRole(GOVERNANCE_ROLE, msg.sender), \"Not governance\");\n _pause();\n }\n\n function unpause() external {\n require(hasRole(GOVERNANCE_ROLE, msg.sender), \"Not governance\");\n _unpause();\n }\n\n /**\n * @notice Relays to nodes to transfers an ERC20 token cross-chain\n * @param to address on other chain to bridge assets to\n * @param chainId which chain to bridge assets onto\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n **/\n function deposit(\n address to,\n uint256 chainId,\n IERC20 token,\n uint256 amount\n ) external nonReentrant whenNotPaused {\n emit TokenDeposit(to, chainId, token, amount);\n token.safeTransferFrom(msg.sender, address(this), amount);\n }\n\n /**\n * @notice Relays to nodes that (typically) a wrapped synAsset ERC20 token has been burned and the underlying needs to be redeeemed on the native chain\n * @param to address on other chain to redeem underlying assets to\n * @param chainId which underlying chain to bridge assets onto\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n **/\n function redeem(\n address to,\n uint256 chainId,\n ERC20Burnable token,\n uint256 amount\n ) external nonReentrant whenNotPaused {\n emit TokenRedeem(to, chainId, token, amount);\n token.burnFrom(msg.sender, amount);\n }\n\n /**\n * @notice Function to be called by the node group to withdraw the underlying assets from the contract\n * @param to address on chain to send underlying assets to\n * @param token ERC20 compatible token to withdraw from the bridge\n * @param amount Amount in native token decimals to withdraw\n * @param fee Amount in native token decimals to save to the contract as fees\n * @param kappa kappa\n **/\n function withdraw(\n address to,\n IERC20 token,\n uint256 amount,\n uint256 fee,\n bytes32 kappa\n ) external nonReentrant whenNotPaused {\n require(\n hasRole(NODEGROUP_ROLE, msg.sender),\n \"Caller is not a node group\"\n );\n require(amount > fee, \"Amount must be greater than fee\");\n require(!kappaMap[kappa], \"Kappa is already present\");\n kappaMap[kappa] = true;\n fees[address(token)] = fees[address(token)].add(fee);\n if (address(token) == WETH_ADDRESS && WETH_ADDRESS != address(0)) {\n IWETH9(WETH_ADDRESS).withdraw(amount.sub(fee));\n (bool success, ) = to.call{value: amount.sub(fee)}(\"\");\n require(success, \"ETH_TRANSFER_FAILED\");\n emit TokenWithdraw(to, token, amount, fee, kappa);\n } else {\n emit TokenWithdraw(to, token, amount, fee, kappa);\n token.safeTransfer(to, amount.sub(fee));\n }\n }\n\n /**\n * @notice Nodes call this function to mint a SynERC20 (or any asset that the bridge is given minter access to). This is called by the nodes after a TokenDeposit event is emitted.\n * @dev This means the SynapseBridge.sol contract must have minter access to the token attempting to be minted\n * @param to address on other chain to redeem underlying assets to\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain post-fees\n * @param fee Amount in native token decimals to save to the contract as fees\n * @param kappa kappa\n **/\n function mint(\n address payable to,\n IERC20Mintable token,\n uint256 amount,\n uint256 fee,\n bytes32 kappa\n ) external nonReentrant whenNotPaused {\n require(\n hasRole(NODEGROUP_ROLE, msg.sender),\n \"Caller is not a node group\"\n );\n require(amount > fee, \"Amount must be greater than fee\");\n require(!kappaMap[kappa], \"Kappa is already present\");\n kappaMap[kappa] = true;\n fees[address(token)] = fees[address(token)].add(fee);\n emit TokenMint(to, token, amount.sub(fee), fee, kappa);\n token.mint(address(this), amount);\n // checks if synFRAX\n if (address(token) == 0x1852F70512298d56e9c8FDd905e02581E04ddb2a) {\n if (\n token.allowance(\n address(this),\n 0xFa7191D292d5633f702B0bd7E3E3BcCC0e633200\n ) < amount.sub(fee)\n ) {\n token.safeApprove(\n address(0xFa7191D292d5633f702B0bd7E3E3BcCC0e633200),\n 0\n );\n token.safeApprove(\n address(0xFa7191D292d5633f702B0bd7E3E3BcCC0e633200),\n type(uint256).max\n );\n }\n try\n IFrax(0xFa7191D292d5633f702B0bd7E3E3BcCC0e633200)\n .exchangeOldForCanonical(address(token), amount.sub(fee))\n returns (uint256 canolical_tokens_out) {\n IERC20(0xFa7191D292d5633f702B0bd7E3E3BcCC0e633200).safeTransfer(\n to,\n canolical_tokens_out\n );\n } catch {\n IERC20(token).safeTransfer(to, amount.sub(fee));\n }\n } else {\n IERC20(token).safeTransfer(to, amount.sub(fee));\n }\n if (chainGasAmount != 0 && address(this).balance > chainGasAmount) {\n to.call.value(chainGasAmount)(\"\");\n }\n }\n\n /**\n * @notice Relays to nodes to both transfer an ERC20 token cross-chain, and then have the nodes execute a swap through a liquidity pool on behalf of the user.\n * @param to address on other chain to bridge assets to\n * @param chainId which chain to bridge assets onto\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n * @param tokenIndexFrom the token the user wants to swap from\n * @param tokenIndexTo the token the user wants to swap to\n * @param minDy the min amount the user would like to receive, or revert to only minting the SynERC20 token crosschain.\n * @param deadline latest timestamp to accept this transaction\n **/\n function depositAndSwap(\n address to,\n uint256 chainId,\n IERC20 token,\n uint256 amount,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 minDy,\n uint256 deadline\n ) external nonReentrant whenNotPaused {\n emit TokenDepositAndSwap(\n to,\n chainId,\n token,\n amount,\n tokenIndexFrom,\n tokenIndexTo,\n minDy,\n deadline\n );\n token.safeTransferFrom(msg.sender, address(this), amount);\n }\n\n /**\n * @notice Relays to nodes that (typically) a wrapped synAsset ERC20 token has been burned and the underlying needs to be redeeemed on the native chain. This function indicates to the nodes that they should attempt to redeem the LP token for the underlying assets (E.g \"swap\" out of the LP token)\n * @param to address on other chain to redeem underlying assets to\n * @param chainId which underlying chain to bridge assets onto\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n * @param tokenIndexFrom the token the user wants to swap from\n * @param tokenIndexTo the token the user wants to swap to\n * @param minDy the min amount the user would like to receive, or revert to only minting the SynERC20 token crosschain.\n * @param deadline latest timestamp to accept this transaction\n **/\n function redeemAndSwap(\n address to,\n uint256 chainId,\n ERC20Burnable token,\n uint256 amount,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 minDy,\n uint256 deadline\n ) external nonReentrant whenNotPaused {\n emit TokenRedeemAndSwap(\n to,\n chainId,\n token,\n amount,\n tokenIndexFrom,\n tokenIndexTo,\n minDy,\n deadline\n );\n token.burnFrom(msg.sender, amount);\n }\n\n /**\n * @notice Relays to nodes that (typically) a wrapped synAsset ERC20 token has been burned and the underlying needs to be redeeemed on the native chain. This function indicates to the nodes that they should attempt to redeem the LP token for the underlying assets (E.g \"swap\" out of the LP token)\n * @param to address on other chain to redeem underlying assets to\n * @param chainId which underlying chain to bridge assets onto\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n * @param swapTokenIndex Specifies which of the underlying LP assets the nodes should attempt to redeem for\n * @param swapMinAmount Specifies the minimum amount of the underlying asset needed for the nodes to execute the redeem/swap\n * @param swapDeadline Specificies the deadline that the nodes are allowed to try to redeem/swap the LP token\n **/\n function redeemAndRemove(\n address to,\n uint256 chainId,\n ERC20Burnable token,\n uint256 amount,\n uint8 swapTokenIndex,\n uint256 swapMinAmount,\n uint256 swapDeadline\n ) external nonReentrant whenNotPaused {\n emit TokenRedeemAndRemove(\n to,\n chainId,\n token,\n amount,\n swapTokenIndex,\n swapMinAmount,\n swapDeadline\n );\n token.burnFrom(msg.sender, amount);\n }\n\n /**\n * @notice Nodes call this function to mint a SynERC20 (or any asset that the bridge is given minter access to), and then attempt to swap the SynERC20 into the desired destination asset. This is called by the nodes after a TokenDepositAndSwap event is emitted.\n * @dev This means the BridgeDeposit.sol contract must have minter access to the token attempting to be minted\n * @param to address on other chain to redeem underlying assets to\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain post-fees\n * @param fee Amount in native token decimals to save to the contract as fees\n * @param pool Destination chain's pool to use to swap SynERC20 -> Asset. The nodes determine this by using PoolConfig.sol.\n * @param tokenIndexFrom Index of the SynERC20 asset in the pool\n * @param tokenIndexTo Index of the desired final asset\n * @param minDy Minumum amount (in final asset decimals) that must be swapped for, otherwise the user will receive the SynERC20.\n * @param deadline Epoch time of the deadline that the swap is allowed to be executed.\n * @param kappa kappa\n **/\n function mintAndSwap(\n address payable to,\n IERC20Mintable token,\n uint256 amount,\n uint256 fee,\n ISwap pool,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 minDy,\n uint256 deadline,\n bytes32 kappa\n ) external nonReentrant whenNotPaused {\n require(\n hasRole(NODEGROUP_ROLE, msg.sender),\n \"Caller is not a node group\"\n );\n require(amount > fee, \"Amount must be greater than fee\");\n require(!kappaMap[kappa], \"Kappa is already present\");\n kappaMap[kappa] = true;\n fees[address(token)] = fees[address(token)].add(fee);\n // Transfer gas airdrop\n if (chainGasAmount != 0 && address(this).balance > chainGasAmount) {\n to.call.value(chainGasAmount)(\"\");\n }\n // first check to make sure more will be given than min amount required\n uint256 expectedOutput = ISwap(pool).calculateSwap(\n tokenIndexFrom,\n tokenIndexTo,\n amount.sub(fee)\n );\n\n if (expectedOutput >= minDy) {\n // proceed with swap\n token.mint(address(this), amount);\n token.safeIncreaseAllowance(address(pool), amount);\n try\n ISwap(pool).swap(\n tokenIndexFrom,\n tokenIndexTo,\n amount.sub(fee),\n minDy,\n deadline\n )\n returns (uint256 finalSwappedAmount) {\n // Swap succeeded, transfer swapped asset\n IERC20 swappedTokenTo = ISwap(pool).getToken(tokenIndexTo);\n if (\n address(swappedTokenTo) == WETH_ADDRESS &&\n WETH_ADDRESS != address(0)\n ) {\n IWETH9(WETH_ADDRESS).withdraw(finalSwappedAmount);\n (bool success, ) = to.call{value: finalSwappedAmount}(\"\");\n require(success, \"ETH_TRANSFER_FAILED\");\n emit TokenMintAndSwap(\n to,\n token,\n finalSwappedAmount,\n fee,\n tokenIndexFrom,\n tokenIndexTo,\n minDy,\n deadline,\n true,\n kappa\n );\n } else {\n swappedTokenTo.safeTransfer(to, finalSwappedAmount);\n emit TokenMintAndSwap(\n to,\n token,\n finalSwappedAmount,\n fee,\n tokenIndexFrom,\n tokenIndexTo,\n minDy,\n deadline,\n true,\n kappa\n );\n }\n } catch {\n IERC20(token).safeTransfer(to, amount.sub(fee));\n emit TokenMintAndSwap(\n to,\n token,\n amount.sub(fee),\n fee,\n tokenIndexFrom,\n tokenIndexTo,\n minDy,\n deadline,\n false,\n kappa\n );\n }\n } else {\n token.mint(address(this), amount);\n IERC20(token).safeTransfer(to, amount.sub(fee));\n emit TokenMintAndSwap(\n to,\n token,\n amount.sub(fee),\n fee,\n tokenIndexFrom,\n tokenIndexTo,\n minDy,\n deadline,\n false,\n kappa\n );\n }\n }\n\n /**\n * @notice Function to be called by the node group to withdraw the underlying assets from the contract\n * @param to address on chain to send underlying assets to\n * @param token ERC20 compatible token to withdraw from the bridge\n * @param amount Amount in native token decimals to withdraw\n * @param fee Amount in native token decimals to save to the contract as fees\n * @param pool Destination chain's pool to use to swap SynERC20 -> Asset. The nodes determine this by using PoolConfig.sol.\n * @param swapTokenIndex Specifies which of the underlying LP assets the nodes should attempt to redeem for\n * @param swapMinAmount Specifies the minimum amount of the underlying asset needed for the nodes to execute the redeem/swap\n * @param swapDeadline Specificies the deadline that the nodes are allowed to try to redeem/swap the LP token\n * @param kappa kappa\n **/\n function withdrawAndRemove(\n address to,\n IERC20 token,\n uint256 amount,\n uint256 fee,\n ISwap pool,\n uint8 swapTokenIndex,\n uint256 swapMinAmount,\n uint256 swapDeadline,\n bytes32 kappa\n ) external nonReentrant whenNotPaused {\n require(\n hasRole(NODEGROUP_ROLE, msg.sender),\n \"Caller is not a node group\"\n );\n require(amount > fee, \"Amount must be greater than fee\");\n require(!kappaMap[kappa], \"Kappa is already present\");\n kappaMap[kappa] = true;\n fees[address(token)] = fees[address(token)].add(fee);\n // first check to make sure more will be given than min amount required\n uint256 expectedOutput = ISwap(pool).calculateRemoveLiquidityOneToken(\n amount.sub(fee),\n swapTokenIndex\n );\n\n if (expectedOutput >= swapMinAmount) {\n token.safeIncreaseAllowance(address(pool), amount.sub(fee));\n try\n ISwap(pool).removeLiquidityOneToken(\n amount.sub(fee),\n swapTokenIndex,\n swapMinAmount,\n swapDeadline\n )\n returns (uint256 finalSwappedAmount) {\n // Swap succeeded, transfer swapped asset\n IERC20 swappedTokenTo = ISwap(pool).getToken(swapTokenIndex);\n swappedTokenTo.safeTransfer(to, finalSwappedAmount);\n emit TokenWithdrawAndRemove(\n to,\n token,\n finalSwappedAmount,\n fee,\n swapTokenIndex,\n swapMinAmount,\n swapDeadline,\n true,\n kappa\n );\n } catch {\n IERC20(token).safeTransfer(to, amount.sub(fee));\n emit TokenWithdrawAndRemove(\n to,\n token,\n amount.sub(fee),\n fee,\n swapTokenIndex,\n swapMinAmount,\n swapDeadline,\n false,\n kappa\n );\n }\n } else {\n token.safeTransfer(to, amount.sub(fee));\n emit TokenWithdrawAndRemove(\n to,\n token,\n amount.sub(fee),\n fee,\n swapTokenIndex,\n swapMinAmount,\n swapDeadline,\n false,\n kappa\n );\n }\n }\n\n // BRIDGE FUNCTIONS TO HANDLE DIFF ADDRESSES\n /**\n * @notice Relays to nodes that (typically) a wrapped synAsset ERC20 token has been burned and the underlying needs to be redeeemed on the native chain\n * @param to address on other chain to redeem underlying assets to\n * @param chainId which underlying chain to bridge assets onto\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n **/\n function redeemV2(\n bytes32 to,\n uint256 chainId,\n ERC20Burnable token,\n uint256 amount\n ) external nonReentrant whenNotPaused {\n emit TokenRedeemV2(to, chainId, token, amount);\n token.burnFrom(msg.sender, amount);\n }\n}\n" + }, + "contracts/bridge/SynapseERC20.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.6.12;\n\nimport \"@openzeppelin/contracts-upgradeable/token/ERC20/ERC20Upgradeable.sol\";\nimport \"@openzeppelin/contracts-upgradeable/token/ERC20/ERC20BurnableUpgradeable.sol\";\nimport \"@openzeppelin/contracts-upgradeable/drafts/ERC20PermitUpgradeable.sol\";\nimport \"@openzeppelin/contracts-upgradeable/access/AccessControlUpgradeable.sol\";\nimport \"@openzeppelin/contracts-upgradeable/proxy/Initializable.sol\";\n\ncontract SynapseERC20 is\n Initializable,\n ContextUpgradeable,\n AccessControlUpgradeable,\n ERC20BurnableUpgradeable,\n ERC20PermitUpgradeable\n{\n bytes32 public constant MINTER_ROLE = keccak256(\"MINTER_ROLE\");\n\n /**\n * @notice Initializes this ERC20 contract with the given parameters.\n * @param name Token name\n * @param symbol Token symbol\n * @param decimals Token name\n * @param owner admin address to be initialized with\n */\n function initialize(\n string memory name,\n string memory symbol,\n uint8 decimals,\n address owner\n ) external initializer {\n __Context_init_unchained();\n __AccessControl_init_unchained();\n __ERC20_init_unchained(name, symbol);\n __ERC20Burnable_init_unchained();\n _setupDecimals(decimals);\n __ERC20Permit_init(name);\n _setupRole(DEFAULT_ADMIN_ROLE, owner);\n }\n\n function mint(address to, uint256 amount) external {\n require(hasRole(MINTER_ROLE, msg.sender), \"Not a minter\");\n _mint(to, amount);\n }\n}\n" + }, + "@openzeppelin/contracts-upgradeable/drafts/ERC20PermitUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.5 <0.8.0;\n\nimport \"../token/ERC20/ERC20Upgradeable.sol\";\nimport \"./IERC20PermitUpgradeable.sol\";\nimport \"../cryptography/ECDSAUpgradeable.sol\";\nimport \"../utils/CountersUpgradeable.sol\";\nimport \"./EIP712Upgradeable.sol\";\nimport \"../proxy/Initializable.sol\";\n\n/**\n * @dev Implementation of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in\n * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612].\n *\n * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by\n * presenting a message signed by the account. By not relying on `{IERC20-approve}`, the token holder account doesn't\n * need to send a transaction, and thus is not required to hold Ether at all.\n *\n * _Available since v3.4._\n */\nabstract contract ERC20PermitUpgradeable is Initializable, ERC20Upgradeable, IERC20PermitUpgradeable, EIP712Upgradeable {\n using CountersUpgradeable for CountersUpgradeable.Counter;\n\n mapping (address => CountersUpgradeable.Counter) private _nonces;\n\n // solhint-disable-next-line var-name-mixedcase\n bytes32 private _PERMIT_TYPEHASH;\n\n /**\n * @dev Initializes the {EIP712} domain separator using the `name` parameter, and setting `version` to `\"1\"`.\n *\n * It's a good idea to use the same `name` that is defined as the ERC20 token name.\n */\n function __ERC20Permit_init(string memory name) internal initializer {\n __Context_init_unchained();\n __EIP712_init_unchained(name, \"1\");\n __ERC20Permit_init_unchained(name);\n }\n\n function __ERC20Permit_init_unchained(string memory name) internal initializer {\n _PERMIT_TYPEHASH = keccak256(\"Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)\");\n }\n\n /**\n * @dev See {IERC20Permit-permit}.\n */\n function permit(address owner, address spender, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s) public virtual override {\n // solhint-disable-next-line not-rely-on-time\n require(block.timestamp <= deadline, \"ERC20Permit: expired deadline\");\n\n bytes32 structHash = keccak256(\n abi.encode(\n _PERMIT_TYPEHASH,\n owner,\n spender,\n value,\n _nonces[owner].current(),\n deadline\n )\n );\n\n bytes32 hash = _hashTypedDataV4(structHash);\n\n address signer = ECDSAUpgradeable.recover(hash, v, r, s);\n require(signer == owner, \"ERC20Permit: invalid signature\");\n\n _nonces[owner].increment();\n _approve(owner, spender, value);\n }\n\n /**\n * @dev See {IERC20Permit-nonces}.\n */\n function nonces(address owner) public view override returns (uint256) {\n return _nonces[owner].current();\n }\n\n /**\n * @dev See {IERC20Permit-DOMAIN_SEPARATOR}.\n */\n // solhint-disable-next-line func-name-mixedcase\n function DOMAIN_SEPARATOR() external view override returns (bytes32) {\n return _domainSeparatorV4();\n }\n uint256[49] private __gap;\n}\n" + }, + "@openzeppelin/contracts-upgradeable/drafts/IERC20PermitUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <0.8.0;\n\n/**\n * @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in\n * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612].\n *\n * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by\n * presenting a message signed by the account. By not relying on `{IERC20-approve}`, the token holder account doesn't\n * need to send a transaction, and thus is not required to hold Ether at all.\n */\ninterface IERC20PermitUpgradeable {\n /**\n * @dev Sets `value` as the allowance of `spender` over `owner`'s tokens,\n * given `owner`'s signed approval.\n *\n * IMPORTANT: The same issues {IERC20-approve} has related to transaction\n * ordering also apply here.\n *\n * Emits an {Approval} event.\n *\n * Requirements:\n *\n * - `spender` cannot be the zero address.\n * - `deadline` must be a timestamp in the future.\n * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner`\n * over the EIP712-formatted function arguments.\n * - the signature must use ``owner``'s current nonce (see {nonces}).\n *\n * For more information on the signature format, see the\n * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP\n * section].\n */\n function permit(address owner, address spender, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s) external;\n\n /**\n * @dev Returns the current nonce for `owner`. This value must be\n * included whenever a signature is generated for {permit}.\n *\n * Every successful call to {permit} increases ``owner``'s nonce by one. This\n * prevents a signature from being used multiple times.\n */\n function nonces(address owner) external view returns (uint256);\n\n /**\n * @dev Returns the domain separator used in the encoding of the signature for `permit`, as defined by {EIP712}.\n */\n // solhint-disable-next-line func-name-mixedcase\n function DOMAIN_SEPARATOR() external view returns (bytes32);\n}\n" + }, + "@openzeppelin/contracts-upgradeable/cryptography/ECDSAUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <0.8.0;\n\n/**\n * @dev Elliptic Curve Digital Signature Algorithm (ECDSA) operations.\n *\n * These functions can be used to verify that a message was signed by the holder\n * of the private keys of a given address.\n */\nlibrary ECDSAUpgradeable {\n /**\n * @dev Returns the address that signed a hashed message (`hash`) with\n * `signature`. This address can then be used for verification purposes.\n *\n * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:\n * this function rejects them by requiring the `s` value to be in the lower\n * half order, and the `v` value to be either 27 or 28.\n *\n * IMPORTANT: `hash` _must_ be the result of a hash operation for the\n * verification to be secure: it is possible to craft signatures that\n * recover to arbitrary addresses for non-hashed data. A safe way to ensure\n * this is by receiving a hash of the original message (which may otherwise\n * be too long), and then calling {toEthSignedMessageHash} on it.\n */\n function recover(bytes32 hash, bytes memory signature) internal pure returns (address) {\n // Check the signature length\n if (signature.length != 65) {\n revert(\"ECDSA: invalid signature length\");\n }\n\n // Divide the signature in r, s and v variables\n bytes32 r;\n bytes32 s;\n uint8 v;\n\n // ecrecover takes the signature parameters, and the only way to get them\n // currently is to use assembly.\n // solhint-disable-next-line no-inline-assembly\n assembly {\n r := mload(add(signature, 0x20))\n s := mload(add(signature, 0x40))\n v := byte(0, mload(add(signature, 0x60)))\n }\n\n return recover(hash, v, r, s);\n }\n\n /**\n * @dev Overload of {ECDSA-recover-bytes32-bytes-} that receives the `v`,\n * `r` and `s` signature fields separately.\n */\n function recover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) internal pure returns (address) {\n // EIP-2 still allows signature malleability for ecrecover(). Remove this possibility and make the signature\n // unique. Appendix F in the Ethereum Yellow paper (https://ethereum.github.io/yellowpaper/paper.pdf), defines\n // the valid range for s in (281): 0 < s < secp256k1n ÷ 2 + 1, and for v in (282): v ∈ {27, 28}. Most\n // signatures from current libraries generate a unique signature with an s-value in the lower half order.\n //\n // If your library generates malleable signatures, such as s-values in the upper range, calculate a new s-value\n // with 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 - s1 and flip v from 27 to 28 or\n // vice versa. If your library also generates signatures with 0/1 for v instead 27/28, add 27 to v to accept\n // these malleable signatures as well.\n require(uint256(s) <= 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0, \"ECDSA: invalid signature 's' value\");\n require(v == 27 || v == 28, \"ECDSA: invalid signature 'v' value\");\n\n // If the signature is valid (and not malleable), return the signer address\n address signer = ecrecover(hash, v, r, s);\n require(signer != address(0), \"ECDSA: invalid signature\");\n\n return signer;\n }\n\n /**\n * @dev Returns an Ethereum Signed Message, created from a `hash`. This\n * replicates the behavior of the\n * https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_sign[`eth_sign`]\n * JSON-RPC method.\n *\n * See {recover}.\n */\n function toEthSignedMessageHash(bytes32 hash) internal pure returns (bytes32) {\n // 32 is the length in bytes of hash,\n // enforced by the type signature above\n return keccak256(abi.encodePacked(\"\\x19Ethereum Signed Message:\\n32\", hash));\n }\n}\n" + }, + "@openzeppelin/contracts-upgradeable/utils/CountersUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <0.8.0;\n\nimport \"../math/SafeMathUpgradeable.sol\";\n\n/**\n * @title Counters\n * @author Matt Condon (@shrugs)\n * @dev Provides counters that can only be incremented or decremented by one. This can be used e.g. to track the number\n * of elements in a mapping, issuing ERC721 ids, or counting request ids.\n *\n * Include with `using Counters for Counters.Counter;`\n * Since it is not possible to overflow a 256 bit integer with increments of one, `increment` can skip the {SafeMath}\n * overflow check, thereby saving gas. This does assume however correct usage, in that the underlying `_value` is never\n * directly accessed.\n */\nlibrary CountersUpgradeable {\n using SafeMathUpgradeable for uint256;\n\n struct Counter {\n // This variable should never be directly accessed by users of the library: interactions must be restricted to\n // the library's function. As of Solidity v0.5.2, this cannot be enforced, though there is a proposal to add\n // this feature: see https://github.com/ethereum/solidity/issues/4637\n uint256 _value; // default: 0\n }\n\n function current(Counter storage counter) internal view returns (uint256) {\n return counter._value;\n }\n\n function increment(Counter storage counter) internal {\n // The {SafeMath} overflow check can be skipped here, see the comment at the top\n counter._value += 1;\n }\n\n function decrement(Counter storage counter) internal {\n counter._value = counter._value.sub(1);\n }\n}\n" + }, + "@openzeppelin/contracts-upgradeable/drafts/EIP712Upgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <0.8.0;\nimport \"../proxy/Initializable.sol\";\n\n/**\n * @dev https://eips.ethereum.org/EIPS/eip-712[EIP 712] is a standard for hashing and signing of typed structured data.\n *\n * The encoding specified in the EIP is very generic, and such a generic implementation in Solidity is not feasible,\n * thus this contract does not implement the encoding itself. Protocols need to implement the type-specific encoding\n * they need in their contracts using a combination of `abi.encode` and `keccak256`.\n *\n * This contract implements the EIP 712 domain separator ({_domainSeparatorV4}) that is used as part of the encoding\n * scheme, and the final step of the encoding to obtain the message digest that is then signed via ECDSA\n * ({_hashTypedDataV4}).\n *\n * The implementation of the domain separator was designed to be as efficient as possible while still properly updating\n * the chain id to protect against replay attacks on an eventual fork of the chain.\n *\n * NOTE: This contract implements the version of the encoding known as \"v4\", as implemented by the JSON RPC method\n * https://docs.metamask.io/guide/signing-data.html[`eth_signTypedDataV4` in MetaMask].\n *\n * _Available since v3.4._\n */\nabstract contract EIP712Upgradeable is Initializable {\n /* solhint-disable var-name-mixedcase */\n bytes32 private _HASHED_NAME;\n bytes32 private _HASHED_VERSION;\n bytes32 private constant _TYPE_HASH = keccak256(\"EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)\");\n /* solhint-enable var-name-mixedcase */\n\n /**\n * @dev Initializes the domain separator and parameter caches.\n *\n * The meaning of `name` and `version` is specified in\n * https://eips.ethereum.org/EIPS/eip-712#definition-of-domainseparator[EIP 712]:\n *\n * - `name`: the user readable name of the signing domain, i.e. the name of the DApp or the protocol.\n * - `version`: the current major version of the signing domain.\n *\n * NOTE: These parameters cannot be changed except through a xref:learn::upgrading-smart-contracts.adoc[smart\n * contract upgrade].\n */\n function __EIP712_init(string memory name, string memory version) internal initializer {\n __EIP712_init_unchained(name, version);\n }\n\n function __EIP712_init_unchained(string memory name, string memory version) internal initializer {\n bytes32 hashedName = keccak256(bytes(name));\n bytes32 hashedVersion = keccak256(bytes(version));\n _HASHED_NAME = hashedName;\n _HASHED_VERSION = hashedVersion;\n }\n\n /**\n * @dev Returns the domain separator for the current chain.\n */\n function _domainSeparatorV4() internal view returns (bytes32) {\n return _buildDomainSeparator(_TYPE_HASH, _EIP712NameHash(), _EIP712VersionHash());\n }\n\n function _buildDomainSeparator(bytes32 typeHash, bytes32 name, bytes32 version) private view returns (bytes32) {\n return keccak256(\n abi.encode(\n typeHash,\n name,\n version,\n _getChainId(),\n address(this)\n )\n );\n }\n\n /**\n * @dev Given an already https://eips.ethereum.org/EIPS/eip-712#definition-of-hashstruct[hashed struct], this\n * function returns the hash of the fully encoded EIP712 message for this domain.\n *\n * This hash can be used together with {ECDSA-recover} to obtain the signer of a message. For example:\n *\n * ```solidity\n * bytes32 digest = _hashTypedDataV4(keccak256(abi.encode(\n * keccak256(\"Mail(address to,string contents)\"),\n * mailTo,\n * keccak256(bytes(mailContents))\n * )));\n * address signer = ECDSA.recover(digest, signature);\n * ```\n */\n function _hashTypedDataV4(bytes32 structHash) internal view virtual returns (bytes32) {\n return keccak256(abi.encodePacked(\"\\x19\\x01\", _domainSeparatorV4(), structHash));\n }\n\n function _getChainId() private view returns (uint256 chainId) {\n this; // silence state mutability warning without generating bytecode - see https://github.com/ethereum/solidity/issues/2691\n // solhint-disable-next-line no-inline-assembly\n assembly {\n chainId := chainid()\n }\n }\n\n /**\n * @dev The hash of the name parameter for the EIP712 domain.\n *\n * NOTE: This function reads from storage by default, but can be redefined to return a constant value if gas costs\n * are a concern.\n */\n function _EIP712NameHash() internal virtual view returns (bytes32) {\n return _HASHED_NAME;\n }\n\n /**\n * @dev The hash of the version parameter for the EIP712 domain.\n *\n * NOTE: This function reads from storage by default, but can be redefined to return a constant value if gas costs\n * are a concern.\n */\n function _EIP712VersionHash() internal virtual view returns (bytes32) {\n return _HASHED_VERSION;\n }\n uint256[50] private __gap;\n}\n" + }, + "contracts/auxiliary/DummyWethProxy.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.6.12;\nimport \"@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol\";\nimport \"@openzeppelin/contracts-upgradeable/proxy/Initializable.sol\";\n\ninterface IWETH9 {\n function name() external view returns (string memory);\n\n function symbol() external view returns (string memory);\n\n function decimals() external view returns (uint8);\n\n function balanceOf(address) external view returns (uint256);\n\n function allowance(address, address) external view returns (uint256);\n\n receive() external payable;\n\n function deposit() external payable;\n\n function withdraw(uint256 wad) external;\n\n function totalSupply() external view returns (uint256);\n\n function approve(address guy, uint256 wad) external returns (bool);\n\n function transfer(address dst, uint256 wad) external returns (bool);\n\n function transferFrom(\n address src,\n address dst,\n uint256 wad\n ) external returns (bool);\n}\n\ncontract DummyWethProxy is Initializable, OwnableUpgradeable {\n function initialize() external initializer {\n __Ownable_init();\n }\n\n IWETH9 public WETH;\n\n function setWETHAddress(address payable _weth) external onlyOwner {\n WETH = IWETH9(_weth);\n }\n\n function withdrawToSelf(uint256 amount) external {\n WETH.withdraw(amount);\n }\n\n function rescue(uint256 amount) external onlyOwner {\n WETH.transfer(owner(), amount);\n }\n\n receive() external payable {}\n\n fallback() external payable {}\n}\n" + }, + "contracts/amm/helper/test/TestMathUtils.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.6.12;\n\nimport \"../../MathUtils.sol\";\n\ncontract TestMathUtils {\n using MathUtils for uint256;\n\n function difference(uint256 a, uint256 b) public pure returns (uint256) {\n return a.difference(b);\n }\n\n function within1(uint256 a, uint256 b) public pure returns (bool) {\n return a.within1(b);\n }\n}\n" + }, + "contracts/bridge/ERC20Migrator.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.6.12;\n\nimport \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/SafeERC20.sol\";\nimport \"@openzeppelin/contracts/math/SafeMath.sol\";\n\n/**\n * @title ERC20Migrator\n * @dev This contract can be used to migrate an ERC20 token from one\n * contract to another, where each token holder has to opt-in to the migration.\n * To opt-in, users must approve for this contract the number of tokens they\n * want to migrate. Once the allowance is set up, anyone can trigger the\n * migration to the new token contract. In this way, token holders \"turn in\"\n * their old balance and will be minted an equal amount in the new token.\n * The new token contract must be mintable.\n * ```\n */\n\ninterface IERC20Mintable is IERC20 {\n function mint(address to, uint256 amount) external;\n}\n\ncontract ERC20Migrator {\n using SafeERC20 for IERC20;\n using SafeMath for uint256;\n\n // Address of the old token contract\n IERC20 private _legacyToken;\n\n // Address of the new token contract\n IERC20Mintable private _newToken;\n\n /**\n * @param legacyToken address of the old token contract\n */\n constructor(IERC20 legacyToken, IERC20Mintable newToken) public {\n _legacyToken = legacyToken;\n _newToken = newToken;\n }\n\n /**\n * @dev Returns the legacy token that is being migrated.\n */\n function legacyToken() external view returns (IERC20) {\n return _legacyToken;\n }\n\n /**\n * @dev Returns the new token to which we are migrating.\n */\n function newToken() external view returns (IERC20) {\n return _newToken;\n }\n\n /**\n * @dev Transfers part of an account's balance in the old token to this\n * contract, and mints the same amount of new tokens for that account.\n * @param amount amount of tokens to be migrated\n */\n function migrate(uint256 amount) external {\n _legacyToken.safeTransferFrom(msg.sender, address(this), amount);\n uint256 amountToMint = amount.mul(5).div(2);\n _newToken.mint(msg.sender, amountToMint);\n }\n}\n" + }, + "contracts/bridge/ECDSANodeManagement.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.6.12;\n\nimport \"./utils/AddressArrayUtils.sol\";\nimport \"@openzeppelin/contracts/math/SafeMath.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/SafeERC20.sol\";\n\ncontract ECDSANodeManagement {\n using AddressArrayUtils for address[];\n using SafeMath for uint256;\n using SafeERC20 for IERC20;\n\n // Status of the keep.\n // Active means the keep is active.\n // Closed means the keep was closed happily.\n // Terminated means the keep was closed due to misbehavior.\n enum Status {\n Active,\n Closed,\n Terminated\n }\n\n // Address of the keep's owner.\n address public owner;\n\n // List of keep members' addresses.\n address[] public members;\n\n // Minimum number of honest keep members required to produce a signature.\n uint256 public honestThreshold;\n\n // Keep's ECDSA public key serialized to 64-bytes, where X and Y coordinates\n // are padded with zeros to 32-byte each.\n bytes public publicKey;\n\n // The timestamp at which keep has been created and key generation process\n // started.\n uint256 internal keyGenerationStartTimestamp;\n\n // Map stores public key by member addresses. All members should submit the\n // same public key.\n mapping(address => bytes) internal submittedPublicKeys;\n\n // The current status of the keep.\n // If the keep is Active members monitor it and support requests from the\n // keep owner.\n // If the owner decides to close the keep the flag is set to Closed.\n // If the owner seizes member bonds the flag is set to Terminated.\n Status internal status;\n\n // Flags execution of contract initialization.\n bool internal isInitialized;\n\n // Notification that the submitted public key does not match a key submitted\n // by other member. The event contains address of the member who tried to\n // submit a public key and a conflicting public key submitted already by other\n // member.\n event ConflictingPublicKeySubmitted(\n address indexed submittingMember,\n bytes conflictingPublicKey\n );\n\n // Notification that keep's ECDSA public key has been successfully established.\n event PublicKeyPublished(bytes publicKey);\n\n // Notification that the keep was closed by the owner.\n // Members no longer need to support this keep.\n event KeepClosed();\n\n // Notification that the keep has been terminated by the owner.\n // Members no longer need to support this keep.\n event KeepTerminated();\n\n /// @notice Returns keep's ECDSA public key.\n /// @return Keep's ECDSA public key.\n function getPublicKey() external view returns (bytes memory) {\n return publicKey;\n }\n\n /// @notice Submits a public key to the keep.\n /// @dev Public key is published successfully if all members submit the same\n /// value. In case of conflicts with others members submissions it will emit\n /// `ConflictingPublicKeySubmitted` event. When all submitted keys match\n /// it will store the key as keep's public key and emit a `PublicKeyPublished`\n /// event.\n /// @param _publicKey Signer's public key.\n function submitPublicKey(bytes calldata _publicKey) external onlyMember {\n require(\n !hasMemberSubmittedPublicKey(msg.sender),\n \"Member already submitted a public key\"\n );\n\n require(_publicKey.length == 64, \"Public key must be 64 bytes long\");\n\n submittedPublicKeys[msg.sender] = _publicKey;\n\n // Check if public keys submitted by all keep members are the same as\n // the currently submitted one.\n uint256 matchingPublicKeysCount = 0;\n for (uint256 i = 0; i < members.length; i++) {\n if (\n keccak256(submittedPublicKeys[members[i]]) !=\n keccak256(_publicKey)\n ) {\n // Emit an event only if compared member already submitted a value.\n if (hasMemberSubmittedPublicKey(members[i])) {\n emit ConflictingPublicKeySubmitted(\n msg.sender,\n submittedPublicKeys[members[i]]\n );\n }\n } else {\n matchingPublicKeysCount++;\n }\n }\n\n if (matchingPublicKeysCount != members.length) {\n return;\n }\n\n // All submitted signatures match.\n publicKey = _publicKey;\n emit PublicKeyPublished(_publicKey);\n }\n\n /// @notice Gets the owner of the keep.\n /// @return Address of the keep owner.\n function getOwner() external view returns (address) {\n return owner;\n }\n\n /// @notice Gets the timestamp the keep was opened at.\n /// @return Timestamp the keep was opened at.\n function getOpenedTimestamp() external view returns (uint256) {\n return keyGenerationStartTimestamp;\n }\n\n /// @notice Closes keep when owner decides that they no longer need it.\n /// Releases bonds to the keep members.\n /// @dev The function can be called only by the owner of the keep and only\n /// if the keep has not been already closed.\n function closeKeep() public onlyOwner onlyWhenActive {\n markAsClosed();\n }\n\n /// @notice Returns true if the keep is active.\n /// @return true if the keep is active, false otherwise.\n function isActive() public view returns (bool) {\n return status == Status.Active;\n }\n\n /// @notice Returns true if the keep is closed and members no longer support\n /// this keep.\n /// @return true if the keep is closed, false otherwise.\n function isClosed() public view returns (bool) {\n return status == Status.Closed;\n }\n\n /// @notice Returns true if the keep has been terminated.\n /// Keep is terminated when bonds are seized and members no longer support\n /// this keep.\n /// @return true if the keep has been terminated, false otherwise.\n function isTerminated() public view returns (bool) {\n return status == Status.Terminated;\n }\n\n /// @notice Returns members of the keep.\n /// @return List of the keep members' addresses.\n function getMembers() public view returns (address[] memory) {\n return members;\n }\n\n /// @notice Initialization function.\n /// @dev We use clone factory to create new keep. That is why this contract\n /// doesn't have a constructor. We provide keep parameters for each instance\n /// function after cloning instances from the master contract.\n /// Initialization must happen in the same transaction in which the clone is\n /// created.\n /// @param _owner Address of the keep owner.\n /// @param _members Addresses of the keep members.\n /// @param _honestThreshold Minimum number of honest keep members.\n function initialize(\n address _owner,\n address[] memory _members,\n uint256 _honestThreshold\n ) public {\n require(!isInitialized, \"Contract already initialized\");\n require(_owner != address(0));\n owner = _owner;\n members = _members;\n honestThreshold = _honestThreshold;\n\n status = Status.Active;\n isInitialized = true;\n\n /* solium-disable-next-line security/no-block-members*/\n keyGenerationStartTimestamp = block.timestamp;\n }\n\n /// @notice Checks if the member already submitted a public key.\n /// @param _member Address of the member.\n /// @return True if member already submitted a public key, else false.\n function hasMemberSubmittedPublicKey(address _member)\n internal\n view\n returns (bool)\n {\n return submittedPublicKeys[_member].length != 0;\n }\n\n /// @notice Marks the keep as closed.\n /// Keep can be marked as closed only when there is no signing in progress\n /// or the requested signing process has timed out.\n function markAsClosed() internal {\n status = Status.Closed;\n emit KeepClosed();\n }\n\n /// @notice Marks the keep as terminated.\n /// Keep can be marked as terminated only when there is no signing in progress\n /// or the requested signing process has timed out.\n function markAsTerminated() internal {\n status = Status.Terminated;\n emit KeepTerminated();\n }\n\n /// @notice Coverts a public key to an ethereum address.\n /// @param _publicKey Public key provided as 64-bytes concatenation of\n /// X and Y coordinates (32-bytes each).\n /// @return Ethereum address.\n function publicKeyToAddress(bytes memory _publicKey)\n internal\n pure\n returns (address)\n {\n // We hash the public key and then truncate last 20 bytes of the digest\n // which is the ethereum address.\n return address(uint160(uint256(keccak256(_publicKey))));\n }\n\n /// @notice Terminates the keep.\n function terminateKeep() internal {\n markAsTerminated();\n }\n\n /// @notice Checks if the caller is the keep's owner.\n /// @dev Throws an error if called by any account other than owner.\n modifier onlyOwner() {\n require(owner == msg.sender, \"Caller is not the keep owner\");\n _;\n }\n\n /// @notice Checks if the caller is a keep member.\n /// @dev Throws an error if called by any account other than one of the members.\n modifier onlyMember() {\n require(members.contains(msg.sender), \"Caller is not the keep member\");\n _;\n }\n\n /// @notice Checks if the keep is currently active.\n /// @dev Throws an error if called when the keep has been already closed.\n modifier onlyWhenActive() {\n require(isActive(), \"Keep is not active\");\n _;\n }\n}\n" + }, + "contracts/bridge/utils/AddressArrayUtils.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.6.12;\n\nlibrary AddressArrayUtils {\n function contains(address[] memory self, address _address)\n internal\n pure\n returns (bool)\n {\n for (uint256 i = 0; i < self.length; i++) {\n if (_address == self[i]) {\n return true;\n }\n }\n return false;\n }\n}" + }, + "contracts/bridge/testing/NodeEnv.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.6.12;\npragma experimental ABIEncoderV2;\n\nimport '@openzeppelin/contracts/access/AccessControl.sol';\nimport \"../utils/EnumerableStringMap.sol\";\n\n/**\n * @title NodeEnv contract\n * @author Synapse Authors\n * @notice This contract implements a key-value store for storing variables on which synapse nodes must coordinate\n * methods are purposely arbitrary to allow these fields to be defined in synapse improvement proposals.\n * @notice This token is used for configuring different tokens on the bridge and mapping them across chains.\n**/\ncontract NodeEnv is AccessControl {\n using EnumerableStringMap for EnumerableStringMap.StringToStringMap;\n // BRIDGEMANAGER_ROLE owns the bridge. They are the only user that can call setters on this contract\n bytes32 public constant BRIDGEMANAGER_ROLE = keccak256('BRIDGEMANAGER_ROLE');\n // _config stores the config\n EnumerableStringMap.StringToStringMap private _config; // key is tokenAddress,chainID\n\n // ConfigUpdate is emitted when the config is updated by the user\n event ConfigUpdate(\n string key\n );\n\n constructor() public {\n _setupRole(DEFAULT_ADMIN_ROLE, msg.sender);\n _setupRole(BRIDGEMANAGER_ROLE, msg.sender);\n }\n\n /**\n * @notice get the length of the config\n *\n * @dev this is useful for enumerating through all keys in the env\n */\n function keyCount()\n external\n view\n returns (uint256){\n return _config.length();\n }\n\n /**\n * @notice gets the key/value pair by it's index\n *\n * Requirements:\n *\n * - `index` must be strictly less than {length}.\n */\n function keyValueByIndex(uint256 index) external view returns(string memory, string memory){\n return _config.at(index);\n }\n\n /**\n * @notice gets the value associated with the key\n */\n function get(string calldata _key) external view returns(string memory){\n string memory key = _key;\n return _config.get(key);\n }\n\n /**\n * @notice sets the key\n *\n * @dev caller must have bridge manager role\n */\n function set(string calldata _key, string calldata _value) external returns(bool) {\n require(\n hasRole(BRIDGEMANAGER_ROLE, msg.sender),\n 'Caller is not Bridge Manager'\n );\n string memory key = _key;\n string memory value = _value;\n\n return _config.set(key, value);\n }\n}" + }, + "contracts/bridge/utils/EnumerableStringMap.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.6.12;\n\nimport \"@openzeppelin/contracts/utils/EnumerableSet.sol\";\n\n/**\n * @title EnumerableStringMap\n * @dev Library for managing an enumerable variant of Solidity's\n * https://solidity.readthedocs.io/en/latest/types.html#mapping-types[`mapping`]\n * type.\n *\n * Maps have the following properties:\n *\n * - Entries are added, removed, and checked for existence in constant time\n * (O(1)).\n * - Entries are enumerated in O(n). No guarantees are made on the ordering.\n *\n * this isn't a terribly gas efficient implementation because it emphasizes usability over gas efficiency\n * by allowing arbitrary length string memorys. If Gettetrs/Setters are going to be used frequently in contracts\n * consider using the OpenZeppeling Bytes32 implementation\n *\n * this also differs from the OpenZeppelin implementation by keccac256 hashing the string memorys\n * so we can use enumerable bytes32 set\n */\nlibrary EnumerableStringMap {\n using EnumerableSet for EnumerableSet.Bytes32Set;\n\n // To implement this library for multiple types with as little code\n // repetition as possible, we write it in terms of a generic Map type with\n // bytes32 keys and values.\n // The Map implementation uses private functions, and user-facing\n // implementations (such as Uint256ToAddressMap) are just wrappers around\n // the underlying Map.\n // This means that we can only create new EnumerableMaps for types that fit\n // in bytes32.\n\n struct Map {\n // Storage of keys as a set\n EnumerableSet.Bytes32Set _keys;\n // Mapping of keys to resulting values to allow key lookup in the set\n mapping(bytes32 => string) _hashKeyMap;\n // values\n mapping(bytes32 => string) _values;\n }\n\n /**\n * @dev Adds a key-value pair to a map, or updates the value for an existing\n * key. O(1).\n *\n * Returns true if the key was added to the map, that is if it was not\n * already present.\n */\n function _set(\n Map storage map,\n string memory key,\n string memory value\n ) private returns (bool) {\n bytes32 keyHash = keccak256(abi.encodePacked(key));\n map._values[keyHash] = value;\n map._hashKeyMap[keyHash] = key;\n return map._keys.add(keyHash);\n }\n\n /**\n * @dev Removes a key-value pair from a map. O(1).\n *\n * Returns true if the key was removed from the map, that is if it was present.\n */\n function _remove(Map storage map, bytes32 keyHash) private returns (bool) {\n delete map._values[keyHash];\n delete map._hashKeyMap[keyHash];\n return map._keys.remove(keyHash);\n }\n\n /**\n * @dev Returns true if the key is in the map. O(1).\n */\n function _contains(Map storage map, bytes32 keyHash) private view returns (bool) {\n return map._keys.contains(keyHash);\n }\n\n /**\n * @dev Returns the number of key-value pairs in the map. O(1).\n */\n function _length(Map storage map) private view returns (uint256) {\n return map._keys.length();\n }\n\n /**\n * @dev Returns the key-value pair stored at position `index` in the map. O(1).\n *\n * Note that there are no guarantees on the ordering of entries inside the\n * array, and it may change when more entries are added or removed.\n *\n * Requirements:\n *\n * - `index` must be strictly less than {length}.\n */\n function _at(Map storage map, uint256 index) private view returns (string memory, string memory) {\n bytes32 keyHash = map._keys.at(index);\n return (map._hashKeyMap[keyHash], map._values[keyHash]);\n }\n\n /**\n * @dev Tries to returns the value associated with `key`. O(1).\n * Does not revert if `key` is not in the map.\n */\n function _tryGet(Map storage map, bytes32 keyHash) private view returns (bool, string memory) {\n string memory value = map._values[keyHash];\n if (keccak256(bytes(value)) == keccak256(bytes(\"\"))) {\n return (_contains(map, keyHash), \"\");\n } else {\n return (true, value);\n }\n }\n\n /**\n * @dev Returns the value associated with `key`. O(1).\n *\n * Requirements:\n *\n * - `key` must be in the map.\n */\n function _get(Map storage map, bytes32 keyHash) private view returns (string memory) {\n string memory value = map._values[keyHash];\n require(_contains(map, keyHash), \"EnumerableMap: nonexistent key\");\n return value;\n }\n\n // StringToStringMap\n struct StringToStringMap {\n Map _inner;\n }\n\n /**\n * @dev Adds a key-value pair to a map, or updates the value for an existing\n * key. O(1).\n *\n * Returns true if the key was added to the map, that is if it was not\n * already present.\n */\n function set(\n StringToStringMap storage map,\n string memory key,\n string memory value\n ) internal returns (bool) {\n return _set(map._inner, key, value);\n }\n\n /**\n * @dev Removes a value from a set. O(1).\n *\n * Returns true if the key was removed from the map, that is if it was present.\n */\n function remove(StringToStringMap storage map, string memory key) internal returns (bool) {\n return _remove(map._inner, keccak256(abi.encodePacked(key)));\n }\n\n /**\n * @dev Returns true if the key is in the map. O(1).\n */\n function contains(StringToStringMap storage map, string memory key) internal view returns (bool) {\n return _contains(map._inner, keccak256(abi.encodePacked(key)));\n }\n\n /**\n * @dev Returns the number of elements in the map. O(1).\n */\n function length(StringToStringMap storage map) internal view returns (uint256) {\n return _length(map._inner);\n }\n\n /**\n * @dev Returns the element stored at position `index` in the set. O(1).\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(StringToStringMap storage map, uint256 index) internal view returns (string memory, string memory) {\n return _at(map._inner, index);\n }\n\n /**\n * @dev Tries to returns the value associated with `key`. O(1).\n * Does not revert if `key` is not in the map.\n *\n * _Available since v3.4._\n */\n function tryGet(StringToStringMap storage map, uint256 key) internal view returns (bool, string memory) {\n (bool success, string memory value) = _tryGet(map._inner, bytes32(key));\n return (success, value);\n }\n\n /**\n * @dev Returns the value associated with `key`. O(1).\n *\n * Requirements:\n *\n * - `key` must be in the map.\n */\n function get(StringToStringMap storage map, string memory key) internal view returns (string memory) {\n return _get(map._inner, keccak256(abi.encodePacked(key)));\n }\n}" + }, + "contracts/bridge/PoolConfig.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.6.12;\npragma experimental ABIEncoderV2;\n\nimport \"@openzeppelin/contracts/access/AccessControl.sol\";\n\ncontract PoolConfig is AccessControl {\n bytes32 public constant BRIDGEMANAGER_ROLE =\n keccak256(\"BRIDGEMANAGER_ROLE\");\n mapping(address => mapping(uint256 => Pool)) private _pool; // key is tokenAddress,chainID\n\n struct Pool {\n address tokenAddress;\n uint256 chainId;\n address poolAddress;\n bool metaswap;\n }\n\n constructor() public {\n _setupRole(DEFAULT_ADMIN_ROLE, msg.sender);\n _setupRole(BRIDGEMANAGER_ROLE, msg.sender);\n }\n\n function getPoolConfig(address tokenAddress, uint256 chainID)\n external\n view\n returns (Pool memory)\n {\n return _pool[tokenAddress][chainID];\n }\n\n function setPoolConfig(\n address tokenAddress,\n uint256 chainID,\n address poolAddress,\n bool metaswap\n ) external returns (Pool memory) {\n require(\n hasRole(BRIDGEMANAGER_ROLE, msg.sender),\n \"Caller is not Bridge Manager\"\n );\n Pool memory newPool = Pool(\n tokenAddress,\n chainID,\n poolAddress,\n metaswap\n );\n _pool[tokenAddress][chainID] = newPool;\n return newPool;\n }\n}\n" + }, + "contracts/bridge/BridgeConfigV3.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.6.12;\npragma experimental ABIEncoderV2;\n\nimport \"@openzeppelin/contracts/access/AccessControl.sol\";\nimport \"@openzeppelin/contracts/math/SafeMath.sol\";\n\n/**\n * @title BridgeConfig contract\n * @notice This token is used for configuring different tokens on the bridge and mapping them across chains.\n **/\n\ncontract BridgeConfigV3 is AccessControl {\n using SafeMath for uint256;\n bytes32 public constant BRIDGEMANAGER_ROLE =\n keccak256(\"BRIDGEMANAGER_ROLE\");\n bytes32[] private _allTokenIDs;\n mapping(bytes32 => Token[]) private _allTokens; // key is tokenID\n mapping(uint256 => mapping(string => bytes32)) private _tokenIDMap; // key is chainID,tokenAddress\n mapping(bytes32 => mapping(uint256 => Token)) private _tokens; // key is tokenID,chainID\n mapping(address => mapping(uint256 => Pool)) private _pool; // key is tokenAddress,chainID\n mapping(uint256 => uint256) private _maxGasPrice; // key is tokenID,chainID\n uint256 public constant bridgeConfigVersion = 3;\n\n // the denominator used to calculate fees. For example, an\n // LP fee might be something like tradeAmount.mul(fee).div(FEE_DENOMINATOR)\n uint256 private constant FEE_DENOMINATOR = 10**10;\n\n // this struct must be initialized using setTokenConfig for each token that directly interacts with the bridge\n struct Token {\n uint256 chainId;\n string tokenAddress;\n uint8 tokenDecimals;\n uint256 maxSwap;\n uint256 minSwap;\n uint256 swapFee;\n uint256 maxSwapFee;\n uint256 minSwapFee;\n bool hasUnderlying;\n bool isUnderlying;\n }\n\n struct Pool {\n address tokenAddress;\n uint256 chainId;\n address poolAddress;\n bool metaswap;\n }\n\n constructor() public {\n _setupRole(DEFAULT_ADMIN_ROLE, msg.sender);\n }\n\n /**\n * @notice Returns a list of all existing token IDs converted to strings\n */\n function getAllTokenIDs() public view returns (string[] memory result) {\n uint256 length = _allTokenIDs.length;\n result = new string[](length);\n for (uint256 i = 0; i < length; ++i) {\n result[i] = toString(_allTokenIDs[i]);\n }\n }\n\n function _getTokenID(string memory tokenAddress, uint256 chainID)\n internal\n view\n returns (string memory)\n {\n return toString(_tokenIDMap[chainID][tokenAddress]);\n }\n\n function getTokenID(string memory tokenAddress, uint256 chainID)\n public\n view\n returns (string memory)\n {\n return _getTokenID(_toLower(tokenAddress), chainID);\n }\n\n /**\n * @notice Returns the token ID (string) of the cross-chain token inputted\n * @param tokenAddress address of token to get ID for\n * @param chainID chainID of which to get token ID for\n */\n function getTokenID(address tokenAddress, uint256 chainID)\n public\n view\n returns (string memory)\n {\n return _getTokenID(_toLower(toString(tokenAddress)), chainID);\n }\n\n /**\n * @notice Returns the full token config struct\n * @param tokenID String input of the token ID for the token\n * @param chainID Chain ID of which token address + config to get\n */\n function getToken(string memory tokenID, uint256 chainID)\n public\n view\n returns (Token memory token)\n {\n return _tokens[toBytes32(tokenID)][chainID];\n }\n\n /**\n * @notice Returns the full token config struct\n * @param tokenID String input of the token ID for the token\n * @param chainID Chain ID of which token address + config to get\n */\n function getTokenByID(string memory tokenID, uint256 chainID)\n public\n view\n returns (Token memory token)\n {\n return _tokens[toBytes32(tokenID)][chainID];\n }\n\n /**\n * @notice Returns token config struct, given an address and chainID\n * @param tokenAddress Matches the token ID by using a combo of address + chain ID\n * @param chainID Chain ID of which token to get config for\n */\n function getTokenByAddress(string memory tokenAddress, uint256 chainID)\n public\n view\n returns (Token memory token)\n {\n return _tokens[_tokenIDMap[chainID][_toLower(tokenAddress)]][chainID];\n }\n\n function getTokenByEVMAddress(address tokenAddress, uint256 chainID)\n public\n view\n returns (Token memory token)\n {\n return\n _tokens[_tokenIDMap[chainID][_toLower(toString(tokenAddress))]][\n chainID\n ];\n }\n\n /**\n * @notice Returns true if the token has an underlying token -- meaning the token is deposited into the bridge\n * @param tokenID String to check if it is a withdraw/underlying token\n */\n function hasUnderlyingToken(string memory tokenID)\n public\n view\n returns (bool)\n {\n bytes32 bytesTokenID = toBytes32(tokenID);\n Token[] memory _mcTokens = _allTokens[bytesTokenID];\n for (uint256 i = 0; i < _mcTokens.length; ++i) {\n if (_mcTokens[i].hasUnderlying) {\n return true;\n }\n }\n return false;\n }\n\n /**\n * @notice Returns which token is the underlying token to withdraw\n * @param tokenID string token ID\n */\n function getUnderlyingToken(string memory tokenID)\n public\n view\n returns (Token memory token)\n {\n bytes32 bytesTokenID = toBytes32(tokenID);\n Token[] memory _mcTokens = _allTokens[bytesTokenID];\n for (uint256 i = 0; i < _mcTokens.length; ++i) {\n if (_mcTokens[i].isUnderlying) {\n return _mcTokens[i];\n }\n }\n }\n\n /**\n @notice Public function returning if token ID exists given a string\n */\n function isTokenIDExist(string memory tokenID) public view returns (bool) {\n return _isTokenIDExist(toBytes32(tokenID));\n }\n\n /**\n @notice Internal function returning if token ID exists given bytes32 version of the ID\n */\n function _isTokenIDExist(bytes32 tokenID) internal view returns (bool) {\n for (uint256 i = 0; i < _allTokenIDs.length; ++i) {\n if (_allTokenIDs[i] == tokenID) {\n return true;\n }\n }\n return false;\n }\n\n /**\n * @notice Internal function which handles logic of setting token ID and dealing with mappings\n * @param tokenID bytes32 version of ID\n * @param chainID which chain to set the token config for\n * @param tokenToAdd Token object to set the mapping to\n */\n function _setTokenConfig(\n bytes32 tokenID,\n uint256 chainID,\n Token memory tokenToAdd\n ) internal returns (bool) {\n _tokens[tokenID][chainID] = tokenToAdd;\n if (!_isTokenIDExist(tokenID)) {\n _allTokenIDs.push(tokenID);\n }\n\n Token[] storage _mcTokens = _allTokens[tokenID];\n for (uint256 i = 0; i < _mcTokens.length; ++i) {\n if (_mcTokens[i].chainId == chainID) {\n string memory oldToken = _mcTokens[i].tokenAddress;\n if (!compareStrings(tokenToAdd.tokenAddress, oldToken)) {\n _mcTokens[i].tokenAddress = tokenToAdd.tokenAddress;\n _tokenIDMap[chainID][oldToken] = keccak256(\"\");\n _tokenIDMap[chainID][tokenToAdd.tokenAddress] = tokenID;\n }\n }\n }\n _mcTokens.push(tokenToAdd);\n _tokenIDMap[chainID][tokenToAdd.tokenAddress] = tokenID;\n return true;\n }\n\n /**\n * @notice Main write function of this contract - Handles creating the struct and passing it to the internal logic function\n * @param tokenID string ID to set the token config object form\n * @param chainID chain ID to use for the token config object\n * @param tokenAddress token address of the token on the given chain\n * @param tokenDecimals decimals of token\n * @param maxSwap maximum amount of token allowed to be transferred at once - in native token decimals\n * @param minSwap minimum amount of token needed to be transferred at once - in native token decimals\n * @param swapFee percent based swap fee -- 10e6 == 10bps\n * @param maxSwapFee max swap fee to be charged - in native token decimals\n * @param minSwapFee min swap fee to be charged - in native token decimals - especially useful for mainnet ETH\n * @param hasUnderlying bool which represents whether this is a global mint token or one to withdraw()\n * @param isUnderlying bool which represents if this token is the one to withdraw on the given chain\n */\n function setTokenConfig(\n string calldata tokenID,\n uint256 chainID,\n address tokenAddress,\n uint8 tokenDecimals,\n uint256 maxSwap,\n uint256 minSwap,\n uint256 swapFee,\n uint256 maxSwapFee,\n uint256 minSwapFee,\n bool hasUnderlying,\n bool isUnderlying\n ) public returns (bool) {\n require(hasRole(BRIDGEMANAGER_ROLE, msg.sender));\n return\n setTokenConfig(\n tokenID,\n chainID,\n toString(tokenAddress),\n tokenDecimals,\n maxSwap,\n minSwap,\n swapFee,\n maxSwapFee,\n minSwapFee,\n hasUnderlying,\n isUnderlying\n );\n }\n\n /**\n * @notice Main write function of this contract - Handles creating the struct and passing it to the internal logic function\n * @param tokenID string ID to set the token config object form\n * @param chainID chain ID to use for the token config object\n * @param tokenAddress token address of the token on the given chain\n * @param tokenDecimals decimals of token\n * @param maxSwap maximum amount of token allowed to be transferred at once - in native token decimals\n * @param minSwap minimum amount of token needed to be transferred at once - in native token decimals\n * @param swapFee percent based swap fee -- 10e6 == 10bps\n * @param maxSwapFee max swap fee to be charged - in native token decimals\n * @param minSwapFee min swap fee to be charged - in native token decimals - especially useful for mainnet ETH\n * @param hasUnderlying bool which represents whether this is a global mint token or one to withdraw()\n * @param isUnderlying bool which represents if this token is the one to withdraw on the given chain\n */\n function setTokenConfig(\n string calldata tokenID,\n uint256 chainID,\n string memory tokenAddress,\n uint8 tokenDecimals,\n uint256 maxSwap,\n uint256 minSwap,\n uint256 swapFee,\n uint256 maxSwapFee,\n uint256 minSwapFee,\n bool hasUnderlying,\n bool isUnderlying\n ) public returns (bool) {\n require(hasRole(BRIDGEMANAGER_ROLE, msg.sender));\n Token memory tokenToAdd;\n tokenToAdd.tokenAddress = _toLower(tokenAddress);\n tokenToAdd.tokenDecimals = tokenDecimals;\n tokenToAdd.maxSwap = maxSwap;\n tokenToAdd.minSwap = minSwap;\n tokenToAdd.swapFee = swapFee;\n tokenToAdd.maxSwapFee = maxSwapFee;\n tokenToAdd.minSwapFee = minSwapFee;\n tokenToAdd.hasUnderlying = hasUnderlying;\n tokenToAdd.isUnderlying = isUnderlying;\n tokenToAdd.chainId = chainID;\n\n return _setTokenConfig(toBytes32(tokenID), chainID, tokenToAdd);\n }\n\n function _calculateSwapFee(\n string memory tokenAddress,\n uint256 chainID,\n uint256 amount\n ) internal view returns (uint256) {\n Token memory token = _tokens[_tokenIDMap[chainID][tokenAddress]][\n chainID\n ];\n uint256 calculatedSwapFee = amount.mul(token.swapFee).div(\n FEE_DENOMINATOR\n );\n if (\n calculatedSwapFee > token.minSwapFee &&\n calculatedSwapFee < token.maxSwapFee\n ) {\n return calculatedSwapFee;\n } else if (calculatedSwapFee > token.maxSwapFee) {\n return token.maxSwapFee;\n } else {\n return token.minSwapFee;\n }\n }\n\n /**\n * @notice Calculates bridge swap fee based on the destination chain's token transfer.\n * @dev This means the fee should be calculated based on the chain that the nodes emit a tx on\n * @param tokenAddress address of the destination token to query token config for\n * @param chainID destination chain ID to query the token config for\n * @param amount in native token decimals\n * @return Fee calculated in token decimals\n */\n function calculateSwapFee(\n string memory tokenAddress,\n uint256 chainID,\n uint256 amount\n ) external view returns (uint256) {\n return _calculateSwapFee(_toLower(tokenAddress), chainID, amount);\n }\n\n /**\n * @notice Calculates bridge swap fee based on the destination chain's token transfer.\n * @dev This means the fee should be calculated based on the chain that the nodes emit a tx on\n * @param tokenAddress address of the destination token to query token config for\n * @param chainID destination chain ID to query the token config for\n * @param amount in native token decimals\n * @return Fee calculated in token decimals\n */\n function calculateSwapFee(\n address tokenAddress,\n uint256 chainID,\n uint256 amount\n ) external view returns (uint256) {\n return\n _calculateSwapFee(\n _toLower(toString(tokenAddress)),\n chainID,\n amount\n );\n }\n\n // GAS PRICING\n\n /**\n * @notice sets the max gas price for a chain\n */\n function setMaxGasPrice(uint256 chainID, uint256 maxPrice) public {\n require(hasRole(BRIDGEMANAGER_ROLE, msg.sender));\n _maxGasPrice[chainID] = maxPrice;\n }\n\n /**\n * @notice gets the max gas price for a chain\n */\n function getMaxGasPrice(uint256 chainID) public view returns (uint256) {\n return _maxGasPrice[chainID];\n }\n\n // POOL CONFIG\n\n function getPoolConfig(address tokenAddress, uint256 chainID)\n external\n view\n returns (Pool memory)\n {\n return _pool[tokenAddress][chainID];\n }\n\n function setPoolConfig(\n address tokenAddress,\n uint256 chainID,\n address poolAddress,\n bool metaswap\n ) external returns (Pool memory) {\n require(\n hasRole(BRIDGEMANAGER_ROLE, msg.sender),\n \"Caller is not Bridge Manager\"\n );\n Pool memory newPool = Pool(\n tokenAddress,\n chainID,\n poolAddress,\n metaswap\n );\n _pool[tokenAddress][chainID] = newPool;\n return newPool;\n }\n\n // UTILITY FUNCTIONS\n\n function toString(bytes32 data) internal pure returns (string memory) {\n uint8 i = 0;\n while (i < 32 && data[i] != 0) {\n ++i;\n }\n bytes memory bs = new bytes(i);\n for (uint8 j = 0; j < i; ++j) {\n bs[j] = data[j];\n }\n return string(bs);\n }\n\n // toBytes32 converts a string to a bytes 32\n function toBytes32(string memory str)\n internal\n pure\n returns (bytes32 result)\n {\n require(bytes(str).length <= 32);\n assembly {\n result := mload(add(str, 32))\n }\n }\n\n function toString(address x) internal pure returns (string memory) {\n bytes memory s = new bytes(40);\n for (uint256 i = 0; i < 20; i++) {\n bytes1 b = bytes1(uint8(uint256(uint160(x)) / (2**(8 * (19 - i)))));\n bytes1 hi = bytes1(uint8(b) / 16);\n bytes1 lo = bytes1(uint8(b) - 16 * uint8(hi));\n s[2 * i] = char(hi);\n s[2 * i + 1] = char(lo);\n }\n\n string memory addrPrefix = \"0x\";\n\n return concat(addrPrefix, string(s));\n }\n\n function concat(string memory _x, string memory _y)\n internal\n pure\n returns (string memory)\n {\n bytes memory _xBytes = bytes(_x);\n bytes memory _yBytes = bytes(_y);\n\n string memory _tmpValue = new string(_xBytes.length + _yBytes.length);\n bytes memory _newValue = bytes(_tmpValue);\n\n uint256 i;\n uint256 j;\n\n for (i = 0; i < _xBytes.length; i++) {\n _newValue[j++] = _xBytes[i];\n }\n\n for (i = 0; i < _yBytes.length; i++) {\n _newValue[j++] = _yBytes[i];\n }\n\n return string(_newValue);\n }\n\n function char(bytes1 b) internal pure returns (bytes1 c) {\n if (uint8(b) < 10) {\n c = bytes1(uint8(b) + 0x30);\n } else {\n c = bytes1(uint8(b) + 0x57);\n }\n }\n\n function compareStrings(string memory a, string memory b)\n internal\n pure\n returns (bool)\n {\n return (keccak256(abi.encodePacked((a))) ==\n keccak256(abi.encodePacked((b))));\n }\n\n function _toLower(string memory str) internal pure returns (string memory) {\n bytes memory bStr = bytes(str);\n bytes memory bLower = new bytes(bStr.length);\n for (uint256 i = 0; i < bStr.length; i++) {\n // Uppercase character...\n if ((uint8(bStr[i]) >= 65) && (uint8(bStr[i]) <= 90)) {\n // So we add 32 to make it lowercase\n bLower[i] = bytes1(uint8(bStr[i]) + 32);\n } else {\n bLower[i] = bStr[i];\n }\n }\n return string(bLower);\n }\n}\n" + }, + "contracts/bridge/wrappers/GMXWrapper.sol": { + "content": "// SPDX-License-Identifier: MIT\n\nimport '@openzeppelin/contracts/math/SafeMath.sol';\n\npragma solidity 0.6.12;\n\ninterface IGMX {\n function burn(address _account, uint256 _amount) external;\n function balanceOf(address account) external view returns (uint256);\n function mint(address _account, uint256 _amount) external;\n}\n\ncontract GMXWrapper {\n using SafeMath for uint256;\n\n address constant public gmx = 0x62edc0692BD897D2295872a9FFCac5425011c661;\n address constant public bridge = 0xC05e61d0E7a63D27546389B7aD62FdFf5A91aACE;\n\n function transfer(address _recipient, uint256 _amount) external returns (bool) {\n require(msg.sender == bridge);\n _transfer(msg.sender, _recipient, _amount);\n return true;\n }\n\n function _transfer(address _sender, address _recipient, uint256 _amount) private {\n require(_sender != address(0), \"BaseToken: transfer from the zero address\");\n require(_recipient != address(0), \"BaseToken: transfer to the zero address\");\n IGMX(gmx).burn(_sender, _amount);\n IGMX(gmx).mint(_recipient, _amount);\n }\n\n function mint(address _addr, uint256 _amount) external {\n require(msg.sender == bridge);\n uint256 preMint = IGMX(gmx).balanceOf(_addr);\n IGMX(gmx).mint(_addr, _amount);\n uint256 postMint = IGMX(gmx).balanceOf(_addr);\n require(preMint.add(_amount) == postMint, \"Mint incomplete\");\n }\n\n function burnFrom(address _addr, uint256 _amount) external {\n require(msg.sender == bridge);\n uint256 preBurn = IGMX(gmx).balanceOf(_addr);\n IGMX(gmx).burn(_addr, _amount);\n uint256 postBurn = IGMX(gmx).balanceOf(_addr);\n require(postBurn.add(_amount) == preBurn, \"Burn incomplete\");\n }\n}" + }, + "contracts/amm/SwapEthWrapper.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.6.12;\n\nimport \"@openzeppelin/contracts/math/SafeMath.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/SafeERC20.sol\";\nimport \"./Swap.sol\";\nimport \"./interfaces/IWETH9.sol\";\n\n/**\n * @title SwapEthWrapper\n * @notice A wrapper contract for Swap contracts that have WETH as one of the pooled tokens.\n * @author Jongseung Lim (@weeb_mcgee)\n */\ncontract SwapEthWrapper {\n using SafeERC20 for IERC20;\n using SafeMath for uint256;\n\n // constants\n uint8 private constant MAX_UINT8 = 2**8 - 1;\n uint256 private constant MAX_UINT256 = 2**256 - 1;\n\n // immutables\n Swap public immutable SWAP;\n LPToken public immutable LP_TOKEN;\n address payable public immutable WETH_ADDRESS;\n address public immutable OWNER;\n uint8 public immutable WETH_INDEX;\n\n IERC20[] public pooledTokens;\n\n /**\n * @notice Deploys this contract with given WETH9 address and Swap address. It will attempt to\n * fetch information about the given Swap pool. If the Swap pool does not contain WETH9,\n * this call will be reverted. Owner address must be given so that `rescue()` function\n * can be limited.\n * @param wethAddress address to the WETH9 contract\n * @param swap address to the Swap contract that has WETH9 as one of the tokens\n * @param owner address that will be allowed to call `rescue()`\n */\n constructor(\n address payable wethAddress,\n Swap swap,\n address owner\n ) public {\n (, , , , , , LPToken lpToken) = swap.swapStorage();\n uint8 wethIndex = MAX_UINT8;\n\n for (uint8 i = 0; i < MAX_UINT8; i++) {\n try swap.getToken(i) returns (IERC20 token) {\n pooledTokens.push(token);\n if (address(token) == wethAddress) {\n wethIndex = i;\n }\n // Approve pooled tokens to be used by Swap\n token.approve(address(swap), MAX_UINT256);\n } catch {\n break;\n }\n }\n require(wethIndex != MAX_UINT8, \"WETH was not found in the swap pool\");\n\n // Set immutable variables\n WETH_INDEX = wethIndex;\n WETH_ADDRESS = wethAddress;\n SWAP = swap;\n LP_TOKEN = lpToken;\n OWNER = owner;\n\n // Approve LPToken to be used by Swap\n lpToken.approve(address(swap), MAX_UINT256);\n }\n\n /**\n * @notice Add liquidity to the pool with the given amounts of tokens.\n * @dev The msg.value of this call should match the value in amounts array\n * in position of WETH9.\n * @param amounts the amounts of each token to add, in their native precision\n * @param minToMint the minimum LP tokens adding this amount of liquidity\n * should mint, otherwise revert. Handy for front-running mitigation\n * @param deadline latest timestamp to accept this transaction\n * @return amount of LP token user minted and received\n */\n function addLiquidity(\n uint256[] memory amounts,\n uint256 minToMint,\n uint256 deadline\n ) external payable returns (uint256) {\n // If using ETH, deposit them to WETH.\n require(msg.value == amounts[WETH_INDEX], \"INCORRECT_MSG_VALUE\");\n if (msg.value > 0) {\n IWETH9(WETH_ADDRESS).deposit{value: msg.value}();\n }\n // Go through amounts array and transfer respective tokens to this contract.\n for (uint256 i = 0; i < amounts.length; i++) {\n uint256 amount = amounts[i];\n if (i != WETH_INDEX && amount > 0) {\n pooledTokens[i].safeTransferFrom(\n msg.sender,\n address(this),\n amount\n );\n }\n }\n // Add the assets to the pool\n uint256 lpTokenAmount = SWAP.addLiquidity(amounts, minToMint, deadline);\n // Send the LPToken to msg.sender\n IERC20(address(LP_TOKEN)).safeTransfer(msg.sender, lpTokenAmount);\n return lpTokenAmount;\n }\n\n /**\n * @notice Burn LP tokens to remove liquidity from the pool.\n * @dev Liquidity can always be removed, even when the pool is paused. Caller\n * will receive ETH instead of WETH9.\n * @param amount the amount of LP tokens to burn\n * @param minAmounts the minimum amounts of each token in the pool\n * acceptable for this burn. Useful as a front-running mitigation\n * @param deadline latest timestamp to accept this transaction\n * @return amounts of tokens user received\n */\n function removeLiquidity(\n uint256 amount,\n uint256[] calldata minAmounts,\n uint256 deadline\n ) external returns (uint256[] memory) {\n // Transfer LPToken from msg.sender to this contract.\n IERC20(address(LP_TOKEN)).safeTransferFrom(\n msg.sender,\n address(this),\n amount\n );\n // Remove liquidity\n uint256[] memory amounts = SWAP.removeLiquidity(\n amount,\n minAmounts,\n deadline\n );\n // Send the tokens back to the user\n for (uint256 i = 0; i < amounts.length; i++) {\n if (i != WETH_INDEX) {\n pooledTokens[i].safeTransfer(msg.sender, amounts[i]);\n } else {\n IWETH9(WETH_ADDRESS).withdraw(amounts[i]);\n // slither-disable-next-line arbitrary-send\n (bool success, ) = msg.sender.call{value: amounts[i]}(\"\");\n require(success, \"ETH_TRANSFER_FAILED\");\n }\n }\n return amounts;\n }\n\n /**\n * @notice Remove liquidity from the pool all in one token.\n * @dev Caller will receive ETH instead of WETH9.\n * @param tokenAmount the amount of the token you want to receive\n * @param tokenIndex the index of the token you want to receive\n * @param minAmount the minimum amount to withdraw, otherwise revert\n * @param deadline latest timestamp to accept this transaction\n * @return amount of chosen token user received\n */\n function removeLiquidityOneToken(\n uint256 tokenAmount,\n uint8 tokenIndex,\n uint256 minAmount,\n uint256 deadline\n ) external returns (uint256) {\n // Transfer LPToken from msg.sender to this contract.\n IERC20(address(LP_TOKEN)).safeTransferFrom(\n msg.sender,\n address(this),\n tokenAmount\n );\n // Withdraw via single token\n uint256 amount = SWAP.removeLiquidityOneToken(\n tokenAmount,\n tokenIndex,\n minAmount,\n deadline\n );\n // Transfer the token to msg.sender accordingly\n if (tokenIndex != WETH_INDEX) {\n pooledTokens[tokenIndex].safeTransfer(msg.sender, amount);\n } else {\n IWETH9(WETH_ADDRESS).withdraw(amount);\n // slither-disable-next-line arbitrary-send\n (bool success, ) = msg.sender.call{value: amount}(\"\");\n require(success, \"ETH_TRANSFER_FAILED\");\n }\n return amount;\n }\n\n /**\n * @notice Remove liquidity from the pool, weighted differently than the\n * pool's current balances.\n * @dev Caller will receive ETH instead of WETH9.\n * @param amounts how much of each token to withdraw\n * @param maxBurnAmount the max LP token provider is willing to pay to\n * remove liquidity. Useful as a front-running mitigation.\n * @param deadline latest timestamp to accept this transaction\n * @return amount of LP tokens burned\n */\n function removeLiquidityImbalance(\n uint256[] calldata amounts,\n uint256 maxBurnAmount,\n uint256 deadline\n ) external returns (uint256) {\n // Transfer LPToken from msg.sender to this contract.\n IERC20(address(LP_TOKEN)).safeTransferFrom(\n msg.sender,\n address(this),\n maxBurnAmount\n );\n // Withdraw in imbalanced ratio\n uint256 burnedLpTokenAmount = SWAP.removeLiquidityImbalance(\n amounts,\n maxBurnAmount,\n deadline\n );\n // Send the tokens back to the user\n for (uint256 i = 0; i < amounts.length; i++) {\n if (i != WETH_INDEX) {\n pooledTokens[i].safeTransfer(msg.sender, amounts[i]);\n } else {\n IWETH9(WETH_ADDRESS).withdraw(amounts[i]);\n // slither-disable-next-line arbitrary-send\n (bool success, ) = msg.sender.call{value: amounts[i]}(\"\");\n require(success, \"ETH_TRANSFER_FAILED\");\n }\n }\n // Send any extra LP tokens back as well\n uint256 extraLpTokenAmount = maxBurnAmount.sub(burnedLpTokenAmount);\n if (extraLpTokenAmount > 0) {\n IERC20(address(LP_TOKEN)).safeTransfer(\n msg.sender,\n extraLpTokenAmount\n );\n }\n return burnedLpTokenAmount;\n }\n\n /**\n * @notice Swap two tokens using the underlying pool. If tokenIndexFrom\n * represents WETH9 in the pool, the caller must set msg.value equal to dx.\n * If the user is swapping to WETH9 in the pool, the user will receive ETH instead.\n * @param tokenIndexFrom the token the user wants to swap from\n * @param tokenIndexTo the token the user wants to swap to\n * @param dx the amount of tokens the user wants to swap from\n * @param minDy the min amount the user would like to receive, or revert.\n * @param deadline latest timestamp to accept this transaction\n */\n function swap(\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx,\n uint256 minDy,\n uint256 deadline\n ) external payable returns (uint256) {\n // Transfer tokens from msg.sender to this contract\n if (tokenIndexFrom != WETH_INDEX) {\n IERC20(pooledTokens[tokenIndexFrom]).safeTransferFrom(\n msg.sender,\n address(this),\n dx\n );\n } else {\n require(msg.value == dx, \"INCORRECT_MSG_VALUE\");\n IWETH9(WETH_ADDRESS).deposit{value: msg.value}();\n }\n // Execute swap\n uint256 dy = SWAP.swap(\n tokenIndexFrom,\n tokenIndexTo,\n dx,\n minDy,\n deadline\n );\n // Transfer the swapped tokens to msg.sender\n if (tokenIndexTo != WETH_INDEX) {\n IERC20(pooledTokens[tokenIndexTo]).safeTransfer(msg.sender, dy);\n } else {\n IWETH9(WETH_ADDRESS).withdraw(dy);\n // slither-disable-next-line arbitrary-send\n (bool success, ) = msg.sender.call{value: dy}(\"\");\n require(success, \"ETH_TRANSFER_FAILED\");\n }\n return dy;\n }\n\n /**\n * @notice Rescues any of the ETH, the pooled tokens, or the LPToken that may be stuck\n * in this contract. Only the OWNER can call this function.\n */\n function rescue() external {\n require(msg.sender == OWNER, \"CALLED_BY_NON_OWNER\");\n IERC20[] memory tokens = pooledTokens;\n for (uint256 i = 0; i < tokens.length; i++) {\n tokens[i].safeTransfer(\n msg.sender,\n tokens[i].balanceOf(address(this))\n );\n }\n IERC20 lpToken_ = IERC20(address(LP_TOKEN));\n lpToken_.safeTransfer(msg.sender, lpToken_.balanceOf(address(this)));\n // slither-disable-next-line arbitrary-send\n (bool success, ) = msg.sender.call{value: address(this).balance}(\"\");\n require(success, \"ETH_TRANSFER_FAILED\");\n }\n\n receive() external payable {}\n\n // VIEW FUNCTIONS\n\n /**\n * @notice A simple method to calculate prices from deposits or\n * withdrawals, excluding fees but including slippage. This is\n * helpful as an input into the various \"min\" parameters on calls\n * to fight front-running\n *\n * @dev This shouldn't be used outside frontends for user estimates.\n *\n * @param amounts an array of token amounts to deposit or withdrawal,\n * corresponding to pooledTokens. The amount should be in each\n * pooled token's native precision. If a token charges a fee on transfers,\n * use the amount that gets transferred after the fee.\n * @param deposit whether this is a deposit or a withdrawal\n * @return token amount the user will receive\n */\n function calculateTokenAmount(uint256[] calldata amounts, bool deposit)\n external\n view\n returns (uint256)\n {\n return SWAP.calculateTokenAmount(amounts, deposit);\n }\n\n /**\n * @notice A simple method to calculate amount of each underlying\n * tokens that is returned upon burning given amount of LP tokens\n * @param amount the amount of LP tokens that would be burned on withdrawal\n * @return array of token balances that the user will receive\n */\n function calculateRemoveLiquidity(uint256 amount)\n external\n view\n returns (uint256[] memory)\n {\n return SWAP.calculateRemoveLiquidity(amount);\n }\n\n /**\n * @notice Calculate the amount of underlying token available to withdraw\n * when withdrawing via only single token\n * @param tokenAmount the amount of LP token to burn\n * @param tokenIndex index of which token will be withdrawn\n * @return availableTokenAmount calculated amount of underlying token\n * available to withdraw\n */\n function calculateRemoveLiquidityOneToken(\n uint256 tokenAmount,\n uint8 tokenIndex\n ) external view returns (uint256 availableTokenAmount) {\n return SWAP.calculateRemoveLiquidityOneToken(tokenAmount, tokenIndex);\n }\n}\n" + }, + "contracts/amm/interfaces/IWETH9.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.4.0;\n\ninterface IWETH9 {\n function name() external view returns (string memory);\n\n function symbol() external view returns (string memory);\n\n function decimals() external view returns (uint8);\n\n function balanceOf(address) external view returns (uint256);\n\n function allowance(address, address) external view returns (uint256);\n\n receive() external payable;\n\n function deposit() external payable;\n\n function withdraw(uint256 wad) external;\n\n function totalSupply() external view returns (uint256);\n\n function approve(address guy, uint256 wad) external returns (bool);\n\n function transfer(address dst, uint256 wad) external returns (bool);\n\n function transferFrom(\n address src,\n address dst,\n uint256 wad\n ) external returns (bool);\n}\n" + }, + "contracts/amm/helper/BaseSwapDeposit.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.6.12;\n\nimport \"@openzeppelin/contracts/math/SafeMath.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/SafeERC20.sol\";\nimport \"../interfaces/ISwap.sol\";\nimport \"@openzeppelin/contracts/utils/ReentrancyGuard.sol\";\n\ncontract BaseSwapDeposit is ReentrancyGuard {\n using SafeERC20 for IERC20;\n using SafeMath for uint256;\n\n ISwap public baseSwap;\n IERC20[] public baseTokens;\n\n uint256 constant MAX_UINT256 = 2**256 - 1;\n\n constructor(ISwap _baseSwap) public {\n baseSwap = _baseSwap;\n // Check and approve base level tokens to be deposited to the base Swap contract\n {\n uint8 i;\n for (; i < 32; i++) {\n try _baseSwap.getToken(i) returns (IERC20 token) {\n baseTokens.push(token);\n token.safeApprove(address(_baseSwap), MAX_UINT256);\n } catch {\n break;\n }\n }\n require(i > 1, \"baseSwap must have at least 2 tokens\");\n }\n }\n\n // Mutative functions\n\n /**\n * @notice Swap two underlying tokens using the meta pool and the base pool\n * @param tokenIndexFrom the token the user wants to swap from\n * @param tokenIndexTo the token the user wants to swap to\n * @param dx the amount of tokens the user wants to swap from\n * @param minDy the min amount the user would like to receive, or revert.\n * @param deadline latest timestamp to accept this transaction\n */\n function swap(\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx,\n uint256 minDy,\n uint256 deadline\n ) external nonReentrant returns (uint256) {\n baseTokens[tokenIndexFrom].safeTransferFrom(msg.sender, address(this), dx);\n uint256 tokenToAmount =\n baseSwap.swap(\n tokenIndexFrom,\n tokenIndexTo,\n dx,\n minDy,\n deadline\n );\n baseTokens[tokenIndexTo].safeTransfer(msg.sender, tokenToAmount);\n return tokenToAmount;\n }\n\n /**\n * @notice Calculate amount of tokens you receive on swap\n * @param tokenIndexFrom the token the user wants to sell\n * @param tokenIndexTo the token the user wants to buy\n * @param dx the amount of tokens the user wants to sell. If the token charges\n * a fee on transfers, use the amount that gets transferred after the fee.\n * @return amount of tokens the user will receive\n */\n function calculateSwap(\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx\n ) external view returns (uint256) {\n return\n baseSwap.calculateSwap(tokenIndexFrom, tokenIndexTo, dx);\n }\n\n /**\n * @notice Returns the address of the pooled token at given index. Reverts if tokenIndex is out of range.\n * @param index the index of the token\n * @return address of the token at given index\n */\n function getToken(uint256 index) external view returns (IERC20) {\n require(index < baseTokens.length, \"index out of range\");\n return baseTokens[index];\n }\n\n}" + }, + "@openzeppelin/contracts/utils/ReentrancyGuard.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <0.8.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 () internal {\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" + }, + "contracts/amm/AaveSwapWrapper.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.6.12;\n\nimport \"@openzeppelin/contracts/math/SafeMath.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/SafeERC20.sol\";\nimport \"./Swap.sol\";\n\ninterface ILendingPool {\n /**\n * @dev Deposits an `amount` of underlying asset into the reserve, receiving in return overlying aTokens.\n * - E.g. User deposits 100 USDC and gets in return 100 aUSDC\n * @param asset The address of the underlying asset to deposit\n * @param amount The amount to be deposited\n * @param onBehalfOf The address that will receive the aTokens, same as msg.sender if the user\n * wants to receive them on his own wallet, or a different address if the beneficiary of aTokens\n * is a different wallet\n * @param referralCode Code used to register the integrator originating the operation, for potential rewards.\n * 0 if the action is executed directly by the user, without any middle-man\n **/\n function deposit(\n address asset,\n uint256 amount,\n address onBehalfOf,\n uint16 referralCode\n ) external;\n\n /**\n * @dev Withdraws an `amount` of underlying asset from the reserve, burning the equivalent aTokens owned\n * E.g. User has 100 aUSDC, calls withdraw() and receives 100 USDC, burning the 100 aUSDC\n * @param asset The address of the underlying asset to withdraw\n * @param amount The underlying amount to be withdrawn\n * - Send the value type(uint256).max in order to withdraw the whole aToken balance\n * @param to Address that will receive the underlying, same as msg.sender if the user\n * wants to receive it on his own wallet, or a different address if the beneficiary is a\n * different wallet\n * @return The final amount withdrawn\n **/\n function withdraw(\n address asset,\n uint256 amount,\n address to\n ) external returns (uint256);\n}\n\n/**\n * @title AaveSwapWrapper\n * @notice A wrapper contract for interacting with aTokens\n */\ncontract AaveSwapWrapper {\n using SafeERC20 for IERC20;\n using SafeMath for uint256;\n mapping(uint8 => bool) private isUnderlyingIndex;\n\n // constants\n uint8 private constant MAX_UINT8 = 2**8 - 1;\n uint256 private constant MAX_UINT256 = 2**256 - 1;\n\n // immutables\n Swap public immutable SWAP;\n LPToken public immutable LP_TOKEN;\n address public immutable OWNER;\n IERC20[] public POOLED_TOKENS;\n IERC20[] public UNDERLYING_TOKENS;\n ILendingPool public LENDING_POOL;\n\n constructor(\n Swap swap,\n IERC20[] memory underlyingTokens,\n address lendingPool,\n address owner\n ) public {\n (, , , , , , LPToken lpToken) = swap.swapStorage();\n for (uint8 i = 0; i < MAX_UINT8; i++) {\n try swap.getToken(i) returns (IERC20 token) {\n POOLED_TOKENS.push(token);\n // Approve pooled tokens to be used by Swap\n token.approve(address(swap), MAX_UINT256);\n } catch {\n break;\n }\n }\n\n for (uint8 i = 0; i < POOLED_TOKENS.length; i++) {\n if (POOLED_TOKENS[i] == underlyingTokens[i]) {\n isUnderlyingIndex[i] = true;\n } else {\n isUnderlyingIndex[i] = false;\n underlyingTokens[i].approve(lendingPool, MAX_UINT256);\n }\n }\n\n // Set immutable variables\n SWAP = swap;\n LP_TOKEN = lpToken;\n OWNER = owner;\n UNDERLYING_TOKENS = underlyingTokens;\n LENDING_POOL = ILendingPool(lendingPool);\n\n // Approve LPToken to be used by Swap\n lpToken.approve(address(swap), MAX_UINT256);\n }\n\n /**\n * @notice Add liquidity to the pool with the given amounts of tokens.\n * @param amounts the amounts of each token to add, in their native precision\n * @param minToMint the minimum LP tokens adding this amount of liquidity\n * should mint, otherwise revert. Handy for front-running mitigation\n * @param deadline latest timestamp to accept this transaction\n * @return amount of LP token user minted and received\n */\n function addLiquidity(\n uint256[] memory amounts,\n uint256 minToMint,\n uint256 deadline\n ) external returns (uint256) {\n // Go through amounts array and transfer respective tokens to this contract.\n for (uint8 i = 0; i < amounts.length; i++) {\n uint256 amount = amounts[i];\n if (amount > 0) {\n UNDERLYING_TOKENS[i].safeTransferFrom(\n msg.sender,\n address(this),\n amount\n );\n if (isUnderlyingIndex[i] == false) {\n LENDING_POOL.deposit(\n address(UNDERLYING_TOKENS[i]),\n amount,\n address(this),\n 0\n );\n }\n }\n }\n\n // Add the assets to the pool\n uint256 lpTokenAmount = SWAP.addLiquidity(amounts, minToMint, deadline);\n // Send the LPToken to msg.sender\n IERC20(address(LP_TOKEN)).safeTransfer(msg.sender, lpTokenAmount);\n return lpTokenAmount;\n }\n\n /**\n * @notice Burn LP tokens to remove liquidity from the pool.\n * @dev Liquidity can always be removed, even when the pool is paused. Caller\n * will receive ETH instead of WETH9.\n * @param amount the amount of LP tokens to burn\n * @param minAmounts the minimum amounts of each token in the pool\n * acceptable for this burn. Useful as a front-running mitigation\n * @param deadline latest timestamp to accept this transaction\n * @return amounts of tokens user received\n */\n function removeLiquidity(\n uint256 amount,\n uint256[] calldata minAmounts,\n uint256 deadline\n ) external returns (uint256[] memory) {\n // Transfer LPToken from msg.sender to this contract.\n IERC20(address(LP_TOKEN)).safeTransferFrom(\n msg.sender,\n address(this),\n amount\n );\n // Remove liquidity\n uint256[] memory amounts = SWAP.removeLiquidity(\n amount,\n minAmounts,\n deadline\n );\n // Send the tokens back to the user\n for (uint8 i = 0; i < amounts.length; i++) {\n if (isUnderlyingIndex[i] == true) {\n UNDERLYING_TOKENS[i].safeTransfer(msg.sender, amounts[i]);\n } else {\n LENDING_POOL.withdraw(\n address(UNDERLYING_TOKENS[i]),\n amounts[i],\n msg.sender\n );\n // underlyingTokens[i].safeTransfer(msg.sender, amounts[i]);\n }\n }\n return amounts;\n }\n\n /**\n * @notice Remove liquidity from the pool all in one token.\n * @dev Caller will receive ETH instead of WETH9.\n * @param tokenAmount the amount of the token you want to receive\n * @param tokenIndex the index of the token you want to receive\n * @param minAmount the minimum amount to withdraw, otherwise revert\n * @param deadline latest timestamp to accept this transaction\n * @return amount of chosen token user received\n */\n function removeLiquidityOneToken(\n uint256 tokenAmount,\n uint8 tokenIndex,\n uint256 minAmount,\n uint256 deadline\n ) external returns (uint256) {\n // Transfer LPToken from msg.sender to this contract.\n IERC20(address(LP_TOKEN)).safeTransferFrom(\n msg.sender,\n address(this),\n tokenAmount\n );\n // Withdraw via single token\n uint256 amount = SWAP.removeLiquidityOneToken(\n tokenAmount,\n tokenIndex,\n minAmount,\n deadline\n );\n // Transfer the token to msg.sender accordingly\n if (isUnderlyingIndex[tokenIndex] == true) {\n UNDERLYING_TOKENS[tokenIndex].safeTransfer(msg.sender, amount);\n } else {\n LENDING_POOL.withdraw(\n address(UNDERLYING_TOKENS[tokenIndex]),\n amount,\n msg.sender\n );\n }\n return amount;\n }\n\n /**\n * @notice Swap two tokens using the underlying pool. If tokenIndexFrom\n * represents WETH9 in the pool, the caller must set msg.value equal to dx.\n * If the user is swapping to WETH9 in the pool, the user will receive ETH instead.\n * @param tokenIndexFrom the token the user wants to swap from\n * @param tokenIndexTo the token the user wants to swap to\n * @param dx the amount of tokens the user wants to swap from\n * @param minDy the min amount the user would like to receive, or revert.\n * @param deadline latest timestamp to accept this transaction\n */\n function swap(\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx,\n uint256 minDy,\n uint256 deadline\n ) external returns (uint256) {\n // Transfer tokens from msg.sender to this contract\n UNDERLYING_TOKENS[tokenIndexFrom].safeTransferFrom(\n msg.sender,\n address(this),\n dx\n );\n if (isUnderlyingIndex[tokenIndexFrom] == false) {\n LENDING_POOL.deposit(\n address(UNDERLYING_TOKENS[tokenIndexFrom]),\n dx,\n address(this),\n 0\n );\n }\n // Execute swap\n uint256 dy = SWAP.swap(\n tokenIndexFrom,\n tokenIndexTo,\n dx,\n minDy,\n deadline\n );\n // Transfer the swapped tokens to msg.sender\n if (isUnderlyingIndex[tokenIndexTo] == false) {\n LENDING_POOL.withdraw(\n address(UNDERLYING_TOKENS[tokenIndexTo]),\n dy,\n msg.sender\n );\n } else {\n UNDERLYING_TOKENS[tokenIndexTo].safeTransfer(msg.sender, dy);\n }\n return dy;\n }\n\n /**\n * @notice Rescues any of the ETH, the pooled tokens, or the LPToken that may be stuck\n * in this contract. Only the OWNER can call this function.\n */\n function rescue() external {\n require(msg.sender == OWNER, \"CALLED_BY_NON_OWNER\");\n IERC20[] memory tokens = POOLED_TOKENS;\n for (uint256 i = 0; i < tokens.length; i++) {\n tokens[i].safeTransfer(\n msg.sender,\n tokens[i].balanceOf(address(this))\n );\n }\n\n for (uint256 i = 0; i < UNDERLYING_TOKENS.length; i++) {\n UNDERLYING_TOKENS[i].safeTransfer(\n msg.sender,\n UNDERLYING_TOKENS[i].balanceOf(address(this))\n );\n }\n\n IERC20 lpToken_ = IERC20(address(LP_TOKEN));\n lpToken_.safeTransfer(msg.sender, lpToken_.balanceOf(address(this)));\n }\n\n // VIEW FUNCTIONS\n\n /**\n * @notice Calculate amount of tokens you receive on swap\n * @param tokenIndexFrom the token the user wants to sell\n * @param tokenIndexTo the token the user wants to buy\n * @param dx the amount of tokens the user wants to sell. If the token charges\n * a fee on transfers, use the amount that gets transferred after the fee.\n * @return amount of tokens the user will receive\n */\n function calculateSwap(\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx\n ) external view virtual returns (uint256) {\n return SWAP.calculateSwap(tokenIndexFrom, tokenIndexTo, dx);\n }\n\n /**\n * @notice A simple method to calculate prices from deposits or\n * withdrawals, excluding fees but including slippage. This is\n * helpful as an input into the various \"min\" parameters on calls\n * to fight front-running\n *\n * @dev This shouldn't be used outside frontends for user estimates.\n *\n * @param amounts an array of token amounts to deposit or withdrawal,\n * corresponding to pooledTokens. The amount should be in each\n * pooled token's native precision. If a token charges a fee on transfers,\n * use the amount that gets transferred after the fee.\n * @param deposit whether this is a deposit or a withdrawal\n * @return token amount the user will receive\n */\n function calculateTokenAmount(uint256[] calldata amounts, bool deposit)\n external\n view\n returns (uint256)\n {\n return SWAP.calculateTokenAmount(amounts, deposit);\n }\n\n /**\n * @notice A simple method to calculate amount of each underlying\n * tokens that is returned upon burning given amount of LP tokens\n * @param amount the amount of LP tokens that would be burned on withdrawal\n * @return array of token balances that the user will receive\n */\n function calculateRemoveLiquidity(uint256 amount)\n external\n view\n returns (uint256[] memory)\n {\n return SWAP.calculateRemoveLiquidity(amount);\n }\n\n /**\n * @notice Calculate the amount of underlying token available to withdraw\n * when withdrawing via only single token\n * @param tokenAmount the amount of LP token to burn\n * @param tokenIndex index of which token will be withdrawn\n * @return availableTokenAmount calculated amount of underlying token\n * available to withdraw\n */\n function calculateRemoveLiquidityOneToken(\n uint256 tokenAmount,\n uint8 tokenIndex\n ) external view returns (uint256 availableTokenAmount) {\n return SWAP.calculateRemoveLiquidityOneToken(tokenAmount, tokenIndex);\n }\n\n /**\n * @notice Return address of the pooled token at given index. Reverts if tokenIndex is out of range.\n * @param index the index of the token\n * @return address of the token at given index\n */\n function getToken(uint8 index) public view virtual returns (IERC20) {\n if (index < UNDERLYING_TOKENS.length) {\n return UNDERLYING_TOKENS[index];\n } else {\n revert();\n }\n }\n}\n" + }, + "contracts/bridge/ECDSAFactory.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.6.12;\n\nimport \"@openzeppelin/contracts/access/Ownable.sol\";\nimport \"@openzeppelin/contracts/proxy/Clones.sol\";\nimport \"./interfaces/IECDSANodeManagement.sol\";\n\ncontract ECDSAFactory is Ownable {\n event ECDSANodeGroupCreated(\n address indexed keepAddress,\n address[] members,\n address indexed owner,\n uint256 honestThreshold\n );\n\n struct LatestNodeGroup {\n address keepAddress;\n address[] members;\n address owner;\n uint256 honestThreshold;\n }\n\n LatestNodeGroup public latestNodeGroup;\n\n constructor() public Ownable() {}\n\n /// @notice Returns members of the keep.\n /// @return List of the keep members' addresses.\n function getMembers() public view returns (address[] memory) {\n return latestNodeGroup.members;\n }\n\n /**\n @notice Deploys a new node \n @param nodeMgmtAddress address of the ECDSANodeManagement contract to initialize with\n @param owner Owner of the ECDSANodeManagement contract who can determine if the node group is closed or active\n @param members Array of node group members addresses\n @param honestThreshold Number of signers to process a transaction \n @return Address of the newest node management contract created\n **/\n function deploy(\n address nodeMgmtAddress,\n address owner,\n address[] memory members,\n uint256 honestThreshold\n ) external onlyOwner returns (address) {\n address nodeClone = Clones.clone(nodeMgmtAddress);\n IECDSANodeManagement(nodeClone).initialize(\n owner,\n members,\n honestThreshold\n );\n\n latestNodeGroup.keepAddress = nodeClone;\n latestNodeGroup.members = members;\n latestNodeGroup.owner = owner;\n latestNodeGroup.honestThreshold = honestThreshold;\n\n emit ECDSANodeGroupCreated(nodeClone, members, owner, honestThreshold);\n return nodeClone;\n }\n}\n" + }, + "contracts/bridge/interfaces/IECDSANodeManagement.sol": { + "content": "// SPDX-License-Identifier: MIT\n\n\npragma solidity 0.6.12;\n\n/**\n * @title IECDSANodeManagement interface\n * @notice Interface for the ECDSA node management interface.\n * @dev implement this interface to develop a a factory-patterned ECDSA node management contract\n **/\ninterface IECDSANodeManagement { \n function initialize(\n address _owner,\n address[] memory _members,\n uint256 _honestThreshold) external;\n}\n\n" + }, + "contracts/auxiliary/DummyWeth.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.6.12;\nimport \"@openzeppelin/contracts/access/Ownable.sol\";\n\ninterface IWETH9 {\n function name() external view returns (string memory);\n\n function symbol() external view returns (string memory);\n\n function decimals() external view returns (uint8);\n\n function balanceOf(address) external view returns (uint256);\n\n function allowance(address, address) external view returns (uint256);\n\n receive() external payable;\n\n function deposit() external payable;\n\n function withdraw(uint256 wad) external;\n\n function totalSupply() external view returns (uint256);\n\n function approve(address guy, uint256 wad) external returns (bool);\n\n function transfer(address dst, uint256 wad) external returns (bool);\n\n function transferFrom(\n address src,\n address dst,\n uint256 wad\n ) external returns (bool);\n}\n\ncontract DummyWeth is Ownable {\n IWETH9 public WETH;\n\n function setWETHAddress(address payable _weth) external onlyOwner {\n WETH = IWETH9(_weth);\n }\n\n function withdrawToSelf(uint256 amount) external {\n WETH.withdraw(amount);\n }\n\n function rescue(uint256 amount) external onlyOwner {\n WETH.transfer(owner(), amount);\n }\n\n receive() external payable {}\n\n fallback() external payable {}\n}\n" + } + }, + "settings": { + "optimizer": { + "enabled": true, + "runs": 10000 + }, + "outputSelection": { + "*": { + "*": [ + "abi", + "evm.bytecode", + "evm.deployedBytecode", + "evm.methodIdentifiers", + "metadata", + "devdoc", + "userdoc", + "storageLayout", + "evm.gasEstimates", + "devdoc", + "userdoc" + ], + "": [ + "ast" + ] + } + }, + "metadata": { + "useLiteralContent": true + } + } +} \ No newline at end of file diff --git a/deployments/avalanche/solcInputs/f830a0c701b69b2055ae5caebfbd7bc2.json b/deployments/avalanche/solcInputs/f830a0c701b69b2055ae5caebfbd7bc2.json new file mode 100644 index 000000000..a03d211fd --- /dev/null +++ b/deployments/avalanche/solcInputs/f830a0c701b69b2055ae5caebfbd7bc2.json @@ -0,0 +1,304 @@ +{ + "language": "Solidity", + "sources": { + "contracts/amm/AaveSwap.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.6.12;\n\nimport \"./Swap.sol\";\n\n/**\n * @title AaveSwap - A StableSwap implementation in solidity, integrated with Aave.\n * @notice This contract is responsible for custody of closely pegged assets (eg. group of stablecoins)\n * and automatic market making system. Users become an LP (Liquidity Provider) by depositing their tokens\n * in desired ratios for an exchange of the pool token that represents their share of the pool.\n * Users can burn pool tokens and withdraw their share of token(s).\n *\n * Each time a swap between the pooled tokens happens, a set fee incurs which effectively gets\n * distributed to the LPs.\n *\n * In case of emergencies, admin can pause additional deposits, swaps, or single-asset withdraws - which\n * stops the ratio of the tokens in the pool from changing.\n * Users can always withdraw their tokens via multi-asset withdraws.\n *\n * @dev Most of the logic is stored as a library `SwapUtils` for the sake of reducing contract's\n * deployment size.\n */\n\ncontract AaveSwap is Swap {\n address internal AAVE_REWARDS;\n address internal AAVE_LENDING_POOL;\n address internal REWARD_TOKEN;\n address internal REWARD_RECEIVER;\n address[] internal AAVE_ASSETS;\n\n /**\n * @notice Initializes this Swap contract with the given parameters.\n * This will also clone a LPToken contract that represents users'\n * LP positions. The owner of LPToken will be this contract - which means\n * only this contract is allowed to mint/burn tokens.\n *\n * @param _pooledTokens an array of ERC20s this pool will accept\n * @param decimals the decimals to use for each pooled token,\n * eg 8 for WBTC. Cannot be larger than POOL_PRECISION_DECIMALS\n * @param lpTokenName the long-form name of the token to be deployed\n * @param lpTokenSymbol the short symbol for the token to be deployed\n * @param _a the amplification coefficient * n * (n - 1). See the\n * StableSwap paper for details\n * @param _fee default swap fee to be initialized with\n * @param _adminFee default adminFee to be initialized with\n * @param lpTokenTargetAddress the address of an existing LPToken contract to use as a target\n */\n function initialize(\n IERC20[] memory _pooledTokens,\n uint8[] memory decimals,\n string memory lpTokenName,\n string memory lpTokenSymbol,\n uint256 _a,\n uint256 _fee,\n uint256 _adminFee,\n address lpTokenTargetAddress\n ) public virtual override initializer {\n Swap.initialize(\n _pooledTokens,\n decimals,\n lpTokenName,\n lpTokenSymbol,\n _a,\n _fee,\n _adminFee,\n lpTokenTargetAddress\n );\n AAVE_REWARDS = 0x01D83Fe6A10D2f2B7AF17034343746188272cAc9;\n AAVE_LENDING_POOL = 0x4F01AeD16D97E3aB5ab2B501154DC9bb0F1A5A2C;\n REWARD_TOKEN = 0xB31f66AA3C1e785363F0875A1B74E27b85FD66c7;\n AAVE_ASSETS = [0x53f7c5869a859F0AeC3D334ee8B4Cf01E3492f21];\n REWARD_RECEIVER = msg.sender;\n }\n\n function setRewardReceiver(address _reward_receiver) external onlyOwner {\n REWARD_RECEIVER = _reward_receiver;\n }\n\n function claimAaveRewards() external {\n AAVE_REWARDS.call(\n abi.encodeWithSignature(\n \"claimRewards(address[],uint256,address)\",\n AAVE_ASSETS,\n type(uint256).max,\n REWARD_RECEIVER\n )\n );\n }\n}\n" + }, + "contracts/amm/Swap.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.6.12;\n\nimport \"@openzeppelin/contracts/math/SafeMath.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/SafeERC20.sol\";\nimport \"@openzeppelin/contracts/proxy/Clones.sol\";\nimport \"@openzeppelin/contracts-upgradeable/utils/ReentrancyGuardUpgradeable.sol\";\nimport \"./OwnerPausableUpgradeable.sol\";\nimport \"./SwapUtils.sol\";\nimport \"./AmplificationUtils.sol\";\n\n/**\n * @title Swap - A StableSwap implementation in solidity.\n * @notice This contract is responsible for custody of closely pegged assets (eg. group of stablecoins)\n * and automatic market making system. Users become an LP (Liquidity Provider) by depositing their tokens\n * in desired ratios for an exchange of the pool token that represents their share of the pool.\n * Users can burn pool tokens and withdraw their share of token(s).\n *\n * Each time a swap between the pooled tokens happens, a set fee incurs which effectively gets\n * distributed to the LPs.\n *\n * In case of emergencies, admin can pause additional deposits, swaps, or single-asset withdraws - which\n * stops the ratio of the tokens in the pool from changing.\n * Users can always withdraw their tokens via multi-asset withdraws.\n *\n * @dev Most of the logic is stored as a library `SwapUtils` for the sake of reducing contract's\n * deployment size.\n */\ncontract Swap is OwnerPausableUpgradeable, ReentrancyGuardUpgradeable {\n using SafeERC20 for IERC20;\n using SafeMath for uint256;\n using SwapUtils for SwapUtils.Swap;\n using AmplificationUtils for SwapUtils.Swap;\n\n // Struct storing data responsible for automatic market maker functionalities. In order to\n // access this data, this contract uses SwapUtils library. For more details, see SwapUtils.sol\n SwapUtils.Swap public swapStorage;\n\n // Maps token address to an index in the pool. Used to prevent duplicate tokens in the pool.\n // getTokenIndex function also relies on this mapping to retrieve token index.\n mapping(address => uint8) private tokenIndexes;\n\n /*** EVENTS ***/\n\n // events replicated from SwapUtils to make the ABI easier for dumb\n // clients\n event TokenSwap(\n address indexed buyer,\n uint256 tokensSold,\n uint256 tokensBought,\n uint128 soldId,\n uint128 boughtId\n );\n event AddLiquidity(\n address indexed provider,\n uint256[] tokenAmounts,\n uint256[] fees,\n uint256 invariant,\n uint256 lpTokenSupply\n );\n event RemoveLiquidity(\n address indexed provider,\n uint256[] tokenAmounts,\n uint256 lpTokenSupply\n );\n event RemoveLiquidityOne(\n address indexed provider,\n uint256 lpTokenAmount,\n uint256 lpTokenSupply,\n uint256 boughtId,\n uint256 tokensBought\n );\n event RemoveLiquidityImbalance(\n address indexed provider,\n uint256[] tokenAmounts,\n uint256[] fees,\n uint256 invariant,\n uint256 lpTokenSupply\n );\n event NewAdminFee(uint256 newAdminFee);\n event NewSwapFee(uint256 newSwapFee);\n event RampA(\n uint256 oldA,\n uint256 newA,\n uint256 initialTime,\n uint256 futureTime\n );\n event StopRampA(uint256 currentA, uint256 time);\n\n /**\n * @notice Initializes this Swap contract with the given parameters.\n * This will also clone a LPToken contract that represents users'\n * LP positions. The owner of LPToken will be this contract - which means\n * only this contract is allowed to mint/burn tokens.\n *\n * @param _pooledTokens an array of ERC20s this pool will accept\n * @param decimals the decimals to use for each pooled token,\n * eg 8 for WBTC. Cannot be larger than POOL_PRECISION_DECIMALS\n * @param lpTokenName the long-form name of the token to be deployed\n * @param lpTokenSymbol the short symbol for the token to be deployed\n * @param _a the amplification coefficient * n * (n - 1). See the\n * StableSwap paper for details\n * @param _fee default swap fee to be initialized with\n * @param _adminFee default adminFee to be initialized with\n * @param lpTokenTargetAddress the address of an existing LPToken contract to use as a target\n */\n function initialize(\n IERC20[] memory _pooledTokens,\n uint8[] memory decimals,\n string memory lpTokenName,\n string memory lpTokenSymbol,\n uint256 _a,\n uint256 _fee,\n uint256 _adminFee,\n address lpTokenTargetAddress\n ) public virtual initializer {\n __OwnerPausable_init();\n __ReentrancyGuard_init();\n // Check _pooledTokens and precisions parameter\n require(_pooledTokens.length > 1, \"_pooledTokens.length <= 1\");\n require(_pooledTokens.length <= 32, \"_pooledTokens.length > 32\");\n require(\n _pooledTokens.length == decimals.length,\n \"_pooledTokens decimals mismatch\"\n );\n\n uint256[] memory precisionMultipliers = new uint256[](decimals.length);\n\n for (uint8 i = 0; i < _pooledTokens.length; i++) {\n if (i > 0) {\n // Check if index is already used. Check if 0th element is a duplicate.\n require(\n tokenIndexes[address(_pooledTokens[i])] == 0 &&\n _pooledTokens[0] != _pooledTokens[i],\n \"Duplicate tokens\"\n );\n }\n require(\n address(_pooledTokens[i]) != address(0),\n \"The 0 address isn't an ERC-20\"\n );\n require(\n decimals[i] <= SwapUtils.POOL_PRECISION_DECIMALS,\n \"Token decimals exceeds max\"\n );\n precisionMultipliers[i] =\n 10 **\n uint256(SwapUtils.POOL_PRECISION_DECIMALS).sub(\n uint256(decimals[i])\n );\n tokenIndexes[address(_pooledTokens[i])] = i;\n }\n\n // Check _a, _fee, _adminFee parameters\n require(_a < AmplificationUtils.MAX_A, \"_a exceeds maximum\");\n require(_fee < SwapUtils.MAX_SWAP_FEE, \"_fee exceeds maximum\");\n require(\n _adminFee < SwapUtils.MAX_ADMIN_FEE,\n \"_adminFee exceeds maximum\"\n );\n\n // Clone and initialize a LPToken contract\n LPToken lpToken = LPToken(Clones.clone(lpTokenTargetAddress));\n require(\n lpToken.initialize(lpTokenName, lpTokenSymbol),\n \"could not init lpToken clone\"\n );\n\n // Initialize swapStorage struct\n swapStorage.lpToken = lpToken;\n swapStorage.pooledTokens = _pooledTokens;\n swapStorage.tokenPrecisionMultipliers = precisionMultipliers;\n swapStorage.balances = new uint256[](_pooledTokens.length);\n swapStorage.initialA = _a.mul(AmplificationUtils.A_PRECISION);\n swapStorage.futureA = _a.mul(AmplificationUtils.A_PRECISION);\n // swapStorage.initialATime = 0;\n // swapStorage.futureATime = 0;\n swapStorage.swapFee = _fee;\n swapStorage.adminFee = _adminFee;\n }\n\n /*** MODIFIERS ***/\n\n /**\n * @notice Modifier to check deadline against current timestamp\n * @param deadline latest timestamp to accept this transaction\n */\n modifier deadlineCheck(uint256 deadline) {\n require(block.timestamp <= deadline, \"Deadline not met\");\n _;\n }\n\n /*** VIEW FUNCTIONS ***/\n\n /**\n * @notice Return A, the amplification coefficient * n * (n - 1)\n * @dev See the StableSwap paper for details\n * @return A parameter\n */\n function getA() external view virtual returns (uint256) {\n return swapStorage.getA();\n }\n\n /**\n * @notice Return A in its raw precision form\n * @dev See the StableSwap paper for details\n * @return A parameter in its raw precision form\n */\n function getAPrecise() external view virtual returns (uint256) {\n return swapStorage.getAPrecise();\n }\n\n /**\n * @notice Return address of the pooled token at given index. Reverts if tokenIndex is out of range.\n * @param index the index of the token\n * @return address of the token at given index\n */\n function getToken(uint8 index) public view virtual returns (IERC20) {\n require(index < swapStorage.pooledTokens.length, \"Out of range\");\n return swapStorage.pooledTokens[index];\n }\n\n /**\n * @notice Return the index of the given token address. Reverts if no matching\n * token is found.\n * @param tokenAddress address of the token\n * @return the index of the given token address\n */\n function getTokenIndex(address tokenAddress)\n public\n view\n virtual\n returns (uint8)\n {\n uint8 index = tokenIndexes[tokenAddress];\n require(\n address(getToken(index)) == tokenAddress,\n \"Token does not exist\"\n );\n return index;\n }\n\n /**\n * @notice Return current balance of the pooled token at given index\n * @param index the index of the token\n * @return current balance of the pooled token at given index with token's native precision\n */\n function getTokenBalance(uint8 index)\n external\n view\n virtual\n returns (uint256)\n {\n require(index < swapStorage.pooledTokens.length, \"Index out of range\");\n return swapStorage.balances[index];\n }\n\n /**\n * @notice Get the virtual price, to help calculate profit\n * @return the virtual price, scaled to the POOL_PRECISION_DECIMALS\n */\n function getVirtualPrice() external view virtual returns (uint256) {\n return swapStorage.getVirtualPrice();\n }\n\n /**\n * @notice Calculate amount of tokens you receive on swap\n * @param tokenIndexFrom the token the user wants to sell\n * @param tokenIndexTo the token the user wants to buy\n * @param dx the amount of tokens the user wants to sell. If the token charges\n * a fee on transfers, use the amount that gets transferred after the fee.\n * @return amount of tokens the user will receive\n */\n function calculateSwap(\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx\n ) external view virtual returns (uint256) {\n return swapStorage.calculateSwap(tokenIndexFrom, tokenIndexTo, dx);\n }\n\n /**\n * @notice A simple method to calculate prices from deposits or\n * withdrawals, excluding fees but including slippage. This is\n * helpful as an input into the various \"min\" parameters on calls\n * to fight front-running\n *\n * @dev This shouldn't be used outside frontends for user estimates.\n *\n * @param amounts an array of token amounts to deposit or withdrawal,\n * corresponding to pooledTokens. The amount should be in each\n * pooled token's native precision. If a token charges a fee on transfers,\n * use the amount that gets transferred after the fee.\n * @param deposit whether this is a deposit or a withdrawal\n * @return token amount the user will receive\n */\n function calculateTokenAmount(uint256[] calldata amounts, bool deposit)\n external\n view\n virtual\n returns (uint256)\n {\n return swapStorage.calculateTokenAmount(amounts, deposit);\n }\n\n /**\n * @notice A simple method to calculate amount of each underlying\n * tokens that is returned upon burning given amount of LP tokens\n * @param amount the amount of LP tokens that would be burned on withdrawal\n * @return array of token balances that the user will receive\n */\n function calculateRemoveLiquidity(uint256 amount)\n external\n view\n virtual\n returns (uint256[] memory)\n {\n return swapStorage.calculateRemoveLiquidity(amount);\n }\n\n /**\n * @notice Calculate the amount of underlying token available to withdraw\n * when withdrawing via only single token\n * @param tokenAmount the amount of LP token to burn\n * @param tokenIndex index of which token will be withdrawn\n * @return availableTokenAmount calculated amount of underlying token\n * available to withdraw\n */\n function calculateRemoveLiquidityOneToken(\n uint256 tokenAmount,\n uint8 tokenIndex\n ) external view virtual returns (uint256 availableTokenAmount) {\n return swapStorage.calculateWithdrawOneToken(tokenAmount, tokenIndex);\n }\n\n /**\n * @notice This function reads the accumulated amount of admin fees of the token with given index\n * @param index Index of the pooled token\n * @return admin's token balance in the token's precision\n */\n function getAdminBalance(uint256 index)\n external\n view\n virtual\n returns (uint256)\n {\n return swapStorage.getAdminBalance(index);\n }\n\n /*** STATE MODIFYING FUNCTIONS ***/\n\n /**\n * @notice Swap two tokens using this pool\n * @param tokenIndexFrom the token the user wants to swap from\n * @param tokenIndexTo the token the user wants to swap to\n * @param dx the amount of tokens the user wants to swap from\n * @param minDy the min amount the user would like to receive, or revert.\n * @param deadline latest timestamp to accept this transaction\n */\n function swap(\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx,\n uint256 minDy,\n uint256 deadline\n )\n external\n virtual\n nonReentrant\n whenNotPaused\n deadlineCheck(deadline)\n returns (uint256)\n {\n return swapStorage.swap(tokenIndexFrom, tokenIndexTo, dx, minDy);\n }\n\n /**\n * @notice Add liquidity to the pool with the given amounts of tokens\n * @param amounts the amounts of each token to add, in their native precision\n * @param minToMint the minimum LP tokens adding this amount of liquidity\n * should mint, otherwise revert. Handy for front-running mitigation\n * @param deadline latest timestamp to accept this transaction\n * @return amount of LP token user minted and received\n */\n function addLiquidity(\n uint256[] calldata amounts,\n uint256 minToMint,\n uint256 deadline\n )\n external\n virtual\n nonReentrant\n whenNotPaused\n deadlineCheck(deadline)\n returns (uint256)\n {\n return swapStorage.addLiquidity(amounts, minToMint);\n }\n\n /**\n * @notice Burn LP tokens to remove liquidity from the pool. Withdraw fee that decays linearly\n * over period of 4 weeks since last deposit will apply.\n * @dev Liquidity can always be removed, even when the pool is paused.\n * @param amount the amount of LP tokens to burn\n * @param minAmounts the minimum amounts of each token in the pool\n * acceptable for this burn. Useful as a front-running mitigation\n * @param deadline latest timestamp to accept this transaction\n * @return amounts of tokens user received\n */\n function removeLiquidity(\n uint256 amount,\n uint256[] calldata minAmounts,\n uint256 deadline\n )\n external\n virtual\n nonReentrant\n deadlineCheck(deadline)\n returns (uint256[] memory)\n {\n return swapStorage.removeLiquidity(amount, minAmounts);\n }\n\n /**\n * @notice Remove liquidity from the pool all in one token. Withdraw fee that decays linearly\n * over period of 4 weeks since last deposit will apply.\n * @param tokenAmount the amount of the token you want to receive\n * @param tokenIndex the index of the token you want to receive\n * @param minAmount the minimum amount to withdraw, otherwise revert\n * @param deadline latest timestamp to accept this transaction\n * @return amount of chosen token user received\n */\n function removeLiquidityOneToken(\n uint256 tokenAmount,\n uint8 tokenIndex,\n uint256 minAmount,\n uint256 deadline\n )\n external\n virtual\n nonReentrant\n whenNotPaused\n deadlineCheck(deadline)\n returns (uint256)\n {\n return\n swapStorage.removeLiquidityOneToken(\n tokenAmount,\n tokenIndex,\n minAmount\n );\n }\n\n /**\n * @notice Remove liquidity from the pool, weighted differently than the\n * pool's current balances. Withdraw fee that decays linearly\n * over period of 4 weeks since last deposit will apply.\n * @param amounts how much of each token to withdraw\n * @param maxBurnAmount the max LP token provider is willing to pay to\n * remove liquidity. Useful as a front-running mitigation.\n * @param deadline latest timestamp to accept this transaction\n * @return amount of LP tokens burned\n */\n function removeLiquidityImbalance(\n uint256[] calldata amounts,\n uint256 maxBurnAmount,\n uint256 deadline\n )\n external\n virtual\n nonReentrant\n whenNotPaused\n deadlineCheck(deadline)\n returns (uint256)\n {\n return swapStorage.removeLiquidityImbalance(amounts, maxBurnAmount);\n }\n\n /*** ADMIN FUNCTIONS ***/\n\n /**\n * @notice Withdraw all admin fees to the contract owner\n */\n function withdrawAdminFees() external onlyOwner {\n swapStorage.withdrawAdminFees(owner());\n }\n\n /**\n * @notice Update the admin fee. Admin fee takes portion of the swap fee.\n * @param newAdminFee new admin fee to be applied on future transactions\n */\n function setAdminFee(uint256 newAdminFee) external onlyOwner {\n swapStorage.setAdminFee(newAdminFee);\n }\n\n /**\n * @notice Update the swap fee to be applied on swaps\n * @param newSwapFee new swap fee to be applied on future transactions\n */\n function setSwapFee(uint256 newSwapFee) external onlyOwner {\n swapStorage.setSwapFee(newSwapFee);\n }\n\n /**\n * @notice Start ramping up or down A parameter towards given futureA and futureTime\n * Checks if the change is too rapid, and commits the new A value only when it falls under\n * the limit range.\n * @param futureA the new A to ramp towards\n * @param futureTime timestamp when the new A should be reached\n */\n function rampA(uint256 futureA, uint256 futureTime) external onlyOwner {\n swapStorage.rampA(futureA, futureTime);\n }\n\n /**\n * @notice Stop ramping A immediately. Reverts if ramp A is already stopped.\n */\n function stopRampA() external onlyOwner {\n swapStorage.stopRampA();\n }\n}\n" + }, + "@openzeppelin/contracts/math/SafeMath.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <0.8.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" + }, + "@openzeppelin/contracts/token/ERC20/SafeERC20.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <0.8.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" + }, + "@openzeppelin/contracts/proxy/Clones.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <0.8.0;\n\n/**\n * @dev https://eips.ethereum.org/EIPS/eip-1167[EIP 1167] is a standard for\n * deploying minimal proxy contracts, also known as \"clones\".\n *\n * > To simply and cheaply clone contract functionality in an immutable way, this standard specifies\n * > a minimal bytecode implementation that delegates all calls to a known, fixed address.\n *\n * The library includes functions to deploy a proxy using either `create` (traditional deployment) or `create2`\n * (salted deterministic deployment). It also includes functions to predict the addresses of clones deployed using the\n * deterministic method.\n *\n * _Available since v3.4._\n */\nlibrary Clones {\n /**\n * @dev Deploys and returns the address of a clone that mimics the behaviour of `master`.\n *\n * This function uses the create opcode, which should never revert.\n */\n function clone(address master) internal returns (address instance) {\n // solhint-disable-next-line no-inline-assembly\n assembly {\n let ptr := mload(0x40)\n mstore(ptr, 0x3d602d80600a3d3981f3363d3d373d3d3d363d73000000000000000000000000)\n mstore(add(ptr, 0x14), shl(0x60, master))\n mstore(add(ptr, 0x28), 0x5af43d82803e903d91602b57fd5bf30000000000000000000000000000000000)\n instance := create(0, ptr, 0x37)\n }\n require(instance != address(0), \"ERC1167: create failed\");\n }\n\n /**\n * @dev Deploys and returns the address of a clone that mimics the behaviour of `master`.\n *\n * This function uses the create2 opcode and a `salt` to deterministically deploy\n * the clone. Using the same `master` and `salt` multiple time will revert, since\n * the clones cannot be deployed twice at the same address.\n */\n function cloneDeterministic(address master, bytes32 salt) internal returns (address instance) {\n // solhint-disable-next-line no-inline-assembly\n assembly {\n let ptr := mload(0x40)\n mstore(ptr, 0x3d602d80600a3d3981f3363d3d373d3d3d363d73000000000000000000000000)\n mstore(add(ptr, 0x14), shl(0x60, master))\n mstore(add(ptr, 0x28), 0x5af43d82803e903d91602b57fd5bf30000000000000000000000000000000000)\n instance := create2(0, ptr, 0x37, salt)\n }\n require(instance != address(0), \"ERC1167: create2 failed\");\n }\n\n /**\n * @dev Computes the address of a clone deployed using {Clones-cloneDeterministic}.\n */\n function predictDeterministicAddress(address master, bytes32 salt, address deployer) internal pure returns (address predicted) {\n // solhint-disable-next-line no-inline-assembly\n assembly {\n let ptr := mload(0x40)\n mstore(ptr, 0x3d602d80600a3d3981f3363d3d373d3d3d363d73000000000000000000000000)\n mstore(add(ptr, 0x14), shl(0x60, master))\n mstore(add(ptr, 0x28), 0x5af43d82803e903d91602b57fd5bf3ff00000000000000000000000000000000)\n mstore(add(ptr, 0x38), shl(0x60, deployer))\n mstore(add(ptr, 0x4c), salt)\n mstore(add(ptr, 0x6c), keccak256(ptr, 0x37))\n predicted := keccak256(add(ptr, 0x37), 0x55)\n }\n }\n\n /**\n * @dev Computes the address of a clone deployed using {Clones-cloneDeterministic}.\n */\n function predictDeterministicAddress(address master, bytes32 salt) internal view returns (address predicted) {\n return predictDeterministicAddress(master, salt, address(this));\n }\n}\n" + }, + "@openzeppelin/contracts-upgradeable/utils/ReentrancyGuardUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <0.8.0;\nimport \"../proxy/Initializable.sol\";\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 ReentrancyGuardUpgradeable is Initializable {\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 function __ReentrancyGuard_init() internal initializer {\n __ReentrancyGuard_init_unchained();\n }\n\n function __ReentrancyGuard_init_unchained() internal initializer {\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 uint256[49] private __gap;\n}\n" + }, + "contracts/amm/OwnerPausableUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.6.12;\n\nimport \"@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol\";\nimport \"@openzeppelin/contracts-upgradeable/utils/PausableUpgradeable.sol\";\n\n/**\n * @title OwnerPausable\n * @notice An ownable contract allows the owner to pause and unpause the\n * contract without a delay.\n * @dev Only methods using the provided modifiers will be paused.\n */\nabstract contract OwnerPausableUpgradeable is\n OwnableUpgradeable,\n PausableUpgradeable\n{\n function __OwnerPausable_init() internal initializer {\n __Context_init_unchained();\n __Ownable_init_unchained();\n __Pausable_init_unchained();\n }\n\n /**\n * @notice Pause the contract. Revert if already paused.\n */\n function pause() external onlyOwner {\n PausableUpgradeable._pause();\n }\n\n /**\n * @notice Unpause the contract. Revert if already unpaused.\n */\n function unpause() external onlyOwner {\n PausableUpgradeable._unpause();\n }\n}\n" + }, + "contracts/amm/SwapUtils.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.6.12;\n\nimport \"@openzeppelin/contracts/math/SafeMath.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/SafeERC20.sol\";\nimport \"./AmplificationUtils.sol\";\nimport \"./LPToken.sol\";\nimport \"./MathUtils.sol\";\n\n/**\n * @title SwapUtils library\n * @notice A library to be used within Swap.sol. Contains functions responsible for custody and AMM functionalities.\n * @dev Contracts relying on this library must initialize SwapUtils.Swap struct then use this library\n * for SwapUtils.Swap struct. Note that this library contains both functions called by users and admins.\n * Admin functions should be protected within contracts using this library.\n */\nlibrary SwapUtils {\n using SafeERC20 for IERC20;\n using SafeMath for uint256;\n using MathUtils for uint256;\n\n /*** EVENTS ***/\n\n event TokenSwap(\n address indexed buyer,\n uint256 tokensSold,\n uint256 tokensBought,\n uint128 soldId,\n uint128 boughtId\n );\n event AddLiquidity(\n address indexed provider,\n uint256[] tokenAmounts,\n uint256[] fees,\n uint256 invariant,\n uint256 lpTokenSupply\n );\n event RemoveLiquidity(\n address indexed provider,\n uint256[] tokenAmounts,\n uint256 lpTokenSupply\n );\n event RemoveLiquidityOne(\n address indexed provider,\n uint256 lpTokenAmount,\n uint256 lpTokenSupply,\n uint256 boughtId,\n uint256 tokensBought\n );\n event RemoveLiquidityImbalance(\n address indexed provider,\n uint256[] tokenAmounts,\n uint256[] fees,\n uint256 invariant,\n uint256 lpTokenSupply\n );\n event NewAdminFee(uint256 newAdminFee);\n event NewSwapFee(uint256 newSwapFee);\n\n struct Swap {\n // variables around the ramp management of A,\n // the amplification coefficient * n * (n - 1)\n // see https://www.curve.fi/stableswap-paper.pdf for details\n uint256 initialA;\n uint256 futureA;\n uint256 initialATime;\n uint256 futureATime;\n // fee calculation\n uint256 swapFee;\n uint256 adminFee;\n LPToken lpToken;\n // contract references for all tokens being pooled\n IERC20[] pooledTokens;\n // multipliers for each pooled token's precision to get to POOL_PRECISION_DECIMALS\n // for example, TBTC has 18 decimals, so the multiplier should be 1. WBTC\n // has 8, so the multiplier should be 10 ** 18 / 10 ** 8 => 10 ** 10\n uint256[] tokenPrecisionMultipliers;\n // the pool balance of each token, in the token's precision\n // the contract's actual token balance might differ\n uint256[] balances;\n }\n\n // Struct storing variables used in calculations in the\n // calculateWithdrawOneTokenDY function to avoid stack too deep errors\n struct CalculateWithdrawOneTokenDYInfo {\n uint256 d0;\n uint256 d1;\n uint256 newY;\n uint256 feePerToken;\n uint256 preciseA;\n }\n\n // Struct storing variables used in calculations in the\n // {add,remove}Liquidity functions to avoid stack too deep errors\n struct ManageLiquidityInfo {\n uint256 d0;\n uint256 d1;\n uint256 d2;\n uint256 preciseA;\n LPToken lpToken;\n uint256 totalSupply;\n uint256[] balances;\n uint256[] multipliers;\n }\n\n // the precision all pools tokens will be converted to\n uint8 public constant POOL_PRECISION_DECIMALS = 18;\n\n // the denominator used to calculate admin and LP fees. For example, an\n // LP fee might be something like tradeAmount.mul(fee).div(FEE_DENOMINATOR)\n uint256 private constant FEE_DENOMINATOR = 10**10;\n\n // Max swap fee is 1% or 100bps of each swap\n uint256 public constant MAX_SWAP_FEE = 10**8;\n\n // Max adminFee is 100% of the swapFee\n // adminFee does not add additional fee on top of swapFee\n // Instead it takes a certain % of the swapFee. Therefore it has no impact on the\n // users but only on the earnings of LPs\n uint256 public constant MAX_ADMIN_FEE = 10**10;\n\n // Constant value used as max loop limit\n uint256 private constant MAX_LOOP_LIMIT = 256;\n\n /*** VIEW & PURE FUNCTIONS ***/\n\n function _getAPrecise(Swap storage self) internal view returns (uint256) {\n return AmplificationUtils._getAPrecise(self);\n }\n\n /**\n * @notice Calculate the dy, the amount of selected token that user receives and\n * the fee of withdrawing in one token\n * @param tokenAmount the amount to withdraw in the pool's precision\n * @param tokenIndex which token will be withdrawn\n * @param self Swap struct to read from\n * @return the amount of token user will receive\n */\n function calculateWithdrawOneToken(\n Swap storage self,\n uint256 tokenAmount,\n uint8 tokenIndex\n ) external view returns (uint256) {\n (uint256 availableTokenAmount, ) = _calculateWithdrawOneToken(\n self,\n tokenAmount,\n tokenIndex,\n self.lpToken.totalSupply()\n );\n return availableTokenAmount;\n }\n\n function _calculateWithdrawOneToken(\n Swap storage self,\n uint256 tokenAmount,\n uint8 tokenIndex,\n uint256 totalSupply\n ) internal view returns (uint256, uint256) {\n uint256 dy;\n uint256 newY;\n uint256 currentY;\n\n (dy, newY, currentY) = calculateWithdrawOneTokenDY(\n self,\n tokenIndex,\n tokenAmount,\n totalSupply\n );\n\n // dy_0 (without fees)\n // dy, dy_0 - dy\n\n uint256 dySwapFee = currentY\n .sub(newY)\n .div(self.tokenPrecisionMultipliers[tokenIndex])\n .sub(dy);\n\n return (dy, dySwapFee);\n }\n\n /**\n * @notice Calculate the dy of withdrawing in one token\n * @param self Swap struct to read from\n * @param tokenIndex which token will be withdrawn\n * @param tokenAmount the amount to withdraw in the pools precision\n * @return the d and the new y after withdrawing one token\n */\n function calculateWithdrawOneTokenDY(\n Swap storage self,\n uint8 tokenIndex,\n uint256 tokenAmount,\n uint256 totalSupply\n )\n internal\n view\n returns (\n uint256,\n uint256,\n uint256\n )\n {\n // Get the current D, then solve the stableswap invariant\n // y_i for D - tokenAmount\n uint256[] memory xp = _xp(self);\n\n require(tokenIndex < xp.length, \"Token index out of range\");\n\n\n CalculateWithdrawOneTokenDYInfo memory v\n = CalculateWithdrawOneTokenDYInfo(0, 0, 0, 0, 0);\n v.preciseA = _getAPrecise(self);\n v.d0 = getD(xp, v.preciseA);\n v.d1 = v.d0.sub(tokenAmount.mul(v.d0).div(totalSupply));\n\n require(tokenAmount <= xp[tokenIndex], \"Withdraw exceeds available\");\n\n v.newY = getYD(v.preciseA, tokenIndex, xp, v.d1);\n\n uint256[] memory xpReduced = new uint256[](xp.length);\n\n v.feePerToken = _feePerToken(self.swapFee, xp.length);\n for (uint256 i = 0; i < xp.length; i++) {\n uint256 xpi = xp[i];\n // if i == tokenIndex, dxExpected = xp[i] * d1 / d0 - newY\n // else dxExpected = xp[i] - (xp[i] * d1 / d0)\n // xpReduced[i] -= dxExpected * fee / FEE_DENOMINATOR\n xpReduced[i] = xpi.sub(\n (\n (i == tokenIndex)\n ? xpi.mul(v.d1).div(v.d0).sub(v.newY)\n : xpi.sub(xpi.mul(v.d1).div(v.d0))\n )\n .mul(v.feePerToken)\n .div(FEE_DENOMINATOR)\n );\n }\n\n uint256 dy = xpReduced[tokenIndex].sub(\n getYD(v.preciseA, tokenIndex, xpReduced, v.d1)\n );\n dy = dy.sub(1).div(self.tokenPrecisionMultipliers[tokenIndex]);\n\n return (dy, v.newY, xp[tokenIndex]);\n }\n\n /**\n * @notice Calculate the price of a token in the pool with given\n * precision-adjusted balances and a particular D.\n *\n * @dev This is accomplished via solving the invariant iteratively.\n * See the StableSwap paper and Curve.fi implementation for further details.\n *\n * x_1**2 + x1 * (sum' - (A*n**n - 1) * D / (A * n**n)) = D ** (n + 1) / (n ** (2 * n) * prod' * A)\n * x_1**2 + b*x_1 = c\n * x_1 = (x_1**2 + c) / (2*x_1 + b)\n *\n * @param a the amplification coefficient * n * (n - 1). See the StableSwap paper for details.\n * @param tokenIndex Index of token we are calculating for.\n * @param xp a precision-adjusted set of pool balances. Array should be\n * the same cardinality as the pool.\n * @param d the stableswap invariant\n * @return the price of the token, in the same precision as in xp\n */\n function getYD(\n uint256 a,\n uint8 tokenIndex,\n uint256[] memory xp,\n uint256 d\n ) internal pure returns (uint256) {\n uint256 numTokens = xp.length;\n require(tokenIndex < numTokens, \"Token not found\");\n\n uint256 c = d;\n uint256 s;\n uint256 nA = a.mul(numTokens);\n\n for (uint256 i = 0; i < numTokens; i++) {\n if (i != tokenIndex) {\n s = s.add(xp[i]);\n c = c.mul(d).div(xp[i].mul(numTokens));\n // If we were to protect the division loss we would have to keep the denominator separate\n // and divide at the end. However this leads to overflow with large numTokens or/and D.\n // c = c * D * D * D * ... overflow!\n }\n }\n c = c.mul(d).mul(AmplificationUtils.A_PRECISION).div(nA.mul(numTokens));\n\n uint256 b = s.add(d.mul(AmplificationUtils.A_PRECISION).div(nA));\n uint256 yPrev;\n uint256 y = d;\n for (uint256 i = 0; i < MAX_LOOP_LIMIT; i++) {\n yPrev = y;\n y = y.mul(y).add(c).div(y.mul(2).add(b).sub(d));\n if (y.within1(yPrev)) {\n return y;\n }\n }\n revert(\"Approximation did not converge\");\n }\n\n /**\n * @notice Get D, the StableSwap invariant, based on a set of balances and a particular A.\n * @param xp a precision-adjusted set of pool balances. Array should be the same cardinality\n * as the pool.\n * @param a the amplification coefficient * n * (n - 1) in A_PRECISION.\n * See the StableSwap paper for details\n * @return the invariant, at the precision of the pool\n */\n function getD(uint256[] memory xp, uint256 a)\n internal\n pure\n returns (uint256)\n {\n uint256 numTokens = xp.length;\n uint256 s;\n for (uint256 i = 0; i < numTokens; i++) {\n s = s.add(xp[i]);\n }\n if (s == 0) {\n return 0;\n }\n\n uint256 prevD;\n uint256 d = s;\n uint256 nA = a.mul(numTokens);\n\n for (uint256 i = 0; i < MAX_LOOP_LIMIT; i++) {\n uint256 dP = d;\n for (uint256 j = 0; j < numTokens; j++) {\n dP = dP.mul(d).div(xp[j].mul(numTokens));\n // If we were to protect the division loss we would have to keep the denominator separate\n // and divide at the end. However this leads to overflow with large numTokens or/and D.\n // dP = dP * D * D * D * ... overflow!\n }\n prevD = d;\n d = nA\n .mul(s)\n .div(AmplificationUtils.A_PRECISION)\n .add(dP.mul(numTokens))\n .mul(d)\n .div(\n nA\n .sub(AmplificationUtils.A_PRECISION)\n .mul(d)\n .div(AmplificationUtils.A_PRECISION)\n .add(numTokens.add(1).mul(dP))\n );\n if (d.within1(prevD)) {\n return d;\n }\n }\n\n // Convergence should occur in 4 loops or less. If this is reached, there may be something wrong\n // with the pool. If this were to occur repeatedly, LPs should withdraw via `removeLiquidity()`\n // function which does not rely on D.\n revert(\"D does not converge\");\n }\n\n /**\n * @notice Given a set of balances and precision multipliers, return the\n * precision-adjusted balances.\n *\n * @param balances an array of token balances, in their native precisions.\n * These should generally correspond with pooled tokens.\n *\n * @param precisionMultipliers an array of multipliers, corresponding to\n * the amounts in the balances array. When multiplied together they\n * should yield amounts at the pool's precision.\n *\n * @return an array of amounts \"scaled\" to the pool's precision\n */\n function _xp(\n uint256[] memory balances,\n uint256[] memory precisionMultipliers\n ) internal pure returns (uint256[] memory) {\n uint256 numTokens = balances.length;\n require(\n numTokens == precisionMultipliers.length,\n \"Balances must match multipliers\"\n );\n uint256[] memory xp = new uint256[](numTokens);\n for (uint256 i = 0; i < numTokens; i++) {\n xp[i] = balances[i].mul(precisionMultipliers[i]);\n }\n return xp;\n }\n\n /**\n * @notice Return the precision-adjusted balances of all tokens in the pool\n * @param self Swap struct to read from\n * @return the pool balances \"scaled\" to the pool's precision, allowing\n * them to be more easily compared.\n */\n function _xp(Swap storage self) internal view returns (uint256[] memory) {\n return _xp(self.balances, self.tokenPrecisionMultipliers);\n }\n\n /**\n * @notice Get the virtual price, to help calculate profit\n * @param self Swap struct to read from\n * @return the virtual price, scaled to precision of POOL_PRECISION_DECIMALS\n */\n function getVirtualPrice(Swap storage self)\n external\n view\n returns (uint256)\n {\n uint256 d = getD(_xp(self), _getAPrecise(self));\n LPToken lpToken = self.lpToken;\n uint256 supply = lpToken.totalSupply();\n if (supply > 0) {\n return d.mul(10**uint256(POOL_PRECISION_DECIMALS)).div(supply);\n }\n return 0;\n }\n\n /**\n * @notice Calculate the new balances of the tokens given the indexes of the token\n * that is swapped from (FROM) and the token that is swapped to (TO).\n * This function is used as a helper function to calculate how much TO token\n * the user should receive on swap.\n *\n * @param preciseA precise form of amplification coefficient\n * @param tokenIndexFrom index of FROM token\n * @param tokenIndexTo index of TO token\n * @param x the new total amount of FROM token\n * @param xp balances of the tokens in the pool\n * @return the amount of TO token that should remain in the pool\n */\n function getY(\n uint256 preciseA,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 x,\n uint256[] memory xp\n ) internal pure returns (uint256) {\n uint256 numTokens = xp.length;\n require(\n tokenIndexFrom != tokenIndexTo,\n \"Can't compare token to itself\"\n );\n require(\n tokenIndexFrom < numTokens && tokenIndexTo < numTokens,\n \"Tokens must be in pool\"\n );\n\n uint256 d = getD(xp, preciseA);\n uint256 c = d;\n uint256 s;\n uint256 nA = numTokens.mul(preciseA);\n\n uint256 _x;\n for (uint256 i = 0; i < numTokens; i++) {\n if (i == tokenIndexFrom) {\n _x = x;\n } else if (i != tokenIndexTo) {\n _x = xp[i];\n } else {\n continue;\n }\n s = s.add(_x);\n c = c.mul(d).div(_x.mul(numTokens));\n // If we were to protect the division loss we would have to keep the denominator separate\n // and divide at the end. However this leads to overflow with large numTokens or/and D.\n // c = c * D * D * D * ... overflow!\n }\n c = c.mul(d).mul(AmplificationUtils.A_PRECISION).div(nA.mul(numTokens));\n uint256 b = s.add(d.mul(AmplificationUtils.A_PRECISION).div(nA));\n uint256 yPrev;\n uint256 y = d;\n\n // iterative approximation\n for (uint256 i = 0; i < MAX_LOOP_LIMIT; i++) {\n yPrev = y;\n y = y.mul(y).add(c).div(y.mul(2).add(b).sub(d));\n if (y.within1(yPrev)) {\n return y;\n }\n }\n revert(\"Approximation did not converge\");\n }\n\n /**\n * @notice Externally calculates a swap between two tokens.\n * @param self Swap struct to read from\n * @param tokenIndexFrom the token to sell\n * @param tokenIndexTo the token to buy\n * @param dx the number of tokens to sell. If the token charges a fee on transfers,\n * use the amount that gets transferred after the fee.\n * @return dy the number of tokens the user will get\n */\n function calculateSwap(\n Swap storage self,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx\n ) external view returns (uint256 dy) {\n (dy, ) = _calculateSwap(\n self,\n tokenIndexFrom,\n tokenIndexTo,\n dx,\n self.balances\n );\n }\n\n /**\n * @notice Internally calculates a swap between two tokens.\n *\n * @dev The caller is expected to transfer the actual amounts (dx and dy)\n * using the token contracts.\n *\n * @param self Swap struct to read from\n * @param tokenIndexFrom the token to sell\n * @param tokenIndexTo the token to buy\n * @param dx the number of tokens to sell. If the token charges a fee on transfers,\n * use the amount that gets transferred after the fee.\n * @return dy the number of tokens the user will get\n * @return dyFee the associated fee\n */\n function _calculateSwap(\n Swap storage self,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx,\n uint256[] memory balances\n ) internal view returns (uint256 dy, uint256 dyFee) {\n uint256[] memory multipliers = self.tokenPrecisionMultipliers;\n uint256[] memory xp = _xp(balances, multipliers);\n require(\n tokenIndexFrom < xp.length && tokenIndexTo < xp.length,\n \"Token index out of range\"\n );\n uint256 x = dx.mul(multipliers[tokenIndexFrom]).add(xp[tokenIndexFrom]);\n uint256 y = getY(\n _getAPrecise(self),\n tokenIndexFrom,\n tokenIndexTo,\n x,\n xp\n );\n dy = xp[tokenIndexTo].sub(y).sub(1);\n dyFee = dy.mul(self.swapFee).div(FEE_DENOMINATOR);\n dy = dy.sub(dyFee).div(multipliers[tokenIndexTo]);\n }\n\n /**\n * @notice A simple method to calculate amount of each underlying\n * tokens that is returned upon burning given amount of\n * LP tokens\n *\n * @param amount the amount of LP tokens that would to be burned on\n * withdrawal\n * @return array of amounts of tokens user will receive\n */\n function calculateRemoveLiquidity(Swap storage self, uint256 amount)\n external\n view\n returns (uint256[] memory)\n {\n return\n _calculateRemoveLiquidity(\n self.balances,\n amount,\n self.lpToken.totalSupply()\n );\n }\n\n function _calculateRemoveLiquidity(\n uint256[] memory balances,\n uint256 amount,\n uint256 totalSupply\n ) internal pure returns (uint256[] memory) {\n require(amount <= totalSupply, \"Cannot exceed total supply\");\n\n uint256[] memory amounts = new uint256[](balances.length);\n\n for (uint256 i = 0; i < balances.length; i++) {\n amounts[i] = balances[i].mul(amount).div(totalSupply);\n }\n return amounts;\n }\n\n /**\n * @notice A simple method to calculate prices from deposits or\n * withdrawals, excluding fees but including slippage. This is\n * helpful as an input into the various \"min\" parameters on calls\n * to fight front-running\n *\n * @dev This shouldn't be used outside frontends for user estimates.\n *\n * @param self Swap struct to read from\n * @param amounts an array of token amounts to deposit or withdrawal,\n * corresponding to pooledTokens. The amount should be in each\n * pooled token's native precision. If a token charges a fee on transfers,\n * use the amount that gets transferred after the fee.\n * @param deposit whether this is a deposit or a withdrawal\n * @return if deposit was true, total amount of lp token that will be minted and if\n * deposit was false, total amount of lp token that will be burned\n */\n function calculateTokenAmount(\n Swap storage self,\n uint256[] calldata amounts,\n bool deposit\n ) external view returns (uint256) {\n uint256 a = _getAPrecise(self);\n uint256[] memory balances = self.balances;\n uint256[] memory multipliers = self.tokenPrecisionMultipliers;\n\n uint256 d0 = getD(_xp(balances, multipliers), a);\n for (uint256 i = 0; i < balances.length; i++) {\n if (deposit) {\n balances[i] = balances[i].add(amounts[i]);\n } else {\n balances[i] = balances[i].sub(\n amounts[i],\n \"Cannot withdraw more than available\"\n );\n }\n }\n uint256 d1 = getD(_xp(balances, multipliers), a);\n uint256 totalSupply = self.lpToken.totalSupply();\n\n if (deposit) {\n return d1.sub(d0).mul(totalSupply).div(d0);\n } else {\n return d0.sub(d1).mul(totalSupply).div(d0);\n }\n }\n\n /**\n * @notice return accumulated amount of admin fees of the token with given index\n * @param self Swap struct to read from\n * @param index Index of the pooled token\n * @return admin balance in the token's precision\n */\n function getAdminBalance(Swap storage self, uint256 index)\n external\n view\n returns (uint256)\n {\n require(index < self.pooledTokens.length, \"Token index out of range\");\n return\n self.pooledTokens[index].balanceOf(address(this)).sub(\n self.balances[index]\n );\n }\n\n /**\n * @notice internal helper function to calculate fee per token multiplier used in\n * swap fee calculations\n * @param swapFee swap fee for the tokens\n * @param numTokens number of tokens pooled\n */\n function _feePerToken(uint256 swapFee, uint256 numTokens)\n internal\n pure\n returns (uint256)\n {\n return swapFee.mul(numTokens).div(numTokens.sub(1).mul(4));\n }\n\n /*** STATE MODIFYING FUNCTIONS ***/\n\n /**\n * @notice swap two tokens in the pool\n * @param self Swap struct to read from and write to\n * @param tokenIndexFrom the token the user wants to sell\n * @param tokenIndexTo the token the user wants to buy\n * @param dx the amount of tokens the user wants to sell\n * @param minDy the min amount the user would like to receive, or revert.\n * @return amount of token user received on swap\n */\n function swap(\n Swap storage self,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx,\n uint256 minDy\n ) external returns (uint256) {\n {\n IERC20 tokenFrom = self.pooledTokens[tokenIndexFrom];\n require(\n dx <= tokenFrom.balanceOf(msg.sender),\n \"Cannot swap more than you own\"\n );\n // Transfer tokens first to see if a fee was charged on transfer\n uint256 beforeBalance = tokenFrom.balanceOf(address(this));\n tokenFrom.safeTransferFrom(msg.sender, address(this), dx);\n\n // Use the actual transferred amount for AMM math\n dx = tokenFrom.balanceOf(address(this)).sub(beforeBalance);\n }\n\n uint256 dy;\n uint256 dyFee;\n uint256[] memory balances = self.balances;\n (dy, dyFee) = _calculateSwap(\n self,\n tokenIndexFrom,\n tokenIndexTo,\n dx,\n balances\n );\n require(dy >= minDy, \"Swap didn't result in min tokens\");\n\n uint256 dyAdminFee = dyFee.mul(self.adminFee).div(FEE_DENOMINATOR).div(\n self.tokenPrecisionMultipliers[tokenIndexTo]\n );\n\n self.balances[tokenIndexFrom] = balances[tokenIndexFrom].add(dx);\n self.balances[tokenIndexTo] = balances[tokenIndexTo].sub(dy).sub(\n dyAdminFee\n );\n\n self.pooledTokens[tokenIndexTo].safeTransfer(msg.sender, dy);\n\n emit TokenSwap(msg.sender, dx, dy, tokenIndexFrom, tokenIndexTo);\n\n return dy;\n }\n\n /**\n * @notice Add liquidity to the pool\n * @param self Swap struct to read from and write to\n * @param amounts the amounts of each token to add, in their native precision\n * @param minToMint the minimum LP tokens adding this amount of liquidity\n * should mint, otherwise revert. Handy for front-running mitigation\n * allowed addresses. If the pool is not in the guarded launch phase, this parameter will be ignored.\n * @return amount of LP token user received\n */\n function addLiquidity(\n Swap storage self,\n uint256[] memory amounts,\n uint256 minToMint\n ) external returns (uint256) {\n IERC20[] memory pooledTokens = self.pooledTokens;\n require(\n amounts.length == pooledTokens.length,\n \"Amounts must match pooled tokens\"\n );\n\n // current state\n ManageLiquidityInfo memory v = ManageLiquidityInfo(\n 0,\n 0,\n 0,\n _getAPrecise(self),\n self.lpToken,\n 0,\n self.balances,\n self.tokenPrecisionMultipliers\n );\n v.totalSupply = v.lpToken.totalSupply();\n\n if (v.totalSupply != 0) {\n v.d0 = getD(_xp(v.balances, v.multipliers), v.preciseA);\n }\n\n uint256[] memory newBalances = new uint256[](pooledTokens.length);\n\n for (uint256 i = 0; i < pooledTokens.length; i++) {\n require(\n v.totalSupply != 0 || amounts[i] > 0,\n \"Must supply all tokens in pool\"\n );\n\n // Transfer tokens first to see if a fee was charged on transfer\n if (amounts[i] != 0) {\n uint256 beforeBalance = pooledTokens[i].balanceOf(\n address(this)\n );\n pooledTokens[i].safeTransferFrom(\n msg.sender,\n address(this),\n amounts[i]\n );\n\n // Update the amounts[] with actual transfer amount\n amounts[i] = pooledTokens[i].balanceOf(address(this)).sub(\n beforeBalance\n );\n }\n\n newBalances[i] = v.balances[i].add(amounts[i]);\n }\n\n // invariant after change\n v.d1 = getD(_xp(newBalances, v.multipliers), v.preciseA);\n require(v.d1 > v.d0, \"D should increase\");\n\n // updated to reflect fees and calculate the user's LP tokens\n v.d2 = v.d1;\n uint256[] memory fees = new uint256[](pooledTokens.length);\n\n if (v.totalSupply != 0) {\n uint256 feePerToken = _feePerToken(\n self.swapFee,\n pooledTokens.length\n );\n for (uint256 i = 0; i < pooledTokens.length; i++) {\n uint256 idealBalance = v.d1.mul(v.balances[i]).div(v.d0);\n fees[i] = feePerToken\n .mul(idealBalance.difference(newBalances[i]))\n .div(FEE_DENOMINATOR);\n self.balances[i] = newBalances[i].sub(\n fees[i].mul(self.adminFee).div(FEE_DENOMINATOR)\n );\n newBalances[i] = newBalances[i].sub(fees[i]);\n }\n v.d2 = getD(_xp(newBalances, v.multipliers), v.preciseA);\n } else {\n // the initial depositor doesn't pay fees\n self.balances = newBalances;\n }\n\n uint256 toMint;\n if (v.totalSupply == 0) {\n toMint = v.d1;\n } else {\n toMint = v.d2.sub(v.d0).mul(v.totalSupply).div(v.d0);\n }\n\n require(toMint >= minToMint, \"Couldn't mint min requested\");\n\n // mint the user's LP tokens\n v.lpToken.mint(msg.sender, toMint);\n\n emit AddLiquidity(\n msg.sender,\n amounts,\n fees,\n v.d1,\n v.totalSupply.add(toMint)\n );\n\n return toMint;\n }\n\n /**\n * @notice Burn LP tokens to remove liquidity from the pool.\n * @dev Liquidity can always be removed, even when the pool is paused.\n * @param self Swap struct to read from and write to\n * @param amount the amount of LP tokens to burn\n * @param minAmounts the minimum amounts of each token in the pool\n * acceptable for this burn. Useful as a front-running mitigation\n * @return amounts of tokens the user received\n */\n function removeLiquidity(\n Swap storage self,\n uint256 amount,\n uint256[] calldata minAmounts\n ) external returns (uint256[] memory) {\n LPToken lpToken = self.lpToken;\n IERC20[] memory pooledTokens = self.pooledTokens;\n require(amount <= lpToken.balanceOf(msg.sender), \">LP.balanceOf\");\n require(\n minAmounts.length == pooledTokens.length,\n \"minAmounts must match poolTokens\"\n );\n\n uint256[] memory balances = self.balances;\n uint256 totalSupply = lpToken.totalSupply();\n\n uint256[] memory amounts = _calculateRemoveLiquidity(\n balances,\n amount,\n totalSupply\n );\n\n for (uint256 i = 0; i < amounts.length; i++) {\n require(amounts[i] >= minAmounts[i], \"amounts[i] < minAmounts[i]\");\n self.balances[i] = balances[i].sub(amounts[i]);\n pooledTokens[i].safeTransfer(msg.sender, amounts[i]);\n }\n\n lpToken.burnFrom(msg.sender, amount);\n\n emit RemoveLiquidity(msg.sender, amounts, totalSupply.sub(amount));\n\n return amounts;\n }\n\n /**\n * @notice Remove liquidity from the pool all in one token.\n * @param self Swap struct to read from and write to\n * @param tokenAmount the amount of the lp tokens to burn\n * @param tokenIndex the index of the token you want to receive\n * @param minAmount the minimum amount to withdraw, otherwise revert\n * @return amount chosen token that user received\n */\n function removeLiquidityOneToken(\n Swap storage self,\n uint256 tokenAmount,\n uint8 tokenIndex,\n uint256 minAmount\n ) external returns (uint256) {\n LPToken lpToken = self.lpToken;\n IERC20[] memory pooledTokens = self.pooledTokens;\n\n require(tokenAmount <= lpToken.balanceOf(msg.sender), \">LP.balanceOf\");\n require(tokenIndex < pooledTokens.length, \"Token not found\");\n\n uint256 totalSupply = lpToken.totalSupply();\n\n (uint256 dy, uint256 dyFee) = _calculateWithdrawOneToken(\n self,\n tokenAmount,\n tokenIndex,\n totalSupply\n );\n\n require(dy >= minAmount, \"dy < minAmount\");\n\n self.balances[tokenIndex] = self.balances[tokenIndex].sub(\n dy.add(dyFee.mul(self.adminFee).div(FEE_DENOMINATOR))\n );\n lpToken.burnFrom(msg.sender, tokenAmount);\n pooledTokens[tokenIndex].safeTransfer(msg.sender, dy);\n\n emit RemoveLiquidityOne(\n msg.sender,\n tokenAmount,\n totalSupply,\n tokenIndex,\n dy\n );\n\n return dy;\n }\n\n /**\n * @notice Remove liquidity from the pool, weighted differently than the\n * pool's current balances.\n *\n * @param self Swap struct to read from and write to\n * @param amounts how much of each token to withdraw\n * @param maxBurnAmount the max LP token provider is willing to pay to\n * remove liquidity. Useful as a front-running mitigation.\n * @return actual amount of LP tokens burned in the withdrawal\n */\n function removeLiquidityImbalance(\n Swap storage self,\n uint256[] memory amounts,\n uint256 maxBurnAmount\n ) public returns (uint256) {\n ManageLiquidityInfo memory v = ManageLiquidityInfo(\n 0,\n 0,\n 0,\n _getAPrecise(self),\n self.lpToken,\n 0,\n self.balances,\n self.tokenPrecisionMultipliers\n );\n v.totalSupply = v.lpToken.totalSupply();\n\n IERC20[] memory pooledTokens = self.pooledTokens;\n\n require(\n amounts.length == pooledTokens.length,\n \"Amounts should match pool tokens\"\n );\n\n require(\n maxBurnAmount <= v.lpToken.balanceOf(msg.sender) &&\n maxBurnAmount != 0,\n \">LP.balanceOf\"\n );\n\n uint256 feePerToken = _feePerToken(self.swapFee, pooledTokens.length);\n uint256[] memory fees = new uint256[](pooledTokens.length);\n {\n uint256[] memory balances1 = new uint256[](pooledTokens.length);\n v.d0 = getD(_xp(v.balances, v.multipliers), v.preciseA);\n for (uint256 i = 0; i < pooledTokens.length; i++) {\n balances1[i] = v.balances[i].sub(\n amounts[i],\n \"Cannot withdraw more than available\"\n );\n }\n v.d1 = getD(_xp(balances1, v.multipliers), v.preciseA);\n\n for (uint256 i = 0; i < pooledTokens.length; i++) {\n uint256 idealBalance = v.d1.mul(v.balances[i]).div(v.d0);\n uint256 difference = idealBalance.difference(balances1[i]);\n fees[i] = feePerToken.mul(difference).div(FEE_DENOMINATOR);\n self.balances[i] = balances1[i].sub(\n fees[i].mul(self.adminFee).div(FEE_DENOMINATOR)\n );\n balances1[i] = balances1[i].sub(fees[i]);\n }\n\n v.d2 = getD(_xp(balances1, v.multipliers), v.preciseA);\n }\n uint256 tokenAmount = v.d0.sub(v.d2).mul(v.totalSupply).div(v.d0);\n require(tokenAmount != 0, \"Burnt amount cannot be zero\");\n tokenAmount = tokenAmount.add(1);\n\n require(tokenAmount <= maxBurnAmount, \"tokenAmount > maxBurnAmount\");\n\n v.lpToken.burnFrom(msg.sender, tokenAmount);\n\n for (uint256 i = 0; i < pooledTokens.length; i++) {\n pooledTokens[i].safeTransfer(msg.sender, amounts[i]);\n }\n\n emit RemoveLiquidityImbalance(\n msg.sender,\n amounts,\n fees,\n v.d1,\n v.totalSupply.sub(tokenAmount)\n );\n\n return tokenAmount;\n }\n\n /**\n * @notice withdraw all admin fees to a given address\n * @param self Swap struct to withdraw fees from\n * @param to Address to send the fees to\n */\n function withdrawAdminFees(Swap storage self, address to) external {\n IERC20[] memory pooledTokens = self.pooledTokens;\n for (uint256 i = 0; i < pooledTokens.length; i++) {\n IERC20 token = pooledTokens[i];\n uint256 balance = token.balanceOf(address(this)).sub(\n self.balances[i]\n );\n if (balance != 0) {\n token.safeTransfer(to, balance);\n }\n }\n }\n\n /**\n * @notice Sets the admin fee\n * @dev adminFee cannot be higher than 100% of the swap fee\n * @param self Swap struct to update\n * @param newAdminFee new admin fee to be applied on future transactions\n */\n function setAdminFee(Swap storage self, uint256 newAdminFee) external {\n require(newAdminFee <= MAX_ADMIN_FEE, \"Fee is too high\");\n self.adminFee = newAdminFee;\n\n emit NewAdminFee(newAdminFee);\n }\n\n /**\n * @notice update the swap fee\n * @dev fee cannot be higher than 1% of each swap\n * @param self Swap struct to update\n * @param newSwapFee new swap fee to be applied on future transactions\n */\n function setSwapFee(Swap storage self, uint256 newSwapFee) external {\n require(newSwapFee <= MAX_SWAP_FEE, \"Fee is too high\");\n self.swapFee = newSwapFee;\n\n emit NewSwapFee(newSwapFee);\n }\n}\n" + }, + "contracts/amm/AmplificationUtils.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.6.12;\n\nimport \"@openzeppelin/contracts/token/ERC20/SafeERC20.sol\";\nimport \"./SwapUtils.sol\";\n\n/**\n * @title AmplificationUtils library\n * @notice A library to calculate and ramp the A parameter of a given `SwapUtils.Swap` struct.\n * This library assumes the struct is fully validated.\n */\nlibrary AmplificationUtils {\n using SafeMath for uint256;\n\n event RampA(\n uint256 oldA,\n uint256 newA,\n uint256 initialTime,\n uint256 futureTime\n );\n event StopRampA(uint256 currentA, uint256 time);\n\n // Constant values used in ramping A calculations\n uint256 public constant A_PRECISION = 100;\n uint256 public constant MAX_A = 10**6;\n uint256 private constant MAX_A_CHANGE = 2;\n uint256 private constant MIN_RAMP_TIME = 7 days;\n\n /**\n * @notice Return A, the amplification coefficient * n * (n - 1)\n * @dev See the StableSwap paper for details\n * @param self Swap struct to read from\n * @return A parameter\n */\n function getA(SwapUtils.Swap storage self) external view returns (uint256) {\n return _getAPrecise(self).div(A_PRECISION);\n }\n\n /**\n * @notice Return A in its raw precision\n * @dev See the StableSwap paper for details\n * @param self Swap struct to read from\n * @return A parameter in its raw precision form\n */\n function getAPrecise(SwapUtils.Swap storage self)\n external\n view\n returns (uint256)\n {\n return _getAPrecise(self);\n }\n\n /**\n * @notice Return A in its raw precision\n * @dev See the StableSwap paper for details\n * @param self Swap struct to read from\n * @return A parameter in its raw precision form\n */\n function _getAPrecise(SwapUtils.Swap storage self)\n internal\n view\n returns (uint256)\n {\n uint256 t1 = self.futureATime; // time when ramp is finished\n uint256 a1 = self.futureA; // final A value when ramp is finished\n\n if (block.timestamp < t1) {\n uint256 t0 = self.initialATime; // time when ramp is started\n uint256 a0 = self.initialA; // initial A value when ramp is started\n if (a1 > a0) {\n // a0 + (a1 - a0) * (block.timestamp - t0) / (t1 - t0)\n return\n a0.add(\n a1.sub(a0).mul(block.timestamp.sub(t0)).div(t1.sub(t0))\n );\n } else {\n // a0 - (a0 - a1) * (block.timestamp - t0) / (t1 - t0)\n return\n a0.sub(\n a0.sub(a1).mul(block.timestamp.sub(t0)).div(t1.sub(t0))\n );\n }\n } else {\n return a1;\n }\n }\n\n /**\n * @notice Start ramping up or down A parameter towards given futureA_ and futureTime_\n * Checks if the change is too rapid, and commits the new A value only when it falls under\n * the limit range.\n * @param self Swap struct to update\n * @param futureA_ the new A to ramp towards\n * @param futureTime_ timestamp when the new A should be reached\n */\n function rampA(\n SwapUtils.Swap storage self,\n uint256 futureA_,\n uint256 futureTime_\n ) external {\n require(\n block.timestamp >= self.initialATime.add(1 days),\n \"Wait 1 day before starting ramp\"\n );\n require(\n futureTime_ >= block.timestamp.add(MIN_RAMP_TIME),\n \"Insufficient ramp time\"\n );\n require(\n futureA_ > 0 && futureA_ < MAX_A,\n \"futureA_ must be > 0 and < MAX_A\"\n );\n\n uint256 initialAPrecise = _getAPrecise(self);\n uint256 futureAPrecise = futureA_.mul(A_PRECISION);\n\n if (futureAPrecise < initialAPrecise) {\n require(\n futureAPrecise.mul(MAX_A_CHANGE) >= initialAPrecise,\n \"futureA_ is too small\"\n );\n } else {\n require(\n futureAPrecise <= initialAPrecise.mul(MAX_A_CHANGE),\n \"futureA_ is too large\"\n );\n }\n\n self.initialA = initialAPrecise;\n self.futureA = futureAPrecise;\n self.initialATime = block.timestamp;\n self.futureATime = futureTime_;\n\n emit RampA(\n initialAPrecise,\n futureAPrecise,\n block.timestamp,\n futureTime_\n );\n }\n\n /**\n * @notice Stops ramping A immediately. Once this function is called, rampA()\n * cannot be called for another 24 hours\n * @param self Swap struct to update\n */\n function stopRampA(SwapUtils.Swap storage self) external {\n require(self.futureATime > block.timestamp, \"Ramp is already stopped\");\n\n uint256 currentA = _getAPrecise(self);\n self.initialA = currentA;\n self.futureA = currentA;\n self.initialATime = block.timestamp;\n self.futureATime = block.timestamp;\n\n emit StopRampA(currentA, block.timestamp);\n }\n}\n" + }, + "@openzeppelin/contracts/token/ERC20/IERC20.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <0.8.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" + }, + "@openzeppelin/contracts/utils/Address.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.2 <0.8.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" + }, + "@openzeppelin/contracts-upgradeable/proxy/Initializable.sol": { + "content": "// SPDX-License-Identifier: MIT\n\n// solhint-disable-next-line compiler-version\npragma solidity >=0.4.24 <0.8.0;\n\nimport \"../utils/AddressUpgradeable.sol\";\n\n/**\n * @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed\n * behind a proxy. Since a proxied contract can't have a constructor, it's common to move constructor logic to an\n * external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer\n * function so it can only be called once. The {initializer} modifier provided by this contract will have this effect.\n *\n * TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as\n * possible by providing the encoded function call as the `_data` argument to {UpgradeableProxy-constructor}.\n *\n * CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure\n * that all initializers are idempotent. This is not verified automatically as constructors are by Solidity.\n */\nabstract contract Initializable {\n\n /**\n * @dev Indicates that the contract has been initialized.\n */\n bool private _initialized;\n\n /**\n * @dev Indicates that the contract is in the process of being initialized.\n */\n bool private _initializing;\n\n /**\n * @dev Modifier to protect an initializer function from being invoked twice.\n */\n modifier initializer() {\n require(_initializing || _isConstructor() || !_initialized, \"Initializable: contract is already initialized\");\n\n bool isTopLevelCall = !_initializing;\n if (isTopLevelCall) {\n _initializing = true;\n _initialized = true;\n }\n\n _;\n\n if (isTopLevelCall) {\n _initializing = false;\n }\n }\n\n /// @dev Returns true if and only if the function is running in the constructor\n function _isConstructor() private view returns (bool) {\n return !AddressUpgradeable.isContract(address(this));\n }\n}\n" + }, + "@openzeppelin/contracts-upgradeable/utils/AddressUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.2 <0.8.0;\n\n/**\n * @dev Collection of functions related to the address type\n */\nlibrary AddressUpgradeable {\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 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" + }, + "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <0.8.0;\n\nimport \"../utils/ContextUpgradeable.sol\";\nimport \"../proxy/Initializable.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 OwnableUpgradeable is Initializable, ContextUpgradeable {\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 function __Ownable_init() internal initializer {\n __Context_init_unchained();\n __Ownable_init_unchained();\n }\n\n function __Ownable_init_unchained() internal initializer {\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 uint256[49] private __gap;\n}\n" + }, + "@openzeppelin/contracts-upgradeable/utils/PausableUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <0.8.0;\n\nimport \"./ContextUpgradeable.sol\";\nimport \"../proxy/Initializable.sol\";\n\n/**\n * @dev Contract module which allows children to implement an emergency stop\n * mechanism that can be triggered by an authorized account.\n *\n * This module is used through inheritance. It will make available the\n * modifiers `whenNotPaused` and `whenPaused`, which can be applied to\n * the functions of your contract. Note that they will not be pausable by\n * simply including this module, only once the modifiers are put in place.\n */\nabstract contract PausableUpgradeable is Initializable, ContextUpgradeable {\n /**\n * @dev Emitted when the pause is triggered by `account`.\n */\n event Paused(address account);\n\n /**\n * @dev Emitted when the pause is lifted by `account`.\n */\n event Unpaused(address account);\n\n bool private _paused;\n\n /**\n * @dev Initializes the contract in unpaused state.\n */\n function __Pausable_init() internal initializer {\n __Context_init_unchained();\n __Pausable_init_unchained();\n }\n\n function __Pausable_init_unchained() internal initializer {\n _paused = false;\n }\n\n /**\n * @dev Returns true if the contract is paused, and false otherwise.\n */\n function paused() public view virtual returns (bool) {\n return _paused;\n }\n\n /**\n * @dev Modifier to make a function callable only when the contract is not paused.\n *\n * Requirements:\n *\n * - The contract must not be paused.\n */\n modifier whenNotPaused() {\n require(!paused(), \"Pausable: paused\");\n _;\n }\n\n /**\n * @dev Modifier to make a function callable only when the contract is paused.\n *\n * Requirements:\n *\n * - The contract must be paused.\n */\n modifier whenPaused() {\n require(paused(), \"Pausable: not paused\");\n _;\n }\n\n /**\n * @dev Triggers stopped state.\n *\n * Requirements:\n *\n * - The contract must not be paused.\n */\n function _pause() internal virtual whenNotPaused {\n _paused = true;\n emit Paused(_msgSender());\n }\n\n /**\n * @dev Returns to normal state.\n *\n * Requirements:\n *\n * - The contract must be paused.\n */\n function _unpause() internal virtual whenPaused {\n _paused = false;\n emit Unpaused(_msgSender());\n }\n uint256[49] private __gap;\n}\n" + }, + "@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <0.8.0;\nimport \"../proxy/Initializable.sol\";\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 ContextUpgradeable is Initializable {\n function __Context_init() internal initializer {\n __Context_init_unchained();\n }\n\n function __Context_init_unchained() internal initializer {\n }\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 uint256[50] private __gap;\n}\n" + }, + "contracts/amm/LPToken.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.6.12;\n\nimport \"@openzeppelin/contracts-upgradeable/token/ERC20/ERC20BurnableUpgradeable.sol\";\nimport \"@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol\";\nimport \"./interfaces/ISwap.sol\";\n\n/**\n * @title Liquidity Provider Token\n * @notice This token is an ERC20 detailed token with added capability to be minted by the owner.\n * It is used to represent user's shares when providing liquidity to swap contracts.\n * @dev Only Swap contracts should initialize and own LPToken contracts.\n */\ncontract LPToken is ERC20BurnableUpgradeable, OwnableUpgradeable {\n using SafeMathUpgradeable for uint256;\n\n /**\n * @notice Initializes this LPToken contract with the given name and symbol\n * @dev The caller of this function will become the owner. A Swap contract should call this\n * in its initializer function.\n * @param name name of this token\n * @param symbol symbol of this token\n */\n function initialize(string memory name, string memory symbol)\n external\n initializer\n returns (bool)\n {\n __Context_init_unchained();\n __ERC20_init_unchained(name, symbol);\n __Ownable_init_unchained();\n return true;\n }\n\n /**\n * @notice Mints the given amount of LPToken to the recipient.\n * @dev only owner can call this mint function\n * @param recipient address of account to receive the tokens\n * @param amount amount of tokens to mint\n */\n function mint(address recipient, uint256 amount) external onlyOwner {\n require(amount != 0, \"LPToken: cannot mint 0\");\n _mint(recipient, amount);\n }\n\n /**\n * @dev Overrides ERC20._beforeTokenTransfer() which get called on every transfers including\n * minting and burning. * This assumes the owner is set to a Swap contract's address.\n */\n function _beforeTokenTransfer(\n address from,\n address to,\n uint256 amount\n ) internal virtual override(ERC20Upgradeable) {\n super._beforeTokenTransfer(from, to, amount);\n require(to != address(this), \"LPToken: cannot send to itself\");\n }\n}\n" + }, + "contracts/amm/MathUtils.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.6.12;\n\nimport \"@openzeppelin/contracts/math/SafeMath.sol\";\n\n/**\n * @title MathUtils library\n * @notice A library to be used in conjunction with SafeMath. Contains functions for calculating\n * differences between two uint256.\n */\nlibrary MathUtils {\n /**\n * @notice Compares a and b and returns true if the difference between a and b\n * is less than 1 or equal to each other.\n * @param a uint256 to compare with\n * @param b uint256 to compare with\n * @return True if the difference between a and b is less than 1 or equal,\n * otherwise return false\n */\n function within1(uint256 a, uint256 b) internal pure returns (bool) {\n return (difference(a, b) <= 1);\n }\n\n /**\n * @notice Calculates absolute difference between a and b\n * @param a uint256 to compare with\n * @param b uint256 to compare with\n * @return Difference between a and b\n */\n function difference(uint256 a, uint256 b) internal pure returns (uint256) {\n if (a > b) {\n return a - b;\n }\n return b - a;\n }\n}\n" + }, + "@openzeppelin/contracts-upgradeable/token/ERC20/ERC20BurnableUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <0.8.0;\n\nimport \"../../utils/ContextUpgradeable.sol\";\nimport \"./ERC20Upgradeable.sol\";\nimport \"../../proxy/Initializable.sol\";\n\n/**\n * @dev Extension of {ERC20} that allows token holders to destroy both their own\n * tokens and those that they have an allowance for, in a way that can be\n * recognized off-chain (via event analysis).\n */\nabstract contract ERC20BurnableUpgradeable is Initializable, ContextUpgradeable, ERC20Upgradeable {\n function __ERC20Burnable_init() internal initializer {\n __Context_init_unchained();\n __ERC20Burnable_init_unchained();\n }\n\n function __ERC20Burnable_init_unchained() internal initializer {\n }\n using SafeMathUpgradeable for uint256;\n\n /**\n * @dev Destroys `amount` tokens from the caller.\n *\n * See {ERC20-_burn}.\n */\n function burn(uint256 amount) public virtual {\n _burn(_msgSender(), amount);\n }\n\n /**\n * @dev Destroys `amount` tokens from `account`, deducting from the caller's\n * allowance.\n *\n * See {ERC20-_burn} and {ERC20-allowance}.\n *\n * Requirements:\n *\n * - the caller must have allowance for ``accounts``'s tokens of at least\n * `amount`.\n */\n function burnFrom(address account, uint256 amount) public virtual {\n uint256 decreasedAllowance = allowance(account, _msgSender()).sub(amount, \"ERC20: burn amount exceeds allowance\");\n\n _approve(account, _msgSender(), decreasedAllowance);\n _burn(account, amount);\n }\n uint256[50] private __gap;\n}\n" + }, + "contracts/amm/interfaces/ISwap.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.6.12;\n\nimport \"@openzeppelin/contracts/token/ERC20/ERC20.sol\";\n\ninterface ISwap {\n // pool data view functions\n function getA() external view returns (uint256);\n\n function getToken(uint8 index) external view returns (IERC20);\n\n function getTokenIndex(address tokenAddress) external view returns (uint8);\n\n function getTokenBalance(uint8 index) external view returns (uint256);\n\n function getVirtualPrice() external view returns (uint256);\n\n // min return calculation functions\n function calculateSwap(\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx\n ) external view returns (uint256);\n\n function calculateTokenAmount(uint256[] calldata amounts, bool deposit)\n external\n view\n returns (uint256);\n\n function calculateRemoveLiquidity(uint256 amount)\n external\n view\n returns (uint256[] memory);\n\n function calculateRemoveLiquidityOneToken(\n uint256 tokenAmount,\n uint8 tokenIndex\n ) external view returns (uint256 availableTokenAmount);\n\n // state modifying functions\n function initialize(\n IERC20[] memory pooledTokens,\n uint8[] memory decimals,\n string memory lpTokenName,\n string memory lpTokenSymbol,\n uint256 a,\n uint256 fee,\n uint256 adminFee,\n address lpTokenTargetAddress\n ) external;\n\n function swap(\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx,\n uint256 minDy,\n uint256 deadline\n ) external returns (uint256);\n\n function addLiquidity(\n uint256[] calldata amounts,\n uint256 minToMint,\n uint256 deadline\n ) external returns (uint256);\n\n function removeLiquidity(\n uint256 amount,\n uint256[] calldata minAmounts,\n uint256 deadline\n ) external returns (uint256[] memory);\n\n function removeLiquidityOneToken(\n uint256 tokenAmount,\n uint8 tokenIndex,\n uint256 minAmount,\n uint256 deadline\n ) external returns (uint256);\n\n function removeLiquidityImbalance(\n uint256[] calldata amounts,\n uint256 maxBurnAmount,\n uint256 deadline\n ) external returns (uint256);\n}\n" + }, + "@openzeppelin/contracts-upgradeable/token/ERC20/ERC20Upgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <0.8.0;\n\nimport \"../../utils/ContextUpgradeable.sol\";\nimport \"./IERC20Upgradeable.sol\";\nimport \"../../math/SafeMathUpgradeable.sol\";\nimport \"../../proxy/Initializable.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 ERC20Upgradeable is Initializable, ContextUpgradeable, IERC20Upgradeable {\n using SafeMathUpgradeable 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 function __ERC20_init(string memory name_, string memory symbol_) internal initializer {\n __Context_init_unchained();\n __ERC20_init_unchained(name_, symbol_);\n }\n\n function __ERC20_init_unchained(string memory name_, string memory symbol_) internal initializer {\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 uint256[44] private __gap;\n}\n" + }, + "@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <0.8.0;\n\n/**\n * @dev Interface of the ERC20 standard as defined in the EIP.\n */\ninterface IERC20Upgradeable {\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" + }, + "@openzeppelin/contracts-upgradeable/math/SafeMathUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <0.8.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 SafeMathUpgradeable {\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" + }, + "@openzeppelin/contracts/token/ERC20/ERC20.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <0.8.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_) public {\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" + }, + "@openzeppelin/contracts/utils/Context.sol": { + "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" + }, + "contracts/amm/SwapFlashLoan.sol": { + "content": "// SPDX-License-Identifier: MIT WITH AGPL-3.0-only\n\npragma solidity 0.6.12;\n\nimport \"./Swap.sol\";\nimport \"./interfaces/IFlashLoanReceiver.sol\";\n\n/**\n * @title Swap - A StableSwap implementation in solidity.\n * @notice This contract is responsible for custody of closely pegged assets (eg. group of stablecoins)\n * and automatic market making system. Users become an LP (Liquidity Provider) by depositing their tokens\n * in desired ratios for an exchange of the pool token that represents their share of the pool.\n * Users can burn pool tokens and withdraw their share of token(s).\n *\n * Each time a swap between the pooled tokens happens, a set fee incurs which effectively gets\n * distributed to the LPs.\n *\n * In case of emergencies, admin can pause additional deposits, swaps, or single-asset withdraws - which\n * stops the ratio of the tokens in the pool from changing.\n * Users can always withdraw their tokens via multi-asset withdraws.\n *\n * @dev Most of the logic is stored as a library `SwapUtils` for the sake of reducing contract's\n * deployment size.\n */\ncontract SwapFlashLoan is Swap {\n // Total fee that is charged on all flashloans in BPS. Borrowers must repay the amount plus the flash loan fee.\n // This fee is split between the protocol and the pool.\n uint256 public flashLoanFeeBPS;\n // Share of the flash loan fee that goes to the protocol in BPS. A portion of each flash loan fee is allocated\n // to the protocol rather than the pool.\n uint256 public protocolFeeShareBPS;\n // Max BPS for limiting flash loan fee settings.\n uint256 public constant MAX_BPS = 10000;\n\n /*** EVENTS ***/\n event FlashLoan(\n address indexed receiver,\n uint8 tokenIndex,\n uint256 amount,\n uint256 amountFee,\n uint256 protocolFee\n );\n\n /**\n * @notice Initializes this Swap contract with the given parameters.\n * This will also clone a LPToken contract that represents users'\n * LP positions. The owner of LPToken will be this contract - which means\n * only this contract is allowed to mint/burn tokens.\n *\n * @param _pooledTokens an array of ERC20s this pool will accept\n * @param decimals the decimals to use for each pooled token,\n * eg 8 for WBTC. Cannot be larger than POOL_PRECISION_DECIMALS\n * @param lpTokenName the long-form name of the token to be deployed\n * @param lpTokenSymbol the short symbol for the token to be deployed\n * @param _a the amplification coefficient * n * (n - 1). See the\n * StableSwap paper for details\n * @param _fee default swap fee to be initialized with\n * @param _adminFee default adminFee to be initialized with\n * @param lpTokenTargetAddress the address of an existing LPToken contract to use as a target\n */\n function initialize(\n IERC20[] memory _pooledTokens,\n uint8[] memory decimals,\n string memory lpTokenName,\n string memory lpTokenSymbol,\n uint256 _a,\n uint256 _fee,\n uint256 _adminFee,\n address lpTokenTargetAddress\n ) public virtual override initializer {\n Swap.initialize(\n _pooledTokens,\n decimals,\n lpTokenName,\n lpTokenSymbol,\n _a,\n _fee,\n _adminFee,\n lpTokenTargetAddress\n );\n flashLoanFeeBPS = 8; // 8 bps\n protocolFeeShareBPS = 0; // 0 bps\n }\n\n /*** STATE MODIFYING FUNCTIONS ***/\n\n /**\n * @notice Borrow the specified token from this pool for this transaction only. This function will call\n * `IFlashLoanReceiver(receiver).executeOperation` and the `receiver` must return the full amount of the token\n * and the associated fee by the end of the callback transaction. If the conditions are not met, this call\n * is reverted.\n * @param receiver the address of the receiver of the token. This address must implement the IFlashLoanReceiver\n * interface and the callback function `executeOperation`.\n * @param token the protocol fee in bps to be applied on the total flash loan fee\n * @param amount the total amount to borrow in this transaction\n * @param params optional data to pass along to the callback function\n */\n function flashLoan(\n address receiver,\n IERC20 token,\n uint256 amount,\n bytes memory params\n ) external nonReentrant {\n uint8 tokenIndex = getTokenIndex(address(token));\n uint256 availableLiquidityBefore = token.balanceOf(address(this));\n uint256 protocolBalanceBefore = availableLiquidityBefore.sub(\n swapStorage.balances[tokenIndex]\n );\n require(\n amount > 0 && availableLiquidityBefore >= amount,\n \"invalid amount\"\n );\n\n // Calculate the additional amount of tokens the pool should end up with\n uint256 amountFee = amount.mul(flashLoanFeeBPS).div(10000);\n // Calculate the portion of the fee that will go to the protocol\n uint256 protocolFee = amountFee.mul(protocolFeeShareBPS).div(10000);\n require(amountFee > 0, \"amount is small for a flashLoan\");\n\n // Transfer the requested amount of tokens\n token.safeTransfer(receiver, amount);\n\n // Execute callback function on receiver\n IFlashLoanReceiver(receiver).executeOperation(\n address(this),\n address(token),\n amount,\n amountFee,\n params\n );\n\n uint256 availableLiquidityAfter = token.balanceOf(address(this));\n require(\n availableLiquidityAfter >= availableLiquidityBefore.add(amountFee),\n \"flashLoan fee is not met\"\n );\n\n swapStorage.balances[tokenIndex] = availableLiquidityAfter\n .sub(protocolBalanceBefore)\n .sub(protocolFee);\n emit FlashLoan(receiver, tokenIndex, amount, amountFee, protocolFee);\n }\n\n /*** ADMIN FUNCTIONS ***/\n\n /**\n * @notice Updates the flash loan fee parameters. This function can only be called by the owner.\n * @param newFlashLoanFeeBPS the total fee in bps to be applied on future flash loans\n * @param newProtocolFeeShareBPS the protocol fee in bps to be applied on the total flash loan fee\n */\n function setFlashLoanFees(\n uint256 newFlashLoanFeeBPS,\n uint256 newProtocolFeeShareBPS\n ) external onlyOwner {\n require(\n newFlashLoanFeeBPS > 0 &&\n newFlashLoanFeeBPS <= MAX_BPS &&\n newProtocolFeeShareBPS <= MAX_BPS,\n \"fees are not in valid range\"\n );\n flashLoanFeeBPS = newFlashLoanFeeBPS;\n protocolFeeShareBPS = newProtocolFeeShareBPS;\n }\n}\n" + }, + "contracts/amm/interfaces/IFlashLoanReceiver.sol": { + "content": "// SPDX-License-Identifier: AGPL-3.0-only\n\npragma solidity 0.6.12;\n\n/**\n * @title IFlashLoanReceiver interface\n * @notice Interface for the Nerve fee IFlashLoanReceiver. Modified from Aave's IFlashLoanReceiver interface.\n * https://github.com/aave/aave-protocol/blob/4b4545fb583fd4f400507b10f3c3114f45b8a037/contracts/flashloan/interfaces/IFlashLoanReceiver.sol\n * @author Aave\n * @dev implement this interface to develop a flashloan-compatible flashLoanReceiver contract\n **/\ninterface IFlashLoanReceiver {\n function executeOperation(\n address pool,\n address token,\n uint256 amount,\n uint256 fee,\n bytes calldata params\n ) external;\n}\n" + }, + "contracts/amm/helper/FlashLoanBorrowerExample.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.6.12;\n\nimport \"@openzeppelin/contracts/math/SafeMath.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/SafeERC20.sol\";\nimport \"../interfaces/IFlashLoanReceiver.sol\";\nimport \"../interfaces/ISwapFlashLoan.sol\";\nimport \"hardhat/console.sol\";\n\ncontract FlashLoanBorrowerExample is IFlashLoanReceiver {\n using SafeMath for uint256;\n\n // Typical executeOperation function should do the 3 following actions\n // 1. Check if the flashLoan was successful\n // 2. Do actions with the borrowed tokens\n // 3. Repay the debt to the `pool`\n function executeOperation(\n address pool,\n address token,\n uint256 amount,\n uint256 fee,\n bytes calldata params\n ) external override {\n // 1. Check if the flashLoan was valid\n require(\n IERC20(token).balanceOf(address(this)) >= amount,\n \"flashloan is broken?\"\n );\n\n // 2. Do actions with the borrowed token\n bytes32 paramsHash = keccak256(params);\n if (paramsHash == keccak256(bytes(\"dontRepayDebt\"))) {\n return;\n } else if (paramsHash == keccak256(bytes(\"reentrancy_addLiquidity\"))) {\n ISwapFlashLoan(pool).addLiquidity(\n new uint256[](0),\n 0,\n block.timestamp\n );\n } else if (paramsHash == keccak256(bytes(\"reentrancy_swap\"))) {\n ISwapFlashLoan(pool).swap(1, 0, 1e6, 0, now);\n } else if (\n paramsHash == keccak256(bytes(\"reentrancy_removeLiquidity\"))\n ) {\n ISwapFlashLoan(pool).removeLiquidity(1e18, new uint256[](0), now);\n } else if (\n paramsHash == keccak256(bytes(\"reentrancy_removeLiquidityOneToken\"))\n ) {\n ISwapFlashLoan(pool).removeLiquidityOneToken(1e18, 0, 1e18, now);\n }\n\n // 3. Payback debt\n uint256 totalDebt = amount.add(fee);\n IERC20(token).transfer(pool, totalDebt);\n }\n\n function flashLoan(\n ISwapFlashLoan swap,\n IERC20 token,\n uint256 amount,\n bytes memory params\n ) external {\n swap.flashLoan(address(this), token, amount, params);\n }\n}\n" + }, + "contracts/amm/interfaces/ISwapFlashLoan.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.6.12;\n\nimport \"./ISwap.sol\";\n\ninterface ISwapFlashLoan is ISwap {\n function flashLoan(\n address receiver,\n IERC20 token,\n uint256 amount,\n bytes memory params\n ) external;\n}\n" + }, + "hardhat/console.sol": { + "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" + }, + "contracts/amm/helper/test/TestSwapReturnValues.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.6.12;\n\nimport \"../../interfaces/ISwap.sol\";\nimport \"hardhat/console.sol\";\n\ncontract TestSwapReturnValues {\n using SafeMath for uint256;\n\n ISwap public swap;\n IERC20 public lpToken;\n uint8 public n;\n\n uint256 public constant MAX_INT = 2**256 - 1;\n\n constructor(\n ISwap swapContract,\n IERC20 lpTokenContract,\n uint8 numOfTokens\n ) public {\n swap = swapContract;\n lpToken = lpTokenContract;\n n = numOfTokens;\n\n // Pre-approve tokens\n for (uint8 i; i < n; i++) {\n swap.getToken(i).approve(address(swap), MAX_INT);\n }\n lpToken.approve(address(swap), MAX_INT);\n }\n\n function test_swap(\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx,\n uint256 minDy\n ) public {\n uint256 balanceBefore =\n swap.getToken(tokenIndexTo).balanceOf(address(this));\n uint256 returnValue =\n swap.swap(tokenIndexFrom, tokenIndexTo, dx, minDy, block.timestamp);\n uint256 balanceAfter =\n swap.getToken(tokenIndexTo).balanceOf(address(this));\n\n console.log(\n \"swap: Expected %s, got %s\",\n balanceAfter.sub(balanceBefore),\n returnValue\n );\n\n require(\n returnValue == balanceAfter.sub(balanceBefore),\n \"swap()'s return value does not match received amount\"\n );\n }\n\n function test_addLiquidity(uint256[] calldata amounts, uint256 minToMint)\n public\n {\n uint256 balanceBefore = lpToken.balanceOf(address(this));\n uint256 returnValue = swap.addLiquidity(amounts, minToMint, MAX_INT);\n uint256 balanceAfter = lpToken.balanceOf(address(this));\n\n console.log(\n \"addLiquidity: Expected %s, got %s\",\n balanceAfter.sub(balanceBefore),\n returnValue\n );\n\n require(\n returnValue == balanceAfter.sub(balanceBefore),\n \"addLiquidity()'s return value does not match minted amount\"\n );\n }\n\n function test_removeLiquidity(uint256 amount, uint256[] memory minAmounts)\n public\n {\n uint256[] memory balanceBefore = new uint256[](n);\n uint256[] memory balanceAfter = new uint256[](n);\n\n for (uint8 i = 0; i < n; i++) {\n balanceBefore[i] = swap.getToken(i).balanceOf(address(this));\n }\n\n uint256[] memory returnValue =\n swap.removeLiquidity(amount, minAmounts, MAX_INT);\n\n for (uint8 i = 0; i < n; i++) {\n balanceAfter[i] = swap.getToken(i).balanceOf(address(this));\n console.log(\n \"removeLiquidity: Expected %s, got %s\",\n balanceAfter[i].sub(balanceBefore[i]),\n returnValue[i]\n );\n require(\n balanceAfter[i].sub(balanceBefore[i]) == returnValue[i],\n \"removeLiquidity()'s return value does not match received amounts of tokens\"\n );\n }\n }\n\n function test_removeLiquidityImbalance(\n uint256[] calldata amounts,\n uint256 maxBurnAmount\n ) public {\n uint256 balanceBefore = lpToken.balanceOf(address(this));\n uint256 returnValue =\n swap.removeLiquidityImbalance(amounts, maxBurnAmount, MAX_INT);\n uint256 balanceAfter = lpToken.balanceOf(address(this));\n\n console.log(\n \"removeLiquidityImbalance: Expected %s, got %s\",\n balanceBefore.sub(balanceAfter),\n returnValue\n );\n\n require(\n returnValue == balanceBefore.sub(balanceAfter),\n \"removeLiquidityImbalance()'s return value does not match burned lpToken amount\"\n );\n }\n\n function test_removeLiquidityOneToken(\n uint256 tokenAmount,\n uint8 tokenIndex,\n uint256 minAmount\n ) public {\n uint256 balanceBefore =\n swap.getToken(tokenIndex).balanceOf(address(this));\n uint256 returnValue =\n swap.removeLiquidityOneToken(\n tokenAmount,\n tokenIndex,\n minAmount,\n MAX_INT\n );\n uint256 balanceAfter =\n swap.getToken(tokenIndex).balanceOf(address(this));\n\n console.log(\n \"removeLiquidityOneToken: Expected %s, got %s\",\n balanceAfter.sub(balanceBefore),\n returnValue\n );\n\n require(\n returnValue == balanceAfter.sub(balanceBefore),\n \"removeLiquidityOneToken()'s return value does not match received token amount\"\n );\n }\n}\n" + }, + "contracts/amm/SwapDeployer.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.6.12;\n\nimport \"@openzeppelin/contracts/access/Ownable.sol\";\nimport \"@openzeppelin/contracts/proxy/Clones.sol\";\nimport \"./interfaces/ISwap.sol\";\n\ncontract SwapDeployer is Ownable {\n event NewSwapPool(\n address indexed deployer,\n address swapAddress,\n IERC20[] pooledTokens\n );\n\n constructor() public Ownable() {}\n\n function deploy(\n address swapAddress,\n IERC20[] memory _pooledTokens,\n uint8[] memory decimals,\n string memory lpTokenName,\n string memory lpTokenSymbol,\n uint256 _a,\n uint256 _fee,\n uint256 _adminFee,\n address lpTokenTargetAddress\n ) external returns (address) {\n address swapClone = Clones.clone(swapAddress);\n ISwap(swapClone).initialize(\n _pooledTokens,\n decimals,\n lpTokenName,\n lpTokenSymbol,\n _a,\n _fee,\n _adminFee,\n lpTokenTargetAddress\n );\n Ownable(swapClone).transferOwnership(owner());\n emit NewSwapPool(msg.sender, swapClone, _pooledTokens);\n return swapClone;\n }\n}\n" + }, + "@openzeppelin/contracts/access/Ownable.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <0.8.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 () internal {\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" + }, + "contracts/bridge/SynapseERC20Factory.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.6.12;\n\nimport \"@openzeppelin/contracts/access/Ownable.sol\";\nimport \"@openzeppelin/contracts/proxy/Clones.sol\";\nimport \"./interfaces/ISynapseERC20.sol\";\n\ncontract SynapseERC20Factory {\n constructor() public {}\n\n event SynapseERC20Created(address contractAddress);\n\n /**\n * @notice Deploys a new node\n * @param synapseERC20Address address of the synapseERC20Address contract to initialize with\n * @param name Token name\n * @param symbol Token symbol\n * @param decimals Token name\n * @param owner admin address to be initialized with\n * @return Address of the newest node management contract created\n **/\n function deploy(\n address synapseERC20Address,\n string memory name,\n string memory symbol,\n uint8 decimals,\n address owner\n ) external returns (address) {\n address synERC20Clone = Clones.clone(synapseERC20Address);\n ISynapseERC20(synERC20Clone).initialize(name, symbol, decimals, owner);\n\n emit SynapseERC20Created(synERC20Clone);\n\n return synERC20Clone;\n }\n}\n" + }, + "contracts/bridge/interfaces/ISynapseERC20.sol": { + "content": "// SPDX-License-Identifier: MIT\n\n\npragma solidity 0.6.12;\n\ninterface ISynapseERC20 { \n function initialize(\n string memory _name, string memory _symbol, uint8 _decimals, address owner) external;\n\n function mint(address to, uint256 amount) external;\n}\n\n" + }, + "contracts/bridge/wrappers/AvaxJewelMigration.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.6.12;\n\nimport '@openzeppelin/contracts/token/ERC20/ERC20.sol';\nimport \"@openzeppelin/contracts/token/ERC20/SafeERC20.sol\";\nimport \"@openzeppelin/contracts/access/Ownable.sol\";\n\nimport '../interfaces/ISynapseBridge.sol';\n\ninterface IERC20Mintable is IERC20 {\n function mint(address to, uint256 amount) external;\n}\n\ncontract AvaxJewelMigration is Ownable {\n using SafeERC20 for IERC20;\n using SafeERC20 for IERC20Mintable;\n\n\n ISynapseBridge constant synapseBridge = ISynapseBridge(0xC05e61d0E7a63D27546389B7aD62FdFf5A91aACE);\n // MULTICHAIN JEWEL \n IERC20 constant legacyToken = IERC20(0x4f60a160D8C2DDdaAfe16FCC57566dB84D674BD6);\n // SYNAPSE JEWEL\n IERC20 constant newToken = IERC20(0x997Ddaa07d716995DE90577C123Db411584E5E46);\n uint256 constant MAX_UINT256 = 2**256 - 1;\n\n constructor() public {\n newToken.safeApprove(address(synapseBridge), MAX_UINT256);\n }\n\n function migrate(uint256 amount) public {\n legacyToken.safeTransferFrom(msg.sender, address(this), amount);\n IERC20Mintable(address(newToken)).mint(msg.sender, amount);\n }\n\n function migrateAndBridge(uint256 amount, address to, uint256 chainId) external {\n migrate(amount);\n synapseBridge.redeem(to, chainId, newToken, amount);\n }\n\n function redeemLegacy() external onlyOwner {\n uint256 legacyBalance = legacyToken.balanceOf(address(this));\n legacyToken.safeTransfer(owner(), legacyBalance);\n }\n} " + }, + "contracts/bridge/interfaces/ISynapseBridge.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.6.12;\n\nimport '@openzeppelin/contracts/token/ERC20/SafeERC20.sol';\nimport '@openzeppelin/contracts/token/ERC20/ERC20Burnable.sol';\n\ninterface ISynapseBridge {\n using SafeERC20 for IERC20;\n\n function deposit(\n address to,\n uint256 chainId,\n IERC20 token,\n uint256 amount\n ) external;\n\n function depositAndSwap(\n address to,\n uint256 chainId,\n IERC20 token,\n uint256 amount,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 minDy,\n uint256 deadline\n ) external;\n\n function redeem(\n address to,\n uint256 chainId,\n IERC20 token,\n uint256 amount\n ) external;\n\n\n function redeemv2(\n bytes32 to,\n uint256 chainId,\n IERC20 token,\n uint256 amount\n ) external;\n\n\n function redeemAndSwap(\n address to,\n uint256 chainId,\n IERC20 token,\n uint256 amount,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 minDy,\n uint256 deadline\n ) external;\n\n function redeemAndRemove(\n address to,\n uint256 chainId,\n IERC20 token,\n uint256 amount,\n uint8 liqTokenIndex,\n uint256 liqMinAmount,\n uint256 liqDeadline\n ) external;\n}\n" + }, + "@openzeppelin/contracts/token/ERC20/ERC20Burnable.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <0.8.0;\n\nimport \"../../utils/Context.sol\";\nimport \"./ERC20.sol\";\n\n/**\n * @dev Extension of {ERC20} that allows token holders to destroy both their own\n * tokens and those that they have an allowance for, in a way that can be\n * recognized off-chain (via event analysis).\n */\nabstract contract ERC20Burnable is Context, ERC20 {\n using SafeMath for uint256;\n\n /**\n * @dev Destroys `amount` tokens from the caller.\n *\n * See {ERC20-_burn}.\n */\n function burn(uint256 amount) public virtual {\n _burn(_msgSender(), amount);\n }\n\n /**\n * @dev Destroys `amount` tokens from `account`, deducting from the caller's\n * allowance.\n *\n * See {ERC20-_burn} and {ERC20-allowance}.\n *\n * Requirements:\n *\n * - the caller must have allowance for ``accounts``'s tokens of at least\n * `amount`.\n */\n function burnFrom(address account, uint256 amount) public virtual {\n uint256 decreasedAllowance = allowance(account, _msgSender()).sub(amount, \"ERC20: burn amount exceeds allowance\");\n\n _approve(account, _msgSender(), decreasedAllowance);\n _burn(account, amount);\n }\n}\n" + }, + "contracts/bridge/wrappers/MoonriverBridgeZap.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.6.12;\n\nimport \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/SafeERC20.sol\";\nimport \"../interfaces/ISwap.sol\";\nimport \"../interfaces/ISynapseBridge.sol\";\nimport \"../interfaces/IWETH9.sol\";\n\ninterface IFrax {\n function exchangeCanonicalForOld(address bridge_token_address, uint256 token_amount) external returns (uint256);\n}\n\ncontract MoonriverBridgeZap {\n using SafeERC20 for IERC20;\n\n ISynapseBridge synapseBridge;\n address payable public immutable WETH_ADDRESS;\n IFrax private constant CANOLICAL_FRAX = IFrax(0x1A93B23281CC1CDE4C4741353F3064709A16197d);\n IERC20 private constant SYN_FRAX = IERC20(0xE96AC70907ffF3Efee79f502C985A7A21Bce407d);\n\n mapping(address => address) public swapMap;\n mapping(address => IERC20[]) public swapTokensMap;\n\n uint256 constant MAX_UINT256 = 2**256 - 1;\n\n constructor(\n address payable _wethAddress,\n address _swapOne,\n address tokenOne,\n address _swapTwo,\n address tokenTwo,\n ISynapseBridge _synapseBridge\n ) public {\n WETH_ADDRESS = _wethAddress;\n synapseBridge = _synapseBridge;\n swapMap[tokenOne] = _swapOne;\n swapMap[tokenTwo] = _swapTwo;\n IERC20(_wethAddress).safeIncreaseAllowance(address(_synapseBridge), MAX_UINT256);\n if (address(_swapOne) != address(0)) {\n {\n uint8 i;\n for (; i < 32; i++) {\n try ISwap(_swapOne).getToken(i) returns (\n IERC20 token\n ) {\n swapTokensMap[_swapOne].push(token);\n token.safeApprove(address(_swapOne), MAX_UINT256);\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n } catch {\n break;\n }\n }\n require(i > 1, \"swap must have at least 2 tokens\");\n }\n }\n if (address(_swapTwo) != address(0)) {\n {\n uint8 i;\n for (; i < 32; i++) {\n try ISwap(_swapTwo).getToken(i) returns (\n IERC20 token\n ) {\n swapTokensMap[_swapTwo].push(token);\n token.safeApprove(address(_swapTwo), MAX_UINT256);\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n } catch {\n break;\n }\n }\n require(i > 1, \"swap must have at least 2 tokens\");\n }\n }\n }\n\n /**\n * @notice Calculate amount of tokens you receive on swap\n * @param tokenIndexFrom the token the user wants to sell\n * @param tokenIndexTo the token the user wants to buy\n * @param dx the amount of tokens the user wants to sell. If the token charges\n * a fee on transfers, use the amount that gets transferred after the fee.\n * @return amount of tokens the user will receive\n */\n function calculateSwap(\n IERC20 token,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx\n ) external view virtual returns (uint256) {\n ISwap swap = ISwap(\n swapMap[address(token)]\n );\n return swap.calculateSwap(tokenIndexFrom, tokenIndexTo, dx);\n }\n\n function swapAndRedeem(\n address to,\n uint256 chainId,\n IERC20 token,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx,\n uint256 minDy,\n uint256 deadline\n ) external {\n ISwap swap = ISwap(swapMap[address(token)]);\n require(address(swap) != address(0), \"Swap is 0x00\");\n IERC20[] memory tokens = swapTokensMap[address(swap)];\n tokens[tokenIndexFrom].safeTransferFrom(\n msg.sender,\n address(this),\n dx\n );\n // swap\n\n uint256 swappedAmount = swap.swap(\n tokenIndexFrom,\n tokenIndexTo,\n dx,\n minDy,\n deadline\n );\n // deposit into bridge, gets nUSD\n if (\n token.allowance(address(this), address(synapseBridge)) <\n swappedAmount\n ) {\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n }\n synapseBridge.redeem(to, chainId, token, swappedAmount);\n }\n\n function swapAndRedeemAndSwap(\n address to,\n uint256 chainId,\n IERC20 token,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx,\n uint256 minDy,\n uint256 deadline,\n uint8 swapTokenIndexFrom,\n uint8 swapTokenIndexTo,\n uint256 swapMinDy,\n uint256 swapDeadline\n ) external {\n require(\n address(swapMap[address(token)]) != address(0),\n \"Swap is 0x00\"\n );\n IERC20[] memory tokens = swapTokensMap[\n swapMap[address(token)]\n ];\n tokens[tokenIndexFrom].safeTransferFrom(\n msg.sender,\n address(this),\n dx\n );\n // swap\n\n uint256 swappedAmount = ISwap(swapMap[address(token)]).swap(tokenIndexFrom, tokenIndexTo, dx, minDy, deadline);\n // deposit into bridge, gets nUSD\n if (\n token.allowance(address(this), address(synapseBridge)) <\n swappedAmount\n ) {\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n }\n synapseBridge.redeemAndSwap(\n to,\n chainId,\n token,\n swappedAmount,\n swapTokenIndexFrom,\n swapTokenIndexTo,\n swapMinDy,\n swapDeadline\n );\n }\n\n function swapAndRedeemAndRemove(\n address to,\n uint256 chainId,\n IERC20 token,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx,\n uint256 minDy,\n uint256 deadline,\n uint8 liqTokenIndex,\n uint256 liqMinAmount,\n uint256 liqDeadline\n ) external {\n ISwap swap = ISwap(swapMap[address(token)]);\n require(address(swap) != address(0), \"Swap is 0x00\");\n IERC20[] memory tokens = swapTokensMap[address(swap)];\n tokens[tokenIndexFrom].safeTransferFrom(\n msg.sender,\n address(this),\n dx\n );\n // swap\n\n uint256 swappedAmount = swap.swap(\n tokenIndexFrom,\n tokenIndexTo,\n dx,\n minDy,\n deadline\n );\n // deposit into bridge, gets nUSD\n if (\n token.allowance(address(this), address(synapseBridge)) <\n swappedAmount\n ) {\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n }\n synapseBridge.redeemAndRemove(\n to,\n chainId,\n token,\n swappedAmount,\n liqTokenIndex,\n liqMinAmount,\n liqDeadline\n );\n }\n\n /**\n * @notice wraps SynapseBridge redeem()\n * @param to address on other chain to redeem underlying assets to\n * @param chainId which underlying chain to bridge assets onto\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n **/\n function redeem(\n address to,\n uint256 chainId,\n IERC20 token,\n uint256 amount\n ) external {\n token.safeTransferFrom(msg.sender, address(this), amount);\n if (address(token) == address(CANOLICAL_FRAX)) {\n uint256 swappedAmount = CANOLICAL_FRAX.exchangeCanonicalForOld(address(SYN_FRAX), amount);\n if (SYN_FRAX.allowance(address(this), address(synapseBridge)) < amount) {\n SYN_FRAX.safeApprove(address(synapseBridge), MAX_UINT256);\n }\n synapseBridge.redeem(to, chainId, SYN_FRAX, swappedAmount);\n } else {\n if (token.allowance(address(this), address(synapseBridge)) < amount) {\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n }\n synapseBridge.redeem(to, chainId, token, amount);\n }\n }\n\n /**\n * @notice Wraps SynapseBridge redeemv2() function\n * @param to address on other chain to bridge assets to\n * @param chainId which chain to bridge assets onto\n * @param token ERC20 compatible token to redeem into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n **/\n function redeemv2(\n bytes32 to,\n uint256 chainId,\n IERC20 token,\n uint256 amount\n ) external {\n token.safeTransferFrom(msg.sender, address(this), amount);\n\n if (token.allowance(address(this), address(synapseBridge)) < amount) {\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n }\n synapseBridge.redeemv2(to, chainId, token, amount);\n }\n\n /**\n * @notice wraps SynapseBridge redeem()\n * @param to address on other chain to redeem underlying assets to\n * @param chainId which underlying chain to bridge assets onto\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n **/\n function deposit(\n address to,\n uint256 chainId,\n IERC20 token,\n uint256 amount\n ) external {\n token.safeTransferFrom(msg.sender, address(this), amount);\n if (token.allowance(address(this), address(synapseBridge)) < amount) {\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n }\n synapseBridge.deposit(to, chainId, token, amount);\n }\n\n /**\n * @notice Wraps SynapseBridge deposit() function to make it compatible w/ ETH -> WETH conversions\n * @param to address on other chain to bridge assets to\n * @param chainId which chain to bridge assets onto\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n **/\n function depositETH(\n address to,\n uint256 chainId,\n uint256 amount\n ) external payable {\n require(msg.value > 0 && msg.value == amount, 'INCORRECT MSG VALUE');\n IWETH9(WETH_ADDRESS).deposit{value: msg.value}();\n synapseBridge.deposit(to, chainId, IERC20(WETH_ADDRESS), amount);\n }\n\n\n\n function swapETHAndRedeem(\n address to,\n uint256 chainId,\n IERC20 token,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx,\n uint256 minDy,\n uint256 deadline\n ) external payable {\n require(WETH_ADDRESS != address(0), \"WETH 0\");\n require(msg.value > 0 && msg.value == dx, \"INCORRECT MSG VALUE\");\n ISwap swap = ISwap(swapMap[address(token)]);\n require(address(swap) != address(0), \"Swap is 0x00\");\n IWETH9(WETH_ADDRESS).deposit{value: msg.value}();\n\n // swap\n uint256 swappedAmount = swap.swap(\n tokenIndexFrom,\n tokenIndexTo,\n dx,\n minDy,\n deadline\n );\n synapseBridge.redeem(to, chainId, token, swappedAmount);\n }\n\n /**\n * @notice Wraps redeemAndSwap on SynapseBridge.sol\n * Relays to nodes that (typically) a wrapped synAsset ERC20 token has been burned and the underlying needs to be redeeemed on the native chain. This function indicates to the nodes that they should attempt to redeem the LP token for the underlying assets (E.g \"swap\" out of the LP token)\n * @param to address on other chain to redeem underlying assets to\n * @param chainId which underlying chain to bridge assets onto\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n * @param tokenIndexFrom the token the user wants to swap from\n * @param tokenIndexTo the token the user wants to swap to\n * @param minDy the min amount the user would like to receive, or revert to only minting the SynERC20 token crosschain.\n * @param deadline latest timestamp to accept this transaction\n **/\n function redeemAndSwap(\n address to,\n uint256 chainId,\n IERC20 token,\n uint256 amount,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 minDy,\n uint256 deadline\n ) external {\n token.safeTransferFrom(msg.sender, address(this), amount);\n if (token.allowance(address(this), address(synapseBridge)) < amount) {\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n }\n synapseBridge.redeemAndSwap(\n to,\n chainId,\n token,\n amount,\n tokenIndexFrom,\n tokenIndexTo,\n minDy,\n deadline\n );\n }\n\n /**\n * @notice Wraps redeemAndRemove on SynapseBridge\n * Relays to nodes that (typically) a wrapped synAsset ERC20 token has been burned and the underlying needs to be redeeemed on the native chain. This function indicates to the nodes that they should attempt to redeem the LP token for the underlying assets (E.g \"swap\" out of the LP token)\n * @param to address on other chain to redeem underlying assets to\n * @param chainId which underlying chain to bridge assets onto\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount of (typically) LP token to pass to the nodes to attempt to removeLiquidity() with to redeem for the underlying assets of the LP token\n * @param liqTokenIndex Specifies which of the underlying LP assets the nodes should attempt to redeem for\n * @param liqMinAmount Specifies the minimum amount of the underlying asset needed for the nodes to execute the redeem/swap\n * @param liqDeadline Specificies the deadline that the nodes are allowed to try to redeem/swap the LP token\n **/\n function redeemAndRemove(\n address to,\n uint256 chainId,\n IERC20 token,\n uint256 amount,\n uint8 liqTokenIndex,\n uint256 liqMinAmount,\n uint256 liqDeadline\n ) external {\n token.safeTransferFrom(msg.sender, address(this), amount);\n if (token.allowance(address(this), address(synapseBridge)) < amount) {\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n }\n synapseBridge.redeemAndRemove(\n to,\n chainId,\n token,\n amount,\n liqTokenIndex,\n liqMinAmount,\n liqDeadline\n );\n }\n}\n" + }, + "contracts/bridge/interfaces/ISwap.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.6.12;\n\nimport '@openzeppelin/contracts/token/ERC20/ERC20.sol';\n\ninterface ISwap {\n // pool data view functions\n function getA() external view returns (uint256);\n\n function getToken(uint8 index) external view returns (IERC20);\n\n function getTokenIndex(address tokenAddress) external view returns (uint8);\n\n function getTokenBalance(uint8 index) external view returns (uint256);\n\n function getVirtualPrice() external view returns (uint256);\n\n // min return calculation functions\n function calculateSwap(\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx\n ) external view returns (uint256);\n\n function calculateTokenAmount(uint256[] calldata amounts, bool deposit)\n external\n view\n returns (uint256);\n\n function calculateRemoveLiquidity(uint256 amount)\n external\n view\n returns (uint256[] memory);\n\n function calculateRemoveLiquidityOneToken(\n uint256 tokenAmount,\n uint8 tokenIndex\n ) external view returns (uint256 availableTokenAmount);\n\n // state modifying functions\n function initialize(\n IERC20[] memory pooledTokens,\n uint8[] memory decimals,\n string memory lpTokenName,\n string memory lpTokenSymbol,\n uint256 a,\n uint256 fee,\n uint256 adminFee,\n address lpTokenTargetAddress\n ) external;\n\n function swap(\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx,\n uint256 minDy,\n uint256 deadline\n ) external returns (uint256);\n\n function addLiquidity(\n uint256[] calldata amounts,\n uint256 minToMint,\n uint256 deadline\n ) external returns (uint256);\n\n function removeLiquidity(\n uint256 amount,\n uint256[] calldata minAmounts,\n uint256 deadline\n ) external returns (uint256[] memory);\n\n function removeLiquidityOneToken(\n uint256 tokenAmount,\n uint8 tokenIndex,\n uint256 minAmount,\n uint256 deadline\n ) external returns (uint256);\n\n function removeLiquidityImbalance(\n uint256[] calldata amounts,\n uint256 maxBurnAmount,\n uint256 deadline\n ) external returns (uint256);\n}\n" + }, + "contracts/bridge/interfaces/IWETH9.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.4.0;\n\ninterface IWETH9 {\n function name() external view returns (string memory);\n\n function symbol() external view returns (string memory);\n\n function decimals() external view returns (uint8);\n\n function balanceOf(address) external view returns (uint256);\n\n function allowance(address, address) external view returns (uint256);\n\n receive() external payable;\n\n function deposit() external payable;\n\n function withdraw(uint256 wad) external;\n\n function totalSupply() external view returns (uint256);\n\n function approve(address guy, uint256 wad) external returns (bool);\n\n function transfer(address dst, uint256 wad) external returns (bool);\n\n function transferFrom(\n address src,\n address dst,\n uint256 wad\n ) external returns (bool);\n}" + }, + "contracts/bridge/wrappers/L2BridgeZap.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.6.12;\n\nimport \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/SafeERC20.sol\";\nimport \"../interfaces/ISwap.sol\";\nimport \"../interfaces/ISynapseBridge.sol\";\nimport \"../interfaces/IWETH9.sol\";\n\ncontract L2BridgeZap {\n using SafeERC20 for IERC20;\n\n ISynapseBridge synapseBridge;\n address payable public immutable WETH_ADDRESS;\n\n mapping(address => address) public swapMap;\n mapping(address => IERC20[]) public swapTokensMap;\n\n uint256 constant MAX_UINT256 = 2**256 - 1;\n\n constructor(\n address payable _wethAddress,\n address _swapOne,\n address tokenOne,\n address _swapTwo,\n address tokenTwo,\n ISynapseBridge _synapseBridge\n ) public {\n WETH_ADDRESS = _wethAddress;\n synapseBridge = _synapseBridge;\n swapMap[tokenOne] = _swapOne;\n swapMap[tokenTwo] = _swapTwo;\n if (_wethAddress != address(0)) {\n IERC20(_wethAddress).safeIncreaseAllowance(address(_synapseBridge), MAX_UINT256);\n }\n if (address(_swapOne) != address(0)) {\n {\n uint8 i;\n for (; i < 32; i++) {\n try ISwap(_swapOne).getToken(i) returns (\n IERC20 token\n ) {\n swapTokensMap[_swapOne].push(token);\n token.safeApprove(address(_swapOne), MAX_UINT256);\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n } catch {\n break;\n }\n }\n require(i > 1, \"swap must have at least 2 tokens\");\n }\n }\n if (address(_swapTwo) != address(0)) {\n {\n uint8 i;\n for (; i < 32; i++) {\n try ISwap(_swapTwo).getToken(i) returns (\n IERC20 token\n ) {\n swapTokensMap[_swapTwo].push(token);\n token.safeApprove(address(_swapTwo), MAX_UINT256);\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n } catch {\n break;\n }\n }\n require(i > 1, \"swap must have at least 2 tokens\");\n }\n }\n }\n\n /**\n * @notice Calculate amount of tokens you receive on swap\n * @param tokenIndexFrom the token the user wants to sell\n * @param tokenIndexTo the token the user wants to buy\n * @param dx the amount of tokens the user wants to sell. If the token charges\n * a fee on transfers, use the amount that gets transferred after the fee.\n * @return amount of tokens the user will receive\n */\n function calculateSwap(\n IERC20 token,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx\n ) external view virtual returns (uint256) {\n ISwap swap = ISwap(\n swapMap[address(token)]\n );\n return swap.calculateSwap(tokenIndexFrom, tokenIndexTo, dx);\n }\n\n function swapAndRedeem(\n address to,\n uint256 chainId,\n IERC20 token,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx,\n uint256 minDy,\n uint256 deadline\n ) external {\n ISwap swap = ISwap(swapMap[address(token)]);\n require(address(swap) != address(0), \"Swap is 0x00\");\n IERC20[] memory tokens = swapTokensMap[address(swap)];\n tokens[tokenIndexFrom].safeTransferFrom(\n msg.sender,\n address(this),\n dx\n );\n // swap\n\n uint256 swappedAmount = swap.swap(\n tokenIndexFrom,\n tokenIndexTo,\n dx,\n minDy,\n deadline\n );\n // deposit into bridge, gets nUSD\n if (\n token.allowance(address(this), address(synapseBridge)) <\n swappedAmount\n ) {\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n }\n synapseBridge.redeem(to, chainId, token, swappedAmount);\n }\n\n function swapAndRedeemAndSwap(\n address to,\n uint256 chainId,\n IERC20 token,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx,\n uint256 minDy,\n uint256 deadline,\n uint8 swapTokenIndexFrom,\n uint8 swapTokenIndexTo,\n uint256 swapMinDy,\n uint256 swapDeadline\n ) external {\n require(\n address(swapMap[address(token)]) != address(0),\n \"Swap is 0x00\"\n );\n IERC20[] memory tokens = swapTokensMap[\n swapMap[address(token)]\n ];\n tokens[tokenIndexFrom].safeTransferFrom(\n msg.sender,\n address(this),\n dx\n );\n // swap\n\n uint256 swappedAmount = ISwap(swapMap[address(token)]).swap(tokenIndexFrom, tokenIndexTo, dx, minDy, deadline);\n // deposit into bridge, gets nUSD\n if (\n token.allowance(address(this), address(synapseBridge)) <\n swappedAmount\n ) {\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n }\n synapseBridge.redeemAndSwap(\n to,\n chainId,\n token,\n swappedAmount,\n swapTokenIndexFrom,\n swapTokenIndexTo,\n swapMinDy,\n swapDeadline\n );\n }\n\n function swapAndRedeemAndRemove(\n address to,\n uint256 chainId,\n IERC20 token,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx,\n uint256 minDy,\n uint256 deadline,\n uint8 liqTokenIndex,\n uint256 liqMinAmount,\n uint256 liqDeadline\n ) external {\n ISwap swap = ISwap(swapMap[address(token)]);\n require(address(swap) != address(0), \"Swap is 0x00\");\n IERC20[] memory tokens = swapTokensMap[address(swap)];\n tokens[tokenIndexFrom].safeTransferFrom(\n msg.sender,\n address(this),\n dx\n );\n // swap\n\n uint256 swappedAmount = swap.swap(\n tokenIndexFrom,\n tokenIndexTo,\n dx,\n minDy,\n deadline\n );\n // deposit into bridge, gets nUSD\n if (\n token.allowance(address(this), address(synapseBridge)) <\n swappedAmount\n ) {\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n }\n synapseBridge.redeemAndRemove(\n to,\n chainId,\n token,\n swappedAmount,\n liqTokenIndex,\n liqMinAmount,\n liqDeadline\n );\n }\n\n /**\n * @notice wraps SynapseBridge redeem()\n * @param to address on other chain to redeem underlying assets to\n * @param chainId which underlying chain to bridge assets onto\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n **/\n function redeem(\n address to,\n uint256 chainId,\n IERC20 token,\n uint256 amount\n ) external {\n token.safeTransferFrom(msg.sender, address(this), amount);\n if (token.allowance(address(this), address(synapseBridge)) < amount) {\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n }\n synapseBridge.redeem(to, chainId, token, amount);\n }\n\n /**\n * @notice wraps SynapseBridge redeem()\n * @param to address on other chain to redeem underlying assets to\n * @param chainId which underlying chain to bridge assets onto\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n **/\n function deposit(\n address to,\n uint256 chainId,\n IERC20 token,\n uint256 amount\n ) external {\n token.safeTransferFrom(msg.sender, address(this), amount);\n if (token.allowance(address(this), address(synapseBridge)) < amount) {\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n }\n synapseBridge.deposit(to, chainId, token, amount);\n }\n\n /**\n * @notice Wraps SynapseBridge deposit() function to make it compatible w/ ETH -> WETH conversions\n * @param to address on other chain to bridge assets to\n * @param chainId which chain to bridge assets onto\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n **/\n function depositETH(\n address to,\n uint256 chainId,\n uint256 amount\n ) external payable {\n require(msg.value > 0 && msg.value == amount, 'INCORRECT MSG VALUE');\n IWETH9(WETH_ADDRESS).deposit{value: msg.value}();\n synapseBridge.deposit(to, chainId, IERC20(WETH_ADDRESS), amount);\n }\n\n\n function swapETHAndRedeem(\n address to,\n uint256 chainId,\n IERC20 token,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx,\n uint256 minDy,\n uint256 deadline\n ) external payable {\n require(WETH_ADDRESS != address(0), \"WETH 0\");\n require(msg.value > 0 && msg.value == dx, \"INCORRECT MSG VALUE\");\n ISwap swap = ISwap(swapMap[address(token)]);\n require(address(swap) != address(0), \"Swap is 0x00\");\n IWETH9(WETH_ADDRESS).deposit{value: msg.value}();\n\n // swap\n uint256 swappedAmount = swap.swap(\n tokenIndexFrom,\n tokenIndexTo,\n dx,\n minDy,\n deadline\n );\n synapseBridge.redeem(to, chainId, token, swappedAmount);\n }\n\n\n function swapETHAndRedeemAndSwap(\n address to,\n uint256 chainId,\n IERC20 token,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx,\n uint256 minDy,\n uint256 deadline,\n uint8 swapTokenIndexFrom,\n uint8 swapTokenIndexTo,\n uint256 swapMinDy,\n uint256 swapDeadline\n ) external payable {\n require(WETH_ADDRESS != address(0), \"WETH 0\");\n require(msg.value > 0 && msg.value == dx, \"INCORRECT MSG VALUE\");\n ISwap swap = ISwap(swapMap[address(token)]);\n require(address(swap) != address(0), \"Swap is 0x00\");\n IWETH9(WETH_ADDRESS).deposit{value: msg.value}();\n\n // swap\n uint256 swappedAmount = swap.swap(\n tokenIndexFrom,\n tokenIndexTo,\n dx,\n minDy,\n deadline\n );\n synapseBridge.redeemAndSwap(to, chainId, token, swappedAmount,swapTokenIndexFrom,\n swapTokenIndexTo,\n swapMinDy,\n swapDeadline);\n }\n\n\n /**\n * @notice Wraps redeemAndSwap on SynapseBridge.sol\n * Relays to nodes that (typically) a wrapped synAsset ERC20 token has been burned and the underlying needs to be redeeemed on the native chain. This function indicates to the nodes that they should attempt to redeem the LP token for the underlying assets (E.g \"swap\" out of the LP token)\n * @param to address on other chain to redeem underlying assets to\n * @param chainId which underlying chain to bridge assets onto\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n * @param tokenIndexFrom the token the user wants to swap from\n * @param tokenIndexTo the token the user wants to swap to\n * @param minDy the min amount the user would like to receive, or revert to only minting the SynERC20 token crosschain.\n * @param deadline latest timestamp to accept this transaction\n **/\n function redeemAndSwap(\n address to,\n uint256 chainId,\n IERC20 token,\n uint256 amount,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 minDy,\n uint256 deadline\n ) external {\n token.safeTransferFrom(msg.sender, address(this), amount);\n if (token.allowance(address(this), address(synapseBridge)) < amount) {\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n }\n synapseBridge.redeemAndSwap(\n to,\n chainId,\n token,\n amount,\n tokenIndexFrom,\n tokenIndexTo,\n minDy,\n deadline\n );\n }\n\n /**\n * @notice Wraps redeemAndRemove on SynapseBridge\n * Relays to nodes that (typically) a wrapped synAsset ERC20 token has been burned and the underlying needs to be redeeemed on the native chain. This function indicates to the nodes that they should attempt to redeem the LP token for the underlying assets (E.g \"swap\" out of the LP token)\n * @param to address on other chain to redeem underlying assets to\n * @param chainId which underlying chain to bridge assets onto\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount of (typically) LP token to pass to the nodes to attempt to removeLiquidity() with to redeem for the underlying assets of the LP token\n * @param liqTokenIndex Specifies which of the underlying LP assets the nodes should attempt to redeem for\n * @param liqMinAmount Specifies the minimum amount of the underlying asset needed for the nodes to execute the redeem/swap\n * @param liqDeadline Specificies the deadline that the nodes are allowed to try to redeem/swap the LP token\n **/\n function redeemAndRemove(\n address to,\n uint256 chainId,\n IERC20 token,\n uint256 amount,\n uint8 liqTokenIndex,\n uint256 liqMinAmount,\n uint256 liqDeadline\n ) external {\n token.safeTransferFrom(msg.sender, address(this), amount);\n if (token.allowance(address(this), address(synapseBridge)) < amount) {\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n }\n synapseBridge.redeemAndRemove(\n to,\n chainId,\n token,\n amount,\n liqTokenIndex,\n liqMinAmount,\n liqDeadline\n );\n }\n\n /**\n * @notice Wraps SynapseBridge redeemv2() function\n * @param to address on other chain to bridge assets to\n * @param chainId which chain to bridge assets onto\n * @param token ERC20 compatible token to redeem into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n **/\n function redeemv2(\n bytes32 to,\n uint256 chainId,\n IERC20 token,\n uint256 amount\n ) external {\n token.safeTransferFrom(msg.sender, address(this), amount);\n\n if (token.allowance(address(this), address(synapseBridge)) < amount) {\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n }\n synapseBridge.redeemv2(to, chainId, token, amount);\n }\n}\n" + }, + "contracts/bridge/wrappers/L1BridgeZap.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.6.12;\n\nimport '@openzeppelin/contracts/token/ERC20/IERC20.sol';\nimport '@openzeppelin/contracts/token/ERC20/SafeERC20.sol';\nimport '../interfaces/ISwap.sol';\nimport '../interfaces/ISynapseBridge.sol';\nimport \"../interfaces/IWETH9.sol\";\n\n\n/**\n * @title L1BridgeZap\n * @notice This contract is responsible for handling user Zaps into the SynapseBridge contract, through the Synapse Swap contracts. It does so\n * It does so by combining the action of addLiquidity() to the base swap pool, and then calling either deposit() or depositAndSwap() on the bridge.\n * This is done in hopes of automating portions of the bridge user experience to users, while keeping the SynapseBridge contract logic small.\n *\n * @dev This contract should be deployed with a base Swap.sol address and a SynapseBridge.sol address, otherwise, it will not function.\n */\ncontract L1BridgeZap {\n using SafeERC20 for IERC20;\n\n uint256 constant MAX_UINT256 = 2**256 - 1;\n \n ISwap baseSwap;\n ISynapseBridge synapseBridge;\n IERC20[] public baseTokens;\n address payable public immutable WETH_ADDRESS;\n \n\n /**\n * @notice Constructs the contract, approves each token inside of baseSwap to be used by baseSwap (needed for addLiquidity())\n */\n constructor(address payable _wethAddress, ISwap _baseSwap, ISynapseBridge _synapseBridge) public {\n WETH_ADDRESS = _wethAddress;\n baseSwap = _baseSwap;\n synapseBridge = _synapseBridge;\n IERC20(_wethAddress).safeIncreaseAllowance(address(_synapseBridge), MAX_UINT256);\n if (address(_baseSwap) != address(0)) {\n {\n uint8 i;\n for (; i < 32; i++) {\n try _baseSwap.getToken(i) returns (IERC20 token) {\n baseTokens.push(token);\n token.safeIncreaseAllowance(address(_baseSwap), MAX_UINT256);\n } catch {\n break;\n }\n }\n require(i > 1, 'baseSwap must have at least 2 tokens');\n }\n }\n }\n \n /**\n * @notice Wraps SynapseBridge deposit() function to make it compatible w/ ETH -> WETH conversions\n * @param to address on other chain to bridge assets to\n * @param chainId which chain to bridge assets onto\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n **/\n function depositETH(\n address to,\n uint256 chainId,\n uint256 amount\n ) external payable {\n require(msg.value > 0 && msg.value == amount, 'INCORRECT MSG VALUE');\n IWETH9(WETH_ADDRESS).deposit{value: msg.value}();\n synapseBridge.deposit(to, chainId, IERC20(WETH_ADDRESS), amount);\n }\n\n /**\n * @notice Wraps SynapseBridge depositAndSwap() function to make it compatible w/ ETH -> WETH conversions\n * @param to address on other chain to bridge assets to\n * @param chainId which chain to bridge assets onto\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n * @param tokenIndexFrom the token the user wants to swap from\n * @param tokenIndexTo the token the user wants to swap to\n * @param minDy the min amount the user would like to receive, or revert to only minting the SynERC20 token crosschain.\n * @param deadline latest timestamp to accept this transaction\n **/\n function depositETHAndSwap(\n address to,\n uint256 chainId,\n uint256 amount,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 minDy,\n uint256 deadline\n ) external payable {\n require(msg.value > 0 && msg.value == amount, 'INCORRECT MSG VALUE');\n IWETH9(WETH_ADDRESS).deposit{value: msg.value}();\n synapseBridge.depositAndSwap(to, chainId, IERC20(WETH_ADDRESS), amount, tokenIndexFrom, tokenIndexTo, minDy, deadline);\n }\n\n\n /**\n * @notice A simple method to calculate prices from deposits or\n * withdrawals, excluding fees but including slippage. This is\n * helpful as an input into the various \"min\" parameters on calls\n * to fight front-running\n *\n * @dev This shouldn't be used outside frontends for user estimates.\n *\n * @param amounts an array of token amounts to deposit or withdrawal,\n * corresponding to pooledTokens. The amount should be in each\n * pooled token's native precision.\n * @param deposit whether this is a deposit or a withdrawal\n * @return token amount the user will receive\n */\n function calculateTokenAmount(uint256[] calldata amounts, bool deposit)\n external\n view\n virtual\n returns (uint256)\n {\n return baseSwap.calculateTokenAmount(amounts, deposit);\n }\n\n /**\n * @notice Calculate the amount of underlying token available to withdraw\n * when withdrawing via only single token\n * @param tokenAmount the amount of LP token to burn\n * @param tokenIndex index of which token will be withdrawn\n * @return availableTokenAmount calculated amount of underlying token\n * available to withdraw\n */\n function calculateRemoveLiquidityOneToken(\n uint256 tokenAmount,\n uint8 tokenIndex\n ) external view virtual returns (uint256 availableTokenAmount) {\n return baseSwap.calculateRemoveLiquidityOneToken(tokenAmount, tokenIndex);\n }\n\n\n /**\n * @notice Combines adding liquidity to the given Swap, and calls deposit() on the bridge using that LP token\n * @param to address on other chain to bridge assets to\n * @param chainId which chain to bridge assets onto\n * @param token ERC20 compatible token to deposit into the bridge\n * @param liquidityAmounts the amounts of each token to add, in their native precision\n * @param minToMint the minimum LP tokens adding this amount of liquidity\n * should mint, otherwise revert. Handy for front-running mitigation\n * @param deadline latest timestamp to accept this transaction\n **/\n function zapAndDeposit(\n address to,\n uint256 chainId,\n IERC20 token,\n uint256[] calldata liquidityAmounts,\n uint256 minToMint,\n uint256 deadline\n ) external {\n // add liquidity\n for (uint256 i = 0; i < baseTokens.length; i++) {\n if (liquidityAmounts[i] != 0) {\n baseTokens[i].safeTransferFrom(\n msg.sender,\n address(this),\n liquidityAmounts[i]\n );\n }\n }\n\n uint256 liqAdded = baseSwap.addLiquidity(\n liquidityAmounts,\n minToMint,\n deadline\n );\n // deposit into bridge, gets nUSD\n if (token.allowance(address(this), address(synapseBridge)) < liqAdded) {\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n }\n synapseBridge.deposit(to, chainId, token, liqAdded);\n }\n\n /**\n * @notice Combines adding liquidity to the given Swap, and calls depositAndSwap() on the bridge using that LP token\n * @param to address on other chain to bridge assets to\n * @param chainId which chain to bridge assets onto\n * @param token ERC20 compatible token to deposit into the bridge\n * @param liquidityAmounts the amounts of each token to add, in their native precision\n * @param minToMint the minimum LP tokens adding this amount of liquidity\n * should mint, otherwise revert. Handy for front-running mitigation\n * @param liqDeadline latest timestamp to accept this transaction\n * @param tokenIndexFrom the token the user wants to swap from\n * @param tokenIndexTo the token the user wants to swap to\n * @param minDy the min amount the user would like to receive, or revert to only minting the SynERC20 token crosschain.\n * @param swapDeadline latest timestamp to accept this transaction\n **/\n function zapAndDepositAndSwap(\n address to,\n uint256 chainId,\n IERC20 token,\n uint256[] calldata liquidityAmounts,\n uint256 minToMint,\n uint256 liqDeadline,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 minDy,\n uint256 swapDeadline\n ) external {\n // add liquidity\n for (uint256 i = 0; i < baseTokens.length; i++) {\n if (liquidityAmounts[i] != 0) {\n baseTokens[i].safeTransferFrom(\n msg.sender,\n address(this),\n liquidityAmounts[i]\n );\n }\n }\n\n uint256 liqAdded = baseSwap.addLiquidity(\n liquidityAmounts,\n minToMint,\n liqDeadline\n );\n // deposit into bridge, bridge attemps to swap into desired asset\n if (token.allowance(address(this), address(synapseBridge)) < liqAdded) {\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n }\n synapseBridge.depositAndSwap(\n to,\n chainId,\n token,\n liqAdded,\n tokenIndexFrom,\n tokenIndexTo,\n minDy,\n swapDeadline\n );\n }\n\n /**\n * @notice Wraps SynapseBridge deposit() function\n * @param to address on other chain to bridge assets to\n * @param chainId which chain to bridge assets onto\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n **/\n function deposit(\n address to,\n uint256 chainId,\n IERC20 token,\n uint256 amount\n ) external {\n token.safeTransferFrom(msg.sender, address(this), amount);\n\n if (token.allowance(address(this), address(synapseBridge)) < amount) {\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n }\n synapseBridge.deposit(to, chainId, token, amount);\n }\n \n /**\n * @notice Wraps SynapseBridge depositAndSwap() function\n * @param to address on other chain to bridge assets to\n * @param chainId which chain to bridge assets onto\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n * @param tokenIndexFrom the token the user wants to swap from\n * @param tokenIndexTo the token the user wants to swap to\n * @param minDy the min amount the user would like to receive, or revert to only minting the SynERC20 token crosschain.\n * @param deadline latest timestamp to accept this transaction\n **/\n function depositAndSwap(\n address to,\n uint256 chainId,\n IERC20 token,\n uint256 amount,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 minDy,\n uint256 deadline\n ) external {\n token.safeTransferFrom(msg.sender, address(this), amount);\n \n if (token.allowance(address(this), address(synapseBridge)) < amount) {\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n }\n synapseBridge.depositAndSwap(to, chainId, token, amount, tokenIndexFrom, tokenIndexTo, minDy, deadline);\n }\n\n\n /**\n * @notice Wraps SynapseBridge redeem() function\n * @param to address on other chain to bridge assets to\n * @param chainId which chain to bridge assets onto\n * @param token ERC20 compatible token to redeem into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n **/\n function redeem(\n address to,\n uint256 chainId,\n IERC20 token,\n uint256 amount\n ) external {\n token.safeTransferFrom(msg.sender, address(this), amount);\n\n if (token.allowance(address(this), address(synapseBridge)) < amount) {\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n }\n synapseBridge.redeem(to, chainId, token, amount);\n }\n\n /**\n * @notice Wraps SynapseBridge redeemv2() function\n * @param to address on other chain to bridge assets to\n * @param chainId which chain to bridge assets onto\n * @param token ERC20 compatible token to redeem into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n **/\n function redeemv2(\n bytes32 to,\n uint256 chainId,\n IERC20 token,\n uint256 amount\n ) external {\n token.safeTransferFrom(msg.sender, address(this), amount);\n\n if (token.allowance(address(this), address(synapseBridge)) < amount) {\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n }\n synapseBridge.redeemv2(to, chainId, token, amount);\n }\n\n}\n" + }, + "contracts/bridge/wrappers/MigratorBridgeZap.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.6.12;\n\nimport '@openzeppelin/contracts/token/ERC20/IERC20.sol';\nimport '@openzeppelin/contracts/token/ERC20/SafeERC20.sol';\nimport '@openzeppelin/contracts/math/SafeMath.sol';\n\nimport '../interfaces/ISynapseBridge.sol';\nimport '../interfaces/IERC20Migrator.sol';\n\ncontract MigratorBridgeZap {\n using SafeERC20 for IERC20;\n using SafeMath for uint256;\n \n ISynapseBridge constant synapseBridge = ISynapseBridge(0xd123f70AE324d34A9E76b67a27bf77593bA8749f);\n IERC20Migrator constant erc20Migrator = IERC20Migrator(0xf0284FB86adA5E4D82555C529677eEA3B2C3E022); \n IERC20 constant legacyToken = IERC20(0x42F6f551ae042cBe50C739158b4f0CAC0Edb9096);\n IERC20 constant newToken = IERC20(0xa4080f1778e69467E905B8d6F72f6e441f9e9484);\n uint256 constant MAX_UINT256 = 2**256 - 1;\n\n constructor() public {\n legacyToken.safeApprove(address(erc20Migrator), MAX_UINT256);\n newToken.safeApprove(address(synapseBridge), MAX_UINT256);\n }\n\n function migrate(uint256 amount) external {\n legacyToken.safeTransferFrom(msg.sender, address(this), amount);\n erc20Migrator.migrate(amount);\n newToken.safeTransfer(msg.sender, amount.mul(5).div(2));\n }\n\n function migrateAndBridge(uint256 amount, address to, uint256 chainId) external {\n legacyToken.safeTransferFrom(msg.sender, address(this), amount);\n erc20Migrator.migrate(amount);\n synapseBridge.redeem(to, chainId, newToken, amount.mul(5).div(2));\n }\n}" + }, + "contracts/bridge/interfaces/IERC20Migrator.sol": { + "content": "// SPDX-License-Identifier: MIT\n\n\npragma solidity 0.6.12;\n\ninterface IERC20Migrator { \n function migrate(uint256 amount) external;\n}\n\n" + }, + "contracts/bridge/wrappers/JewelBridgeSwap.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.6.12;\n\nimport '@openzeppelin/contracts/token/ERC20/ERC20.sol';\nimport \"@openzeppelin/contracts/token/ERC20/SafeERC20.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/ERC20Burnable.sol\";\nimport \"@openzeppelin/contracts/math/SafeMath.sol\";\n\ninterface IERC20Mintable is IERC20 {\n function mint(address to, uint256 amount) external;\n}\n\ncontract JewelBridgeSwap {\n using SafeERC20 for IERC20;\n using SafeERC20 for IERC20Mintable;\n using SafeMath for uint256;\n\n // Maps token address to an index in the pool. Used to prevent duplicate tokens in the pool.\n // getTokenIndex function also relies on this mapping to retrieve token index.\n mapping(address => uint8) private tokenIndexes;\n IERC20[2] pooledTokens;\n \n constructor(IERC20 tokenA, IERC20 mintableTokenB) public {\n pooledTokens[0] = tokenA;\n pooledTokens[1] = mintableTokenB;\n tokenIndexes[address(tokenA)] = 0;\n tokenIndexes[address(mintableTokenB)] = 1;\n }\n\n /**\n * @notice Return address of the pooled token at given index. Reverts if tokenIndex is out of range.\n * @param index the index of the token\n * @return address of the token at given index\n */\n function getToken(uint8 index) public view returns (IERC20) {\n require(index < pooledTokens.length, \"Out of range\");\n return pooledTokens[index];\n }\n\n /**\n * @notice Return the index of the given token address. Reverts if no matching\n * token is found.\n * @param tokenAddress address of the token\n * @return the index of the given token address\n */\n function getTokenIndex(address tokenAddress)\n public\n view\n returns (uint8)\n {\n uint8 index = tokenIndexes[tokenAddress];\n require(\n address(getToken(index)) == tokenAddress,\n \"Token does not exist\"\n );\n return index;\n }\n\n /**\n * @notice Calculate amount of tokens you receive on swap\n * @param tokenIndexFrom the token the user wants to sell\n * @param tokenIndexTo the token the user wants to buy\n * @param dx the amount of tokens the user wants to swap. \n * @return amount of tokens the user will receive\n */\n function calculateSwap(\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx\n ) external view returns (uint256) {\n return dx;\n }\n\n /**\n * @notice Swap two tokens using this pool\n * @param tokenIndexFrom the token the user wants to swap from\n * @param tokenIndexTo the token the user wants to swap to\n * @param dx the amount of tokens the user wants to swap from\n * @param minDy the min amount the user would like to receive, or revert.\n * @param deadline latest timestamp to accept this transaction\n */\n function swap(\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx,\n uint256 minDy,\n uint256 deadline\n )\n external\n returns (uint256)\n {\n {\n IERC20 tokenFrom = pooledTokens[tokenIndexFrom];\n require(\n dx <= tokenFrom.balanceOf(msg.sender),\n \"Cannot swap more than you own\"\n );\n // Transfer tokens first to see if a fee was charged on transfer\n uint256 beforeBalance = tokenFrom.balanceOf(address(this));\n tokenFrom.safeTransferFrom(msg.sender, address(this), dx);\n\n // Use the actual transferred amount for AMM math\n dx = tokenFrom.balanceOf(address(this)).sub(beforeBalance);\n }\n\n // redeem JEWEL for synJEWEL\n if (tokenIndexFrom == 0 && tokenIndexTo == 1) {\n IERC20Mintable(address(pooledTokens[tokenIndexTo])).mint(msg.sender, dx);\n return dx;\n // redeem synJEWEL for JEWEL\n } else if (tokenIndexFrom == 1 && tokenIndexTo == 0) {\n ERC20Burnable(address(pooledTokens[tokenIndexFrom])).burn(dx);\n pooledTokens[tokenIndexTo].safeTransfer(msg.sender, dx);\n return dx;\n } else {\n revert(\"Unsupported indexes\");\n }\n }\n}" + }, + "contracts/bridge/testing/SynapseToken.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity >=0.6.0 <0.8.0;\n\n\nimport \"@openzeppelin/contracts/token/ERC20/ERC20.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/ERC20Burnable.sol\";\nimport \"@openzeppelin/contracts/access/AccessControl.sol\";\nimport \"@openzeppelin/contracts/drafts/ERC20Permit.sol\";\n\ncontract Synapse is ERC20, ERC20Burnable, AccessControl, ERC20Permit {\n bytes32 public constant MINTER_ROLE = keccak256(\"MINTER_ROLE\");\n\n constructor() public ERC20(\"Synapse\", \"SYN\") ERC20Permit(\"Synapse\") {\n _setupRole(DEFAULT_ADMIN_ROLE, msg.sender);\n _setupRole(MINTER_ROLE, msg.sender);\n }\n\n function mint(address to, uint256 amount) external {\n require(hasRole(MINTER_ROLE, msg.sender));\n _mint(to, amount);\n }\n}" + }, + "@openzeppelin/contracts/access/AccessControl.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <0.8.0;\n\nimport \"../utils/EnumerableSet.sol\";\nimport \"../utils/Address.sol\";\nimport \"../utils/Context.sol\";\n\n/**\n * @dev Contract module that allows children to implement role-based access\n * control mechanisms.\n *\n * Roles are referred to by their `bytes32` identifier. These should be exposed\n * in the external API and be unique. The best way to achieve this is by\n * using `public constant` hash digests:\n *\n * ```\n * bytes32 public constant MY_ROLE = keccak256(\"MY_ROLE\");\n * ```\n *\n * Roles can be used to represent a set of permissions. To restrict access to a\n * function call, use {hasRole}:\n *\n * ```\n * function foo() public {\n * require(hasRole(MY_ROLE, msg.sender));\n * ...\n * }\n * ```\n *\n * Roles can be granted and revoked dynamically via the {grantRole} and\n * {revokeRole} functions. Each role has an associated admin role, and only\n * accounts that have a role's admin role can call {grantRole} and {revokeRole}.\n *\n * By default, the admin role for all roles is `DEFAULT_ADMIN_ROLE`, which means\n * that only accounts with this role will be able to grant or revoke other\n * roles. More complex role relationships can be created by using\n * {_setRoleAdmin}.\n *\n * WARNING: The `DEFAULT_ADMIN_ROLE` is also its own admin: it has permission to\n * grant and revoke this role. Extra precautions should be taken to secure\n * accounts that have been granted it.\n */\nabstract contract AccessControl is Context {\n using EnumerableSet for EnumerableSet.AddressSet;\n using Address for address;\n\n struct RoleData {\n EnumerableSet.AddressSet members;\n bytes32 adminRole;\n }\n\n mapping (bytes32 => RoleData) private _roles;\n\n bytes32 public constant DEFAULT_ADMIN_ROLE = 0x00;\n\n /**\n * @dev Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole`\n *\n * `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite\n * {RoleAdminChanged} not being emitted signaling this.\n *\n * _Available since v3.1._\n */\n event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole);\n\n /**\n * @dev Emitted when `account` is granted `role`.\n *\n * `sender` is the account that originated the contract call, an admin role\n * bearer except when using {_setupRole}.\n */\n event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender);\n\n /**\n * @dev Emitted when `account` is revoked `role`.\n *\n * `sender` is the account that originated the contract call:\n * - if using `revokeRole`, it is the admin role bearer\n * - if using `renounceRole`, it is the role bearer (i.e. `account`)\n */\n event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender);\n\n /**\n * @dev Returns `true` if `account` has been granted `role`.\n */\n function hasRole(bytes32 role, address account) public view returns (bool) {\n return _roles[role].members.contains(account);\n }\n\n /**\n * @dev Returns the number of accounts that have `role`. Can be used\n * together with {getRoleMember} to enumerate all bearers of a role.\n */\n function getRoleMemberCount(bytes32 role) public view returns (uint256) {\n return _roles[role].members.length();\n }\n\n /**\n * @dev Returns one of the accounts that have `role`. `index` must be a\n * value between 0 and {getRoleMemberCount}, non-inclusive.\n *\n * Role bearers are not sorted in any particular way, and their ordering may\n * change at any point.\n *\n * WARNING: When using {getRoleMember} and {getRoleMemberCount}, make sure\n * you perform all queries on the same block. See the following\n * https://forum.openzeppelin.com/t/iterating-over-elements-on-enumerableset-in-openzeppelin-contracts/2296[forum post]\n * for more information.\n */\n function getRoleMember(bytes32 role, uint256 index) public view returns (address) {\n return _roles[role].members.at(index);\n }\n\n /**\n * @dev Returns the admin role that controls `role`. See {grantRole} and\n * {revokeRole}.\n *\n * To change a role's admin, use {_setRoleAdmin}.\n */\n function getRoleAdmin(bytes32 role) public view returns (bytes32) {\n return _roles[role].adminRole;\n }\n\n /**\n * @dev Grants `role` to `account`.\n *\n * If `account` had not been already granted `role`, emits a {RoleGranted}\n * event.\n *\n * Requirements:\n *\n * - the caller must have ``role``'s admin role.\n */\n function grantRole(bytes32 role, address account) public virtual {\n require(hasRole(_roles[role].adminRole, _msgSender()), \"AccessControl: sender must be an admin to grant\");\n\n _grantRole(role, account);\n }\n\n /**\n * @dev Revokes `role` from `account`.\n *\n * If `account` had been granted `role`, emits a {RoleRevoked} event.\n *\n * Requirements:\n *\n * - the caller must have ``role``'s admin role.\n */\n function revokeRole(bytes32 role, address account) public virtual {\n require(hasRole(_roles[role].adminRole, _msgSender()), \"AccessControl: sender must be an admin to revoke\");\n\n _revokeRole(role, account);\n }\n\n /**\n * @dev Revokes `role` from the calling account.\n *\n * Roles are often managed via {grantRole} and {revokeRole}: this function's\n * purpose is to provide a mechanism for accounts to lose their privileges\n * if they are compromised (such as when a trusted device is misplaced).\n *\n * If the calling account had been granted `role`, emits a {RoleRevoked}\n * event.\n *\n * Requirements:\n *\n * - the caller must be `account`.\n */\n function renounceRole(bytes32 role, address account) public virtual {\n require(account == _msgSender(), \"AccessControl: can only renounce roles for self\");\n\n _revokeRole(role, account);\n }\n\n /**\n * @dev Grants `role` to `account`.\n *\n * If `account` had not been already granted `role`, emits a {RoleGranted}\n * event. Note that unlike {grantRole}, this function doesn't perform any\n * checks on the calling account.\n *\n * [WARNING]\n * ====\n * This function should only be called from the constructor when setting\n * up the initial roles for the system.\n *\n * Using this function in any other way is effectively circumventing the admin\n * system imposed by {AccessControl}.\n * ====\n */\n function _setupRole(bytes32 role, address account) internal virtual {\n _grantRole(role, account);\n }\n\n /**\n * @dev Sets `adminRole` as ``role``'s admin role.\n *\n * Emits a {RoleAdminChanged} event.\n */\n function _setRoleAdmin(bytes32 role, bytes32 adminRole) internal virtual {\n emit RoleAdminChanged(role, _roles[role].adminRole, adminRole);\n _roles[role].adminRole = adminRole;\n }\n\n function _grantRole(bytes32 role, address account) private {\n if (_roles[role].members.add(account)) {\n emit RoleGranted(role, account, _msgSender());\n }\n }\n\n function _revokeRole(bytes32 role, address account) private {\n if (_roles[role].members.remove(account)) {\n emit RoleRevoked(role, account, _msgSender());\n }\n }\n}\n" + }, + "@openzeppelin/contracts/drafts/ERC20Permit.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.5 <0.8.0;\n\nimport \"../token/ERC20/ERC20.sol\";\nimport \"./IERC20Permit.sol\";\nimport \"../cryptography/ECDSA.sol\";\nimport \"../utils/Counters.sol\";\nimport \"./EIP712.sol\";\n\n/**\n * @dev Implementation of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in\n * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612].\n *\n * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by\n * presenting a message signed by the account. By not relying on `{IERC20-approve}`, the token holder account doesn't\n * need to send a transaction, and thus is not required to hold Ether at all.\n *\n * _Available since v3.4._\n */\nabstract contract ERC20Permit is ERC20, IERC20Permit, EIP712 {\n using Counters for Counters.Counter;\n\n mapping (address => Counters.Counter) private _nonces;\n\n // solhint-disable-next-line var-name-mixedcase\n bytes32 private immutable _PERMIT_TYPEHASH = keccak256(\"Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)\");\n\n /**\n * @dev Initializes the {EIP712} domain separator using the `name` parameter, and setting `version` to `\"1\"`.\n *\n * It's a good idea to use the same `name` that is defined as the ERC20 token name.\n */\n constructor(string memory name) internal EIP712(name, \"1\") {\n }\n\n /**\n * @dev See {IERC20Permit-permit}.\n */\n function permit(address owner, address spender, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s) public virtual override {\n // solhint-disable-next-line not-rely-on-time\n require(block.timestamp <= deadline, \"ERC20Permit: expired deadline\");\n\n bytes32 structHash = keccak256(\n abi.encode(\n _PERMIT_TYPEHASH,\n owner,\n spender,\n value,\n _nonces[owner].current(),\n deadline\n )\n );\n\n bytes32 hash = _hashTypedDataV4(structHash);\n\n address signer = ECDSA.recover(hash, v, r, s);\n require(signer == owner, \"ERC20Permit: invalid signature\");\n\n _nonces[owner].increment();\n _approve(owner, spender, value);\n }\n\n /**\n * @dev See {IERC20Permit-nonces}.\n */\n function nonces(address owner) public view override returns (uint256) {\n return _nonces[owner].current();\n }\n\n /**\n * @dev See {IERC20Permit-DOMAIN_SEPARATOR}.\n */\n // solhint-disable-next-line func-name-mixedcase\n function DOMAIN_SEPARATOR() external view override returns (bytes32) {\n return _domainSeparatorV4();\n }\n}\n" + }, + "@openzeppelin/contracts/utils/EnumerableSet.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <0.8.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" + }, + "@openzeppelin/contracts/drafts/IERC20Permit.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <0.8.0;\n\n/**\n * @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in\n * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612].\n *\n * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by\n * presenting a message signed by the account. By not relying on `{IERC20-approve}`, the token holder account doesn't\n * need to send a transaction, and thus is not required to hold Ether at all.\n */\ninterface IERC20Permit {\n /**\n * @dev Sets `value` as the allowance of `spender` over `owner`'s tokens,\n * given `owner`'s signed approval.\n *\n * IMPORTANT: The same issues {IERC20-approve} has related to transaction\n * ordering also apply here.\n *\n * Emits an {Approval} event.\n *\n * Requirements:\n *\n * - `spender` cannot be the zero address.\n * - `deadline` must be a timestamp in the future.\n * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner`\n * over the EIP712-formatted function arguments.\n * - the signature must use ``owner``'s current nonce (see {nonces}).\n *\n * For more information on the signature format, see the\n * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP\n * section].\n */\n function permit(address owner, address spender, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s) external;\n\n /**\n * @dev Returns the current nonce for `owner`. This value must be\n * included whenever a signature is generated for {permit}.\n *\n * Every successful call to {permit} increases ``owner``'s nonce by one. This\n * prevents a signature from being used multiple times.\n */\n function nonces(address owner) external view returns (uint256);\n\n /**\n * @dev Returns the domain separator used in the encoding of the signature for `permit`, as defined by {EIP712}.\n */\n // solhint-disable-next-line func-name-mixedcase\n function DOMAIN_SEPARATOR() external view returns (bytes32);\n}\n" + }, + "@openzeppelin/contracts/cryptography/ECDSA.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <0.8.0;\n\n/**\n * @dev Elliptic Curve Digital Signature Algorithm (ECDSA) operations.\n *\n * These functions can be used to verify that a message was signed by the holder\n * of the private keys of a given address.\n */\nlibrary ECDSA {\n /**\n * @dev Returns the address that signed a hashed message (`hash`) with\n * `signature`. This address can then be used for verification purposes.\n *\n * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:\n * this function rejects them by requiring the `s` value to be in the lower\n * half order, and the `v` value to be either 27 or 28.\n *\n * IMPORTANT: `hash` _must_ be the result of a hash operation for the\n * verification to be secure: it is possible to craft signatures that\n * recover to arbitrary addresses for non-hashed data. A safe way to ensure\n * this is by receiving a hash of the original message (which may otherwise\n * be too long), and then calling {toEthSignedMessageHash} on it.\n */\n function recover(bytes32 hash, bytes memory signature) internal pure returns (address) {\n // Check the signature length\n if (signature.length != 65) {\n revert(\"ECDSA: invalid signature length\");\n }\n\n // Divide the signature in r, s and v variables\n bytes32 r;\n bytes32 s;\n uint8 v;\n\n // ecrecover takes the signature parameters, and the only way to get them\n // currently is to use assembly.\n // solhint-disable-next-line no-inline-assembly\n assembly {\n r := mload(add(signature, 0x20))\n s := mload(add(signature, 0x40))\n v := byte(0, mload(add(signature, 0x60)))\n }\n\n return recover(hash, v, r, s);\n }\n\n /**\n * @dev Overload of {ECDSA-recover-bytes32-bytes-} that receives the `v`,\n * `r` and `s` signature fields separately.\n */\n function recover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) internal pure returns (address) {\n // EIP-2 still allows signature malleability for ecrecover(). Remove this possibility and make the signature\n // unique. Appendix F in the Ethereum Yellow paper (https://ethereum.github.io/yellowpaper/paper.pdf), defines\n // the valid range for s in (281): 0 < s < secp256k1n ÷ 2 + 1, and for v in (282): v ∈ {27, 28}. Most\n // signatures from current libraries generate a unique signature with an s-value in the lower half order.\n //\n // If your library generates malleable signatures, such as s-values in the upper range, calculate a new s-value\n // with 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 - s1 and flip v from 27 to 28 or\n // vice versa. If your library also generates signatures with 0/1 for v instead 27/28, add 27 to v to accept\n // these malleable signatures as well.\n require(uint256(s) <= 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0, \"ECDSA: invalid signature 's' value\");\n require(v == 27 || v == 28, \"ECDSA: invalid signature 'v' value\");\n\n // If the signature is valid (and not malleable), return the signer address\n address signer = ecrecover(hash, v, r, s);\n require(signer != address(0), \"ECDSA: invalid signature\");\n\n return signer;\n }\n\n /**\n * @dev Returns an Ethereum Signed Message, created from a `hash`. This\n * replicates the behavior of the\n * https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_sign[`eth_sign`]\n * JSON-RPC method.\n *\n * See {recover}.\n */\n function toEthSignedMessageHash(bytes32 hash) internal pure returns (bytes32) {\n // 32 is the length in bytes of hash,\n // enforced by the type signature above\n return keccak256(abi.encodePacked(\"\\x19Ethereum Signed Message:\\n32\", hash));\n }\n}\n" + }, + "@openzeppelin/contracts/utils/Counters.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <0.8.0;\n\nimport \"../math/SafeMath.sol\";\n\n/**\n * @title Counters\n * @author Matt Condon (@shrugs)\n * @dev Provides counters that can only be incremented or decremented by one. This can be used e.g. to track the number\n * of elements in a mapping, issuing ERC721 ids, or counting request ids.\n *\n * Include with `using Counters for Counters.Counter;`\n * Since it is not possible to overflow a 256 bit integer with increments of one, `increment` can skip the {SafeMath}\n * overflow check, thereby saving gas. This does assume however correct usage, in that the underlying `_value` is never\n * directly accessed.\n */\nlibrary Counters {\n using SafeMath for uint256;\n\n struct Counter {\n // This variable should never be directly accessed by users of the library: interactions must be restricted to\n // the library's function. As of Solidity v0.5.2, this cannot be enforced, though there is a proposal to add\n // this feature: see https://github.com/ethereum/solidity/issues/4637\n uint256 _value; // default: 0\n }\n\n function current(Counter storage counter) internal view returns (uint256) {\n return counter._value;\n }\n\n function increment(Counter storage counter) internal {\n // The {SafeMath} overflow check can be skipped here, see the comment at the top\n counter._value += 1;\n }\n\n function decrement(Counter storage counter) internal {\n counter._value = counter._value.sub(1);\n }\n}\n" + }, + "@openzeppelin/contracts/drafts/EIP712.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <0.8.0;\n\n/**\n * @dev https://eips.ethereum.org/EIPS/eip-712[EIP 712] is a standard for hashing and signing of typed structured data.\n *\n * The encoding specified in the EIP is very generic, and such a generic implementation in Solidity is not feasible,\n * thus this contract does not implement the encoding itself. Protocols need to implement the type-specific encoding\n * they need in their contracts using a combination of `abi.encode` and `keccak256`.\n *\n * This contract implements the EIP 712 domain separator ({_domainSeparatorV4}) that is used as part of the encoding\n * scheme, and the final step of the encoding to obtain the message digest that is then signed via ECDSA\n * ({_hashTypedDataV4}).\n *\n * The implementation of the domain separator was designed to be as efficient as possible while still properly updating\n * the chain id to protect against replay attacks on an eventual fork of the chain.\n *\n * NOTE: This contract implements the version of the encoding known as \"v4\", as implemented by the JSON RPC method\n * https://docs.metamask.io/guide/signing-data.html[`eth_signTypedDataV4` in MetaMask].\n *\n * _Available since v3.4._\n */\nabstract contract EIP712 {\n /* solhint-disable var-name-mixedcase */\n // Cache the domain separator as an immutable value, but also store the chain id that it corresponds to, in order to\n // invalidate the cached domain separator if the chain id changes.\n bytes32 private immutable _CACHED_DOMAIN_SEPARATOR;\n uint256 private immutable _CACHED_CHAIN_ID;\n\n bytes32 private immutable _HASHED_NAME;\n bytes32 private immutable _HASHED_VERSION;\n bytes32 private immutable _TYPE_HASH;\n /* solhint-enable var-name-mixedcase */\n\n /**\n * @dev Initializes the domain separator and parameter caches.\n *\n * The meaning of `name` and `version` is specified in\n * https://eips.ethereum.org/EIPS/eip-712#definition-of-domainseparator[EIP 712]:\n *\n * - `name`: the user readable name of the signing domain, i.e. the name of the DApp or the protocol.\n * - `version`: the current major version of the signing domain.\n *\n * NOTE: These parameters cannot be changed except through a xref:learn::upgrading-smart-contracts.adoc[smart\n * contract upgrade].\n */\n constructor(string memory name, string memory version) internal {\n bytes32 hashedName = keccak256(bytes(name));\n bytes32 hashedVersion = keccak256(bytes(version));\n bytes32 typeHash = keccak256(\"EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)\");\n _HASHED_NAME = hashedName;\n _HASHED_VERSION = hashedVersion;\n _CACHED_CHAIN_ID = _getChainId();\n _CACHED_DOMAIN_SEPARATOR = _buildDomainSeparator(typeHash, hashedName, hashedVersion);\n _TYPE_HASH = typeHash;\n }\n\n /**\n * @dev Returns the domain separator for the current chain.\n */\n function _domainSeparatorV4() internal view virtual returns (bytes32) {\n if (_getChainId() == _CACHED_CHAIN_ID) {\n return _CACHED_DOMAIN_SEPARATOR;\n } else {\n return _buildDomainSeparator(_TYPE_HASH, _HASHED_NAME, _HASHED_VERSION);\n }\n }\n\n function _buildDomainSeparator(bytes32 typeHash, bytes32 name, bytes32 version) private view returns (bytes32) {\n return keccak256(\n abi.encode(\n typeHash,\n name,\n version,\n _getChainId(),\n address(this)\n )\n );\n }\n\n /**\n * @dev Given an already https://eips.ethereum.org/EIPS/eip-712#definition-of-hashstruct[hashed struct], this\n * function returns the hash of the fully encoded EIP712 message for this domain.\n *\n * This hash can be used together with {ECDSA-recover} to obtain the signer of a message. For example:\n *\n * ```solidity\n * bytes32 digest = _hashTypedDataV4(keccak256(abi.encode(\n * keccak256(\"Mail(address to,string contents)\"),\n * mailTo,\n * keccak256(bytes(mailContents))\n * )));\n * address signer = ECDSA.recover(digest, signature);\n * ```\n */\n function _hashTypedDataV4(bytes32 structHash) internal view virtual returns (bytes32) {\n return keccak256(abi.encodePacked(\"\\x19\\x01\", _domainSeparatorV4(), structHash));\n }\n\n function _getChainId() private view returns (uint256 chainId) {\n this; // silence state mutability warning without generating bytecode - see https://github.com/ethereum/solidity/issues/2691\n // solhint-disable-next-line no-inline-assembly\n assembly {\n chainId := chainid()\n }\n }\n}\n" + }, + "contracts/bridge/mocks/ERC20Mock.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.6.12;\n\nimport \"@openzeppelin/contracts/token/ERC20/ERC20.sol\";\n\ncontract ERC20Mock is ERC20 {\n constructor(\n string memory name,\n string memory symbol,\n uint256 supply\n ) public ERC20(name, symbol) {\n _mint(msg.sender, supply);\n }\n\n function mint(address to, uint256 amount) external {\n _mint(to, amount);\n }\n}" + }, + "contracts/bridge/interfaces/IMetaSwapDeposit.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.6.12;\nimport '@openzeppelin/contracts/token/ERC20/ERC20.sol';\n\n/**\n * @title IMetaSwapDeposit interface\n * @notice Interface for the meta swap contract.\n * @dev implement this interface to develop a a factory-patterned ECDSA node management contract\n **/\ninterface IMetaSwapDeposit {\n // min return calculation functions\n function calculateSwap(\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx\n ) external view returns (uint256);\n\n function swap(\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx,\n uint256 minDy,\n uint256 deadline\n ) external returns (uint256);\n\n function getToken(uint256 index) external view returns (IERC20);\n}\n" + }, + "contracts/amm/interfaces/IMetaSwapDeposit.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.6.12;\n\nimport \"@openzeppelin/contracts/token/ERC20/ERC20.sol\";\nimport \"./ISwap.sol\";\nimport \"./IMetaSwap.sol\";\n\ninterface IMetaSwapDeposit {\n function initialize(\n ISwap baseSwap_,\n IMetaSwap metaSwap_,\n IERC20 metaLPToken_\n ) external;\n}\n" + }, + "contracts/amm/interfaces/IMetaSwap.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.6.12;\n\nimport \"@openzeppelin/contracts/token/ERC20/ERC20.sol\";\n\ninterface IMetaSwap {\n // pool data view functions\n function getA() external view returns (uint256);\n\n function getToken(uint8 index) external view returns (IERC20);\n\n function getTokenIndex(address tokenAddress) external view returns (uint8);\n\n function getTokenBalance(uint8 index) external view returns (uint256);\n\n function getVirtualPrice() external view returns (uint256);\n\n function isGuarded() external view returns (bool);\n\n // min return calculation functions\n function calculateSwap(\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx\n ) external view returns (uint256);\n\n function calculateSwapUnderlying(\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx\n ) external view returns (uint256);\n\n function calculateTokenAmount(uint256[] calldata amounts, bool deposit)\n external\n view\n returns (uint256);\n\n function calculateRemoveLiquidity(uint256 amount)\n external\n view\n returns (uint256[] memory);\n\n function calculateRemoveLiquidityOneToken(\n uint256 tokenAmount,\n uint8 tokenIndex\n ) external view returns (uint256 availableTokenAmount);\n\n // state modifying functions\n function initializeMetaSwap(\n IERC20[] memory pooledTokens,\n uint8[] memory decimals,\n string memory lpTokenName,\n string memory lpTokenSymbol,\n uint256 a,\n uint256 fee,\n uint256 adminFee,\n address lpTokenTargetAddress,\n address baseSwap\n ) external;\n\n function swap(\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx,\n uint256 minDy,\n uint256 deadline\n ) external returns (uint256);\n\n function swapUnderlying(\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx,\n uint256 minDy,\n uint256 deadline\n ) external returns (uint256);\n\n function addLiquidity(\n uint256[] calldata amounts,\n uint256 minToMint,\n uint256 deadline\n ) external returns (uint256);\n\n function removeLiquidity(\n uint256 amount,\n uint256[] calldata minAmounts,\n uint256 deadline\n ) external returns (uint256[] memory);\n\n function removeLiquidityOneToken(\n uint256 tokenAmount,\n uint8 tokenIndex,\n uint256 minAmount,\n uint256 deadline\n ) external returns (uint256);\n\n function removeLiquidityImbalance(\n uint256[] calldata amounts,\n uint256 maxBurnAmount,\n uint256 deadline\n ) external returns (uint256);\n\n function swapStorage()\n external\n view\n returns (\n uint256 initialA,\n uint256 futureA,\n uint256 initialATime,\n uint256 futureATime,\n uint256 swapFee,\n uint256 adminFee,\n address lpToken\n );\n}\n" + }, + "contracts/amm/helper/GenericERC20.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.6.12;\n\nimport \"@openzeppelin/contracts/token/ERC20/ERC20.sol\";\nimport \"@openzeppelin/contracts/access/Ownable.sol\";\n\n/**\n * @title Generic ERC20 token\n * @notice This contract simulates a generic ERC20 token that is mintable and burnable.\n */\ncontract GenericERC20 is ERC20, Ownable {\n /**\n * @notice Deploy this contract with given name, symbol, and decimals\n * @dev the caller of this constructor will become the owner of this contract\n * @param name_ name of this token\n * @param symbol_ symbol of this token\n * @param decimals_ number of decimals this token will be based on\n */\n constructor(\n string memory name_,\n string memory symbol_,\n uint8 decimals_\n ) public ERC20(name_, symbol_) {\n _setupDecimals(decimals_);\n }\n\n /**\n * @notice Mints given amount of tokens to recipient\n * @dev only owner can call this mint function\n * @param recipient address of account to receive the tokens\n * @param amount amount of tokens to mint\n */\n function mint(address recipient, uint256 amount) external onlyOwner {\n require(amount != 0, \"amount == 0\");\n _mint(recipient, amount);\n }\n}\n" + }, + "contracts/bridge/wrappers/HarmonyBridgeZap.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.6.12;\n\nimport \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/SafeERC20.sol\";\nimport \"../interfaces/ISwap.sol\";\nimport \"../interfaces/ISynapseBridge.sol\";\nimport \"../interfaces/IWETH9.sol\";\n\ninterface IFrax {\n function exchangeCanonicalForOld(address bridge_token_address, uint256 token_amount) external returns (uint256);\n}\n\ncontract HarmonyBridgeZap {\n using SafeERC20 for IERC20;\n\n ISynapseBridge synapseBridge;\n address payable public immutable WETH_ADDRESS;\n IFrax private constant CANOLICAL_FRAX = IFrax(0xFa7191D292d5633f702B0bd7E3E3BcCC0e633200);\n IERC20 private constant SYN_FRAX = IERC20(0x1852F70512298d56e9c8FDd905e02581E04ddb2a);\n\n mapping(address => address) public swapMap;\n mapping(address => IERC20[]) public swapTokensMap;\n\n uint256 constant MAX_UINT256 = 2**256 - 1;\n\n constructor(\n address payable _wethAddress,\n address _swapOne,\n address tokenOne,\n address _swapTwo,\n address tokenTwo,\n address _swapThree,\n address tokenThree,\n ISynapseBridge _synapseBridge\n ) public {\n WETH_ADDRESS = _wethAddress;\n synapseBridge = _synapseBridge;\n swapMap[tokenOne] = _swapOne;\n swapMap[tokenTwo] = _swapTwo;\n swapMap[tokenThree] = _swapThree;\n\n if (address(_swapOne) != address(0)) {\n {\n uint8 i;\n for (; i < 32; i++) {\n try ISwap(_swapOne).getToken(i) returns (\n IERC20 token\n ) {\n swapTokensMap[_swapOne].push(token);\n token.safeApprove(address(_swapOne), MAX_UINT256);\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n } catch {\n break;\n }\n }\n require(i > 1, \"swap must have at least 2 tokens\");\n }\n }\n if (address(_swapTwo) != address(0)) {\n {\n uint8 i;\n for (; i < 32; i++) {\n try ISwap(_swapTwo).getToken(i) returns (\n IERC20 token\n ) {\n swapTokensMap[_swapTwo].push(token);\n token.safeApprove(address(_swapTwo), MAX_UINT256);\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n } catch {\n break;\n }\n }\n require(i > 1, \"swap must have at least 2 tokens\");\n }\n }\n\n if (address(_swapThree) != address(0)) {\n {\n uint8 i;\n for (; i < 32; i++) {\n try ISwap(_swapThree).getToken(i) returns (\n IERC20 token\n ) {\n swapTokensMap[_swapThree].push(token);\n token.safeApprove(address(_swapThree), MAX_UINT256);\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n } catch {\n break;\n }\n }\n require(i > 1, \"swap must have at least 2 tokens\");\n }\n }\n }\n\n /**\n * @notice Calculate amount of tokens you receive on swap\n * @param tokenIndexFrom the token the user wants to sell\n * @param tokenIndexTo the token the user wants to buy\n * @param dx the amount of tokens the user wants to sell. If the token charges\n * a fee on transfers, use the amount that gets transferred after the fee.\n * @return amount of tokens the user will receive\n */\n function calculateSwap(\n IERC20 token,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx\n ) external view virtual returns (uint256) {\n ISwap swap = ISwap(\n swapMap[address(token)]\n );\n return swap.calculateSwap(tokenIndexFrom, tokenIndexTo, dx);\n }\n\n function swapAndRedeem(\n address to,\n uint256 chainId,\n IERC20 token,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx,\n uint256 minDy,\n uint256 deadline\n ) external {\n ISwap swap = ISwap(swapMap[address(token)]);\n require(address(swap) != address(0), \"Swap is 0x00\");\n IERC20[] memory tokens = swapTokensMap[address(swap)];\n tokens[tokenIndexFrom].safeTransferFrom(\n msg.sender,\n address(this),\n dx\n );\n // swap\n\n uint256 swappedAmount = swap.swap(\n tokenIndexFrom,\n tokenIndexTo,\n dx,\n minDy,\n deadline\n );\n // deposit into bridge, gets nUSD\n if (\n token.allowance(address(this), address(synapseBridge)) <\n swappedAmount\n ) {\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n }\n synapseBridge.redeem(to, chainId, token, swappedAmount);\n }\n\n function swapAndRedeemAndSwap(\n address to,\n uint256 chainId,\n IERC20 token,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx,\n uint256 minDy,\n uint256 deadline,\n uint8 swapTokenIndexFrom,\n uint8 swapTokenIndexTo,\n uint256 swapMinDy,\n uint256 swapDeadline\n ) external {\n require(\n address(swapMap[address(token)]) != address(0),\n \"Swap is 0x00\"\n );\n IERC20[] memory tokens = swapTokensMap[\n swapMap[address(token)]\n ];\n tokens[tokenIndexFrom].safeTransferFrom(\n msg.sender,\n address(this),\n dx\n );\n // swap\n\n uint256 swappedAmount = ISwap(swapMap[address(token)]).swap(tokenIndexFrom, tokenIndexTo, dx, minDy, deadline);\n // deposit into bridge, gets nUSD\n if (\n token.allowance(address(this), address(synapseBridge)) <\n swappedAmount\n ) {\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n }\n synapseBridge.redeemAndSwap(\n to,\n chainId,\n token,\n swappedAmount,\n swapTokenIndexFrom,\n swapTokenIndexTo,\n swapMinDy,\n swapDeadline\n );\n }\n\n function swapAndRedeemAndRemove(\n address to,\n uint256 chainId,\n IERC20 token,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx,\n uint256 minDy,\n uint256 deadline,\n uint8 liqTokenIndex,\n uint256 liqMinAmount,\n uint256 liqDeadline\n ) external {\n ISwap swap = ISwap(swapMap[address(token)]);\n require(address(swap) != address(0), \"Swap is 0x00\");\n IERC20[] memory tokens = swapTokensMap[address(swap)];\n tokens[tokenIndexFrom].safeTransferFrom(\n msg.sender,\n address(this),\n dx\n );\n // swap\n\n uint256 swappedAmount = swap.swap(\n tokenIndexFrom,\n tokenIndexTo,\n dx,\n minDy,\n deadline\n );\n // deposit into bridge, gets nUSD\n if (\n token.allowance(address(this), address(synapseBridge)) <\n swappedAmount\n ) {\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n }\n synapseBridge.redeemAndRemove(\n to,\n chainId,\n token,\n swappedAmount,\n liqTokenIndex,\n liqMinAmount,\n liqDeadline\n );\n }\n\n /**\n * @notice wraps SynapseBridge redeem()\n * @param to address on other chain to redeem underlying assets to\n * @param chainId which underlying chain to bridge assets onto\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n **/\n function redeem(\n address to,\n uint256 chainId,\n IERC20 token,\n uint256 amount\n ) external {\n token.safeTransferFrom(msg.sender, address(this), amount);\n if (address(token) == address(CANOLICAL_FRAX)) {\n uint256 swappedAmount = CANOLICAL_FRAX.exchangeCanonicalForOld(address(SYN_FRAX), amount);\n if (SYN_FRAX.allowance(address(this), address(synapseBridge)) < amount) {\n SYN_FRAX.safeApprove(address(synapseBridge), MAX_UINT256);\n }\n synapseBridge.redeem(to, chainId, SYN_FRAX, swappedAmount);\n } else {\n if (token.allowance(address(this), address(synapseBridge)) < amount) {\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n }\n synapseBridge.redeem(to, chainId, token, amount);\n }\n \n }\n\n /**\n * @notice Wraps SynapseBridge redeemv2() function\n * @param to address on other chain to bridge assets to\n * @param chainId which chain to bridge assets onto\n * @param token ERC20 compatible token to redeem into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n **/\n function redeemv2(\n bytes32 to,\n uint256 chainId,\n IERC20 token,\n uint256 amount\n ) external {\n token.safeTransferFrom(msg.sender, address(this), amount);\n\n if (token.allowance(address(this), address(synapseBridge)) < amount) {\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n }\n synapseBridge.redeemv2(to, chainId, token, amount);\n }\n\n /**\n * @notice wraps SynapseBridge redeem()\n * @param to address on other chain to redeem underlying assets to\n * @param chainId which underlying chain to bridge assets onto\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n **/\n function deposit(\n address to,\n uint256 chainId,\n IERC20 token,\n uint256 amount\n ) external {\n token.safeTransferFrom(msg.sender, address(this), amount);\n if (token.allowance(address(this), address(synapseBridge)) < amount) {\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n }\n synapseBridge.deposit(to, chainId, token, amount);\n }\n\n function swapETHAndRedeem(\n address to,\n uint256 chainId,\n IERC20 token,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx,\n uint256 minDy,\n uint256 deadline\n ) external payable {\n require(WETH_ADDRESS != address(0), \"WETH 0\");\n require(msg.value > 0 && msg.value == dx, \"INCORRECT MSG VALUE\");\n ISwap swap = ISwap(swapMap[address(token)]);\n require(address(swap) != address(0), \"Swap is 0x00\");\n IWETH9(WETH_ADDRESS).deposit{value: msg.value}();\n\n // swap\n uint256 swappedAmount = swap.swap(\n tokenIndexFrom,\n tokenIndexTo,\n dx,\n minDy,\n deadline\n );\n synapseBridge.redeem(to, chainId, token, swappedAmount);\n }\n\n /**\n * @notice Wraps redeemAndSwap on SynapseBridge.sol\n * Relays to nodes that (typically) a wrapped synAsset ERC20 token has been burned and the underlying needs to be redeeemed on the native chain. This function indicates to the nodes that they should attempt to redeem the LP token for the underlying assets (E.g \"swap\" out of the LP token)\n * @param to address on other chain to redeem underlying assets to\n * @param chainId which underlying chain to bridge assets onto\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n * @param tokenIndexFrom the token the user wants to swap from\n * @param tokenIndexTo the token the user wants to swap to\n * @param minDy the min amount the user would like to receive, or revert to only minting the SynERC20 token crosschain.\n * @param deadline latest timestamp to accept this transaction\n **/\n function redeemAndSwap(\n address to,\n uint256 chainId,\n IERC20 token,\n uint256 amount,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 minDy,\n uint256 deadline\n ) external {\n token.safeTransferFrom(msg.sender, address(this), amount);\n if (token.allowance(address(this), address(synapseBridge)) < amount) {\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n }\n synapseBridge.redeemAndSwap(\n to,\n chainId,\n token,\n amount,\n tokenIndexFrom,\n tokenIndexTo,\n minDy,\n deadline\n );\n }\n\n /**\n * @notice Wraps redeemAndRemove on SynapseBridge\n * Relays to nodes that (typically) a wrapped synAsset ERC20 token has been burned and the underlying needs to be redeeemed on the native chain. This function indicates to the nodes that they should attempt to redeem the LP token for the underlying assets (E.g \"swap\" out of the LP token)\n * @param to address on other chain to redeem underlying assets to\n * @param chainId which underlying chain to bridge assets onto\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount of (typically) LP token to pass to the nodes to attempt to removeLiquidity() with to redeem for the underlying assets of the LP token\n * @param liqTokenIndex Specifies which of the underlying LP assets the nodes should attempt to redeem for\n * @param liqMinAmount Specifies the minimum amount of the underlying asset needed for the nodes to execute the redeem/swap\n * @param liqDeadline Specificies the deadline that the nodes are allowed to try to redeem/swap the LP token\n **/\n function redeemAndRemove(\n address to,\n uint256 chainId,\n IERC20 token,\n uint256 amount,\n uint8 liqTokenIndex,\n uint256 liqMinAmount,\n uint256 liqDeadline\n ) external {\n token.safeTransferFrom(msg.sender, address(this), amount);\n if (token.allowance(address(this), address(synapseBridge)) < amount) {\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n }\n synapseBridge.redeemAndRemove(\n to,\n chainId,\n token,\n amount,\n liqTokenIndex,\n liqMinAmount,\n liqDeadline\n );\n }\n}\n" + }, + "contracts/bridge/wrappers/AvalancheBridgeZap.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.6.12;\n\nimport \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/SafeERC20.sol\";\nimport \"../interfaces/ISwap.sol\";\nimport \"../interfaces/ISynapseBridge.sol\";\nimport \"../interfaces/IWETH9.sol\";\n\ncontract AvalancheBridgeZap {\n using SafeERC20 for IERC20;\n\n ISynapseBridge synapseBridge;\n address payable public immutable WETH_ADDRESS;\n\n mapping(address => address) public swapMap;\n mapping(address => IERC20[]) public swapTokensMap;\n\n uint256 constant MAX_UINT256 = 2**256 - 1;\n\n constructor(\n address payable _wethAddress,\n address _swapOne,\n address tokenOne,\n address _swapTwo,\n address tokenTwo,\n ISynapseBridge _synapseBridge\n ) public {\n WETH_ADDRESS = _wethAddress;\n synapseBridge = _synapseBridge;\n swapMap[tokenOne] = _swapOne;\n swapMap[tokenTwo] = _swapTwo;\n if (_wethAddress != address(0)) {\n IERC20(_wethAddress).safeIncreaseAllowance(address(_synapseBridge), MAX_UINT256);\n }\n if (address(_swapOne) != address(0)) {\n {\n uint8 i;\n for (; i < 32; i++) {\n try ISwap(_swapOne).getToken(i) returns (\n IERC20 token\n ) {\n swapTokensMap[_swapOne].push(token);\n token.safeApprove(address(_swapOne), MAX_UINT256);\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n } catch {\n break;\n }\n }\n require(i > 1, \"swap must have at least 2 tokens\");\n }\n }\n if (address(_swapTwo) != address(0)) {\n {\n uint8 i;\n for (; i < 32; i++) {\n try ISwap(_swapTwo).getToken(i) returns (\n IERC20 token\n ) {\n swapTokensMap[_swapTwo].push(token);\n token.safeApprove(address(_swapTwo), MAX_UINT256);\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n } catch {\n break;\n }\n }\n require(i > 1, \"swap must have at least 2 tokens\");\n }\n }\n }\n\n /**\n * @notice Calculate amount of tokens you receive on swap\n * @param tokenIndexFrom the token the user wants to sell\n * @param tokenIndexTo the token the user wants to buy\n * @param dx the amount of tokens the user wants to sell. If the token charges\n * a fee on transfers, use the amount that gets transferred after the fee.\n * @return amount of tokens the user will receive\n */\n function calculateSwap(\n IERC20 token,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx\n ) external view virtual returns (uint256) {\n ISwap swap = ISwap(\n swapMap[address(token)]\n );\n return swap.calculateSwap(tokenIndexFrom, tokenIndexTo, dx);\n }\n\n function swapAndRedeem(\n address to,\n uint256 chainId,\n IERC20 token,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx,\n uint256 minDy,\n uint256 deadline\n ) external {\n ISwap swap = ISwap(swapMap[address(token)]);\n require(address(swap) != address(0), \"Swap is 0x00\");\n IERC20[] memory tokens = swapTokensMap[address(swap)];\n tokens[tokenIndexFrom].safeTransferFrom(\n msg.sender,\n address(this),\n dx\n );\n // swap\n\n uint256 swappedAmount = swap.swap(\n tokenIndexFrom,\n tokenIndexTo,\n dx,\n minDy,\n deadline\n );\n // deposit into bridge, gets nUSD\n if (\n token.allowance(address(this), address(synapseBridge)) <\n swappedAmount\n ) {\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n }\n synapseBridge.redeem(to, chainId, token, swappedAmount);\n }\n\n function swapAndRedeemAndSwap(\n address to,\n uint256 chainId,\n IERC20 token,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx,\n uint256 minDy,\n uint256 deadline,\n uint8 swapTokenIndexFrom,\n uint8 swapTokenIndexTo,\n uint256 swapMinDy,\n uint256 swapDeadline\n ) external {\n require(\n address(swapMap[address(token)]) != address(0),\n \"Swap is 0x00\"\n );\n IERC20[] memory tokens = swapTokensMap[\n swapMap[address(token)]\n ];\n tokens[tokenIndexFrom].safeTransferFrom(\n msg.sender,\n address(this),\n dx\n );\n // swap\n\n uint256 swappedAmount = ISwap(swapMap[address(token)]).swap(tokenIndexFrom, tokenIndexTo, dx, minDy, deadline);\n // deposit into bridge, gets nUSD\n if (\n token.allowance(address(this), address(synapseBridge)) <\n swappedAmount\n ) {\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n }\n synapseBridge.redeemAndSwap(\n to,\n chainId,\n token,\n swappedAmount,\n swapTokenIndexFrom,\n swapTokenIndexTo,\n swapMinDy,\n swapDeadline\n );\n }\n\n function swapAndRedeemAndRemove(\n address to,\n uint256 chainId,\n IERC20 token,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx,\n uint256 minDy,\n uint256 deadline,\n uint8 liqTokenIndex,\n uint256 liqMinAmount,\n uint256 liqDeadline\n ) external {\n ISwap swap = ISwap(swapMap[address(token)]);\n require(address(swap) != address(0), \"Swap is 0x00\");\n IERC20[] memory tokens = swapTokensMap[address(swap)];\n tokens[tokenIndexFrom].safeTransferFrom(\n msg.sender,\n address(this),\n dx\n );\n // swap\n\n uint256 swappedAmount = swap.swap(\n tokenIndexFrom,\n tokenIndexTo,\n dx,\n minDy,\n deadline\n );\n // deposit into bridge, gets nUSD\n if (\n token.allowance(address(this), address(synapseBridge)) <\n swappedAmount\n ) {\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n }\n synapseBridge.redeemAndRemove(\n to,\n chainId,\n token,\n swappedAmount,\n liqTokenIndex,\n liqMinAmount,\n liqDeadline\n );\n }\n\n /**\n * @notice wraps SynapseBridge redeem()\n * @param to address on other chain to redeem underlying assets to\n * @param chainId which underlying chain to bridge assets onto\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n **/\n function redeem(\n address to,\n uint256 chainId,\n IERC20 token,\n uint256 amount\n ) external {\n token.safeTransferFrom(msg.sender, address(this), amount);\n if (token.allowance(address(this), address(synapseBridge)) < amount) {\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n }\n synapseBridge.redeem(to, chainId, token, amount);\n }\n\n /**\n * @notice wraps SynapseBridge redeem()\n * @param to address on other chain to redeem underlying assets to\n * @param chainId which underlying chain to bridge assets onto\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n **/\n function deposit(\n address to,\n uint256 chainId,\n IERC20 token,\n uint256 amount\n ) external {\n token.safeTransferFrom(msg.sender, address(this), amount);\n if (token.allowance(address(this), address(synapseBridge)) < amount) {\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n }\n synapseBridge.deposit(to, chainId, token, amount);\n }\n\n /**\n * @notice Wraps SynapseBridge deposit() function to make it compatible w/ ETH -> WETH conversions\n * @param to address on other chain to bridge assets to\n * @param chainId which chain to bridge assets onto\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n **/\n function depositETH(\n address to,\n uint256 chainId,\n uint256 amount\n ) external payable {\n require(msg.value > 0 && msg.value == amount, 'INCORRECT MSG VALUE');\n IWETH9(WETH_ADDRESS).deposit{value: msg.value}();\n synapseBridge.deposit(to, chainId, IERC20(WETH_ADDRESS), amount);\n }\n\n\n function swapETHAndRedeem(\n address to,\n uint256 chainId,\n IERC20 token,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx,\n uint256 minDy,\n uint256 deadline\n ) external payable {\n require(WETH_ADDRESS != address(0), \"WETH 0\");\n require(msg.value > 0 && msg.value == dx, \"INCORRECT MSG VALUE\");\n ISwap swap = ISwap(swapMap[address(token)]);\n require(address(swap) != address(0), \"Swap is 0x00\");\n IWETH9(WETH_ADDRESS).deposit{value: msg.value}();\n\n // swap\n uint256 swappedAmount = swap.swap(\n tokenIndexFrom,\n tokenIndexTo,\n dx,\n minDy,\n deadline\n );\n synapseBridge.redeem(to, chainId, token, swappedAmount);\n }\n\n\n function swapETHAndRedeemAndSwap(\n address to,\n uint256 chainId,\n IERC20 token,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx,\n uint256 minDy,\n uint256 deadline,\n uint8 swapTokenIndexFrom,\n uint8 swapTokenIndexTo,\n uint256 swapMinDy,\n uint256 swapDeadline\n ) external payable {\n require(WETH_ADDRESS != address(0), \"WETH 0\");\n require(msg.value > 0 && msg.value == dx, \"INCORRECT MSG VALUE\");\n ISwap swap = ISwap(swapMap[address(token)]);\n require(address(swap) != address(0), \"Swap is 0x00\");\n IWETH9(WETH_ADDRESS).deposit{value: msg.value}();\n\n // swap\n uint256 swappedAmount = swap.swap(\n tokenIndexFrom,\n tokenIndexTo,\n dx,\n minDy,\n deadline\n );\n synapseBridge.redeemAndSwap(to, chainId, token, swappedAmount,swapTokenIndexFrom,\n swapTokenIndexTo,\n swapMinDy,\n swapDeadline);\n }\n\n\n /**\n * @notice Wraps redeemAndSwap on SynapseBridge.sol\n * Relays to nodes that (typically) a wrapped synAsset ERC20 token has been burned and the underlying needs to be redeeemed on the native chain. This function indicates to the nodes that they should attempt to redeem the LP token for the underlying assets (E.g \"swap\" out of the LP token)\n * @param to address on other chain to redeem underlying assets to\n * @param chainId which underlying chain to bridge assets onto\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n * @param tokenIndexFrom the token the user wants to swap from\n * @param tokenIndexTo the token the user wants to swap to\n * @param minDy the min amount the user would like to receive, or revert to only minting the SynERC20 token crosschain.\n * @param deadline latest timestamp to accept this transaction\n **/\n function redeemAndSwap(\n address to,\n uint256 chainId,\n IERC20 token,\n uint256 amount,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 minDy,\n uint256 deadline\n ) external {\n token.safeTransferFrom(msg.sender, address(this), amount);\n if (token.allowance(address(this), address(synapseBridge)) < amount) {\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n }\n synapseBridge.redeemAndSwap(\n to,\n chainId,\n token,\n amount,\n tokenIndexFrom,\n tokenIndexTo,\n minDy,\n deadline\n );\n }\n\n /**\n * @notice Wraps redeemAndRemove on SynapseBridge\n * Relays to nodes that (typically) a wrapped synAsset ERC20 token has been burned and the underlying needs to be redeeemed on the native chain. This function indicates to the nodes that they should attempt to redeem the LP token for the underlying assets (E.g \"swap\" out of the LP token)\n * @param to address on other chain to redeem underlying assets to\n * @param chainId which underlying chain to bridge assets onto\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount of (typically) LP token to pass to the nodes to attempt to removeLiquidity() with to redeem for the underlying assets of the LP token\n * @param liqTokenIndex Specifies which of the underlying LP assets the nodes should attempt to redeem for\n * @param liqMinAmount Specifies the minimum amount of the underlying asset needed for the nodes to execute the redeem/swap\n * @param liqDeadline Specificies the deadline that the nodes are allowed to try to redeem/swap the LP token\n **/\n function redeemAndRemove(\n address to,\n uint256 chainId,\n IERC20 token,\n uint256 amount,\n uint8 liqTokenIndex,\n uint256 liqMinAmount,\n uint256 liqDeadline\n ) external {\n token.safeTransferFrom(msg.sender, address(this), amount);\n if (token.allowance(address(this), address(synapseBridge)) < amount) {\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n }\n synapseBridge.redeemAndRemove(\n to,\n chainId,\n token,\n amount,\n liqTokenIndex,\n liqMinAmount,\n liqDeadline\n );\n }\n\n /**\n * @notice Wraps SynapseBridge redeemv2() function\n * @param to address on other chain to bridge assets to\n * @param chainId which chain to bridge assets onto\n * @param token ERC20 compatible token to redeem into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n **/\n function redeemv2(\n bytes32 to,\n uint256 chainId,\n IERC20 token,\n uint256 amount\n ) external {\n token.safeTransferFrom(msg.sender, address(this), amount);\n\n if (token.allowance(address(this), address(synapseBridge)) < amount) {\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n }\n synapseBridge.redeemv2(to, chainId, token, amount);\n }\n}\n" + }, + "contracts/bridge/SynapseBridge.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.6.12;\n\nimport \"@openzeppelin/contracts-upgradeable/proxy/Initializable.sol\";\nimport \"@openzeppelin/contracts-upgradeable/access/AccessControlUpgradeable.sol\";\nimport \"@openzeppelin/contracts-upgradeable/utils/ReentrancyGuardUpgradeable.sol\";\nimport \"@openzeppelin/contracts-upgradeable/utils/PausableUpgradeable.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/SafeERC20.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/ERC20Burnable.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport \"@openzeppelin/contracts/math/SafeMath.sol\";\n\nimport \"./interfaces/ISwap.sol\";\nimport \"./interfaces/IWETH9.sol\";\n\ninterface IERC20Mintable is IERC20 {\n function mint(address to, uint256 amount) external;\n}\n\ncontract SynapseBridge is\n Initializable,\n AccessControlUpgradeable,\n ReentrancyGuardUpgradeable,\n PausableUpgradeable\n{\n using SafeERC20 for IERC20;\n using SafeERC20 for IERC20Mintable;\n using SafeMath for uint256;\n\n bytes32 public constant NODEGROUP_ROLE = keccak256(\"NODEGROUP_ROLE\");\n bytes32 public constant GOVERNANCE_ROLE = keccak256(\"GOVERNANCE_ROLE\");\n\n mapping(address => uint256) private fees;\n\n uint256 public startBlockNumber;\n uint256 public constant bridgeVersion = 6;\n uint256 public chainGasAmount;\n address payable public WETH_ADDRESS;\n\n mapping(bytes32 => bool) private kappaMap;\n\n receive() external payable {}\n\n function initialize() external initializer {\n startBlockNumber = block.number;\n _setupRole(DEFAULT_ADMIN_ROLE, msg.sender);\n __AccessControl_init();\n }\n\n function setChainGasAmount(uint256 amount) external {\n require(hasRole(GOVERNANCE_ROLE, msg.sender), \"Not governance\");\n chainGasAmount = amount;\n }\n\n function setWethAddress(address payable _wethAddress) external {\n require(hasRole(DEFAULT_ADMIN_ROLE, msg.sender), \"Not admin\");\n WETH_ADDRESS = _wethAddress;\n }\n\n function addKappas(bytes32[] calldata kappas) external {\n require(hasRole(GOVERNANCE_ROLE, msg.sender), \"Not governance\");\n for (uint256 i = 0; i < kappas.length; ++i) {\n kappaMap[kappas[i]] = true;\n }\n }\n\n event TokenDeposit(\n address indexed to,\n uint256 chainId,\n IERC20 token,\n uint256 amount\n );\n event TokenRedeem(\n address indexed to,\n uint256 chainId,\n IERC20 token,\n uint256 amount\n );\n event TokenWithdraw(\n address indexed to,\n IERC20 token,\n uint256 amount,\n uint256 fee,\n bytes32 indexed kappa\n );\n event TokenMint(\n address indexed to,\n IERC20Mintable token,\n uint256 amount,\n uint256 fee,\n bytes32 indexed kappa\n );\n event TokenDepositAndSwap(\n address indexed to,\n uint256 chainId,\n IERC20 token,\n uint256 amount,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 minDy,\n uint256 deadline\n );\n event TokenMintAndSwap(\n address indexed to,\n IERC20Mintable token,\n uint256 amount,\n uint256 fee,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 minDy,\n uint256 deadline,\n bool swapSuccess,\n bytes32 indexed kappa\n );\n event TokenRedeemAndSwap(\n address indexed to,\n uint256 chainId,\n IERC20 token,\n uint256 amount,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 minDy,\n uint256 deadline\n );\n event TokenRedeemAndRemove(\n address indexed to,\n uint256 chainId,\n IERC20 token,\n uint256 amount,\n uint8 swapTokenIndex,\n uint256 swapMinAmount,\n uint256 swapDeadline\n );\n event TokenWithdrawAndRemove(\n address indexed to,\n IERC20 token,\n uint256 amount,\n uint256 fee,\n uint8 swapTokenIndex,\n uint256 swapMinAmount,\n uint256 swapDeadline,\n bool swapSuccess,\n bytes32 indexed kappa\n );\n\n // v2 events\n event TokenRedeemV2(\n bytes32 indexed to,\n uint256 chainId,\n IERC20 token,\n uint256 amount\n );\n\n // VIEW FUNCTIONS ***/\n function getFeeBalance(address tokenAddress)\n external\n view\n returns (uint256)\n {\n return fees[tokenAddress];\n }\n\n function kappaExists(bytes32 kappa) external view returns (bool) {\n return kappaMap[kappa];\n }\n\n // FEE FUNCTIONS ***/\n /**\n * * @notice withdraw specified ERC20 token fees to a given address\n * * @param token ERC20 token in which fees acccumulated to transfer\n * * @param to Address to send the fees to\n */\n function withdrawFees(IERC20 token, address to) external whenNotPaused {\n require(hasRole(GOVERNANCE_ROLE, msg.sender), \"Not governance\");\n require(to != address(0), \"Address is 0x000\");\n if (fees[address(token)] != 0) {\n token.safeTransfer(to, fees[address(token)]);\n fees[address(token)] = 0;\n }\n }\n\n // PAUSABLE FUNCTIONS ***/\n function pause() external {\n require(hasRole(GOVERNANCE_ROLE, msg.sender), \"Not governance\");\n _pause();\n }\n\n function unpause() external {\n require(hasRole(GOVERNANCE_ROLE, msg.sender), \"Not governance\");\n _unpause();\n }\n\n /**\n * @notice Relays to nodes to transfers an ERC20 token cross-chain\n * @param to address on other chain to bridge assets to\n * @param chainId which chain to bridge assets onto\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n **/\n function deposit(\n address to,\n uint256 chainId,\n IERC20 token,\n uint256 amount\n ) external nonReentrant whenNotPaused {\n emit TokenDeposit(to, chainId, token, amount);\n token.safeTransferFrom(msg.sender, address(this), amount);\n }\n\n /**\n * @notice Relays to nodes that (typically) a wrapped synAsset ERC20 token has been burned and the underlying needs to be redeeemed on the native chain\n * @param to address on other chain to redeem underlying assets to\n * @param chainId which underlying chain to bridge assets onto\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n **/\n function redeem(\n address to,\n uint256 chainId,\n ERC20Burnable token,\n uint256 amount\n ) external nonReentrant whenNotPaused {\n emit TokenRedeem(to, chainId, token, amount);\n token.burnFrom(msg.sender, amount);\n }\n\n /**\n * @notice Function to be called by the node group to withdraw the underlying assets from the contract\n * @param to address on chain to send underlying assets to\n * @param token ERC20 compatible token to withdraw from the bridge\n * @param amount Amount in native token decimals to withdraw\n * @param fee Amount in native token decimals to save to the contract as fees\n * @param kappa kappa\n **/\n function withdraw(\n address to,\n IERC20 token,\n uint256 amount,\n uint256 fee,\n bytes32 kappa\n ) external nonReentrant whenNotPaused {\n require(\n hasRole(NODEGROUP_ROLE, msg.sender),\n \"Caller is not a node group\"\n );\n require(amount > fee, \"Amount must be greater than fee\");\n require(!kappaMap[kappa], \"Kappa is already present\");\n kappaMap[kappa] = true;\n fees[address(token)] = fees[address(token)].add(fee);\n if (address(token) == WETH_ADDRESS && WETH_ADDRESS != address(0)) {\n IWETH9(WETH_ADDRESS).withdraw(amount.sub(fee));\n (bool success, ) = to.call{value: amount.sub(fee)}(\"\");\n require(success, \"ETH_TRANSFER_FAILED\");\n emit TokenWithdraw(to, token, amount, fee, kappa);\n } else {\n emit TokenWithdraw(to, token, amount, fee, kappa);\n token.safeTransfer(to, amount.sub(fee));\n }\n }\n\n /**\n * @notice Nodes call this function to mint a SynERC20 (or any asset that the bridge is given minter access to). This is called by the nodes after a TokenDeposit event is emitted.\n * @dev This means the SynapseBridge.sol contract must have minter access to the token attempting to be minted\n * @param to address on other chain to redeem underlying assets to\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain post-fees\n * @param fee Amount in native token decimals to save to the contract as fees\n * @param kappa kappa\n **/\n function mint(\n address payable to,\n IERC20Mintable token,\n uint256 amount,\n uint256 fee,\n bytes32 kappa\n ) external nonReentrant whenNotPaused {\n require(\n hasRole(NODEGROUP_ROLE, msg.sender),\n \"Caller is not a node group\"\n );\n require(amount > fee, \"Amount must be greater than fee\");\n require(!kappaMap[kappa], \"Kappa is already present\");\n kappaMap[kappa] = true;\n fees[address(token)] = fees[address(token)].add(fee);\n emit TokenMint(to, token, amount.sub(fee), fee, kappa);\n token.mint(address(this), amount);\n IERC20(token).safeTransfer(to, amount.sub(fee));\n if (chainGasAmount != 0 && address(this).balance > chainGasAmount) {\n to.call.value(chainGasAmount)(\"\");\n }\n }\n\n /**\n * @notice Relays to nodes to both transfer an ERC20 token cross-chain, and then have the nodes execute a swap through a liquidity pool on behalf of the user.\n * @param to address on other chain to bridge assets to\n * @param chainId which chain to bridge assets onto\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n * @param tokenIndexFrom the token the user wants to swap from\n * @param tokenIndexTo the token the user wants to swap to\n * @param minDy the min amount the user would like to receive, or revert to only minting the SynERC20 token crosschain.\n * @param deadline latest timestamp to accept this transaction\n **/\n function depositAndSwap(\n address to,\n uint256 chainId,\n IERC20 token,\n uint256 amount,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 minDy,\n uint256 deadline\n ) external nonReentrant whenNotPaused {\n emit TokenDepositAndSwap(\n to,\n chainId,\n token,\n amount,\n tokenIndexFrom,\n tokenIndexTo,\n minDy,\n deadline\n );\n token.safeTransferFrom(msg.sender, address(this), amount);\n }\n\n /**\n * @notice Relays to nodes that (typically) a wrapped synAsset ERC20 token has been burned and the underlying needs to be redeeemed on the native chain. This function indicates to the nodes that they should attempt to redeem the LP token for the underlying assets (E.g \"swap\" out of the LP token)\n * @param to address on other chain to redeem underlying assets to\n * @param chainId which underlying chain to bridge assets onto\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n * @param tokenIndexFrom the token the user wants to swap from\n * @param tokenIndexTo the token the user wants to swap to\n * @param minDy the min amount the user would like to receive, or revert to only minting the SynERC20 token crosschain.\n * @param deadline latest timestamp to accept this transaction\n **/\n function redeemAndSwap(\n address to,\n uint256 chainId,\n ERC20Burnable token,\n uint256 amount,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 minDy,\n uint256 deadline\n ) external nonReentrant whenNotPaused {\n emit TokenRedeemAndSwap(\n to,\n chainId,\n token,\n amount,\n tokenIndexFrom,\n tokenIndexTo,\n minDy,\n deadline\n );\n token.burnFrom(msg.sender, amount);\n }\n\n /**\n * @notice Relays to nodes that (typically) a wrapped synAsset ERC20 token has been burned and the underlying needs to be redeeemed on the native chain. This function indicates to the nodes that they should attempt to redeem the LP token for the underlying assets (E.g \"swap\" out of the LP token)\n * @param to address on other chain to redeem underlying assets to\n * @param chainId which underlying chain to bridge assets onto\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n * @param swapTokenIndex Specifies which of the underlying LP assets the nodes should attempt to redeem for\n * @param swapMinAmount Specifies the minimum amount of the underlying asset needed for the nodes to execute the redeem/swap\n * @param swapDeadline Specificies the deadline that the nodes are allowed to try to redeem/swap the LP token\n **/\n function redeemAndRemove(\n address to,\n uint256 chainId,\n ERC20Burnable token,\n uint256 amount,\n uint8 swapTokenIndex,\n uint256 swapMinAmount,\n uint256 swapDeadline\n ) external nonReentrant whenNotPaused {\n emit TokenRedeemAndRemove(\n to,\n chainId,\n token,\n amount,\n swapTokenIndex,\n swapMinAmount,\n swapDeadline\n );\n token.burnFrom(msg.sender, amount);\n }\n\n /**\n * @notice Nodes call this function to mint a SynERC20 (or any asset that the bridge is given minter access to), and then attempt to swap the SynERC20 into the desired destination asset. This is called by the nodes after a TokenDepositAndSwap event is emitted.\n * @dev This means the BridgeDeposit.sol contract must have minter access to the token attempting to be minted\n * @param to address on other chain to redeem underlying assets to\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain post-fees\n * @param fee Amount in native token decimals to save to the contract as fees\n * @param pool Destination chain's pool to use to swap SynERC20 -> Asset. The nodes determine this by using PoolConfig.sol.\n * @param tokenIndexFrom Index of the SynERC20 asset in the pool\n * @param tokenIndexTo Index of the desired final asset\n * @param minDy Minumum amount (in final asset decimals) that must be swapped for, otherwise the user will receive the SynERC20.\n * @param deadline Epoch time of the deadline that the swap is allowed to be executed.\n * @param kappa kappa\n **/\n function mintAndSwap(\n address payable to,\n IERC20Mintable token,\n uint256 amount,\n uint256 fee,\n ISwap pool,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 minDy,\n uint256 deadline,\n bytes32 kappa\n ) external nonReentrant whenNotPaused {\n require(\n hasRole(NODEGROUP_ROLE, msg.sender),\n \"Caller is not a node group\"\n );\n require(amount > fee, \"Amount must be greater than fee\");\n require(!kappaMap[kappa], \"Kappa is already present\");\n kappaMap[kappa] = true;\n fees[address(token)] = fees[address(token)].add(fee);\n // Transfer gas airdrop\n if (chainGasAmount != 0 && address(this).balance > chainGasAmount) {\n to.call.value(chainGasAmount)(\"\");\n }\n // first check to make sure more will be given than min amount required\n uint256 expectedOutput = ISwap(pool).calculateSwap(\n tokenIndexFrom,\n tokenIndexTo,\n amount.sub(fee)\n );\n\n if (expectedOutput >= minDy) {\n // proceed with swap\n token.mint(address(this), amount);\n token.safeIncreaseAllowance(address(pool), amount);\n try\n ISwap(pool).swap(\n tokenIndexFrom,\n tokenIndexTo,\n amount.sub(fee),\n minDy,\n deadline\n )\n returns (uint256 finalSwappedAmount) {\n // Swap succeeded, transfer swapped asset\n IERC20 swappedTokenTo = ISwap(pool).getToken(tokenIndexTo);\n if (\n address(swappedTokenTo) == WETH_ADDRESS &&\n WETH_ADDRESS != address(0)\n ) {\n IWETH9(WETH_ADDRESS).withdraw(finalSwappedAmount);\n (bool success, ) = to.call{value: finalSwappedAmount}(\"\");\n require(success, \"ETH_TRANSFER_FAILED\");\n emit TokenMintAndSwap(\n to,\n token,\n finalSwappedAmount,\n fee,\n tokenIndexFrom,\n tokenIndexTo,\n minDy,\n deadline,\n true,\n kappa\n );\n } else {\n swappedTokenTo.safeTransfer(to, finalSwappedAmount);\n emit TokenMintAndSwap(\n to,\n token,\n finalSwappedAmount,\n fee,\n tokenIndexFrom,\n tokenIndexTo,\n minDy,\n deadline,\n true,\n kappa\n );\n }\n } catch {\n IERC20(token).safeTransfer(to, amount.sub(fee));\n emit TokenMintAndSwap(\n to,\n token,\n amount.sub(fee),\n fee,\n tokenIndexFrom,\n tokenIndexTo,\n minDy,\n deadline,\n false,\n kappa\n );\n }\n } else {\n token.mint(address(this), amount);\n IERC20(token).safeTransfer(to, amount.sub(fee));\n emit TokenMintAndSwap(\n to,\n token,\n amount.sub(fee),\n fee,\n tokenIndexFrom,\n tokenIndexTo,\n minDy,\n deadline,\n false,\n kappa\n );\n }\n }\n\n /**\n * @notice Function to be called by the node group to withdraw the underlying assets from the contract\n * @param to address on chain to send underlying assets to\n * @param token ERC20 compatible token to withdraw from the bridge\n * @param amount Amount in native token decimals to withdraw\n * @param fee Amount in native token decimals to save to the contract as fees\n * @param pool Destination chain's pool to use to swap SynERC20 -> Asset. The nodes determine this by using PoolConfig.sol.\n * @param swapTokenIndex Specifies which of the underlying LP assets the nodes should attempt to redeem for\n * @param swapMinAmount Specifies the minimum amount of the underlying asset needed for the nodes to execute the redeem/swap\n * @param swapDeadline Specificies the deadline that the nodes are allowed to try to redeem/swap the LP token\n * @param kappa kappa\n **/\n function withdrawAndRemove(\n address to,\n IERC20 token,\n uint256 amount,\n uint256 fee,\n ISwap pool,\n uint8 swapTokenIndex,\n uint256 swapMinAmount,\n uint256 swapDeadline,\n bytes32 kappa\n ) external nonReentrant whenNotPaused {\n require(\n hasRole(NODEGROUP_ROLE, msg.sender),\n \"Caller is not a node group\"\n );\n require(amount > fee, \"Amount must be greater than fee\");\n require(!kappaMap[kappa], \"Kappa is already present\");\n kappaMap[kappa] = true;\n fees[address(token)] = fees[address(token)].add(fee);\n // first check to make sure more will be given than min amount required\n uint256 expectedOutput = ISwap(pool).calculateRemoveLiquidityOneToken(\n amount.sub(fee),\n swapTokenIndex\n );\n\n if (expectedOutput >= swapMinAmount) {\n token.safeIncreaseAllowance(address(pool), amount.sub(fee));\n try\n ISwap(pool).removeLiquidityOneToken(\n amount.sub(fee),\n swapTokenIndex,\n swapMinAmount,\n swapDeadline\n )\n returns (uint256 finalSwappedAmount) {\n // Swap succeeded, transfer swapped asset\n IERC20 swappedTokenTo = ISwap(pool).getToken(swapTokenIndex);\n swappedTokenTo.safeTransfer(to, finalSwappedAmount);\n emit TokenWithdrawAndRemove(\n to,\n token,\n finalSwappedAmount,\n fee,\n swapTokenIndex,\n swapMinAmount,\n swapDeadline,\n true,\n kappa\n );\n } catch {\n IERC20(token).safeTransfer(to, amount.sub(fee));\n emit TokenWithdrawAndRemove(\n to,\n token,\n amount.sub(fee),\n fee,\n swapTokenIndex,\n swapMinAmount,\n swapDeadline,\n false,\n kappa\n );\n }\n } else {\n token.safeTransfer(to, amount.sub(fee));\n emit TokenWithdrawAndRemove(\n to,\n token,\n amount.sub(fee),\n fee,\n swapTokenIndex,\n swapMinAmount,\n swapDeadline,\n false,\n kappa\n );\n }\n }\n\n // BRIDGE FUNCTIONS TO HANDLE DIFF ADDRESSES\n /**\n * @notice Relays to nodes that (typically) a wrapped synAsset ERC20 token has been burned and the underlying needs to be redeeemed on the native chain\n * @param to address on other chain to redeem underlying assets to\n * @param chainId which underlying chain to bridge assets onto\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n **/\n function redeemV2(\n bytes32 to,\n uint256 chainId,\n ERC20Burnable token,\n uint256 amount\n ) external nonReentrant whenNotPaused {\n emit TokenRedeemV2(to, chainId, token, amount);\n token.burnFrom(msg.sender, amount);\n }\n}\n" + }, + "@openzeppelin/contracts-upgradeable/access/AccessControlUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <0.8.0;\n\nimport \"../utils/EnumerableSetUpgradeable.sol\";\nimport \"../utils/AddressUpgradeable.sol\";\nimport \"../utils/ContextUpgradeable.sol\";\nimport \"../proxy/Initializable.sol\";\n\n/**\n * @dev Contract module that allows children to implement role-based access\n * control mechanisms.\n *\n * Roles are referred to by their `bytes32` identifier. These should be exposed\n * in the external API and be unique. The best way to achieve this is by\n * using `public constant` hash digests:\n *\n * ```\n * bytes32 public constant MY_ROLE = keccak256(\"MY_ROLE\");\n * ```\n *\n * Roles can be used to represent a set of permissions. To restrict access to a\n * function call, use {hasRole}:\n *\n * ```\n * function foo() public {\n * require(hasRole(MY_ROLE, msg.sender));\n * ...\n * }\n * ```\n *\n * Roles can be granted and revoked dynamically via the {grantRole} and\n * {revokeRole} functions. Each role has an associated admin role, and only\n * accounts that have a role's admin role can call {grantRole} and {revokeRole}.\n *\n * By default, the admin role for all roles is `DEFAULT_ADMIN_ROLE`, which means\n * that only accounts with this role will be able to grant or revoke other\n * roles. More complex role relationships can be created by using\n * {_setRoleAdmin}.\n *\n * WARNING: The `DEFAULT_ADMIN_ROLE` is also its own admin: it has permission to\n * grant and revoke this role. Extra precautions should be taken to secure\n * accounts that have been granted it.\n */\nabstract contract AccessControlUpgradeable is Initializable, ContextUpgradeable {\n function __AccessControl_init() internal initializer {\n __Context_init_unchained();\n __AccessControl_init_unchained();\n }\n\n function __AccessControl_init_unchained() internal initializer {\n }\n using EnumerableSetUpgradeable for EnumerableSetUpgradeable.AddressSet;\n using AddressUpgradeable for address;\n\n struct RoleData {\n EnumerableSetUpgradeable.AddressSet members;\n bytes32 adminRole;\n }\n\n mapping (bytes32 => RoleData) private _roles;\n\n bytes32 public constant DEFAULT_ADMIN_ROLE = 0x00;\n\n /**\n * @dev Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole`\n *\n * `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite\n * {RoleAdminChanged} not being emitted signaling this.\n *\n * _Available since v3.1._\n */\n event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole);\n\n /**\n * @dev Emitted when `account` is granted `role`.\n *\n * `sender` is the account that originated the contract call, an admin role\n * bearer except when using {_setupRole}.\n */\n event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender);\n\n /**\n * @dev Emitted when `account` is revoked `role`.\n *\n * `sender` is the account that originated the contract call:\n * - if using `revokeRole`, it is the admin role bearer\n * - if using `renounceRole`, it is the role bearer (i.e. `account`)\n */\n event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender);\n\n /**\n * @dev Returns `true` if `account` has been granted `role`.\n */\n function hasRole(bytes32 role, address account) public view returns (bool) {\n return _roles[role].members.contains(account);\n }\n\n /**\n * @dev Returns the number of accounts that have `role`. Can be used\n * together with {getRoleMember} to enumerate all bearers of a role.\n */\n function getRoleMemberCount(bytes32 role) public view returns (uint256) {\n return _roles[role].members.length();\n }\n\n /**\n * @dev Returns one of the accounts that have `role`. `index` must be a\n * value between 0 and {getRoleMemberCount}, non-inclusive.\n *\n * Role bearers are not sorted in any particular way, and their ordering may\n * change at any point.\n *\n * WARNING: When using {getRoleMember} and {getRoleMemberCount}, make sure\n * you perform all queries on the same block. See the following\n * https://forum.openzeppelin.com/t/iterating-over-elements-on-enumerableset-in-openzeppelin-contracts/2296[forum post]\n * for more information.\n */\n function getRoleMember(bytes32 role, uint256 index) public view returns (address) {\n return _roles[role].members.at(index);\n }\n\n /**\n * @dev Returns the admin role that controls `role`. See {grantRole} and\n * {revokeRole}.\n *\n * To change a role's admin, use {_setRoleAdmin}.\n */\n function getRoleAdmin(bytes32 role) public view returns (bytes32) {\n return _roles[role].adminRole;\n }\n\n /**\n * @dev Grants `role` to `account`.\n *\n * If `account` had not been already granted `role`, emits a {RoleGranted}\n * event.\n *\n * Requirements:\n *\n * - the caller must have ``role``'s admin role.\n */\n function grantRole(bytes32 role, address account) public virtual {\n require(hasRole(_roles[role].adminRole, _msgSender()), \"AccessControl: sender must be an admin to grant\");\n\n _grantRole(role, account);\n }\n\n /**\n * @dev Revokes `role` from `account`.\n *\n * If `account` had been granted `role`, emits a {RoleRevoked} event.\n *\n * Requirements:\n *\n * - the caller must have ``role``'s admin role.\n */\n function revokeRole(bytes32 role, address account) public virtual {\n require(hasRole(_roles[role].adminRole, _msgSender()), \"AccessControl: sender must be an admin to revoke\");\n\n _revokeRole(role, account);\n }\n\n /**\n * @dev Revokes `role` from the calling account.\n *\n * Roles are often managed via {grantRole} and {revokeRole}: this function's\n * purpose is to provide a mechanism for accounts to lose their privileges\n * if they are compromised (such as when a trusted device is misplaced).\n *\n * If the calling account had been granted `role`, emits a {RoleRevoked}\n * event.\n *\n * Requirements:\n *\n * - the caller must be `account`.\n */\n function renounceRole(bytes32 role, address account) public virtual {\n require(account == _msgSender(), \"AccessControl: can only renounce roles for self\");\n\n _revokeRole(role, account);\n }\n\n /**\n * @dev Grants `role` to `account`.\n *\n * If `account` had not been already granted `role`, emits a {RoleGranted}\n * event. Note that unlike {grantRole}, this function doesn't perform any\n * checks on the calling account.\n *\n * [WARNING]\n * ====\n * This function should only be called from the constructor when setting\n * up the initial roles for the system.\n *\n * Using this function in any other way is effectively circumventing the admin\n * system imposed by {AccessControl}.\n * ====\n */\n function _setupRole(bytes32 role, address account) internal virtual {\n _grantRole(role, account);\n }\n\n /**\n * @dev Sets `adminRole` as ``role``'s admin role.\n *\n * Emits a {RoleAdminChanged} event.\n */\n function _setRoleAdmin(bytes32 role, bytes32 adminRole) internal virtual {\n emit RoleAdminChanged(role, _roles[role].adminRole, adminRole);\n _roles[role].adminRole = adminRole;\n }\n\n function _grantRole(bytes32 role, address account) private {\n if (_roles[role].members.add(account)) {\n emit RoleGranted(role, account, _msgSender());\n }\n }\n\n function _revokeRole(bytes32 role, address account) private {\n if (_roles[role].members.remove(account)) {\n emit RoleRevoked(role, account, _msgSender());\n }\n }\n uint256[49] private __gap;\n}\n" + }, + "@openzeppelin/contracts-upgradeable/utils/EnumerableSetUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <0.8.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 EnumerableSetUpgradeable {\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" + }, + "contracts/bridge/MoonriverSynapseBridge.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.6.12;\n\nimport \"@openzeppelin/contracts-upgradeable/proxy/Initializable.sol\";\nimport \"@openzeppelin/contracts-upgradeable/access/AccessControlUpgradeable.sol\";\nimport \"@openzeppelin/contracts-upgradeable/utils/ReentrancyGuardUpgradeable.sol\";\nimport \"@openzeppelin/contracts-upgradeable/utils/PausableUpgradeable.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/SafeERC20.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/ERC20Burnable.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport \"@openzeppelin/contracts/math/SafeMath.sol\";\n\nimport \"./interfaces/ISwap.sol\";\nimport \"./interfaces/IWETH9.sol\";\n\ninterface IERC20Mintable is IERC20 {\n function mint(address to, uint256 amount) external;\n}\n\ninterface IFrax {\n function exchangeOldForCanonical(\n address bridge_token_address,\n uint256 token_amount\n ) external returns (uint256);\n}\n\ncontract MRSynapseBridge is\n Initializable,\n AccessControlUpgradeable,\n ReentrancyGuardUpgradeable,\n PausableUpgradeable\n{\n using SafeERC20 for IERC20;\n using SafeERC20 for IERC20Mintable;\n using SafeMath for uint256;\n\n bytes32 public constant NODEGROUP_ROLE = keccak256(\"NODEGROUP_ROLE\");\n bytes32 public constant GOVERNANCE_ROLE = keccak256(\"GOVERNANCE_ROLE\");\n\n mapping(address => uint256) private fees;\n\n uint256 public startBlockNumber;\n uint256 public constant bridgeVersion = 6;\n uint256 public chainGasAmount;\n address payable public WETH_ADDRESS;\n\n mapping(bytes32 => bool) private kappaMap;\n\n receive() external payable {}\n\n function initialize() external initializer {\n startBlockNumber = block.number;\n _setupRole(DEFAULT_ADMIN_ROLE, msg.sender);\n __AccessControl_init();\n }\n\n function setChainGasAmount(uint256 amount) external {\n require(hasRole(GOVERNANCE_ROLE, msg.sender), \"Not governance\");\n chainGasAmount = amount;\n }\n\n function setWethAddress(address payable _wethAddress) external {\n require(hasRole(DEFAULT_ADMIN_ROLE, msg.sender), \"Not admin\");\n WETH_ADDRESS = _wethAddress;\n }\n\n function addKappas(bytes32[] calldata kappas) external {\n require(hasRole(GOVERNANCE_ROLE, msg.sender), \"Not governance\");\n for (uint256 i = 0; i < kappas.length; ++i) {\n kappaMap[kappas[i]] = true;\n }\n }\n\n event TokenDeposit(\n address indexed to,\n uint256 chainId,\n IERC20 token,\n uint256 amount\n );\n event TokenRedeem(\n address indexed to,\n uint256 chainId,\n IERC20 token,\n uint256 amount\n );\n event TokenWithdraw(\n address indexed to,\n IERC20 token,\n uint256 amount,\n uint256 fee,\n bytes32 indexed kappa\n );\n event TokenMint(\n address indexed to,\n IERC20Mintable token,\n uint256 amount,\n uint256 fee,\n bytes32 indexed kappa\n );\n event TokenDepositAndSwap(\n address indexed to,\n uint256 chainId,\n IERC20 token,\n uint256 amount,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 minDy,\n uint256 deadline\n );\n event TokenMintAndSwap(\n address indexed to,\n IERC20Mintable token,\n uint256 amount,\n uint256 fee,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 minDy,\n uint256 deadline,\n bool swapSuccess,\n bytes32 indexed kappa\n );\n event TokenRedeemAndSwap(\n address indexed to,\n uint256 chainId,\n IERC20 token,\n uint256 amount,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 minDy,\n uint256 deadline\n );\n event TokenRedeemAndRemove(\n address indexed to,\n uint256 chainId,\n IERC20 token,\n uint256 amount,\n uint8 swapTokenIndex,\n uint256 swapMinAmount,\n uint256 swapDeadline\n );\n event TokenWithdrawAndRemove(\n address indexed to,\n IERC20 token,\n uint256 amount,\n uint256 fee,\n uint8 swapTokenIndex,\n uint256 swapMinAmount,\n uint256 swapDeadline,\n bool swapSuccess,\n bytes32 indexed kappa\n );\n\n // v2 events\n event TokenRedeemV2(\n bytes32 indexed to,\n uint256 chainId,\n IERC20 token,\n uint256 amount\n );\n\n // VIEW FUNCTIONS ***/\n function getFeeBalance(address tokenAddress)\n external\n view\n returns (uint256)\n {\n return fees[tokenAddress];\n }\n\n function kappaExists(bytes32 kappa) external view returns (bool) {\n return kappaMap[kappa];\n }\n\n // FEE FUNCTIONS ***/\n /**\n * * @notice withdraw specified ERC20 token fees to a given address\n * * @param token ERC20 token in which fees acccumulated to transfer\n * * @param to Address to send the fees to\n */\n function withdrawFees(IERC20 token, address to) external whenNotPaused {\n require(hasRole(GOVERNANCE_ROLE, msg.sender), \"Not governance\");\n require(to != address(0), \"Address is 0x000\");\n if (fees[address(token)] != 0) {\n token.safeTransfer(to, fees[address(token)]);\n fees[address(token)] = 0;\n }\n }\n\n // PAUSABLE FUNCTIONS ***/\n function pause() external {\n require(hasRole(GOVERNANCE_ROLE, msg.sender), \"Not governance\");\n _pause();\n }\n\n function unpause() external {\n require(hasRole(GOVERNANCE_ROLE, msg.sender), \"Not governance\");\n _unpause();\n }\n\n /**\n * @notice Relays to nodes to transfers an ERC20 token cross-chain\n * @param to address on other chain to bridge assets to\n * @param chainId which chain to bridge assets onto\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n **/\n function deposit(\n address to,\n uint256 chainId,\n IERC20 token,\n uint256 amount\n ) external nonReentrant whenNotPaused {\n emit TokenDeposit(to, chainId, token, amount);\n token.safeTransferFrom(msg.sender, address(this), amount);\n }\n\n /**\n * @notice Relays to nodes that (typically) a wrapped synAsset ERC20 token has been burned and the underlying needs to be redeeemed on the native chain\n * @param to address on other chain to redeem underlying assets to\n * @param chainId which underlying chain to bridge assets onto\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n **/\n function redeem(\n address to,\n uint256 chainId,\n ERC20Burnable token,\n uint256 amount\n ) external nonReentrant whenNotPaused {\n emit TokenRedeem(to, chainId, token, amount);\n token.burnFrom(msg.sender, amount);\n }\n\n /**\n * @notice Function to be called by the node group to withdraw the underlying assets from the contract\n * @param to address on chain to send underlying assets to\n * @param token ERC20 compatible token to withdraw from the bridge\n * @param amount Amount in native token decimals to withdraw\n * @param fee Amount in native token decimals to save to the contract as fees\n * @param kappa kappa\n **/\n function withdraw(\n address to,\n IERC20 token,\n uint256 amount,\n uint256 fee,\n bytes32 kappa\n ) external nonReentrant whenNotPaused {\n require(\n hasRole(NODEGROUP_ROLE, msg.sender),\n \"Caller is not a node group\"\n );\n require(amount > fee, \"Amount must be greater than fee\");\n require(!kappaMap[kappa], \"Kappa is already present\");\n kappaMap[kappa] = true;\n fees[address(token)] = fees[address(token)].add(fee);\n if (address(token) == WETH_ADDRESS && WETH_ADDRESS != address(0)) {\n IWETH9(WETH_ADDRESS).withdraw(amount.sub(fee));\n (bool success, ) = to.call{value: amount.sub(fee)}(\"\");\n require(success, \"ETH_TRANSFER_FAILED\");\n emit TokenWithdraw(to, token, amount, fee, kappa);\n } else {\n emit TokenWithdraw(to, token, amount, fee, kappa);\n token.safeTransfer(to, amount.sub(fee));\n }\n }\n\n /**\n * @notice Nodes call this function to mint a SynERC20 (or any asset that the bridge is given minter access to). This is called by the nodes after a TokenDeposit event is emitted.\n * @dev This means the SynapseBridge.sol contract must have minter access to the token attempting to be minted\n * @param to address on other chain to redeem underlying assets to\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain post-fees\n * @param fee Amount in native token decimals to save to the contract as fees\n * @param kappa kappa\n **/\n function mint(\n address payable to,\n IERC20Mintable token,\n uint256 amount,\n uint256 fee,\n bytes32 kappa\n ) external nonReentrant whenNotPaused {\n require(\n hasRole(NODEGROUP_ROLE, msg.sender),\n \"Caller is not a node group\"\n );\n require(amount > fee, \"Amount must be greater than fee\");\n require(!kappaMap[kappa], \"Kappa is already present\");\n kappaMap[kappa] = true;\n fees[address(token)] = fees[address(token)].add(fee);\n emit TokenMint(to, token, amount.sub(fee), fee, kappa);\n token.mint(address(this), amount);\n // checks if synFRAX\n if (address(token) == 0xE96AC70907ffF3Efee79f502C985A7A21Bce407d) {\n token.safeIncreaseAllowance(\n 0x1A93B23281CC1CDE4C4741353F3064709A16197d,\n amount.sub(fee)\n );\n try\n IFrax(0x1A93B23281CC1CDE4C4741353F3064709A16197d)\n .exchangeOldForCanonical(address(token), amount.sub(fee))\n returns (uint256 canolical_tokens_out) {\n IERC20(0x1A93B23281CC1CDE4C4741353F3064709A16197d).safeTransfer(\n to,\n canolical_tokens_out\n );\n } catch {\n IERC20(token).safeTransfer(to, amount.sub(fee));\n }\n } else {\n IERC20(token).safeTransfer(to, amount.sub(fee));\n }\n if (chainGasAmount != 0 && address(this).balance > chainGasAmount) {\n to.call.value(chainGasAmount)(\"\");\n }\n }\n\n /**\n * @notice Relays to nodes to both transfer an ERC20 token cross-chain, and then have the nodes execute a swap through a liquidity pool on behalf of the user.\n * @param to address on other chain to bridge assets to\n * @param chainId which chain to bridge assets onto\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n * @param tokenIndexFrom the token the user wants to swap from\n * @param tokenIndexTo the token the user wants to swap to\n * @param minDy the min amount the user would like to receive, or revert to only minting the SynERC20 token crosschain.\n * @param deadline latest timestamp to accept this transaction\n **/\n function depositAndSwap(\n address to,\n uint256 chainId,\n IERC20 token,\n uint256 amount,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 minDy,\n uint256 deadline\n ) external nonReentrant whenNotPaused {\n emit TokenDepositAndSwap(\n to,\n chainId,\n token,\n amount,\n tokenIndexFrom,\n tokenIndexTo,\n minDy,\n deadline\n );\n token.safeTransferFrom(msg.sender, address(this), amount);\n }\n\n /**\n * @notice Relays to nodes that (typically) a wrapped synAsset ERC20 token has been burned and the underlying needs to be redeeemed on the native chain. This function indicates to the nodes that they should attempt to redeem the LP token for the underlying assets (E.g \"swap\" out of the LP token)\n * @param to address on other chain to redeem underlying assets to\n * @param chainId which underlying chain to bridge assets onto\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n * @param tokenIndexFrom the token the user wants to swap from\n * @param tokenIndexTo the token the user wants to swap to\n * @param minDy the min amount the user would like to receive, or revert to only minting the SynERC20 token crosschain.\n * @param deadline latest timestamp to accept this transaction\n **/\n function redeemAndSwap(\n address to,\n uint256 chainId,\n ERC20Burnable token,\n uint256 amount,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 minDy,\n uint256 deadline\n ) external nonReentrant whenNotPaused {\n emit TokenRedeemAndSwap(\n to,\n chainId,\n token,\n amount,\n tokenIndexFrom,\n tokenIndexTo,\n minDy,\n deadline\n );\n token.burnFrom(msg.sender, amount);\n }\n\n /**\n * @notice Relays to nodes that (typically) a wrapped synAsset ERC20 token has been burned and the underlying needs to be redeeemed on the native chain. This function indicates to the nodes that they should attempt to redeem the LP token for the underlying assets (E.g \"swap\" out of the LP token)\n * @param to address on other chain to redeem underlying assets to\n * @param chainId which underlying chain to bridge assets onto\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n * @param swapTokenIndex Specifies which of the underlying LP assets the nodes should attempt to redeem for\n * @param swapMinAmount Specifies the minimum amount of the underlying asset needed for the nodes to execute the redeem/swap\n * @param swapDeadline Specificies the deadline that the nodes are allowed to try to redeem/swap the LP token\n **/\n function redeemAndRemove(\n address to,\n uint256 chainId,\n ERC20Burnable token,\n uint256 amount,\n uint8 swapTokenIndex,\n uint256 swapMinAmount,\n uint256 swapDeadline\n ) external nonReentrant whenNotPaused {\n emit TokenRedeemAndRemove(\n to,\n chainId,\n token,\n amount,\n swapTokenIndex,\n swapMinAmount,\n swapDeadline\n );\n token.burnFrom(msg.sender, amount);\n }\n\n /**\n * @notice Nodes call this function to mint a SynERC20 (or any asset that the bridge is given minter access to), and then attempt to swap the SynERC20 into the desired destination asset. This is called by the nodes after a TokenDepositAndSwap event is emitted.\n * @dev This means the BridgeDeposit.sol contract must have minter access to the token attempting to be minted\n * @param to address on other chain to redeem underlying assets to\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain post-fees\n * @param fee Amount in native token decimals to save to the contract as fees\n * @param pool Destination chain's pool to use to swap SynERC20 -> Asset. The nodes determine this by using PoolConfig.sol.\n * @param tokenIndexFrom Index of the SynERC20 asset in the pool\n * @param tokenIndexTo Index of the desired final asset\n * @param minDy Minumum amount (in final asset decimals) that must be swapped for, otherwise the user will receive the SynERC20.\n * @param deadline Epoch time of the deadline that the swap is allowed to be executed.\n * @param kappa kappa\n **/\n function mintAndSwap(\n address payable to,\n IERC20Mintable token,\n uint256 amount,\n uint256 fee,\n ISwap pool,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 minDy,\n uint256 deadline,\n bytes32 kappa\n ) external nonReentrant whenNotPaused {\n require(\n hasRole(NODEGROUP_ROLE, msg.sender),\n \"Caller is not a node group\"\n );\n require(amount > fee, \"Amount must be greater than fee\");\n require(!kappaMap[kappa], \"Kappa is already present\");\n kappaMap[kappa] = true;\n fees[address(token)] = fees[address(token)].add(fee);\n // Transfer gas airdrop\n if (chainGasAmount != 0 && address(this).balance > chainGasAmount) {\n to.call.value(chainGasAmount)(\"\");\n }\n // first check to make sure more will be given than min amount required\n uint256 expectedOutput = ISwap(pool).calculateSwap(\n tokenIndexFrom,\n tokenIndexTo,\n amount.sub(fee)\n );\n\n if (expectedOutput >= minDy) {\n // proceed with swap\n token.mint(address(this), amount);\n token.safeIncreaseAllowance(address(pool), amount);\n try\n ISwap(pool).swap(\n tokenIndexFrom,\n tokenIndexTo,\n amount.sub(fee),\n minDy,\n deadline\n )\n returns (uint256 finalSwappedAmount) {\n // Swap succeeded, transfer swapped asset\n IERC20 swappedTokenTo = ISwap(pool).getToken(tokenIndexTo);\n if (\n address(swappedTokenTo) == WETH_ADDRESS &&\n WETH_ADDRESS != address(0)\n ) {\n IWETH9(WETH_ADDRESS).withdraw(finalSwappedAmount);\n (bool success, ) = to.call{value: finalSwappedAmount}(\"\");\n require(success, \"ETH_TRANSFER_FAILED\");\n emit TokenMintAndSwap(\n to,\n token,\n finalSwappedAmount,\n fee,\n tokenIndexFrom,\n tokenIndexTo,\n minDy,\n deadline,\n true,\n kappa\n );\n } else {\n swappedTokenTo.safeTransfer(to, finalSwappedAmount);\n emit TokenMintAndSwap(\n to,\n token,\n finalSwappedAmount,\n fee,\n tokenIndexFrom,\n tokenIndexTo,\n minDy,\n deadline,\n true,\n kappa\n );\n }\n } catch {\n IERC20(token).safeTransfer(to, amount.sub(fee));\n emit TokenMintAndSwap(\n to,\n token,\n amount.sub(fee),\n fee,\n tokenIndexFrom,\n tokenIndexTo,\n minDy,\n deadline,\n false,\n kappa\n );\n }\n } else {\n token.mint(address(this), amount);\n IERC20(token).safeTransfer(to, amount.sub(fee));\n emit TokenMintAndSwap(\n to,\n token,\n amount.sub(fee),\n fee,\n tokenIndexFrom,\n tokenIndexTo,\n minDy,\n deadline,\n false,\n kappa\n );\n }\n }\n\n /**\n * @notice Function to be called by the node group to withdraw the underlying assets from the contract\n * @param to address on chain to send underlying assets to\n * @param token ERC20 compatible token to withdraw from the bridge\n * @param amount Amount in native token decimals to withdraw\n * @param fee Amount in native token decimals to save to the contract as fees\n * @param pool Destination chain's pool to use to swap SynERC20 -> Asset. The nodes determine this by using PoolConfig.sol.\n * @param swapTokenIndex Specifies which of the underlying LP assets the nodes should attempt to redeem for\n * @param swapMinAmount Specifies the minimum amount of the underlying asset needed for the nodes to execute the redeem/swap\n * @param swapDeadline Specificies the deadline that the nodes are allowed to try to redeem/swap the LP token\n * @param kappa kappa\n **/\n function withdrawAndRemove(\n address to,\n IERC20 token,\n uint256 amount,\n uint256 fee,\n ISwap pool,\n uint8 swapTokenIndex,\n uint256 swapMinAmount,\n uint256 swapDeadline,\n bytes32 kappa\n ) external nonReentrant whenNotPaused {\n require(\n hasRole(NODEGROUP_ROLE, msg.sender),\n \"Caller is not a node group\"\n );\n require(amount > fee, \"Amount must be greater than fee\");\n require(!kappaMap[kappa], \"Kappa is already present\");\n kappaMap[kappa] = true;\n fees[address(token)] = fees[address(token)].add(fee);\n // first check to make sure more will be given than min amount required\n uint256 expectedOutput = ISwap(pool).calculateRemoveLiquidityOneToken(\n amount.sub(fee),\n swapTokenIndex\n );\n\n if (expectedOutput >= swapMinAmount) {\n token.safeIncreaseAllowance(address(pool), amount.sub(fee));\n try\n ISwap(pool).removeLiquidityOneToken(\n amount.sub(fee),\n swapTokenIndex,\n swapMinAmount,\n swapDeadline\n )\n returns (uint256 finalSwappedAmount) {\n // Swap succeeded, transfer swapped asset\n IERC20 swappedTokenTo = ISwap(pool).getToken(swapTokenIndex);\n swappedTokenTo.safeTransfer(to, finalSwappedAmount);\n emit TokenWithdrawAndRemove(\n to,\n token,\n finalSwappedAmount,\n fee,\n swapTokenIndex,\n swapMinAmount,\n swapDeadline,\n true,\n kappa\n );\n } catch {\n IERC20(token).safeTransfer(to, amount.sub(fee));\n emit TokenWithdrawAndRemove(\n to,\n token,\n amount.sub(fee),\n fee,\n swapTokenIndex,\n swapMinAmount,\n swapDeadline,\n false,\n kappa\n );\n }\n } else {\n token.safeTransfer(to, amount.sub(fee));\n emit TokenWithdrawAndRemove(\n to,\n token,\n amount.sub(fee),\n fee,\n swapTokenIndex,\n swapMinAmount,\n swapDeadline,\n false,\n kappa\n );\n }\n }\n\n // BRIDGE FUNCTIONS TO HANDLE DIFF ADDRESSES\n /**\n * @notice Relays to nodes that (typically) a wrapped synAsset ERC20 token has been burned and the underlying needs to be redeeemed on the native chain\n * @param to address on other chain to redeem underlying assets to\n * @param chainId which underlying chain to bridge assets onto\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n **/\n function redeemV2(\n bytes32 to,\n uint256 chainId,\n ERC20Burnable token,\n uint256 amount\n ) external nonReentrant whenNotPaused {\n emit TokenRedeemV2(to, chainId, token, amount);\n token.burnFrom(msg.sender, amount);\n }\n}\n" + }, + "contracts/bridge/HarmonySynapseBridge.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.6.12;\n\nimport \"@openzeppelin/contracts-upgradeable/proxy/Initializable.sol\";\nimport \"@openzeppelin/contracts-upgradeable/access/AccessControlUpgradeable.sol\";\nimport \"@openzeppelin/contracts-upgradeable/utils/ReentrancyGuardUpgradeable.sol\";\nimport \"@openzeppelin/contracts-upgradeable/utils/PausableUpgradeable.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/SafeERC20.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/ERC20Burnable.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport \"@openzeppelin/contracts/math/SafeMath.sol\";\n\nimport \"./interfaces/ISwap.sol\";\nimport \"./interfaces/IWETH9.sol\";\n\ninterface IERC20Mintable is IERC20 {\n function mint(address to, uint256 amount) external;\n}\n\ninterface IFrax {\n function exchangeOldForCanonical(\n address bridge_token_address,\n uint256 token_amount\n ) external returns (uint256);\n}\n\ncontract HarmonySynapseBridge is\n Initializable,\n AccessControlUpgradeable,\n ReentrancyGuardUpgradeable,\n PausableUpgradeable\n{\n using SafeERC20 for IERC20;\n using SafeERC20 for IERC20Mintable;\n using SafeMath for uint256;\n\n bytes32 public constant NODEGROUP_ROLE = keccak256(\"NODEGROUP_ROLE\");\n bytes32 public constant GOVERNANCE_ROLE = keccak256(\"GOVERNANCE_ROLE\");\n\n mapping(address => uint256) private fees;\n\n uint256 public startBlockNumber;\n uint256 public constant bridgeVersion = 6;\n uint256 public chainGasAmount;\n address payable public WETH_ADDRESS;\n\n mapping(bytes32 => bool) private kappaMap;\n\n receive() external payable {}\n\n function initialize() external initializer {\n startBlockNumber = block.number;\n _setupRole(DEFAULT_ADMIN_ROLE, msg.sender);\n __AccessControl_init();\n }\n\n function setChainGasAmount(uint256 amount) external {\n require(hasRole(GOVERNANCE_ROLE, msg.sender), \"Not governance\");\n chainGasAmount = amount;\n }\n\n function setWethAddress(address payable _wethAddress) external {\n require(hasRole(DEFAULT_ADMIN_ROLE, msg.sender), \"Not admin\");\n WETH_ADDRESS = _wethAddress;\n }\n\n function addKappas(bytes32[] calldata kappas) external {\n require(hasRole(GOVERNANCE_ROLE, msg.sender), \"Not governance\");\n for (uint256 i = 0; i < kappas.length; ++i) {\n kappaMap[kappas[i]] = true;\n }\n }\n\n event TokenDeposit(\n address indexed to,\n uint256 chainId,\n IERC20 token,\n uint256 amount\n );\n event TokenRedeem(\n address indexed to,\n uint256 chainId,\n IERC20 token,\n uint256 amount\n );\n event TokenWithdraw(\n address indexed to,\n IERC20 token,\n uint256 amount,\n uint256 fee,\n bytes32 indexed kappa\n );\n event TokenMint(\n address indexed to,\n IERC20Mintable token,\n uint256 amount,\n uint256 fee,\n bytes32 indexed kappa\n );\n event TokenDepositAndSwap(\n address indexed to,\n uint256 chainId,\n IERC20 token,\n uint256 amount,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 minDy,\n uint256 deadline\n );\n event TokenMintAndSwap(\n address indexed to,\n IERC20Mintable token,\n uint256 amount,\n uint256 fee,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 minDy,\n uint256 deadline,\n bool swapSuccess,\n bytes32 indexed kappa\n );\n event TokenRedeemAndSwap(\n address indexed to,\n uint256 chainId,\n IERC20 token,\n uint256 amount,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 minDy,\n uint256 deadline\n );\n event TokenRedeemAndRemove(\n address indexed to,\n uint256 chainId,\n IERC20 token,\n uint256 amount,\n uint8 swapTokenIndex,\n uint256 swapMinAmount,\n uint256 swapDeadline\n );\n event TokenWithdrawAndRemove(\n address indexed to,\n IERC20 token,\n uint256 amount,\n uint256 fee,\n uint8 swapTokenIndex,\n uint256 swapMinAmount,\n uint256 swapDeadline,\n bool swapSuccess,\n bytes32 indexed kappa\n );\n\n // v2 events\n event TokenRedeemV2(\n bytes32 indexed to,\n uint256 chainId,\n IERC20 token,\n uint256 amount\n );\n\n // VIEW FUNCTIONS ***/\n function getFeeBalance(address tokenAddress)\n external\n view\n returns (uint256)\n {\n return fees[tokenAddress];\n }\n\n function kappaExists(bytes32 kappa) external view returns (bool) {\n return kappaMap[kappa];\n }\n\n // FEE FUNCTIONS ***/\n /**\n * * @notice withdraw specified ERC20 token fees to a given address\n * * @param token ERC20 token in which fees acccumulated to transfer\n * * @param to Address to send the fees to\n */\n function withdrawFees(IERC20 token, address to) external whenNotPaused {\n require(hasRole(GOVERNANCE_ROLE, msg.sender), \"Not governance\");\n require(to != address(0), \"Address is 0x000\");\n if (fees[address(token)] != 0) {\n token.safeTransfer(to, fees[address(token)]);\n fees[address(token)] = 0;\n }\n }\n\n // PAUSABLE FUNCTIONS ***/\n function pause() external {\n require(hasRole(GOVERNANCE_ROLE, msg.sender), \"Not governance\");\n _pause();\n }\n\n function unpause() external {\n require(hasRole(GOVERNANCE_ROLE, msg.sender), \"Not governance\");\n _unpause();\n }\n\n /**\n * @notice Relays to nodes to transfers an ERC20 token cross-chain\n * @param to address on other chain to bridge assets to\n * @param chainId which chain to bridge assets onto\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n **/\n function deposit(\n address to,\n uint256 chainId,\n IERC20 token,\n uint256 amount\n ) external nonReentrant whenNotPaused {\n emit TokenDeposit(to, chainId, token, amount);\n token.safeTransferFrom(msg.sender, address(this), amount);\n }\n\n /**\n * @notice Relays to nodes that (typically) a wrapped synAsset ERC20 token has been burned and the underlying needs to be redeeemed on the native chain\n * @param to address on other chain to redeem underlying assets to\n * @param chainId which underlying chain to bridge assets onto\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n **/\n function redeem(\n address to,\n uint256 chainId,\n ERC20Burnable token,\n uint256 amount\n ) external nonReentrant whenNotPaused {\n emit TokenRedeem(to, chainId, token, amount);\n token.burnFrom(msg.sender, amount);\n }\n\n /**\n * @notice Function to be called by the node group to withdraw the underlying assets from the contract\n * @param to address on chain to send underlying assets to\n * @param token ERC20 compatible token to withdraw from the bridge\n * @param amount Amount in native token decimals to withdraw\n * @param fee Amount in native token decimals to save to the contract as fees\n * @param kappa kappa\n **/\n function withdraw(\n address to,\n IERC20 token,\n uint256 amount,\n uint256 fee,\n bytes32 kappa\n ) external nonReentrant whenNotPaused {\n require(\n hasRole(NODEGROUP_ROLE, msg.sender),\n \"Caller is not a node group\"\n );\n require(amount > fee, \"Amount must be greater than fee\");\n require(!kappaMap[kappa], \"Kappa is already present\");\n kappaMap[kappa] = true;\n fees[address(token)] = fees[address(token)].add(fee);\n if (address(token) == WETH_ADDRESS && WETH_ADDRESS != address(0)) {\n IWETH9(WETH_ADDRESS).withdraw(amount.sub(fee));\n (bool success, ) = to.call{value: amount.sub(fee)}(\"\");\n require(success, \"ETH_TRANSFER_FAILED\");\n emit TokenWithdraw(to, token, amount, fee, kappa);\n } else {\n emit TokenWithdraw(to, token, amount, fee, kappa);\n token.safeTransfer(to, amount.sub(fee));\n }\n }\n\n /**\n * @notice Nodes call this function to mint a SynERC20 (or any asset that the bridge is given minter access to). This is called by the nodes after a TokenDeposit event is emitted.\n * @dev This means the SynapseBridge.sol contract must have minter access to the token attempting to be minted\n * @param to address on other chain to redeem underlying assets to\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain post-fees\n * @param fee Amount in native token decimals to save to the contract as fees\n * @param kappa kappa\n **/\n function mint(\n address payable to,\n IERC20Mintable token,\n uint256 amount,\n uint256 fee,\n bytes32 kappa\n ) external nonReentrant whenNotPaused {\n require(\n hasRole(NODEGROUP_ROLE, msg.sender),\n \"Caller is not a node group\"\n );\n require(amount > fee, \"Amount must be greater than fee\");\n require(!kappaMap[kappa], \"Kappa is already present\");\n kappaMap[kappa] = true;\n fees[address(token)] = fees[address(token)].add(fee);\n emit TokenMint(to, token, amount.sub(fee), fee, kappa);\n token.mint(address(this), amount);\n // checks if synFRAX\n if (address(token) == 0x1852F70512298d56e9c8FDd905e02581E04ddb2a) {\n if (\n token.allowance(\n address(this),\n 0xFa7191D292d5633f702B0bd7E3E3BcCC0e633200\n ) < amount.sub(fee)\n ) {\n token.safeApprove(\n address(0xFa7191D292d5633f702B0bd7E3E3BcCC0e633200),\n 0\n );\n token.safeApprove(\n address(0xFa7191D292d5633f702B0bd7E3E3BcCC0e633200),\n type(uint256).max\n );\n }\n try\n IFrax(0xFa7191D292d5633f702B0bd7E3E3BcCC0e633200)\n .exchangeOldForCanonical(address(token), amount.sub(fee))\n returns (uint256 canolical_tokens_out) {\n IERC20(0xFa7191D292d5633f702B0bd7E3E3BcCC0e633200).safeTransfer(\n to,\n canolical_tokens_out\n );\n } catch {\n IERC20(token).safeTransfer(to, amount.sub(fee));\n }\n } else {\n IERC20(token).safeTransfer(to, amount.sub(fee));\n }\n if (chainGasAmount != 0 && address(this).balance > chainGasAmount) {\n to.call.value(chainGasAmount)(\"\");\n }\n }\n\n /**\n * @notice Relays to nodes to both transfer an ERC20 token cross-chain, and then have the nodes execute a swap through a liquidity pool on behalf of the user.\n * @param to address on other chain to bridge assets to\n * @param chainId which chain to bridge assets onto\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n * @param tokenIndexFrom the token the user wants to swap from\n * @param tokenIndexTo the token the user wants to swap to\n * @param minDy the min amount the user would like to receive, or revert to only minting the SynERC20 token crosschain.\n * @param deadline latest timestamp to accept this transaction\n **/\n function depositAndSwap(\n address to,\n uint256 chainId,\n IERC20 token,\n uint256 amount,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 minDy,\n uint256 deadline\n ) external nonReentrant whenNotPaused {\n emit TokenDepositAndSwap(\n to,\n chainId,\n token,\n amount,\n tokenIndexFrom,\n tokenIndexTo,\n minDy,\n deadline\n );\n token.safeTransferFrom(msg.sender, address(this), amount);\n }\n\n /**\n * @notice Relays to nodes that (typically) a wrapped synAsset ERC20 token has been burned and the underlying needs to be redeeemed on the native chain. This function indicates to the nodes that they should attempt to redeem the LP token for the underlying assets (E.g \"swap\" out of the LP token)\n * @param to address on other chain to redeem underlying assets to\n * @param chainId which underlying chain to bridge assets onto\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n * @param tokenIndexFrom the token the user wants to swap from\n * @param tokenIndexTo the token the user wants to swap to\n * @param minDy the min amount the user would like to receive, or revert to only minting the SynERC20 token crosschain.\n * @param deadline latest timestamp to accept this transaction\n **/\n function redeemAndSwap(\n address to,\n uint256 chainId,\n ERC20Burnable token,\n uint256 amount,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 minDy,\n uint256 deadline\n ) external nonReentrant whenNotPaused {\n emit TokenRedeemAndSwap(\n to,\n chainId,\n token,\n amount,\n tokenIndexFrom,\n tokenIndexTo,\n minDy,\n deadline\n );\n token.burnFrom(msg.sender, amount);\n }\n\n /**\n * @notice Relays to nodes that (typically) a wrapped synAsset ERC20 token has been burned and the underlying needs to be redeeemed on the native chain. This function indicates to the nodes that they should attempt to redeem the LP token for the underlying assets (E.g \"swap\" out of the LP token)\n * @param to address on other chain to redeem underlying assets to\n * @param chainId which underlying chain to bridge assets onto\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n * @param swapTokenIndex Specifies which of the underlying LP assets the nodes should attempt to redeem for\n * @param swapMinAmount Specifies the minimum amount of the underlying asset needed for the nodes to execute the redeem/swap\n * @param swapDeadline Specificies the deadline that the nodes are allowed to try to redeem/swap the LP token\n **/\n function redeemAndRemove(\n address to,\n uint256 chainId,\n ERC20Burnable token,\n uint256 amount,\n uint8 swapTokenIndex,\n uint256 swapMinAmount,\n uint256 swapDeadline\n ) external nonReentrant whenNotPaused {\n emit TokenRedeemAndRemove(\n to,\n chainId,\n token,\n amount,\n swapTokenIndex,\n swapMinAmount,\n swapDeadline\n );\n token.burnFrom(msg.sender, amount);\n }\n\n /**\n * @notice Nodes call this function to mint a SynERC20 (or any asset that the bridge is given minter access to), and then attempt to swap the SynERC20 into the desired destination asset. This is called by the nodes after a TokenDepositAndSwap event is emitted.\n * @dev This means the BridgeDeposit.sol contract must have minter access to the token attempting to be minted\n * @param to address on other chain to redeem underlying assets to\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain post-fees\n * @param fee Amount in native token decimals to save to the contract as fees\n * @param pool Destination chain's pool to use to swap SynERC20 -> Asset. The nodes determine this by using PoolConfig.sol.\n * @param tokenIndexFrom Index of the SynERC20 asset in the pool\n * @param tokenIndexTo Index of the desired final asset\n * @param minDy Minumum amount (in final asset decimals) that must be swapped for, otherwise the user will receive the SynERC20.\n * @param deadline Epoch time of the deadline that the swap is allowed to be executed.\n * @param kappa kappa\n **/\n function mintAndSwap(\n address payable to,\n IERC20Mintable token,\n uint256 amount,\n uint256 fee,\n ISwap pool,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 minDy,\n uint256 deadline,\n bytes32 kappa\n ) external nonReentrant whenNotPaused {\n require(\n hasRole(NODEGROUP_ROLE, msg.sender),\n \"Caller is not a node group\"\n );\n require(amount > fee, \"Amount must be greater than fee\");\n require(!kappaMap[kappa], \"Kappa is already present\");\n kappaMap[kappa] = true;\n fees[address(token)] = fees[address(token)].add(fee);\n // Transfer gas airdrop\n if (chainGasAmount != 0 && address(this).balance > chainGasAmount) {\n to.call.value(chainGasAmount)(\"\");\n }\n // first check to make sure more will be given than min amount required\n uint256 expectedOutput = ISwap(pool).calculateSwap(\n tokenIndexFrom,\n tokenIndexTo,\n amount.sub(fee)\n );\n\n if (expectedOutput >= minDy) {\n // proceed with swap\n token.mint(address(this), amount);\n token.safeIncreaseAllowance(address(pool), amount);\n try\n ISwap(pool).swap(\n tokenIndexFrom,\n tokenIndexTo,\n amount.sub(fee),\n minDy,\n deadline\n )\n returns (uint256 finalSwappedAmount) {\n // Swap succeeded, transfer swapped asset\n IERC20 swappedTokenTo = ISwap(pool).getToken(tokenIndexTo);\n if (\n address(swappedTokenTo) == WETH_ADDRESS &&\n WETH_ADDRESS != address(0)\n ) {\n IWETH9(WETH_ADDRESS).withdraw(finalSwappedAmount);\n (bool success, ) = to.call{value: finalSwappedAmount}(\"\");\n require(success, \"ETH_TRANSFER_FAILED\");\n emit TokenMintAndSwap(\n to,\n token,\n finalSwappedAmount,\n fee,\n tokenIndexFrom,\n tokenIndexTo,\n minDy,\n deadline,\n true,\n kappa\n );\n } else {\n swappedTokenTo.safeTransfer(to, finalSwappedAmount);\n emit TokenMintAndSwap(\n to,\n token,\n finalSwappedAmount,\n fee,\n tokenIndexFrom,\n tokenIndexTo,\n minDy,\n deadline,\n true,\n kappa\n );\n }\n } catch {\n IERC20(token).safeTransfer(to, amount.sub(fee));\n emit TokenMintAndSwap(\n to,\n token,\n amount.sub(fee),\n fee,\n tokenIndexFrom,\n tokenIndexTo,\n minDy,\n deadline,\n false,\n kappa\n );\n }\n } else {\n token.mint(address(this), amount);\n IERC20(token).safeTransfer(to, amount.sub(fee));\n emit TokenMintAndSwap(\n to,\n token,\n amount.sub(fee),\n fee,\n tokenIndexFrom,\n tokenIndexTo,\n minDy,\n deadline,\n false,\n kappa\n );\n }\n }\n\n /**\n * @notice Function to be called by the node group to withdraw the underlying assets from the contract\n * @param to address on chain to send underlying assets to\n * @param token ERC20 compatible token to withdraw from the bridge\n * @param amount Amount in native token decimals to withdraw\n * @param fee Amount in native token decimals to save to the contract as fees\n * @param pool Destination chain's pool to use to swap SynERC20 -> Asset. The nodes determine this by using PoolConfig.sol.\n * @param swapTokenIndex Specifies which of the underlying LP assets the nodes should attempt to redeem for\n * @param swapMinAmount Specifies the minimum amount of the underlying asset needed for the nodes to execute the redeem/swap\n * @param swapDeadline Specificies the deadline that the nodes are allowed to try to redeem/swap the LP token\n * @param kappa kappa\n **/\n function withdrawAndRemove(\n address to,\n IERC20 token,\n uint256 amount,\n uint256 fee,\n ISwap pool,\n uint8 swapTokenIndex,\n uint256 swapMinAmount,\n uint256 swapDeadline,\n bytes32 kappa\n ) external nonReentrant whenNotPaused {\n require(\n hasRole(NODEGROUP_ROLE, msg.sender),\n \"Caller is not a node group\"\n );\n require(amount > fee, \"Amount must be greater than fee\");\n require(!kappaMap[kappa], \"Kappa is already present\");\n kappaMap[kappa] = true;\n fees[address(token)] = fees[address(token)].add(fee);\n // first check to make sure more will be given than min amount required\n uint256 expectedOutput = ISwap(pool).calculateRemoveLiquidityOneToken(\n amount.sub(fee),\n swapTokenIndex\n );\n\n if (expectedOutput >= swapMinAmount) {\n token.safeIncreaseAllowance(address(pool), amount.sub(fee));\n try\n ISwap(pool).removeLiquidityOneToken(\n amount.sub(fee),\n swapTokenIndex,\n swapMinAmount,\n swapDeadline\n )\n returns (uint256 finalSwappedAmount) {\n // Swap succeeded, transfer swapped asset\n IERC20 swappedTokenTo = ISwap(pool).getToken(swapTokenIndex);\n swappedTokenTo.safeTransfer(to, finalSwappedAmount);\n emit TokenWithdrawAndRemove(\n to,\n token,\n finalSwappedAmount,\n fee,\n swapTokenIndex,\n swapMinAmount,\n swapDeadline,\n true,\n kappa\n );\n } catch {\n IERC20(token).safeTransfer(to, amount.sub(fee));\n emit TokenWithdrawAndRemove(\n to,\n token,\n amount.sub(fee),\n fee,\n swapTokenIndex,\n swapMinAmount,\n swapDeadline,\n false,\n kappa\n );\n }\n } else {\n token.safeTransfer(to, amount.sub(fee));\n emit TokenWithdrawAndRemove(\n to,\n token,\n amount.sub(fee),\n fee,\n swapTokenIndex,\n swapMinAmount,\n swapDeadline,\n false,\n kappa\n );\n }\n }\n\n // BRIDGE FUNCTIONS TO HANDLE DIFF ADDRESSES\n /**\n * @notice Relays to nodes that (typically) a wrapped synAsset ERC20 token has been burned and the underlying needs to be redeeemed on the native chain\n * @param to address on other chain to redeem underlying assets to\n * @param chainId which underlying chain to bridge assets onto\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n **/\n function redeemV2(\n bytes32 to,\n uint256 chainId,\n ERC20Burnable token,\n uint256 amount\n ) external nonReentrant whenNotPaused {\n emit TokenRedeemV2(to, chainId, token, amount);\n token.burnFrom(msg.sender, amount);\n }\n}\n" + }, + "contracts/bridge/SynapseERC20.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.6.12;\n\nimport \"@openzeppelin/contracts-upgradeable/token/ERC20/ERC20Upgradeable.sol\";\nimport \"@openzeppelin/contracts-upgradeable/token/ERC20/ERC20BurnableUpgradeable.sol\";\nimport \"@openzeppelin/contracts-upgradeable/drafts/ERC20PermitUpgradeable.sol\";\nimport \"@openzeppelin/contracts-upgradeable/access/AccessControlUpgradeable.sol\";\nimport \"@openzeppelin/contracts-upgradeable/proxy/Initializable.sol\";\n\ncontract SynapseERC20 is\n Initializable,\n ContextUpgradeable,\n AccessControlUpgradeable,\n ERC20BurnableUpgradeable,\n ERC20PermitUpgradeable\n{\n bytes32 public constant MINTER_ROLE = keccak256(\"MINTER_ROLE\");\n\n /**\n * @notice Initializes this ERC20 contract with the given parameters.\n * @param name Token name\n * @param symbol Token symbol\n * @param decimals Token name\n * @param owner admin address to be initialized with\n */\n function initialize(\n string memory name,\n string memory symbol,\n uint8 decimals,\n address owner\n ) external initializer {\n __Context_init_unchained();\n __AccessControl_init_unchained();\n __ERC20_init_unchained(name, symbol);\n __ERC20Burnable_init_unchained();\n _setupDecimals(decimals);\n __ERC20Permit_init(name);\n _setupRole(DEFAULT_ADMIN_ROLE, owner);\n }\n\n function mint(address to, uint256 amount) external {\n require(hasRole(MINTER_ROLE, msg.sender), \"Not a minter\");\n _mint(to, amount);\n }\n}\n" + }, + "@openzeppelin/contracts-upgradeable/drafts/ERC20PermitUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.5 <0.8.0;\n\nimport \"../token/ERC20/ERC20Upgradeable.sol\";\nimport \"./IERC20PermitUpgradeable.sol\";\nimport \"../cryptography/ECDSAUpgradeable.sol\";\nimport \"../utils/CountersUpgradeable.sol\";\nimport \"./EIP712Upgradeable.sol\";\nimport \"../proxy/Initializable.sol\";\n\n/**\n * @dev Implementation of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in\n * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612].\n *\n * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by\n * presenting a message signed by the account. By not relying on `{IERC20-approve}`, the token holder account doesn't\n * need to send a transaction, and thus is not required to hold Ether at all.\n *\n * _Available since v3.4._\n */\nabstract contract ERC20PermitUpgradeable is Initializable, ERC20Upgradeable, IERC20PermitUpgradeable, EIP712Upgradeable {\n using CountersUpgradeable for CountersUpgradeable.Counter;\n\n mapping (address => CountersUpgradeable.Counter) private _nonces;\n\n // solhint-disable-next-line var-name-mixedcase\n bytes32 private _PERMIT_TYPEHASH;\n\n /**\n * @dev Initializes the {EIP712} domain separator using the `name` parameter, and setting `version` to `\"1\"`.\n *\n * It's a good idea to use the same `name` that is defined as the ERC20 token name.\n */\n function __ERC20Permit_init(string memory name) internal initializer {\n __Context_init_unchained();\n __EIP712_init_unchained(name, \"1\");\n __ERC20Permit_init_unchained(name);\n }\n\n function __ERC20Permit_init_unchained(string memory name) internal initializer {\n _PERMIT_TYPEHASH = keccak256(\"Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)\");\n }\n\n /**\n * @dev See {IERC20Permit-permit}.\n */\n function permit(address owner, address spender, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s) public virtual override {\n // solhint-disable-next-line not-rely-on-time\n require(block.timestamp <= deadline, \"ERC20Permit: expired deadline\");\n\n bytes32 structHash = keccak256(\n abi.encode(\n _PERMIT_TYPEHASH,\n owner,\n spender,\n value,\n _nonces[owner].current(),\n deadline\n )\n );\n\n bytes32 hash = _hashTypedDataV4(structHash);\n\n address signer = ECDSAUpgradeable.recover(hash, v, r, s);\n require(signer == owner, \"ERC20Permit: invalid signature\");\n\n _nonces[owner].increment();\n _approve(owner, spender, value);\n }\n\n /**\n * @dev See {IERC20Permit-nonces}.\n */\n function nonces(address owner) public view override returns (uint256) {\n return _nonces[owner].current();\n }\n\n /**\n * @dev See {IERC20Permit-DOMAIN_SEPARATOR}.\n */\n // solhint-disable-next-line func-name-mixedcase\n function DOMAIN_SEPARATOR() external view override returns (bytes32) {\n return _domainSeparatorV4();\n }\n uint256[49] private __gap;\n}\n" + }, + "@openzeppelin/contracts-upgradeable/drafts/IERC20PermitUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <0.8.0;\n\n/**\n * @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in\n * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612].\n *\n * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by\n * presenting a message signed by the account. By not relying on `{IERC20-approve}`, the token holder account doesn't\n * need to send a transaction, and thus is not required to hold Ether at all.\n */\ninterface IERC20PermitUpgradeable {\n /**\n * @dev Sets `value` as the allowance of `spender` over `owner`'s tokens,\n * given `owner`'s signed approval.\n *\n * IMPORTANT: The same issues {IERC20-approve} has related to transaction\n * ordering also apply here.\n *\n * Emits an {Approval} event.\n *\n * Requirements:\n *\n * - `spender` cannot be the zero address.\n * - `deadline` must be a timestamp in the future.\n * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner`\n * over the EIP712-formatted function arguments.\n * - the signature must use ``owner``'s current nonce (see {nonces}).\n *\n * For more information on the signature format, see the\n * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP\n * section].\n */\n function permit(address owner, address spender, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s) external;\n\n /**\n * @dev Returns the current nonce for `owner`. This value must be\n * included whenever a signature is generated for {permit}.\n *\n * Every successful call to {permit} increases ``owner``'s nonce by one. This\n * prevents a signature from being used multiple times.\n */\n function nonces(address owner) external view returns (uint256);\n\n /**\n * @dev Returns the domain separator used in the encoding of the signature for `permit`, as defined by {EIP712}.\n */\n // solhint-disable-next-line func-name-mixedcase\n function DOMAIN_SEPARATOR() external view returns (bytes32);\n}\n" + }, + "@openzeppelin/contracts-upgradeable/cryptography/ECDSAUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <0.8.0;\n\n/**\n * @dev Elliptic Curve Digital Signature Algorithm (ECDSA) operations.\n *\n * These functions can be used to verify that a message was signed by the holder\n * of the private keys of a given address.\n */\nlibrary ECDSAUpgradeable {\n /**\n * @dev Returns the address that signed a hashed message (`hash`) with\n * `signature`. This address can then be used for verification purposes.\n *\n * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:\n * this function rejects them by requiring the `s` value to be in the lower\n * half order, and the `v` value to be either 27 or 28.\n *\n * IMPORTANT: `hash` _must_ be the result of a hash operation for the\n * verification to be secure: it is possible to craft signatures that\n * recover to arbitrary addresses for non-hashed data. A safe way to ensure\n * this is by receiving a hash of the original message (which may otherwise\n * be too long), and then calling {toEthSignedMessageHash} on it.\n */\n function recover(bytes32 hash, bytes memory signature) internal pure returns (address) {\n // Check the signature length\n if (signature.length != 65) {\n revert(\"ECDSA: invalid signature length\");\n }\n\n // Divide the signature in r, s and v variables\n bytes32 r;\n bytes32 s;\n uint8 v;\n\n // ecrecover takes the signature parameters, and the only way to get them\n // currently is to use assembly.\n // solhint-disable-next-line no-inline-assembly\n assembly {\n r := mload(add(signature, 0x20))\n s := mload(add(signature, 0x40))\n v := byte(0, mload(add(signature, 0x60)))\n }\n\n return recover(hash, v, r, s);\n }\n\n /**\n * @dev Overload of {ECDSA-recover-bytes32-bytes-} that receives the `v`,\n * `r` and `s` signature fields separately.\n */\n function recover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) internal pure returns (address) {\n // EIP-2 still allows signature malleability for ecrecover(). Remove this possibility and make the signature\n // unique. Appendix F in the Ethereum Yellow paper (https://ethereum.github.io/yellowpaper/paper.pdf), defines\n // the valid range for s in (281): 0 < s < secp256k1n ÷ 2 + 1, and for v in (282): v ∈ {27, 28}. Most\n // signatures from current libraries generate a unique signature with an s-value in the lower half order.\n //\n // If your library generates malleable signatures, such as s-values in the upper range, calculate a new s-value\n // with 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 - s1 and flip v from 27 to 28 or\n // vice versa. If your library also generates signatures with 0/1 for v instead 27/28, add 27 to v to accept\n // these malleable signatures as well.\n require(uint256(s) <= 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0, \"ECDSA: invalid signature 's' value\");\n require(v == 27 || v == 28, \"ECDSA: invalid signature 'v' value\");\n\n // If the signature is valid (and not malleable), return the signer address\n address signer = ecrecover(hash, v, r, s);\n require(signer != address(0), \"ECDSA: invalid signature\");\n\n return signer;\n }\n\n /**\n * @dev Returns an Ethereum Signed Message, created from a `hash`. This\n * replicates the behavior of the\n * https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_sign[`eth_sign`]\n * JSON-RPC method.\n *\n * See {recover}.\n */\n function toEthSignedMessageHash(bytes32 hash) internal pure returns (bytes32) {\n // 32 is the length in bytes of hash,\n // enforced by the type signature above\n return keccak256(abi.encodePacked(\"\\x19Ethereum Signed Message:\\n32\", hash));\n }\n}\n" + }, + "@openzeppelin/contracts-upgradeable/utils/CountersUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <0.8.0;\n\nimport \"../math/SafeMathUpgradeable.sol\";\n\n/**\n * @title Counters\n * @author Matt Condon (@shrugs)\n * @dev Provides counters that can only be incremented or decremented by one. This can be used e.g. to track the number\n * of elements in a mapping, issuing ERC721 ids, or counting request ids.\n *\n * Include with `using Counters for Counters.Counter;`\n * Since it is not possible to overflow a 256 bit integer with increments of one, `increment` can skip the {SafeMath}\n * overflow check, thereby saving gas. This does assume however correct usage, in that the underlying `_value` is never\n * directly accessed.\n */\nlibrary CountersUpgradeable {\n using SafeMathUpgradeable for uint256;\n\n struct Counter {\n // This variable should never be directly accessed by users of the library: interactions must be restricted to\n // the library's function. As of Solidity v0.5.2, this cannot be enforced, though there is a proposal to add\n // this feature: see https://github.com/ethereum/solidity/issues/4637\n uint256 _value; // default: 0\n }\n\n function current(Counter storage counter) internal view returns (uint256) {\n return counter._value;\n }\n\n function increment(Counter storage counter) internal {\n // The {SafeMath} overflow check can be skipped here, see the comment at the top\n counter._value += 1;\n }\n\n function decrement(Counter storage counter) internal {\n counter._value = counter._value.sub(1);\n }\n}\n" + }, + "@openzeppelin/contracts-upgradeable/drafts/EIP712Upgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <0.8.0;\nimport \"../proxy/Initializable.sol\";\n\n/**\n * @dev https://eips.ethereum.org/EIPS/eip-712[EIP 712] is a standard for hashing and signing of typed structured data.\n *\n * The encoding specified in the EIP is very generic, and such a generic implementation in Solidity is not feasible,\n * thus this contract does not implement the encoding itself. Protocols need to implement the type-specific encoding\n * they need in their contracts using a combination of `abi.encode` and `keccak256`.\n *\n * This contract implements the EIP 712 domain separator ({_domainSeparatorV4}) that is used as part of the encoding\n * scheme, and the final step of the encoding to obtain the message digest that is then signed via ECDSA\n * ({_hashTypedDataV4}).\n *\n * The implementation of the domain separator was designed to be as efficient as possible while still properly updating\n * the chain id to protect against replay attacks on an eventual fork of the chain.\n *\n * NOTE: This contract implements the version of the encoding known as \"v4\", as implemented by the JSON RPC method\n * https://docs.metamask.io/guide/signing-data.html[`eth_signTypedDataV4` in MetaMask].\n *\n * _Available since v3.4._\n */\nabstract contract EIP712Upgradeable is Initializable {\n /* solhint-disable var-name-mixedcase */\n bytes32 private _HASHED_NAME;\n bytes32 private _HASHED_VERSION;\n bytes32 private constant _TYPE_HASH = keccak256(\"EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)\");\n /* solhint-enable var-name-mixedcase */\n\n /**\n * @dev Initializes the domain separator and parameter caches.\n *\n * The meaning of `name` and `version` is specified in\n * https://eips.ethereum.org/EIPS/eip-712#definition-of-domainseparator[EIP 712]:\n *\n * - `name`: the user readable name of the signing domain, i.e. the name of the DApp or the protocol.\n * - `version`: the current major version of the signing domain.\n *\n * NOTE: These parameters cannot be changed except through a xref:learn::upgrading-smart-contracts.adoc[smart\n * contract upgrade].\n */\n function __EIP712_init(string memory name, string memory version) internal initializer {\n __EIP712_init_unchained(name, version);\n }\n\n function __EIP712_init_unchained(string memory name, string memory version) internal initializer {\n bytes32 hashedName = keccak256(bytes(name));\n bytes32 hashedVersion = keccak256(bytes(version));\n _HASHED_NAME = hashedName;\n _HASHED_VERSION = hashedVersion;\n }\n\n /**\n * @dev Returns the domain separator for the current chain.\n */\n function _domainSeparatorV4() internal view returns (bytes32) {\n return _buildDomainSeparator(_TYPE_HASH, _EIP712NameHash(), _EIP712VersionHash());\n }\n\n function _buildDomainSeparator(bytes32 typeHash, bytes32 name, bytes32 version) private view returns (bytes32) {\n return keccak256(\n abi.encode(\n typeHash,\n name,\n version,\n _getChainId(),\n address(this)\n )\n );\n }\n\n /**\n * @dev Given an already https://eips.ethereum.org/EIPS/eip-712#definition-of-hashstruct[hashed struct], this\n * function returns the hash of the fully encoded EIP712 message for this domain.\n *\n * This hash can be used together with {ECDSA-recover} to obtain the signer of a message. For example:\n *\n * ```solidity\n * bytes32 digest = _hashTypedDataV4(keccak256(abi.encode(\n * keccak256(\"Mail(address to,string contents)\"),\n * mailTo,\n * keccak256(bytes(mailContents))\n * )));\n * address signer = ECDSA.recover(digest, signature);\n * ```\n */\n function _hashTypedDataV4(bytes32 structHash) internal view virtual returns (bytes32) {\n return keccak256(abi.encodePacked(\"\\x19\\x01\", _domainSeparatorV4(), structHash));\n }\n\n function _getChainId() private view returns (uint256 chainId) {\n this; // silence state mutability warning without generating bytecode - see https://github.com/ethereum/solidity/issues/2691\n // solhint-disable-next-line no-inline-assembly\n assembly {\n chainId := chainid()\n }\n }\n\n /**\n * @dev The hash of the name parameter for the EIP712 domain.\n *\n * NOTE: This function reads from storage by default, but can be redefined to return a constant value if gas costs\n * are a concern.\n */\n function _EIP712NameHash() internal virtual view returns (bytes32) {\n return _HASHED_NAME;\n }\n\n /**\n * @dev The hash of the version parameter for the EIP712 domain.\n *\n * NOTE: This function reads from storage by default, but can be redefined to return a constant value if gas costs\n * are a concern.\n */\n function _EIP712VersionHash() internal virtual view returns (bytes32) {\n return _HASHED_VERSION;\n }\n uint256[50] private __gap;\n}\n" + }, + "contracts/auxiliary/DummyWethProxy.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.6.12;\nimport \"@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol\";\nimport \"@openzeppelin/contracts-upgradeable/proxy/Initializable.sol\";\n\ninterface IWETH9 {\n function name() external view returns (string memory);\n\n function symbol() external view returns (string memory);\n\n function decimals() external view returns (uint8);\n\n function balanceOf(address) external view returns (uint256);\n\n function allowance(address, address) external view returns (uint256);\n\n receive() external payable;\n\n function deposit() external payable;\n\n function withdraw(uint256 wad) external;\n\n function totalSupply() external view returns (uint256);\n\n function approve(address guy, uint256 wad) external returns (bool);\n\n function transfer(address dst, uint256 wad) external returns (bool);\n\n function transferFrom(\n address src,\n address dst,\n uint256 wad\n ) external returns (bool);\n}\n\ncontract DummyWethProxy is Initializable, OwnableUpgradeable {\n function initialize() external initializer {\n __Ownable_init();\n }\n\n IWETH9 public WETH;\n\n function setWETHAddress(address payable _weth) external onlyOwner {\n WETH = IWETH9(_weth);\n }\n\n function withdrawToSelf(uint256 amount) external {\n WETH.withdraw(amount);\n }\n\n function rescue(uint256 amount) external onlyOwner {\n WETH.transfer(owner(), amount);\n }\n\n receive() external payable {}\n\n fallback() external payable {}\n}\n" + }, + "contracts/amm/helper/test/TestMathUtils.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.6.12;\n\nimport \"../../MathUtils.sol\";\n\ncontract TestMathUtils {\n using MathUtils for uint256;\n\n function difference(uint256 a, uint256 b) public pure returns (uint256) {\n return a.difference(b);\n }\n\n function within1(uint256 a, uint256 b) public pure returns (bool) {\n return a.within1(b);\n }\n}\n" + }, + "contracts/bridge/ERC20Migrator.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.6.12;\n\nimport \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/SafeERC20.sol\";\nimport \"@openzeppelin/contracts/math/SafeMath.sol\";\n\n/**\n * @title ERC20Migrator\n * @dev This contract can be used to migrate an ERC20 token from one\n * contract to another, where each token holder has to opt-in to the migration.\n * To opt-in, users must approve for this contract the number of tokens they\n * want to migrate. Once the allowance is set up, anyone can trigger the\n * migration to the new token contract. In this way, token holders \"turn in\"\n * their old balance and will be minted an equal amount in the new token.\n * The new token contract must be mintable.\n * ```\n */\n\ninterface IERC20Mintable is IERC20 {\n function mint(address to, uint256 amount) external;\n}\n\ncontract ERC20Migrator {\n using SafeERC20 for IERC20;\n using SafeMath for uint256;\n\n // Address of the old token contract\n IERC20 private _legacyToken;\n\n // Address of the new token contract\n IERC20Mintable private _newToken;\n\n /**\n * @param legacyToken address of the old token contract\n */\n constructor(IERC20 legacyToken, IERC20Mintable newToken) public {\n _legacyToken = legacyToken;\n _newToken = newToken;\n }\n\n /**\n * @dev Returns the legacy token that is being migrated.\n */\n function legacyToken() external view returns (IERC20) {\n return _legacyToken;\n }\n\n /**\n * @dev Returns the new token to which we are migrating.\n */\n function newToken() external view returns (IERC20) {\n return _newToken;\n }\n\n /**\n * @dev Transfers part of an account's balance in the old token to this\n * contract, and mints the same amount of new tokens for that account.\n * @param amount amount of tokens to be migrated\n */\n function migrate(uint256 amount) external {\n _legacyToken.safeTransferFrom(msg.sender, address(this), amount);\n uint256 amountToMint = amount.mul(5).div(2);\n _newToken.mint(msg.sender, amountToMint);\n }\n}\n" + }, + "contracts/bridge/ECDSANodeManagement.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.6.12;\n\nimport \"./utils/AddressArrayUtils.sol\";\nimport \"@openzeppelin/contracts/math/SafeMath.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/SafeERC20.sol\";\n\ncontract ECDSANodeManagement {\n using AddressArrayUtils for address[];\n using SafeMath for uint256;\n using SafeERC20 for IERC20;\n\n // Status of the keep.\n // Active means the keep is active.\n // Closed means the keep was closed happily.\n // Terminated means the keep was closed due to misbehavior.\n enum Status {\n Active,\n Closed,\n Terminated\n }\n\n // Address of the keep's owner.\n address public owner;\n\n // List of keep members' addresses.\n address[] public members;\n\n // Minimum number of honest keep members required to produce a signature.\n uint256 public honestThreshold;\n\n // Keep's ECDSA public key serialized to 64-bytes, where X and Y coordinates\n // are padded with zeros to 32-byte each.\n bytes public publicKey;\n\n // The timestamp at which keep has been created and key generation process\n // started.\n uint256 internal keyGenerationStartTimestamp;\n\n // Map stores public key by member addresses. All members should submit the\n // same public key.\n mapping(address => bytes) internal submittedPublicKeys;\n\n // The current status of the keep.\n // If the keep is Active members monitor it and support requests from the\n // keep owner.\n // If the owner decides to close the keep the flag is set to Closed.\n // If the owner seizes member bonds the flag is set to Terminated.\n Status internal status;\n\n // Flags execution of contract initialization.\n bool internal isInitialized;\n\n // Notification that the submitted public key does not match a key submitted\n // by other member. The event contains address of the member who tried to\n // submit a public key and a conflicting public key submitted already by other\n // member.\n event ConflictingPublicKeySubmitted(\n address indexed submittingMember,\n bytes conflictingPublicKey\n );\n\n // Notification that keep's ECDSA public key has been successfully established.\n event PublicKeyPublished(bytes publicKey);\n\n // Notification that the keep was closed by the owner.\n // Members no longer need to support this keep.\n event KeepClosed();\n\n // Notification that the keep has been terminated by the owner.\n // Members no longer need to support this keep.\n event KeepTerminated();\n\n /// @notice Returns keep's ECDSA public key.\n /// @return Keep's ECDSA public key.\n function getPublicKey() external view returns (bytes memory) {\n return publicKey;\n }\n\n /// @notice Submits a public key to the keep.\n /// @dev Public key is published successfully if all members submit the same\n /// value. In case of conflicts with others members submissions it will emit\n /// `ConflictingPublicKeySubmitted` event. When all submitted keys match\n /// it will store the key as keep's public key and emit a `PublicKeyPublished`\n /// event.\n /// @param _publicKey Signer's public key.\n function submitPublicKey(bytes calldata _publicKey) external onlyMember {\n require(\n !hasMemberSubmittedPublicKey(msg.sender),\n \"Member already submitted a public key\"\n );\n\n require(_publicKey.length == 64, \"Public key must be 64 bytes long\");\n\n submittedPublicKeys[msg.sender] = _publicKey;\n\n // Check if public keys submitted by all keep members are the same as\n // the currently submitted one.\n uint256 matchingPublicKeysCount = 0;\n for (uint256 i = 0; i < members.length; i++) {\n if (\n keccak256(submittedPublicKeys[members[i]]) !=\n keccak256(_publicKey)\n ) {\n // Emit an event only if compared member already submitted a value.\n if (hasMemberSubmittedPublicKey(members[i])) {\n emit ConflictingPublicKeySubmitted(\n msg.sender,\n submittedPublicKeys[members[i]]\n );\n }\n } else {\n matchingPublicKeysCount++;\n }\n }\n\n if (matchingPublicKeysCount != members.length) {\n return;\n }\n\n // All submitted signatures match.\n publicKey = _publicKey;\n emit PublicKeyPublished(_publicKey);\n }\n\n /// @notice Gets the owner of the keep.\n /// @return Address of the keep owner.\n function getOwner() external view returns (address) {\n return owner;\n }\n\n /// @notice Gets the timestamp the keep was opened at.\n /// @return Timestamp the keep was opened at.\n function getOpenedTimestamp() external view returns (uint256) {\n return keyGenerationStartTimestamp;\n }\n\n /// @notice Closes keep when owner decides that they no longer need it.\n /// Releases bonds to the keep members.\n /// @dev The function can be called only by the owner of the keep and only\n /// if the keep has not been already closed.\n function closeKeep() public onlyOwner onlyWhenActive {\n markAsClosed();\n }\n\n /// @notice Returns true if the keep is active.\n /// @return true if the keep is active, false otherwise.\n function isActive() public view returns (bool) {\n return status == Status.Active;\n }\n\n /// @notice Returns true if the keep is closed and members no longer support\n /// this keep.\n /// @return true if the keep is closed, false otherwise.\n function isClosed() public view returns (bool) {\n return status == Status.Closed;\n }\n\n /// @notice Returns true if the keep has been terminated.\n /// Keep is terminated when bonds are seized and members no longer support\n /// this keep.\n /// @return true if the keep has been terminated, false otherwise.\n function isTerminated() public view returns (bool) {\n return status == Status.Terminated;\n }\n\n /// @notice Returns members of the keep.\n /// @return List of the keep members' addresses.\n function getMembers() public view returns (address[] memory) {\n return members;\n }\n\n /// @notice Initialization function.\n /// @dev We use clone factory to create new keep. That is why this contract\n /// doesn't have a constructor. We provide keep parameters for each instance\n /// function after cloning instances from the master contract.\n /// Initialization must happen in the same transaction in which the clone is\n /// created.\n /// @param _owner Address of the keep owner.\n /// @param _members Addresses of the keep members.\n /// @param _honestThreshold Minimum number of honest keep members.\n function initialize(\n address _owner,\n address[] memory _members,\n uint256 _honestThreshold\n ) public {\n require(!isInitialized, \"Contract already initialized\");\n require(_owner != address(0));\n owner = _owner;\n members = _members;\n honestThreshold = _honestThreshold;\n\n status = Status.Active;\n isInitialized = true;\n\n /* solium-disable-next-line security/no-block-members*/\n keyGenerationStartTimestamp = block.timestamp;\n }\n\n /// @notice Checks if the member already submitted a public key.\n /// @param _member Address of the member.\n /// @return True if member already submitted a public key, else false.\n function hasMemberSubmittedPublicKey(address _member)\n internal\n view\n returns (bool)\n {\n return submittedPublicKeys[_member].length != 0;\n }\n\n /// @notice Marks the keep as closed.\n /// Keep can be marked as closed only when there is no signing in progress\n /// or the requested signing process has timed out.\n function markAsClosed() internal {\n status = Status.Closed;\n emit KeepClosed();\n }\n\n /// @notice Marks the keep as terminated.\n /// Keep can be marked as terminated only when there is no signing in progress\n /// or the requested signing process has timed out.\n function markAsTerminated() internal {\n status = Status.Terminated;\n emit KeepTerminated();\n }\n\n /// @notice Coverts a public key to an ethereum address.\n /// @param _publicKey Public key provided as 64-bytes concatenation of\n /// X and Y coordinates (32-bytes each).\n /// @return Ethereum address.\n function publicKeyToAddress(bytes memory _publicKey)\n internal\n pure\n returns (address)\n {\n // We hash the public key and then truncate last 20 bytes of the digest\n // which is the ethereum address.\n return address(uint160(uint256(keccak256(_publicKey))));\n }\n\n /// @notice Terminates the keep.\n function terminateKeep() internal {\n markAsTerminated();\n }\n\n /// @notice Checks if the caller is the keep's owner.\n /// @dev Throws an error if called by any account other than owner.\n modifier onlyOwner() {\n require(owner == msg.sender, \"Caller is not the keep owner\");\n _;\n }\n\n /// @notice Checks if the caller is a keep member.\n /// @dev Throws an error if called by any account other than one of the members.\n modifier onlyMember() {\n require(members.contains(msg.sender), \"Caller is not the keep member\");\n _;\n }\n\n /// @notice Checks if the keep is currently active.\n /// @dev Throws an error if called when the keep has been already closed.\n modifier onlyWhenActive() {\n require(isActive(), \"Keep is not active\");\n _;\n }\n}\n" + }, + "contracts/bridge/utils/AddressArrayUtils.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.6.12;\n\nlibrary AddressArrayUtils {\n function contains(address[] memory self, address _address)\n internal\n pure\n returns (bool)\n {\n for (uint256 i = 0; i < self.length; i++) {\n if (_address == self[i]) {\n return true;\n }\n }\n return false;\n }\n}" + }, + "contracts/bridge/testing/NodeEnv.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.6.12;\npragma experimental ABIEncoderV2;\n\nimport '@openzeppelin/contracts/access/AccessControl.sol';\nimport \"../utils/EnumerableStringMap.sol\";\n\n/**\n * @title NodeEnv contract\n * @author Synapse Authors\n * @notice This contract implements a key-value store for storing variables on which synapse nodes must coordinate\n * methods are purposely arbitrary to allow these fields to be defined in synapse improvement proposals.\n * @notice This token is used for configuring different tokens on the bridge and mapping them across chains.\n**/\ncontract NodeEnv is AccessControl {\n using EnumerableStringMap for EnumerableStringMap.StringToStringMap;\n // BRIDGEMANAGER_ROLE owns the bridge. They are the only user that can call setters on this contract\n bytes32 public constant BRIDGEMANAGER_ROLE = keccak256('BRIDGEMANAGER_ROLE');\n // _config stores the config\n EnumerableStringMap.StringToStringMap private _config; // key is tokenAddress,chainID\n\n // ConfigUpdate is emitted when the config is updated by the user\n event ConfigUpdate(\n string key\n );\n\n constructor() public {\n _setupRole(DEFAULT_ADMIN_ROLE, msg.sender);\n _setupRole(BRIDGEMANAGER_ROLE, msg.sender);\n }\n\n /**\n * @notice get the length of the config\n *\n * @dev this is useful for enumerating through all keys in the env\n */\n function keyCount()\n external\n view\n returns (uint256){\n return _config.length();\n }\n\n /**\n * @notice gets the key/value pair by it's index\n *\n * Requirements:\n *\n * - `index` must be strictly less than {length}.\n */\n function keyValueByIndex(uint256 index) external view returns(string memory, string memory){\n return _config.at(index);\n }\n\n /**\n * @notice gets the value associated with the key\n */\n function get(string calldata _key) external view returns(string memory){\n string memory key = _key;\n return _config.get(key);\n }\n\n /**\n * @notice sets the key\n *\n * @dev caller must have bridge manager role\n */\n function set(string calldata _key, string calldata _value) external returns(bool) {\n require(\n hasRole(BRIDGEMANAGER_ROLE, msg.sender),\n 'Caller is not Bridge Manager'\n );\n string memory key = _key;\n string memory value = _value;\n\n return _config.set(key, value);\n }\n}" + }, + "contracts/bridge/utils/EnumerableStringMap.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.6.12;\n\nimport \"@openzeppelin/contracts/utils/EnumerableSet.sol\";\n\n/**\n * @title EnumerableStringMap\n * @dev Library for managing an enumerable variant of Solidity's\n * https://solidity.readthedocs.io/en/latest/types.html#mapping-types[`mapping`]\n * type.\n *\n * Maps have the following properties:\n *\n * - Entries are added, removed, and checked for existence in constant time\n * (O(1)).\n * - Entries are enumerated in O(n). No guarantees are made on the ordering.\n *\n * this isn't a terribly gas efficient implementation because it emphasizes usability over gas efficiency\n * by allowing arbitrary length string memorys. If Gettetrs/Setters are going to be used frequently in contracts\n * consider using the OpenZeppeling Bytes32 implementation\n *\n * this also differs from the OpenZeppelin implementation by keccac256 hashing the string memorys\n * so we can use enumerable bytes32 set\n */\nlibrary EnumerableStringMap {\n using EnumerableSet for EnumerableSet.Bytes32Set;\n\n // To implement this library for multiple types with as little code\n // repetition as possible, we write it in terms of a generic Map type with\n // bytes32 keys and values.\n // The Map implementation uses private functions, and user-facing\n // implementations (such as Uint256ToAddressMap) are just wrappers around\n // the underlying Map.\n // This means that we can only create new EnumerableMaps for types that fit\n // in bytes32.\n\n struct Map {\n // Storage of keys as a set\n EnumerableSet.Bytes32Set _keys;\n // Mapping of keys to resulting values to allow key lookup in the set\n mapping(bytes32 => string) _hashKeyMap;\n // values\n mapping(bytes32 => string) _values;\n }\n\n /**\n * @dev Adds a key-value pair to a map, or updates the value for an existing\n * key. O(1).\n *\n * Returns true if the key was added to the map, that is if it was not\n * already present.\n */\n function _set(\n Map storage map,\n string memory key,\n string memory value\n ) private returns (bool) {\n bytes32 keyHash = keccak256(abi.encodePacked(key));\n map._values[keyHash] = value;\n map._hashKeyMap[keyHash] = key;\n return map._keys.add(keyHash);\n }\n\n /**\n * @dev Removes a key-value pair from a map. O(1).\n *\n * Returns true if the key was removed from the map, that is if it was present.\n */\n function _remove(Map storage map, bytes32 keyHash) private returns (bool) {\n delete map._values[keyHash];\n delete map._hashKeyMap[keyHash];\n return map._keys.remove(keyHash);\n }\n\n /**\n * @dev Returns true if the key is in the map. O(1).\n */\n function _contains(Map storage map, bytes32 keyHash) private view returns (bool) {\n return map._keys.contains(keyHash);\n }\n\n /**\n * @dev Returns the number of key-value pairs in the map. O(1).\n */\n function _length(Map storage map) private view returns (uint256) {\n return map._keys.length();\n }\n\n /**\n * @dev Returns the key-value pair stored at position `index` in the map. O(1).\n *\n * Note that there are no guarantees on the ordering of entries inside the\n * array, and it may change when more entries are added or removed.\n *\n * Requirements:\n *\n * - `index` must be strictly less than {length}.\n */\n function _at(Map storage map, uint256 index) private view returns (string memory, string memory) {\n bytes32 keyHash = map._keys.at(index);\n return (map._hashKeyMap[keyHash], map._values[keyHash]);\n }\n\n /**\n * @dev Tries to returns the value associated with `key`. O(1).\n * Does not revert if `key` is not in the map.\n */\n function _tryGet(Map storage map, bytes32 keyHash) private view returns (bool, string memory) {\n string memory value = map._values[keyHash];\n if (keccak256(bytes(value)) == keccak256(bytes(\"\"))) {\n return (_contains(map, keyHash), \"\");\n } else {\n return (true, value);\n }\n }\n\n /**\n * @dev Returns the value associated with `key`. O(1).\n *\n * Requirements:\n *\n * - `key` must be in the map.\n */\n function _get(Map storage map, bytes32 keyHash) private view returns (string memory) {\n string memory value = map._values[keyHash];\n require(_contains(map, keyHash), \"EnumerableMap: nonexistent key\");\n return value;\n }\n\n // StringToStringMap\n struct StringToStringMap {\n Map _inner;\n }\n\n /**\n * @dev Adds a key-value pair to a map, or updates the value for an existing\n * key. O(1).\n *\n * Returns true if the key was added to the map, that is if it was not\n * already present.\n */\n function set(\n StringToStringMap storage map,\n string memory key,\n string memory value\n ) internal returns (bool) {\n return _set(map._inner, key, value);\n }\n\n /**\n * @dev Removes a value from a set. O(1).\n *\n * Returns true if the key was removed from the map, that is if it was present.\n */\n function remove(StringToStringMap storage map, string memory key) internal returns (bool) {\n return _remove(map._inner, keccak256(abi.encodePacked(key)));\n }\n\n /**\n * @dev Returns true if the key is in the map. O(1).\n */\n function contains(StringToStringMap storage map, string memory key) internal view returns (bool) {\n return _contains(map._inner, keccak256(abi.encodePacked(key)));\n }\n\n /**\n * @dev Returns the number of elements in the map. O(1).\n */\n function length(StringToStringMap storage map) internal view returns (uint256) {\n return _length(map._inner);\n }\n\n /**\n * @dev Returns the element stored at position `index` in the set. O(1).\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(StringToStringMap storage map, uint256 index) internal view returns (string memory, string memory) {\n return _at(map._inner, index);\n }\n\n /**\n * @dev Tries to returns the value associated with `key`. O(1).\n * Does not revert if `key` is not in the map.\n *\n * _Available since v3.4._\n */\n function tryGet(StringToStringMap storage map, uint256 key) internal view returns (bool, string memory) {\n (bool success, string memory value) = _tryGet(map._inner, bytes32(key));\n return (success, value);\n }\n\n /**\n * @dev Returns the value associated with `key`. O(1).\n *\n * Requirements:\n *\n * - `key` must be in the map.\n */\n function get(StringToStringMap storage map, string memory key) internal view returns (string memory) {\n return _get(map._inner, keccak256(abi.encodePacked(key)));\n }\n}" + }, + "contracts/bridge/PoolConfig.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.6.12;\npragma experimental ABIEncoderV2;\n\nimport \"@openzeppelin/contracts/access/AccessControl.sol\";\n\ncontract PoolConfig is AccessControl {\n bytes32 public constant BRIDGEMANAGER_ROLE =\n keccak256(\"BRIDGEMANAGER_ROLE\");\n mapping(address => mapping(uint256 => Pool)) private _pool; // key is tokenAddress,chainID\n\n struct Pool {\n address tokenAddress;\n uint256 chainId;\n address poolAddress;\n bool metaswap;\n }\n\n constructor() public {\n _setupRole(DEFAULT_ADMIN_ROLE, msg.sender);\n _setupRole(BRIDGEMANAGER_ROLE, msg.sender);\n }\n\n function getPoolConfig(address tokenAddress, uint256 chainID)\n external\n view\n returns (Pool memory)\n {\n return _pool[tokenAddress][chainID];\n }\n\n function setPoolConfig(\n address tokenAddress,\n uint256 chainID,\n address poolAddress,\n bool metaswap\n ) external returns (Pool memory) {\n require(\n hasRole(BRIDGEMANAGER_ROLE, msg.sender),\n \"Caller is not Bridge Manager\"\n );\n Pool memory newPool = Pool(\n tokenAddress,\n chainID,\n poolAddress,\n metaswap\n );\n _pool[tokenAddress][chainID] = newPool;\n return newPool;\n }\n}\n" + }, + "contracts/bridge/BridgeConfigV3.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.6.12;\npragma experimental ABIEncoderV2;\n\nimport \"@openzeppelin/contracts/access/AccessControl.sol\";\nimport \"@openzeppelin/contracts/math/SafeMath.sol\";\n\n/**\n * @title BridgeConfig contract\n * @notice This token is used for configuring different tokens on the bridge and mapping them across chains.\n **/\n\ncontract BridgeConfigV3 is AccessControl {\n using SafeMath for uint256;\n bytes32 public constant BRIDGEMANAGER_ROLE =\n keccak256(\"BRIDGEMANAGER_ROLE\");\n bytes32[] private _allTokenIDs;\n mapping(bytes32 => Token[]) private _allTokens; // key is tokenID\n mapping(uint256 => mapping(string => bytes32)) private _tokenIDMap; // key is chainID,tokenAddress\n mapping(bytes32 => mapping(uint256 => Token)) private _tokens; // key is tokenID,chainID\n mapping(address => mapping(uint256 => Pool)) private _pool; // key is tokenAddress,chainID\n mapping(uint256 => uint256) private _maxGasPrice; // key is tokenID,chainID\n uint256 public constant bridgeConfigVersion = 3;\n\n // the denominator used to calculate fees. For example, an\n // LP fee might be something like tradeAmount.mul(fee).div(FEE_DENOMINATOR)\n uint256 private constant FEE_DENOMINATOR = 10**10;\n\n // this struct must be initialized using setTokenConfig for each token that directly interacts with the bridge\n struct Token {\n uint256 chainId;\n string tokenAddress;\n uint8 tokenDecimals;\n uint256 maxSwap;\n uint256 minSwap;\n uint256 swapFee;\n uint256 maxSwapFee;\n uint256 minSwapFee;\n bool hasUnderlying;\n bool isUnderlying;\n }\n\n struct Pool {\n address tokenAddress;\n uint256 chainId;\n address poolAddress;\n bool metaswap;\n }\n\n constructor() public {\n _setupRole(DEFAULT_ADMIN_ROLE, msg.sender);\n }\n\n /**\n * @notice Returns a list of all existing token IDs converted to strings\n */\n function getAllTokenIDs() public view returns (string[] memory result) {\n uint256 length = _allTokenIDs.length;\n result = new string[](length);\n for (uint256 i = 0; i < length; ++i) {\n result[i] = toString(_allTokenIDs[i]);\n }\n }\n\n function _getTokenID(string memory tokenAddress, uint256 chainID)\n internal\n view\n returns (string memory)\n {\n return toString(_tokenIDMap[chainID][tokenAddress]);\n }\n\n function getTokenID(string memory tokenAddress, uint256 chainID)\n public\n view\n returns (string memory)\n {\n return _getTokenID(_toLower(tokenAddress), chainID);\n }\n\n /**\n * @notice Returns the token ID (string) of the cross-chain token inputted\n * @param tokenAddress address of token to get ID for\n * @param chainID chainID of which to get token ID for\n */\n function getTokenID(address tokenAddress, uint256 chainID)\n public\n view\n returns (string memory)\n {\n return _getTokenID(_toLower(toString(tokenAddress)), chainID);\n }\n\n /**\n * @notice Returns the full token config struct\n * @param tokenID String input of the token ID for the token\n * @param chainID Chain ID of which token address + config to get\n */\n function getToken(string memory tokenID, uint256 chainID)\n public\n view\n returns (Token memory token)\n {\n return _tokens[toBytes32(tokenID)][chainID];\n }\n\n /**\n * @notice Returns the full token config struct\n * @param tokenID String input of the token ID for the token\n * @param chainID Chain ID of which token address + config to get\n */\n function getTokenByID(string memory tokenID, uint256 chainID)\n public\n view\n returns (Token memory token)\n {\n return _tokens[toBytes32(tokenID)][chainID];\n }\n\n /**\n * @notice Returns token config struct, given an address and chainID\n * @param tokenAddress Matches the token ID by using a combo of address + chain ID\n * @param chainID Chain ID of which token to get config for\n */\n function getTokenByAddress(string memory tokenAddress, uint256 chainID)\n public\n view\n returns (Token memory token)\n {\n return _tokens[_tokenIDMap[chainID][_toLower(tokenAddress)]][chainID];\n }\n\n function getTokenByEVMAddress(address tokenAddress, uint256 chainID)\n public\n view\n returns (Token memory token)\n {\n return\n _tokens[_tokenIDMap[chainID][_toLower(toString(tokenAddress))]][\n chainID\n ];\n }\n\n /**\n * @notice Returns true if the token has an underlying token -- meaning the token is deposited into the bridge\n * @param tokenID String to check if it is a withdraw/underlying token\n */\n function hasUnderlyingToken(string memory tokenID)\n public\n view\n returns (bool)\n {\n bytes32 bytesTokenID = toBytes32(tokenID);\n Token[] memory _mcTokens = _allTokens[bytesTokenID];\n for (uint256 i = 0; i < _mcTokens.length; ++i) {\n if (_mcTokens[i].hasUnderlying) {\n return true;\n }\n }\n return false;\n }\n\n /**\n * @notice Returns which token is the underlying token to withdraw\n * @param tokenID string token ID\n */\n function getUnderlyingToken(string memory tokenID)\n public\n view\n returns (Token memory token)\n {\n bytes32 bytesTokenID = toBytes32(tokenID);\n Token[] memory _mcTokens = _allTokens[bytesTokenID];\n for (uint256 i = 0; i < _mcTokens.length; ++i) {\n if (_mcTokens[i].isUnderlying) {\n return _mcTokens[i];\n }\n }\n }\n\n /**\n @notice Public function returning if token ID exists given a string\n */\n function isTokenIDExist(string memory tokenID) public view returns (bool) {\n return _isTokenIDExist(toBytes32(tokenID));\n }\n\n /**\n @notice Internal function returning if token ID exists given bytes32 version of the ID\n */\n function _isTokenIDExist(bytes32 tokenID) internal view returns (bool) {\n for (uint256 i = 0; i < _allTokenIDs.length; ++i) {\n if (_allTokenIDs[i] == tokenID) {\n return true;\n }\n }\n return false;\n }\n\n /**\n * @notice Internal function which handles logic of setting token ID and dealing with mappings\n * @param tokenID bytes32 version of ID\n * @param chainID which chain to set the token config for\n * @param tokenToAdd Token object to set the mapping to\n */\n function _setTokenConfig(\n bytes32 tokenID,\n uint256 chainID,\n Token memory tokenToAdd\n ) internal returns (bool) {\n _tokens[tokenID][chainID] = tokenToAdd;\n if (!_isTokenIDExist(tokenID)) {\n _allTokenIDs.push(tokenID);\n }\n\n Token[] storage _mcTokens = _allTokens[tokenID];\n for (uint256 i = 0; i < _mcTokens.length; ++i) {\n if (_mcTokens[i].chainId == chainID) {\n string memory oldToken = _mcTokens[i].tokenAddress;\n if (!compareStrings(tokenToAdd.tokenAddress, oldToken)) {\n _mcTokens[i].tokenAddress = tokenToAdd.tokenAddress;\n _tokenIDMap[chainID][oldToken] = keccak256(\"\");\n _tokenIDMap[chainID][tokenToAdd.tokenAddress] = tokenID;\n }\n }\n }\n _mcTokens.push(tokenToAdd);\n _tokenIDMap[chainID][tokenToAdd.tokenAddress] = tokenID;\n return true;\n }\n\n /**\n * @notice Main write function of this contract - Handles creating the struct and passing it to the internal logic function\n * @param tokenID string ID to set the token config object form\n * @param chainID chain ID to use for the token config object\n * @param tokenAddress token address of the token on the given chain\n * @param tokenDecimals decimals of token\n * @param maxSwap maximum amount of token allowed to be transferred at once - in native token decimals\n * @param minSwap minimum amount of token needed to be transferred at once - in native token decimals\n * @param swapFee percent based swap fee -- 10e6 == 10bps\n * @param maxSwapFee max swap fee to be charged - in native token decimals\n * @param minSwapFee min swap fee to be charged - in native token decimals - especially useful for mainnet ETH\n * @param hasUnderlying bool which represents whether this is a global mint token or one to withdraw()\n * @param isUnderlying bool which represents if this token is the one to withdraw on the given chain\n */\n function setTokenConfig(\n string calldata tokenID,\n uint256 chainID,\n address tokenAddress,\n uint8 tokenDecimals,\n uint256 maxSwap,\n uint256 minSwap,\n uint256 swapFee,\n uint256 maxSwapFee,\n uint256 minSwapFee,\n bool hasUnderlying,\n bool isUnderlying\n ) public returns (bool) {\n require(hasRole(BRIDGEMANAGER_ROLE, msg.sender));\n return\n setTokenConfig(\n tokenID,\n chainID,\n toString(tokenAddress),\n tokenDecimals,\n maxSwap,\n minSwap,\n swapFee,\n maxSwapFee,\n minSwapFee,\n hasUnderlying,\n isUnderlying\n );\n }\n\n /**\n * @notice Main write function of this contract - Handles creating the struct and passing it to the internal logic function\n * @param tokenID string ID to set the token config object form\n * @param chainID chain ID to use for the token config object\n * @param tokenAddress token address of the token on the given chain\n * @param tokenDecimals decimals of token\n * @param maxSwap maximum amount of token allowed to be transferred at once - in native token decimals\n * @param minSwap minimum amount of token needed to be transferred at once - in native token decimals\n * @param swapFee percent based swap fee -- 10e6 == 10bps\n * @param maxSwapFee max swap fee to be charged - in native token decimals\n * @param minSwapFee min swap fee to be charged - in native token decimals - especially useful for mainnet ETH\n * @param hasUnderlying bool which represents whether this is a global mint token or one to withdraw()\n * @param isUnderlying bool which represents if this token is the one to withdraw on the given chain\n */\n function setTokenConfig(\n string calldata tokenID,\n uint256 chainID,\n string memory tokenAddress,\n uint8 tokenDecimals,\n uint256 maxSwap,\n uint256 minSwap,\n uint256 swapFee,\n uint256 maxSwapFee,\n uint256 minSwapFee,\n bool hasUnderlying,\n bool isUnderlying\n ) public returns (bool) {\n require(hasRole(BRIDGEMANAGER_ROLE, msg.sender));\n Token memory tokenToAdd;\n tokenToAdd.tokenAddress = _toLower(tokenAddress);\n tokenToAdd.tokenDecimals = tokenDecimals;\n tokenToAdd.maxSwap = maxSwap;\n tokenToAdd.minSwap = minSwap;\n tokenToAdd.swapFee = swapFee;\n tokenToAdd.maxSwapFee = maxSwapFee;\n tokenToAdd.minSwapFee = minSwapFee;\n tokenToAdd.hasUnderlying = hasUnderlying;\n tokenToAdd.isUnderlying = isUnderlying;\n tokenToAdd.chainId = chainID;\n\n return _setTokenConfig(toBytes32(tokenID), chainID, tokenToAdd);\n }\n\n function _calculateSwapFee(\n string memory tokenAddress,\n uint256 chainID,\n uint256 amount\n ) internal view returns (uint256) {\n Token memory token = _tokens[_tokenIDMap[chainID][tokenAddress]][\n chainID\n ];\n uint256 calculatedSwapFee = amount.mul(token.swapFee).div(\n FEE_DENOMINATOR\n );\n if (\n calculatedSwapFee > token.minSwapFee &&\n calculatedSwapFee < token.maxSwapFee\n ) {\n return calculatedSwapFee;\n } else if (calculatedSwapFee > token.maxSwapFee) {\n return token.maxSwapFee;\n } else {\n return token.minSwapFee;\n }\n }\n\n /**\n * @notice Calculates bridge swap fee based on the destination chain's token transfer.\n * @dev This means the fee should be calculated based on the chain that the nodes emit a tx on\n * @param tokenAddress address of the destination token to query token config for\n * @param chainID destination chain ID to query the token config for\n * @param amount in native token decimals\n * @return Fee calculated in token decimals\n */\n function calculateSwapFee(\n string memory tokenAddress,\n uint256 chainID,\n uint256 amount\n ) external view returns (uint256) {\n return _calculateSwapFee(_toLower(tokenAddress), chainID, amount);\n }\n\n /**\n * @notice Calculates bridge swap fee based on the destination chain's token transfer.\n * @dev This means the fee should be calculated based on the chain that the nodes emit a tx on\n * @param tokenAddress address of the destination token to query token config for\n * @param chainID destination chain ID to query the token config for\n * @param amount in native token decimals\n * @return Fee calculated in token decimals\n */\n function calculateSwapFee(\n address tokenAddress,\n uint256 chainID,\n uint256 amount\n ) external view returns (uint256) {\n return\n _calculateSwapFee(\n _toLower(toString(tokenAddress)),\n chainID,\n amount\n );\n }\n\n // GAS PRICING\n\n /**\n * @notice sets the max gas price for a chain\n */\n function setMaxGasPrice(uint256 chainID, uint256 maxPrice) public {\n require(hasRole(BRIDGEMANAGER_ROLE, msg.sender));\n _maxGasPrice[chainID] = maxPrice;\n }\n\n /**\n * @notice gets the max gas price for a chain\n */\n function getMaxGasPrice(uint256 chainID) public view returns (uint256) {\n return _maxGasPrice[chainID];\n }\n\n // POOL CONFIG\n\n function getPoolConfig(address tokenAddress, uint256 chainID)\n external\n view\n returns (Pool memory)\n {\n return _pool[tokenAddress][chainID];\n }\n\n function setPoolConfig(\n address tokenAddress,\n uint256 chainID,\n address poolAddress,\n bool metaswap\n ) external returns (Pool memory) {\n require(\n hasRole(BRIDGEMANAGER_ROLE, msg.sender),\n \"Caller is not Bridge Manager\"\n );\n Pool memory newPool = Pool(\n tokenAddress,\n chainID,\n poolAddress,\n metaswap\n );\n _pool[tokenAddress][chainID] = newPool;\n return newPool;\n }\n\n // UTILITY FUNCTIONS\n\n function toString(bytes32 data) internal pure returns (string memory) {\n uint8 i = 0;\n while (i < 32 && data[i] != 0) {\n ++i;\n }\n bytes memory bs = new bytes(i);\n for (uint8 j = 0; j < i; ++j) {\n bs[j] = data[j];\n }\n return string(bs);\n }\n\n // toBytes32 converts a string to a bytes 32\n function toBytes32(string memory str)\n internal\n pure\n returns (bytes32 result)\n {\n require(bytes(str).length <= 32);\n assembly {\n result := mload(add(str, 32))\n }\n }\n\n function toString(address x) internal pure returns (string memory) {\n bytes memory s = new bytes(40);\n for (uint256 i = 0; i < 20; i++) {\n bytes1 b = bytes1(uint8(uint256(uint160(x)) / (2**(8 * (19 - i)))));\n bytes1 hi = bytes1(uint8(b) / 16);\n bytes1 lo = bytes1(uint8(b) - 16 * uint8(hi));\n s[2 * i] = char(hi);\n s[2 * i + 1] = char(lo);\n }\n\n string memory addrPrefix = \"0x\";\n\n return concat(addrPrefix, string(s));\n }\n\n function concat(string memory _x, string memory _y)\n internal\n pure\n returns (string memory)\n {\n bytes memory _xBytes = bytes(_x);\n bytes memory _yBytes = bytes(_y);\n\n string memory _tmpValue = new string(_xBytes.length + _yBytes.length);\n bytes memory _newValue = bytes(_tmpValue);\n\n uint256 i;\n uint256 j;\n\n for (i = 0; i < _xBytes.length; i++) {\n _newValue[j++] = _xBytes[i];\n }\n\n for (i = 0; i < _yBytes.length; i++) {\n _newValue[j++] = _yBytes[i];\n }\n\n return string(_newValue);\n }\n\n function char(bytes1 b) internal pure returns (bytes1 c) {\n if (uint8(b) < 10) {\n c = bytes1(uint8(b) + 0x30);\n } else {\n c = bytes1(uint8(b) + 0x57);\n }\n }\n\n function compareStrings(string memory a, string memory b)\n internal\n pure\n returns (bool)\n {\n return (keccak256(abi.encodePacked((a))) ==\n keccak256(abi.encodePacked((b))));\n }\n\n function _toLower(string memory str) internal pure returns (string memory) {\n bytes memory bStr = bytes(str);\n bytes memory bLower = new bytes(bStr.length);\n for (uint256 i = 0; i < bStr.length; i++) {\n // Uppercase character...\n if ((uint8(bStr[i]) >= 65) && (uint8(bStr[i]) <= 90)) {\n // So we add 32 to make it lowercase\n bLower[i] = bytes1(uint8(bStr[i]) + 32);\n } else {\n bLower[i] = bStr[i];\n }\n }\n return string(bLower);\n }\n}\n" + }, + "contracts/bridge/wrappers/GMXWrapper.sol": { + "content": "// SPDX-License-Identifier: MIT\n\nimport '@openzeppelin/contracts/math/SafeMath.sol';\n\npragma solidity 0.6.12;\n\ninterface IGMX {\n function burn(address _account, uint256 _amount) external;\n function balanceOf(address account) external view returns (uint256);\n function mint(address _account, uint256 _amount) external;\n}\n\ncontract GMXWrapper {\n using SafeMath for uint256;\n\n address constant public gmx = 0x62edc0692BD897D2295872a9FFCac5425011c661;\n address constant public bridge = 0xC05e61d0E7a63D27546389B7aD62FdFf5A91aACE;\n\n function transfer(address _recipient, uint256 _amount) external returns (bool) {\n require(msg.sender == bridge);\n _transfer(msg.sender, _recipient, _amount);\n return true;\n }\n\n function _transfer(address _sender, address _recipient, uint256 _amount) private {\n require(_sender != address(0), \"BaseToken: transfer from the zero address\");\n require(_recipient != address(0), \"BaseToken: transfer to the zero address\");\n IGMX(gmx).burn(_sender, _amount);\n IGMX(gmx).mint(_recipient, _amount);\n }\n\n function mint(address _addr, uint256 _amount) external {\n require(msg.sender == bridge);\n uint256 preMint = IGMX(gmx).balanceOf(_addr);\n IGMX(gmx).mint(_addr, _amount);\n uint256 postMint = IGMX(gmx).balanceOf(_addr);\n require(preMint.add(_amount) == postMint, \"Mint incomplete\");\n }\n\n function burnFrom(address _addr, uint256 _amount) external {\n require(msg.sender == bridge);\n uint256 preBurn = IGMX(gmx).balanceOf(_addr);\n IGMX(gmx).burn(_addr, _amount);\n uint256 postBurn = IGMX(gmx).balanceOf(_addr);\n require(postBurn.add(_amount) == preBurn, \"Burn incomplete\");\n }\n}" + }, + "contracts/amm/SwapEthWrapper.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.6.12;\n\nimport \"@openzeppelin/contracts/math/SafeMath.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/SafeERC20.sol\";\nimport \"./Swap.sol\";\nimport \"./interfaces/IWETH9.sol\";\n\n/**\n * @title SwapEthWrapper\n * @notice A wrapper contract for Swap contracts that have WETH as one of the pooled tokens.\n * @author Jongseung Lim (@weeb_mcgee)\n */\ncontract SwapEthWrapper {\n using SafeERC20 for IERC20;\n using SafeMath for uint256;\n\n // constants\n uint8 private constant MAX_UINT8 = 2**8 - 1;\n uint256 private constant MAX_UINT256 = 2**256 - 1;\n\n // immutables\n Swap public immutable SWAP;\n LPToken public immutable LP_TOKEN;\n address payable public immutable WETH_ADDRESS;\n address public immutable OWNER;\n uint8 public immutable WETH_INDEX;\n\n IERC20[] public pooledTokens;\n\n /**\n * @notice Deploys this contract with given WETH9 address and Swap address. It will attempt to\n * fetch information about the given Swap pool. If the Swap pool does not contain WETH9,\n * this call will be reverted. Owner address must be given so that `rescue()` function\n * can be limited.\n * @param wethAddress address to the WETH9 contract\n * @param swap address to the Swap contract that has WETH9 as one of the tokens\n * @param owner address that will be allowed to call `rescue()`\n */\n constructor(\n address payable wethAddress,\n Swap swap,\n address owner\n ) public {\n (, , , , , , LPToken lpToken) = swap.swapStorage();\n uint8 wethIndex = MAX_UINT8;\n\n for (uint8 i = 0; i < MAX_UINT8; i++) {\n try swap.getToken(i) returns (IERC20 token) {\n pooledTokens.push(token);\n if (address(token) == wethAddress) {\n wethIndex = i;\n }\n // Approve pooled tokens to be used by Swap\n token.approve(address(swap), MAX_UINT256);\n } catch {\n break;\n }\n }\n require(wethIndex != MAX_UINT8, \"WETH was not found in the swap pool\");\n\n // Set immutable variables\n WETH_INDEX = wethIndex;\n WETH_ADDRESS = wethAddress;\n SWAP = swap;\n LP_TOKEN = lpToken;\n OWNER = owner;\n\n // Approve LPToken to be used by Swap\n lpToken.approve(address(swap), MAX_UINT256);\n }\n\n /**\n * @notice Add liquidity to the pool with the given amounts of tokens.\n * @dev The msg.value of this call should match the value in amounts array\n * in position of WETH9.\n * @param amounts the amounts of each token to add, in their native precision\n * @param minToMint the minimum LP tokens adding this amount of liquidity\n * should mint, otherwise revert. Handy for front-running mitigation\n * @param deadline latest timestamp to accept this transaction\n * @return amount of LP token user minted and received\n */\n function addLiquidity(\n uint256[] memory amounts,\n uint256 minToMint,\n uint256 deadline\n ) external payable returns (uint256) {\n // If using ETH, deposit them to WETH.\n require(msg.value == amounts[WETH_INDEX], \"INCORRECT_MSG_VALUE\");\n if (msg.value > 0) {\n IWETH9(WETH_ADDRESS).deposit{value: msg.value}();\n }\n // Go through amounts array and transfer respective tokens to this contract.\n for (uint256 i = 0; i < amounts.length; i++) {\n uint256 amount = amounts[i];\n if (i != WETH_INDEX && amount > 0) {\n pooledTokens[i].safeTransferFrom(\n msg.sender,\n address(this),\n amount\n );\n }\n }\n // Add the assets to the pool\n uint256 lpTokenAmount = SWAP.addLiquidity(amounts, minToMint, deadline);\n // Send the LPToken to msg.sender\n IERC20(address(LP_TOKEN)).safeTransfer(msg.sender, lpTokenAmount);\n return lpTokenAmount;\n }\n\n /**\n * @notice Burn LP tokens to remove liquidity from the pool.\n * @dev Liquidity can always be removed, even when the pool is paused. Caller\n * will receive ETH instead of WETH9.\n * @param amount the amount of LP tokens to burn\n * @param minAmounts the minimum amounts of each token in the pool\n * acceptable for this burn. Useful as a front-running mitigation\n * @param deadline latest timestamp to accept this transaction\n * @return amounts of tokens user received\n */\n function removeLiquidity(\n uint256 amount,\n uint256[] calldata minAmounts,\n uint256 deadline\n ) external returns (uint256[] memory) {\n // Transfer LPToken from msg.sender to this contract.\n IERC20(address(LP_TOKEN)).safeTransferFrom(\n msg.sender,\n address(this),\n amount\n );\n // Remove liquidity\n uint256[] memory amounts = SWAP.removeLiquidity(\n amount,\n minAmounts,\n deadline\n );\n // Send the tokens back to the user\n for (uint256 i = 0; i < amounts.length; i++) {\n if (i != WETH_INDEX) {\n pooledTokens[i].safeTransfer(msg.sender, amounts[i]);\n } else {\n IWETH9(WETH_ADDRESS).withdraw(amounts[i]);\n // slither-disable-next-line arbitrary-send\n (bool success, ) = msg.sender.call{value: amounts[i]}(\"\");\n require(success, \"ETH_TRANSFER_FAILED\");\n }\n }\n return amounts;\n }\n\n /**\n * @notice Remove liquidity from the pool all in one token.\n * @dev Caller will receive ETH instead of WETH9.\n * @param tokenAmount the amount of the token you want to receive\n * @param tokenIndex the index of the token you want to receive\n * @param minAmount the minimum amount to withdraw, otherwise revert\n * @param deadline latest timestamp to accept this transaction\n * @return amount of chosen token user received\n */\n function removeLiquidityOneToken(\n uint256 tokenAmount,\n uint8 tokenIndex,\n uint256 minAmount,\n uint256 deadline\n ) external returns (uint256) {\n // Transfer LPToken from msg.sender to this contract.\n IERC20(address(LP_TOKEN)).safeTransferFrom(\n msg.sender,\n address(this),\n tokenAmount\n );\n // Withdraw via single token\n uint256 amount = SWAP.removeLiquidityOneToken(\n tokenAmount,\n tokenIndex,\n minAmount,\n deadline\n );\n // Transfer the token to msg.sender accordingly\n if (tokenIndex != WETH_INDEX) {\n pooledTokens[tokenIndex].safeTransfer(msg.sender, amount);\n } else {\n IWETH9(WETH_ADDRESS).withdraw(amount);\n // slither-disable-next-line arbitrary-send\n (bool success, ) = msg.sender.call{value: amount}(\"\");\n require(success, \"ETH_TRANSFER_FAILED\");\n }\n return amount;\n }\n\n /**\n * @notice Remove liquidity from the pool, weighted differently than the\n * pool's current balances.\n * @dev Caller will receive ETH instead of WETH9.\n * @param amounts how much of each token to withdraw\n * @param maxBurnAmount the max LP token provider is willing to pay to\n * remove liquidity. Useful as a front-running mitigation.\n * @param deadline latest timestamp to accept this transaction\n * @return amount of LP tokens burned\n */\n function removeLiquidityImbalance(\n uint256[] calldata amounts,\n uint256 maxBurnAmount,\n uint256 deadline\n ) external returns (uint256) {\n // Transfer LPToken from msg.sender to this contract.\n IERC20(address(LP_TOKEN)).safeTransferFrom(\n msg.sender,\n address(this),\n maxBurnAmount\n );\n // Withdraw in imbalanced ratio\n uint256 burnedLpTokenAmount = SWAP.removeLiquidityImbalance(\n amounts,\n maxBurnAmount,\n deadline\n );\n // Send the tokens back to the user\n for (uint256 i = 0; i < amounts.length; i++) {\n if (i != WETH_INDEX) {\n pooledTokens[i].safeTransfer(msg.sender, amounts[i]);\n } else {\n IWETH9(WETH_ADDRESS).withdraw(amounts[i]);\n // slither-disable-next-line arbitrary-send\n (bool success, ) = msg.sender.call{value: amounts[i]}(\"\");\n require(success, \"ETH_TRANSFER_FAILED\");\n }\n }\n // Send any extra LP tokens back as well\n uint256 extraLpTokenAmount = maxBurnAmount.sub(burnedLpTokenAmount);\n if (extraLpTokenAmount > 0) {\n IERC20(address(LP_TOKEN)).safeTransfer(\n msg.sender,\n extraLpTokenAmount\n );\n }\n return burnedLpTokenAmount;\n }\n\n /**\n * @notice Swap two tokens using the underlying pool. If tokenIndexFrom\n * represents WETH9 in the pool, the caller must set msg.value equal to dx.\n * If the user is swapping to WETH9 in the pool, the user will receive ETH instead.\n * @param tokenIndexFrom the token the user wants to swap from\n * @param tokenIndexTo the token the user wants to swap to\n * @param dx the amount of tokens the user wants to swap from\n * @param minDy the min amount the user would like to receive, or revert.\n * @param deadline latest timestamp to accept this transaction\n */\n function swap(\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx,\n uint256 minDy,\n uint256 deadline\n ) external payable returns (uint256) {\n // Transfer tokens from msg.sender to this contract\n if (tokenIndexFrom != WETH_INDEX) {\n IERC20(pooledTokens[tokenIndexFrom]).safeTransferFrom(\n msg.sender,\n address(this),\n dx\n );\n } else {\n require(msg.value == dx, \"INCORRECT_MSG_VALUE\");\n IWETH9(WETH_ADDRESS).deposit{value: msg.value}();\n }\n // Execute swap\n uint256 dy = SWAP.swap(\n tokenIndexFrom,\n tokenIndexTo,\n dx,\n minDy,\n deadline\n );\n // Transfer the swapped tokens to msg.sender\n if (tokenIndexTo != WETH_INDEX) {\n IERC20(pooledTokens[tokenIndexTo]).safeTransfer(msg.sender, dy);\n } else {\n IWETH9(WETH_ADDRESS).withdraw(dy);\n // slither-disable-next-line arbitrary-send\n (bool success, ) = msg.sender.call{value: dy}(\"\");\n require(success, \"ETH_TRANSFER_FAILED\");\n }\n return dy;\n }\n\n /**\n * @notice Rescues any of the ETH, the pooled tokens, or the LPToken that may be stuck\n * in this contract. Only the OWNER can call this function.\n */\n function rescue() external {\n require(msg.sender == OWNER, \"CALLED_BY_NON_OWNER\");\n IERC20[] memory tokens = pooledTokens;\n for (uint256 i = 0; i < tokens.length; i++) {\n tokens[i].safeTransfer(\n msg.sender,\n tokens[i].balanceOf(address(this))\n );\n }\n IERC20 lpToken_ = IERC20(address(LP_TOKEN));\n lpToken_.safeTransfer(msg.sender, lpToken_.balanceOf(address(this)));\n // slither-disable-next-line arbitrary-send\n (bool success, ) = msg.sender.call{value: address(this).balance}(\"\");\n require(success, \"ETH_TRANSFER_FAILED\");\n }\n\n receive() external payable {}\n\n // VIEW FUNCTIONS\n\n /**\n * @notice A simple method to calculate prices from deposits or\n * withdrawals, excluding fees but including slippage. This is\n * helpful as an input into the various \"min\" parameters on calls\n * to fight front-running\n *\n * @dev This shouldn't be used outside frontends for user estimates.\n *\n * @param amounts an array of token amounts to deposit or withdrawal,\n * corresponding to pooledTokens. The amount should be in each\n * pooled token's native precision. If a token charges a fee on transfers,\n * use the amount that gets transferred after the fee.\n * @param deposit whether this is a deposit or a withdrawal\n * @return token amount the user will receive\n */\n function calculateTokenAmount(uint256[] calldata amounts, bool deposit)\n external\n view\n returns (uint256)\n {\n return SWAP.calculateTokenAmount(amounts, deposit);\n }\n\n /**\n * @notice A simple method to calculate amount of each underlying\n * tokens that is returned upon burning given amount of LP tokens\n * @param amount the amount of LP tokens that would be burned on withdrawal\n * @return array of token balances that the user will receive\n */\n function calculateRemoveLiquidity(uint256 amount)\n external\n view\n returns (uint256[] memory)\n {\n return SWAP.calculateRemoveLiquidity(amount);\n }\n\n /**\n * @notice Calculate the amount of underlying token available to withdraw\n * when withdrawing via only single token\n * @param tokenAmount the amount of LP token to burn\n * @param tokenIndex index of which token will be withdrawn\n * @return availableTokenAmount calculated amount of underlying token\n * available to withdraw\n */\n function calculateRemoveLiquidityOneToken(\n uint256 tokenAmount,\n uint8 tokenIndex\n ) external view returns (uint256 availableTokenAmount) {\n return SWAP.calculateRemoveLiquidityOneToken(tokenAmount, tokenIndex);\n }\n}\n" + }, + "contracts/amm/interfaces/IWETH9.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.4.0;\n\ninterface IWETH9 {\n function name() external view returns (string memory);\n\n function symbol() external view returns (string memory);\n\n function decimals() external view returns (uint8);\n\n function balanceOf(address) external view returns (uint256);\n\n function allowance(address, address) external view returns (uint256);\n\n receive() external payable;\n\n function deposit() external payable;\n\n function withdraw(uint256 wad) external;\n\n function totalSupply() external view returns (uint256);\n\n function approve(address guy, uint256 wad) external returns (bool);\n\n function transfer(address dst, uint256 wad) external returns (bool);\n\n function transferFrom(\n address src,\n address dst,\n uint256 wad\n ) external returns (bool);\n}\n" + }, + "contracts/amm/helper/BaseSwapDeposit.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.6.12;\n\nimport \"@openzeppelin/contracts/math/SafeMath.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/SafeERC20.sol\";\nimport \"../interfaces/ISwap.sol\";\nimport \"@openzeppelin/contracts/utils/ReentrancyGuard.sol\";\n\ncontract BaseSwapDeposit is ReentrancyGuard {\n using SafeERC20 for IERC20;\n using SafeMath for uint256;\n\n ISwap public baseSwap;\n IERC20[] public baseTokens;\n\n uint256 constant MAX_UINT256 = 2**256 - 1;\n\n constructor(ISwap _baseSwap) public {\n baseSwap = _baseSwap;\n // Check and approve base level tokens to be deposited to the base Swap contract\n {\n uint8 i;\n for (; i < 32; i++) {\n try _baseSwap.getToken(i) returns (IERC20 token) {\n baseTokens.push(token);\n token.safeApprove(address(_baseSwap), MAX_UINT256);\n } catch {\n break;\n }\n }\n require(i > 1, \"baseSwap must have at least 2 tokens\");\n }\n }\n\n // Mutative functions\n\n /**\n * @notice Swap two underlying tokens using the meta pool and the base pool\n * @param tokenIndexFrom the token the user wants to swap from\n * @param tokenIndexTo the token the user wants to swap to\n * @param dx the amount of tokens the user wants to swap from\n * @param minDy the min amount the user would like to receive, or revert.\n * @param deadline latest timestamp to accept this transaction\n */\n function swap(\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx,\n uint256 minDy,\n uint256 deadline\n ) external nonReentrant returns (uint256) {\n baseTokens[tokenIndexFrom].safeTransferFrom(msg.sender, address(this), dx);\n uint256 tokenToAmount =\n baseSwap.swap(\n tokenIndexFrom,\n tokenIndexTo,\n dx,\n minDy,\n deadline\n );\n baseTokens[tokenIndexTo].safeTransfer(msg.sender, tokenToAmount);\n return tokenToAmount;\n }\n\n /**\n * @notice Calculate amount of tokens you receive on swap\n * @param tokenIndexFrom the token the user wants to sell\n * @param tokenIndexTo the token the user wants to buy\n * @param dx the amount of tokens the user wants to sell. If the token charges\n * a fee on transfers, use the amount that gets transferred after the fee.\n * @return amount of tokens the user will receive\n */\n function calculateSwap(\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx\n ) external view returns (uint256) {\n return\n baseSwap.calculateSwap(tokenIndexFrom, tokenIndexTo, dx);\n }\n\n /**\n * @notice Returns the address of the pooled token at given index. Reverts if tokenIndex is out of range.\n * @param index the index of the token\n * @return address of the token at given index\n */\n function getToken(uint256 index) external view returns (IERC20) {\n require(index < baseTokens.length, \"index out of range\");\n return baseTokens[index];\n }\n\n}" + }, + "@openzeppelin/contracts/utils/ReentrancyGuard.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <0.8.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 () internal {\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" + }, + "contracts/amm/AaveSwapWrapper.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.6.12;\n\nimport \"@openzeppelin/contracts/math/SafeMath.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/SafeERC20.sol\";\nimport \"./Swap.sol\";\n\ninterface ILendingPool {\n /**\n * @dev Deposits an `amount` of underlying asset into the reserve, receiving in return overlying aTokens.\n * - E.g. User deposits 100 USDC and gets in return 100 aUSDC\n * @param asset The address of the underlying asset to deposit\n * @param amount The amount to be deposited\n * @param onBehalfOf The address that will receive the aTokens, same as msg.sender if the user\n * wants to receive them on his own wallet, or a different address if the beneficiary of aTokens\n * is a different wallet\n * @param referralCode Code used to register the integrator originating the operation, for potential rewards.\n * 0 if the action is executed directly by the user, without any middle-man\n **/\n function deposit(\n address asset,\n uint256 amount,\n address onBehalfOf,\n uint16 referralCode\n ) external;\n\n /**\n * @dev Withdraws an `amount` of underlying asset from the reserve, burning the equivalent aTokens owned\n * E.g. User has 100 aUSDC, calls withdraw() and receives 100 USDC, burning the 100 aUSDC\n * @param asset The address of the underlying asset to withdraw\n * @param amount The underlying amount to be withdrawn\n * - Send the value type(uint256).max in order to withdraw the whole aToken balance\n * @param to Address that will receive the underlying, same as msg.sender if the user\n * wants to receive it on his own wallet, or a different address if the beneficiary is a\n * different wallet\n * @return The final amount withdrawn\n **/\n function withdraw(\n address asset,\n uint256 amount,\n address to\n ) external returns (uint256);\n}\n\n/**\n * @title AaveSwapWrapper\n * @notice A wrapper contract for interacting with aTokens\n */\ncontract AaveSwapWrapper {\n using SafeERC20 for IERC20;\n using SafeMath for uint256;\n mapping(uint8 => bool) private isUnderlyingIndex;\n\n // constants\n uint8 private constant MAX_UINT8 = 2**8 - 1;\n uint256 private constant MAX_UINT256 = 2**256 - 1;\n\n // immutables\n Swap public immutable SWAP;\n LPToken public immutable LP_TOKEN;\n address public immutable OWNER;\n IERC20[] public POOLED_TOKENS;\n IERC20[] public UNDERLYING_TOKENS;\n ILendingPool public LENDING_POOL;\n\n constructor(\n Swap swap,\n IERC20[] memory underlyingTokens,\n address lendingPool,\n address owner\n ) public {\n (, , , , , , LPToken lpToken) = swap.swapStorage();\n for (uint8 i = 0; i < MAX_UINT8; i++) {\n try swap.getToken(i) returns (IERC20 token) {\n POOLED_TOKENS.push(token);\n // Approve pooled tokens to be used by Swap\n token.approve(address(swap), MAX_UINT256);\n } catch {\n break;\n }\n }\n\n for (uint8 i = 0; i < POOLED_TOKENS.length; i++) {\n if (POOLED_TOKENS[i] == underlyingTokens[i]) {\n isUnderlyingIndex[i] = true;\n } else {\n isUnderlyingIndex[i] = false;\n underlyingTokens[i].approve(lendingPool, MAX_UINT256);\n }\n }\n\n // Set immutable variables\n SWAP = swap;\n LP_TOKEN = lpToken;\n OWNER = owner;\n UNDERLYING_TOKENS = underlyingTokens;\n LENDING_POOL = ILendingPool(lendingPool);\n\n // Approve LPToken to be used by Swap\n lpToken.approve(address(swap), MAX_UINT256);\n }\n\n /**\n * @notice Add liquidity to the pool with the given amounts of tokens.\n * @param amounts the amounts of each token to add, in their native precision\n * @param minToMint the minimum LP tokens adding this amount of liquidity\n * should mint, otherwise revert. Handy for front-running mitigation\n * @param deadline latest timestamp to accept this transaction\n * @return amount of LP token user minted and received\n */\n function addLiquidity(\n uint256[] memory amounts,\n uint256 minToMint,\n uint256 deadline\n ) external returns (uint256) {\n // Go through amounts array and transfer respective tokens to this contract.\n for (uint8 i = 0; i < amounts.length; i++) {\n uint256 amount = amounts[i];\n if (amount > 0) {\n UNDERLYING_TOKENS[i].safeTransferFrom(\n msg.sender,\n address(this),\n amount\n );\n if (isUnderlyingIndex[i] == false) {\n LENDING_POOL.deposit(\n address(UNDERLYING_TOKENS[i]),\n amount,\n address(this),\n 0\n );\n }\n }\n }\n\n // Add the assets to the pool\n uint256 lpTokenAmount = SWAP.addLiquidity(amounts, minToMint, deadline);\n // Send the LPToken to msg.sender\n IERC20(address(LP_TOKEN)).safeTransfer(msg.sender, lpTokenAmount);\n return lpTokenAmount;\n }\n\n /**\n * @notice Burn LP tokens to remove liquidity from the pool.\n * @dev Liquidity can always be removed, even when the pool is paused. Caller\n * will receive ETH instead of WETH9.\n * @param amount the amount of LP tokens to burn\n * @param minAmounts the minimum amounts of each token in the pool\n * acceptable for this burn. Useful as a front-running mitigation\n * @param deadline latest timestamp to accept this transaction\n * @return amounts of tokens user received\n */\n function removeLiquidity(\n uint256 amount,\n uint256[] calldata minAmounts,\n uint256 deadline\n ) external returns (uint256[] memory) {\n // Transfer LPToken from msg.sender to this contract.\n IERC20(address(LP_TOKEN)).safeTransferFrom(\n msg.sender,\n address(this),\n amount\n );\n // Remove liquidity\n uint256[] memory amounts = SWAP.removeLiquidity(\n amount,\n minAmounts,\n deadline\n );\n // Send the tokens back to the user\n for (uint8 i = 0; i < amounts.length; i++) {\n if (isUnderlyingIndex[i] == true) {\n UNDERLYING_TOKENS[i].safeTransfer(msg.sender, amounts[i]);\n } else {\n LENDING_POOL.withdraw(\n address(UNDERLYING_TOKENS[i]),\n amounts[i],\n msg.sender\n );\n // underlyingTokens[i].safeTransfer(msg.sender, amounts[i]);\n }\n }\n return amounts;\n }\n\n /**\n * @notice Remove liquidity from the pool all in one token.\n * @dev Caller will receive ETH instead of WETH9.\n * @param tokenAmount the amount of the token you want to receive\n * @param tokenIndex the index of the token you want to receive\n * @param minAmount the minimum amount to withdraw, otherwise revert\n * @param deadline latest timestamp to accept this transaction\n * @return amount of chosen token user received\n */\n function removeLiquidityOneToken(\n uint256 tokenAmount,\n uint8 tokenIndex,\n uint256 minAmount,\n uint256 deadline\n ) external returns (uint256) {\n // Transfer LPToken from msg.sender to this contract.\n IERC20(address(LP_TOKEN)).safeTransferFrom(\n msg.sender,\n address(this),\n tokenAmount\n );\n // Withdraw via single token\n uint256 amount = SWAP.removeLiquidityOneToken(\n tokenAmount,\n tokenIndex,\n minAmount,\n deadline\n );\n // Transfer the token to msg.sender accordingly\n if (isUnderlyingIndex[tokenIndex] == true) {\n UNDERLYING_TOKENS[tokenIndex].safeTransfer(msg.sender, amount);\n } else {\n LENDING_POOL.withdraw(\n address(UNDERLYING_TOKENS[tokenIndex]),\n amount,\n msg.sender\n );\n }\n return amount;\n }\n\n /**\n * @notice Swap two tokens using the underlying pool. If tokenIndexFrom\n * represents WETH9 in the pool, the caller must set msg.value equal to dx.\n * If the user is swapping to WETH9 in the pool, the user will receive ETH instead.\n * @param tokenIndexFrom the token the user wants to swap from\n * @param tokenIndexTo the token the user wants to swap to\n * @param dx the amount of tokens the user wants to swap from\n * @param minDy the min amount the user would like to receive, or revert.\n * @param deadline latest timestamp to accept this transaction\n */\n function swap(\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx,\n uint256 minDy,\n uint256 deadline\n ) external returns (uint256) {\n // Transfer tokens from msg.sender to this contract\n UNDERLYING_TOKENS[tokenIndexFrom].safeTransferFrom(\n msg.sender,\n address(this),\n dx\n );\n if (isUnderlyingIndex[tokenIndexFrom] == false) {\n LENDING_POOL.deposit(\n address(UNDERLYING_TOKENS[tokenIndexFrom]),\n dx,\n address(this),\n 0\n );\n }\n // Execute swap\n uint256 dy = SWAP.swap(\n tokenIndexFrom,\n tokenIndexTo,\n dx,\n minDy,\n deadline\n );\n // Transfer the swapped tokens to msg.sender\n if (isUnderlyingIndex[tokenIndexTo] == false) {\n LENDING_POOL.withdraw(\n address(UNDERLYING_TOKENS[tokenIndexTo]),\n dy,\n msg.sender\n );\n } else {\n UNDERLYING_TOKENS[tokenIndexTo].safeTransfer(msg.sender, dy);\n }\n return dy;\n }\n\n /**\n * @notice Rescues any of the ETH, the pooled tokens, or the LPToken that may be stuck\n * in this contract. Only the OWNER can call this function.\n */\n function rescue() external {\n require(msg.sender == OWNER, \"CALLED_BY_NON_OWNER\");\n IERC20[] memory tokens = POOLED_TOKENS;\n for (uint256 i = 0; i < tokens.length; i++) {\n tokens[i].safeTransfer(\n msg.sender,\n tokens[i].balanceOf(address(this))\n );\n }\n\n for (uint256 i = 0; i < UNDERLYING_TOKENS.length; i++) {\n UNDERLYING_TOKENS[i].safeTransfer(\n msg.sender,\n UNDERLYING_TOKENS[i].balanceOf(address(this))\n );\n }\n\n IERC20 lpToken_ = IERC20(address(LP_TOKEN));\n lpToken_.safeTransfer(msg.sender, lpToken_.balanceOf(address(this)));\n }\n\n // VIEW FUNCTIONS\n\n /**\n * @notice Calculate amount of tokens you receive on swap\n * @param tokenIndexFrom the token the user wants to sell\n * @param tokenIndexTo the token the user wants to buy\n * @param dx the amount of tokens the user wants to sell. If the token charges\n * a fee on transfers, use the amount that gets transferred after the fee.\n * @return amount of tokens the user will receive\n */\n function calculateSwap(\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx\n ) external view virtual returns (uint256) {\n return SWAP.calculateSwap(tokenIndexFrom, tokenIndexTo, dx);\n }\n\n /**\n * @notice A simple method to calculate prices from deposits or\n * withdrawals, excluding fees but including slippage. This is\n * helpful as an input into the various \"min\" parameters on calls\n * to fight front-running\n *\n * @dev This shouldn't be used outside frontends for user estimates.\n *\n * @param amounts an array of token amounts to deposit or withdrawal,\n * corresponding to pooledTokens. The amount should be in each\n * pooled token's native precision. If a token charges a fee on transfers,\n * use the amount that gets transferred after the fee.\n * @param deposit whether this is a deposit or a withdrawal\n * @return token amount the user will receive\n */\n function calculateTokenAmount(uint256[] calldata amounts, bool deposit)\n external\n view\n returns (uint256)\n {\n return SWAP.calculateTokenAmount(amounts, deposit);\n }\n\n /**\n * @notice A simple method to calculate amount of each underlying\n * tokens that is returned upon burning given amount of LP tokens\n * @param amount the amount of LP tokens that would be burned on withdrawal\n * @return array of token balances that the user will receive\n */\n function calculateRemoveLiquidity(uint256 amount)\n external\n view\n returns (uint256[] memory)\n {\n return SWAP.calculateRemoveLiquidity(amount);\n }\n\n /**\n * @notice Calculate the amount of underlying token available to withdraw\n * when withdrawing via only single token\n * @param tokenAmount the amount of LP token to burn\n * @param tokenIndex index of which token will be withdrawn\n * @return availableTokenAmount calculated amount of underlying token\n * available to withdraw\n */\n function calculateRemoveLiquidityOneToken(\n uint256 tokenAmount,\n uint8 tokenIndex\n ) external view returns (uint256 availableTokenAmount) {\n return SWAP.calculateRemoveLiquidityOneToken(tokenAmount, tokenIndex);\n }\n\n /**\n * @notice Return address of the pooled token at given index. Reverts if tokenIndex is out of range.\n * @param index the index of the token\n * @return address of the token at given index\n */\n function getToken(uint8 index) public view virtual returns (IERC20) {\n if (index < UNDERLYING_TOKENS.length) {\n return UNDERLYING_TOKENS[index];\n } else {\n revert();\n }\n }\n}\n" + }, + "contracts/bridge/ECDSAFactory.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.6.12;\n\nimport \"@openzeppelin/contracts/access/Ownable.sol\";\nimport \"@openzeppelin/contracts/proxy/Clones.sol\";\nimport \"./interfaces/IECDSANodeManagement.sol\";\n\ncontract ECDSAFactory is Ownable {\n event ECDSANodeGroupCreated(\n address indexed keepAddress,\n address[] members,\n address indexed owner,\n uint256 honestThreshold\n );\n\n struct LatestNodeGroup {\n address keepAddress;\n address[] members;\n address owner;\n uint256 honestThreshold;\n }\n\n LatestNodeGroup public latestNodeGroup;\n\n constructor() public Ownable() {}\n\n /// @notice Returns members of the keep.\n /// @return List of the keep members' addresses.\n function getMembers() public view returns (address[] memory) {\n return latestNodeGroup.members;\n }\n\n /**\n @notice Deploys a new node \n @param nodeMgmtAddress address of the ECDSANodeManagement contract to initialize with\n @param owner Owner of the ECDSANodeManagement contract who can determine if the node group is closed or active\n @param members Array of node group members addresses\n @param honestThreshold Number of signers to process a transaction \n @return Address of the newest node management contract created\n **/\n function deploy(\n address nodeMgmtAddress,\n address owner,\n address[] memory members,\n uint256 honestThreshold\n ) external onlyOwner returns (address) {\n address nodeClone = Clones.clone(nodeMgmtAddress);\n IECDSANodeManagement(nodeClone).initialize(\n owner,\n members,\n honestThreshold\n );\n\n latestNodeGroup.keepAddress = nodeClone;\n latestNodeGroup.members = members;\n latestNodeGroup.owner = owner;\n latestNodeGroup.honestThreshold = honestThreshold;\n\n emit ECDSANodeGroupCreated(nodeClone, members, owner, honestThreshold);\n return nodeClone;\n }\n}\n" + }, + "contracts/bridge/interfaces/IECDSANodeManagement.sol": { + "content": "// SPDX-License-Identifier: MIT\n\n\npragma solidity 0.6.12;\n\n/**\n * @title IECDSANodeManagement interface\n * @notice Interface for the ECDSA node management interface.\n * @dev implement this interface to develop a a factory-patterned ECDSA node management contract\n **/\ninterface IECDSANodeManagement { \n function initialize(\n address _owner,\n address[] memory _members,\n uint256 _honestThreshold) external;\n}\n\n" + }, + "contracts/auxiliary/DummyWeth.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.6.12;\nimport \"@openzeppelin/contracts/access/Ownable.sol\";\n\ninterface IWETH9 {\n function name() external view returns (string memory);\n\n function symbol() external view returns (string memory);\n\n function decimals() external view returns (uint8);\n\n function balanceOf(address) external view returns (uint256);\n\n function allowance(address, address) external view returns (uint256);\n\n receive() external payable;\n\n function deposit() external payable;\n\n function withdraw(uint256 wad) external;\n\n function totalSupply() external view returns (uint256);\n\n function approve(address guy, uint256 wad) external returns (bool);\n\n function transfer(address dst, uint256 wad) external returns (bool);\n\n function transferFrom(\n address src,\n address dst,\n uint256 wad\n ) external returns (bool);\n}\n\ncontract DummyWeth is Ownable {\n IWETH9 public WETH;\n\n function setWETHAddress(address payable _weth) external onlyOwner {\n WETH = IWETH9(_weth);\n }\n\n function withdrawToSelf(uint256 amount) external {\n WETH.withdraw(amount);\n }\n\n function rescue(uint256 amount) external onlyOwner {\n WETH.transfer(owner(), amount);\n }\n\n receive() external payable {}\n\n fallback() external payable {}\n}\n" + } + }, + "settings": { + "optimizer": { + "enabled": true, + "runs": 10000 + }, + "outputSelection": { + "*": { + "*": [ + "abi", + "evm.bytecode", + "evm.deployedBytecode", + "evm.methodIdentifiers", + "metadata", + "devdoc", + "userdoc", + "storageLayout", + "evm.gasEstimates", + "devdoc", + "userdoc" + ], + "": [ + "ast" + ] + } + }, + "metadata": { + "useLiteralContent": true + } + } +} \ No newline at end of file diff --git a/deployments/cronos/DAI.json b/deployments/cronos/DAI.json new file mode 100644 index 000000000..cd5f17947 --- /dev/null +++ b/deployments/cronos/DAI.json @@ -0,0 +1,366 @@ +{ + "address": "0xf2001b145b43032aaf5ee2884e456ccd805f677d", + "abi": [ + { + "inputs": [ + { + "internalType": "string", + "name": "name_", + "type": "string" + }, + { + "internalType": "string", + "name": "symbol_", + "type": "string" + }, + { + "internalType": "uint8", + "name": "decimals_", + "type": "uint8" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "Approval", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "previousOwner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "OwnershipTransferred", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "Transfer", + "type": "event" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "address", + "name": "spender", + "type": "address" + } + ], + "name": "allowance", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "approve", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "balanceOf", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "decimals", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "subtractedValue", + "type": "uint256" + } + ], + "name": "decreaseAllowance", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "addedValue", + "type": "uint256" + } + ], + "name": "increaseAllowance", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "recipient", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "mint", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "name", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "renounceOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "symbol", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "totalSupply", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "recipient", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "transfer", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "internalType": "address", + "name": "recipient", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "transferFrom", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } + ] +} \ No newline at end of file diff --git a/deployments/cronos/USDC.json b/deployments/cronos/USDC.json new file mode 100644 index 000000000..00763b9d4 --- /dev/null +++ b/deployments/cronos/USDC.json @@ -0,0 +1,226 @@ +{ + "address": "0xc21223249ca28397b4b6541dffaecc539bff0c59", + "abi": [ + { + "constant": true, + "inputs": [], + "name": "name", + "outputs": [ + { + "name": "", + "type": "string" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "name": "_spender", + "type": "address" + }, + { + "name": "_value", + "type": "uint256" + } + ], + "name": "approve", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "totalSupply", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "name": "_from", + "type": "address" + }, + { + "name": "_to", + "type": "address" + }, + { + "name": "_value", + "type": "uint256" + } + ], + "name": "transferFrom", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "decimals", + "outputs": [ + { + "name": "", + "type": "uint8" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "name": "_owner", + "type": "address" + } + ], + "name": "balanceOf", + "outputs": [ + { + "name": "balance", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "symbol", + "outputs": [ + { + "name": "", + "type": "string" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "name": "_to", + "type": "address" + }, + { + "name": "_value", + "type": "uint256" + } + ], + "name": "transfer", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "name": "_owner", + "type": "address" + }, + { + "name": "_spender", + "type": "address" + } + ], + "name": "allowance", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "payable": true, + "stateMutability": "payable", + "type": "fallback" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "name": "spender", + "type": "address" + }, + { + "indexed": false, + "name": "value", + "type": "uint256" + } + ], + "name": "Approval", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "name": "from", + "type": "address" + }, + { + "indexed": true, + "name": "to", + "type": "address" + }, + { + "indexed": false, + "name": "value", + "type": "uint256" + } + ], + "name": "Transfer", + "type": "event" + } + ] + } + \ No newline at end of file diff --git a/deployments/cronos/USDT.json b/deployments/cronos/USDT.json new file mode 100644 index 000000000..79f92898f --- /dev/null +++ b/deployments/cronos/USDT.json @@ -0,0 +1,366 @@ +{ + "address": "0x66e428c3f67a68878562e79a0234c1f83c208770", + "abi": [ + { + "inputs": [ + { + "internalType": "string", + "name": "name_", + "type": "string" + }, + { + "internalType": "string", + "name": "symbol_", + "type": "string" + }, + { + "internalType": "uint8", + "name": "decimals_", + "type": "uint8" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "Approval", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "previousOwner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "OwnershipTransferred", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "Transfer", + "type": "event" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "address", + "name": "spender", + "type": "address" + } + ], + "name": "allowance", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "approve", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "balanceOf", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "decimals", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "subtractedValue", + "type": "uint256" + } + ], + "name": "decreaseAllowance", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "addedValue", + "type": "uint256" + } + ], + "name": "increaseAllowance", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "recipient", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "mint", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "name", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "renounceOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "symbol", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "totalSupply", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "recipient", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "transfer", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "internalType": "address", + "name": "recipient", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "transferFrom", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } + ] +} \ No newline at end of file diff --git a/deployments/cronos/nETH.json b/deployments/cronos/nETH.json new file mode 100644 index 000000000..d0b89c6c7 --- /dev/null +++ b/deployments/cronos/nETH.json @@ -0,0 +1,1104 @@ +{ + "address": "0x41E95B1F1c7849c50Bb9Caf92AB33302c0de945F", + "abi": [ + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "Approval", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "bytes32", + "name": "previousAdminRole", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "bytes32", + "name": "newAdminRole", + "type": "bytes32" + } + ], + "name": "RoleAdminChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "sender", + "type": "address" + } + ], + "name": "RoleGranted", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "sender", + "type": "address" + } + ], + "name": "RoleRevoked", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "Transfer", + "type": "event" + }, + { + "inputs": [], + "name": "DEFAULT_ADMIN_ROLE", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "DOMAIN_SEPARATOR", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "MINTER_ROLE", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "address", + "name": "spender", + "type": "address" + } + ], + "name": "allowance", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "approve", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "balanceOf", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "burn", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "burnFrom", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "decimals", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "subtractedValue", + "type": "uint256" + } + ], + "name": "decreaseAllowance", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + } + ], + "name": "getRoleAdmin", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "internalType": "uint256", + "name": "index", + "type": "uint256" + } + ], + "name": "getRoleMember", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + } + ], + "name": "getRoleMemberCount", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "grantRole", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "hasRole", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "addedValue", + "type": "uint256" + } + ], + "name": "increaseAllowance", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "name", + "type": "string" + }, + { + "internalType": "string", + "name": "symbol", + "type": "string" + }, + { + "internalType": "uint8", + "name": "decimals", + "type": "uint8" + }, + { + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "initialize", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "mint", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "name", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "nonces", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" + }, + { + "internalType": "uint8", + "name": "v", + "type": "uint8" + }, + { + "internalType": "bytes32", + "name": "r", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "s", + "type": "bytes32" + } + ], + "name": "permit", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "renounceRole", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "revokeRole", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "symbol", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "totalSupply", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "recipient", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "transfer", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "internalType": "address", + "name": "recipient", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "transferFrom", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + } + ], + "transactionHash": "0xc14b4a30e52e66641c38cf4f52fdfa594f9bc3a887a4e693881b18c620dcfcff", + "receipt": { + "to": null, + "from": "0x0AF91FA049A7e1894F480bFE5bBa20142C6c29a9", + "contractAddress": "0x41E95B1F1c7849c50Bb9Caf92AB33302c0de945F", + "transactionIndex": 12, + "gasUsed": "1935674", + "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "blockHash": "0x1b6b902a8e0fd2e583662f0eb569030d44710e1c96938de1a16758c8131b99a5", + "transactionHash": "0xc14b4a30e52e66641c38cf4f52fdfa594f9bc3a887a4e693881b18c620dcfcff", + "logs": [], + "blockNumber": 2263766, + "cumulativeGasUsed": "4437941", + "status": 1, + "byzantium": true + }, + "args": [], + "solcInputHash": "4d8253a299fa09b105ed2b87dd0189d4", + "metadata": "{\"compiler\":{\"version\":\"0.6.12+commit.27d51765\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"spender\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"Approval\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"previousAdminRole\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"newAdminRole\",\"type\":\"bytes32\"}],\"name\":\"RoleAdminChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"RoleGranted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"RoleRevoked\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"Transfer\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"DEFAULT_ADMIN_ROLE\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"DOMAIN_SEPARATOR\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"MINTER_ROLE\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"spender\",\"type\":\"address\"}],\"name\":\"allowance\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"spender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"approve\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"balanceOf\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"burn\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"burnFrom\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"decimals\",\"outputs\":[{\"internalType\":\"uint8\",\"name\":\"\",\"type\":\"uint8\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"spender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"subtractedValue\",\"type\":\"uint256\"}],\"name\":\"decreaseAllowance\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"}],\"name\":\"getRoleAdmin\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"internalType\":\"uint256\",\"name\":\"index\",\"type\":\"uint256\"}],\"name\":\"getRoleMember\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"}],\"name\":\"getRoleMemberCount\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"grantRole\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"hasRole\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"spender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"addedValue\",\"type\":\"uint256\"}],\"name\":\"increaseAllowance\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"string\",\"name\":\"name\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"symbol\",\"type\":\"string\"},{\"internalType\":\"uint8\",\"name\":\"decimals\",\"type\":\"uint8\"},{\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"}],\"name\":\"initialize\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"mint\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"name\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"}],\"name\":\"nonces\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"spender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"deadline\",\"type\":\"uint256\"},{\"internalType\":\"uint8\",\"name\":\"v\",\"type\":\"uint8\"},{\"internalType\":\"bytes32\",\"name\":\"r\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"s\",\"type\":\"bytes32\"}],\"name\":\"permit\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"renounceRole\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"revokeRole\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"symbol\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"totalSupply\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"recipient\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"transfer\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"recipient\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"transferFrom\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{\"DOMAIN_SEPARATOR()\":{\"details\":\"See {IERC20Permit-DOMAIN_SEPARATOR}.\"},\"allowance(address,address)\":{\"details\":\"See {IERC20-allowance}.\"},\"approve(address,uint256)\":{\"details\":\"See {IERC20-approve}. Requirements: - `spender` cannot be the zero address.\"},\"balanceOf(address)\":{\"details\":\"See {IERC20-balanceOf}.\"},\"burn(uint256)\":{\"details\":\"Destroys `amount` tokens from the caller. See {ERC20-_burn}.\"},\"burnFrom(address,uint256)\":{\"details\":\"Destroys `amount` tokens from `account`, deducting from the caller's allowance. See {ERC20-_burn} and {ERC20-allowance}. Requirements: - the caller must have allowance for ``accounts``'s tokens of at least `amount`.\"},\"decimals()\":{\"details\":\"Returns the number of decimals used to get its user representation. For example, if `decimals` equals `2`, a balance of `505` tokens should be displayed to a user as `5,05` (`505 / 10 ** 2`). Tokens usually opt for a value of 18, imitating the relationship between Ether and Wei. This is the value {ERC20} uses, unless {_setupDecimals} is called. NOTE: This information is only used for _display_ purposes: it in no way affects any of the arithmetic of the contract, including {IERC20-balanceOf} and {IERC20-transfer}.\"},\"decreaseAllowance(address,uint256)\":{\"details\":\"Atomically decreases the allowance granted to `spender` by the caller. This is an alternative to {approve} that can be used as a mitigation for problems described in {IERC20-approve}. Emits an {Approval} event indicating the updated allowance. Requirements: - `spender` cannot be the zero address. - `spender` must have allowance for the caller of at least `subtractedValue`.\"},\"getRoleAdmin(bytes32)\":{\"details\":\"Returns the admin role that controls `role`. See {grantRole} and {revokeRole}. To change a role's admin, use {_setRoleAdmin}.\"},\"getRoleMember(bytes32,uint256)\":{\"details\":\"Returns one of the accounts that have `role`. `index` must be a value between 0 and {getRoleMemberCount}, non-inclusive. Role bearers are not sorted in any particular way, and their ordering may change at any point. WARNING: When using {getRoleMember} and {getRoleMemberCount}, make sure you perform all queries on the same block. See the following https://forum.openzeppelin.com/t/iterating-over-elements-on-enumerableset-in-openzeppelin-contracts/2296[forum post] for more information.\"},\"getRoleMemberCount(bytes32)\":{\"details\":\"Returns the number of accounts that have `role`. Can be used together with {getRoleMember} to enumerate all bearers of a role.\"},\"grantRole(bytes32,address)\":{\"details\":\"Grants `role` to `account`. If `account` had not been already granted `role`, emits a {RoleGranted} event. Requirements: - the caller must have ``role``'s admin role.\"},\"hasRole(bytes32,address)\":{\"details\":\"Returns `true` if `account` has been granted `role`.\"},\"increaseAllowance(address,uint256)\":{\"details\":\"Atomically increases the allowance granted to `spender` by the caller. This is an alternative to {approve} that can be used as a mitigation for problems described in {IERC20-approve}. Emits an {Approval} event indicating the updated allowance. Requirements: - `spender` cannot be the zero address.\"},\"initialize(string,string,uint8,address)\":{\"params\":{\"decimals\":\"Token name\",\"name\":\"Token name\",\"owner\":\"admin address to be initialized with\",\"symbol\":\"Token symbol\"}},\"name()\":{\"details\":\"Returns the name of the token.\"},\"nonces(address)\":{\"details\":\"See {IERC20Permit-nonces}.\"},\"permit(address,address,uint256,uint256,uint8,bytes32,bytes32)\":{\"details\":\"See {IERC20Permit-permit}.\"},\"renounceRole(bytes32,address)\":{\"details\":\"Revokes `role` from the calling account. Roles are often managed via {grantRole} and {revokeRole}: this function's purpose is to provide a mechanism for accounts to lose their privileges if they are compromised (such as when a trusted device is misplaced). If the calling account had been granted `role`, emits a {RoleRevoked} event. Requirements: - the caller must be `account`.\"},\"revokeRole(bytes32,address)\":{\"details\":\"Revokes `role` from `account`. If `account` had been granted `role`, emits a {RoleRevoked} event. Requirements: - the caller must have ``role``'s admin role.\"},\"symbol()\":{\"details\":\"Returns the symbol of the token, usually a shorter version of the name.\"},\"totalSupply()\":{\"details\":\"See {IERC20-totalSupply}.\"},\"transfer(address,uint256)\":{\"details\":\"See {IERC20-transfer}. Requirements: - `recipient` cannot be the zero address. - the caller must have a balance of at least `amount`.\"},\"transferFrom(address,address,uint256)\":{\"details\":\"See {IERC20-transferFrom}. Emits an {Approval} event indicating the updated allowance. This is not required by the EIP. See the note at the beginning of {ERC20}. Requirements: - `sender` and `recipient` cannot be the zero address. - `sender` must have a balance of at least `amount`. - the caller must have allowance for ``sender``'s tokens of at least `amount`.\"}},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{\"initialize(string,string,uint8,address)\":{\"notice\":\"Initializes this ERC20 contract with the given parameters.\"}},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/bridge/SynapseERC20.sol\":\"SynapseERC20\"},\"evmVersion\":\"istanbul\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":10000},\"remappings\":[]},\"sources\":{\"@openzeppelin/contracts-upgradeable/access/AccessControlUpgradeable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity >=0.6.0 <0.8.0;\\n\\nimport \\\"../utils/EnumerableSetUpgradeable.sol\\\";\\nimport \\\"../utils/AddressUpgradeable.sol\\\";\\nimport \\\"../utils/ContextUpgradeable.sol\\\";\\nimport \\\"../proxy/Initializable.sol\\\";\\n\\n/**\\n * @dev Contract module that allows children to implement role-based access\\n * control mechanisms.\\n *\\n * Roles are referred to by their `bytes32` identifier. These should be exposed\\n * in the external API and be unique. The best way to achieve this is by\\n * using `public constant` hash digests:\\n *\\n * ```\\n * bytes32 public constant MY_ROLE = keccak256(\\\"MY_ROLE\\\");\\n * ```\\n *\\n * Roles can be used to represent a set of permissions. To restrict access to a\\n * function call, use {hasRole}:\\n *\\n * ```\\n * function foo() public {\\n * require(hasRole(MY_ROLE, msg.sender));\\n * ...\\n * }\\n * ```\\n *\\n * Roles can be granted and revoked dynamically via the {grantRole} and\\n * {revokeRole} functions. Each role has an associated admin role, and only\\n * accounts that have a role's admin role can call {grantRole} and {revokeRole}.\\n *\\n * By default, the admin role for all roles is `DEFAULT_ADMIN_ROLE`, which means\\n * that only accounts with this role will be able to grant or revoke other\\n * roles. More complex role relationships can be created by using\\n * {_setRoleAdmin}.\\n *\\n * WARNING: The `DEFAULT_ADMIN_ROLE` is also its own admin: it has permission to\\n * grant and revoke this role. Extra precautions should be taken to secure\\n * accounts that have been granted it.\\n */\\nabstract contract AccessControlUpgradeable is Initializable, ContextUpgradeable {\\n function __AccessControl_init() internal initializer {\\n __Context_init_unchained();\\n __AccessControl_init_unchained();\\n }\\n\\n function __AccessControl_init_unchained() internal initializer {\\n }\\n using EnumerableSetUpgradeable for EnumerableSetUpgradeable.AddressSet;\\n using AddressUpgradeable for address;\\n\\n struct RoleData {\\n EnumerableSetUpgradeable.AddressSet members;\\n bytes32 adminRole;\\n }\\n\\n mapping (bytes32 => RoleData) private _roles;\\n\\n bytes32 public constant DEFAULT_ADMIN_ROLE = 0x00;\\n\\n /**\\n * @dev Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole`\\n *\\n * `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite\\n * {RoleAdminChanged} not being emitted signaling this.\\n *\\n * _Available since v3.1._\\n */\\n event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole);\\n\\n /**\\n * @dev Emitted when `account` is granted `role`.\\n *\\n * `sender` is the account that originated the contract call, an admin role\\n * bearer except when using {_setupRole}.\\n */\\n event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender);\\n\\n /**\\n * @dev Emitted when `account` is revoked `role`.\\n *\\n * `sender` is the account that originated the contract call:\\n * - if using `revokeRole`, it is the admin role bearer\\n * - if using `renounceRole`, it is the role bearer (i.e. `account`)\\n */\\n event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender);\\n\\n /**\\n * @dev Returns `true` if `account` has been granted `role`.\\n */\\n function hasRole(bytes32 role, address account) public view returns (bool) {\\n return _roles[role].members.contains(account);\\n }\\n\\n /**\\n * @dev Returns the number of accounts that have `role`. Can be used\\n * together with {getRoleMember} to enumerate all bearers of a role.\\n */\\n function getRoleMemberCount(bytes32 role) public view returns (uint256) {\\n return _roles[role].members.length();\\n }\\n\\n /**\\n * @dev Returns one of the accounts that have `role`. `index` must be a\\n * value between 0 and {getRoleMemberCount}, non-inclusive.\\n *\\n * Role bearers are not sorted in any particular way, and their ordering may\\n * change at any point.\\n *\\n * WARNING: When using {getRoleMember} and {getRoleMemberCount}, make sure\\n * you perform all queries on the same block. See the following\\n * https://forum.openzeppelin.com/t/iterating-over-elements-on-enumerableset-in-openzeppelin-contracts/2296[forum post]\\n * for more information.\\n */\\n function getRoleMember(bytes32 role, uint256 index) public view returns (address) {\\n return _roles[role].members.at(index);\\n }\\n\\n /**\\n * @dev Returns the admin role that controls `role`. See {grantRole} and\\n * {revokeRole}.\\n *\\n * To change a role's admin, use {_setRoleAdmin}.\\n */\\n function getRoleAdmin(bytes32 role) public view returns (bytes32) {\\n return _roles[role].adminRole;\\n }\\n\\n /**\\n * @dev Grants `role` to `account`.\\n *\\n * If `account` had not been already granted `role`, emits a {RoleGranted}\\n * event.\\n *\\n * Requirements:\\n *\\n * - the caller must have ``role``'s admin role.\\n */\\n function grantRole(bytes32 role, address account) public virtual {\\n require(hasRole(_roles[role].adminRole, _msgSender()), \\\"AccessControl: sender must be an admin to grant\\\");\\n\\n _grantRole(role, account);\\n }\\n\\n /**\\n * @dev Revokes `role` from `account`.\\n *\\n * If `account` had been granted `role`, emits a {RoleRevoked} event.\\n *\\n * Requirements:\\n *\\n * - the caller must have ``role``'s admin role.\\n */\\n function revokeRole(bytes32 role, address account) public virtual {\\n require(hasRole(_roles[role].adminRole, _msgSender()), \\\"AccessControl: sender must be an admin to revoke\\\");\\n\\n _revokeRole(role, account);\\n }\\n\\n /**\\n * @dev Revokes `role` from the calling account.\\n *\\n * Roles are often managed via {grantRole} and {revokeRole}: this function's\\n * purpose is to provide a mechanism for accounts to lose their privileges\\n * if they are compromised (such as when a trusted device is misplaced).\\n *\\n * If the calling account had been granted `role`, emits a {RoleRevoked}\\n * event.\\n *\\n * Requirements:\\n *\\n * - the caller must be `account`.\\n */\\n function renounceRole(bytes32 role, address account) public virtual {\\n require(account == _msgSender(), \\\"AccessControl: can only renounce roles for self\\\");\\n\\n _revokeRole(role, account);\\n }\\n\\n /**\\n * @dev Grants `role` to `account`.\\n *\\n * If `account` had not been already granted `role`, emits a {RoleGranted}\\n * event. Note that unlike {grantRole}, this function doesn't perform any\\n * checks on the calling account.\\n *\\n * [WARNING]\\n * ====\\n * This function should only be called from the constructor when setting\\n * up the initial roles for the system.\\n *\\n * Using this function in any other way is effectively circumventing the admin\\n * system imposed by {AccessControl}.\\n * ====\\n */\\n function _setupRole(bytes32 role, address account) internal virtual {\\n _grantRole(role, account);\\n }\\n\\n /**\\n * @dev Sets `adminRole` as ``role``'s admin role.\\n *\\n * Emits a {RoleAdminChanged} event.\\n */\\n function _setRoleAdmin(bytes32 role, bytes32 adminRole) internal virtual {\\n emit RoleAdminChanged(role, _roles[role].adminRole, adminRole);\\n _roles[role].adminRole = adminRole;\\n }\\n\\n function _grantRole(bytes32 role, address account) private {\\n if (_roles[role].members.add(account)) {\\n emit RoleGranted(role, account, _msgSender());\\n }\\n }\\n\\n function _revokeRole(bytes32 role, address account) private {\\n if (_roles[role].members.remove(account)) {\\n emit RoleRevoked(role, account, _msgSender());\\n }\\n }\\n uint256[49] private __gap;\\n}\\n\",\"keccak256\":\"0xa3c77c9ea6b47301c7ab5bf3addc1d809d13a27a179c4629a1b55308e8633d14\",\"license\":\"MIT\"},\"@openzeppelin/contracts-upgradeable/cryptography/ECDSAUpgradeable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity >=0.6.0 <0.8.0;\\n\\n/**\\n * @dev Elliptic Curve Digital Signature Algorithm (ECDSA) operations.\\n *\\n * These functions can be used to verify that a message was signed by the holder\\n * of the private keys of a given address.\\n */\\nlibrary ECDSAUpgradeable {\\n /**\\n * @dev Returns the address that signed a hashed message (`hash`) with\\n * `signature`. This address can then be used for verification purposes.\\n *\\n * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:\\n * this function rejects them by requiring the `s` value to be in the lower\\n * half order, and the `v` value to be either 27 or 28.\\n *\\n * IMPORTANT: `hash` _must_ be the result of a hash operation for the\\n * verification to be secure: it is possible to craft signatures that\\n * recover to arbitrary addresses for non-hashed data. A safe way to ensure\\n * this is by receiving a hash of the original message (which may otherwise\\n * be too long), and then calling {toEthSignedMessageHash} on it.\\n */\\n function recover(bytes32 hash, bytes memory signature) internal pure returns (address) {\\n // Check the signature length\\n if (signature.length != 65) {\\n revert(\\\"ECDSA: invalid signature length\\\");\\n }\\n\\n // Divide the signature in r, s and v variables\\n bytes32 r;\\n bytes32 s;\\n uint8 v;\\n\\n // ecrecover takes the signature parameters, and the only way to get them\\n // currently is to use assembly.\\n // solhint-disable-next-line no-inline-assembly\\n assembly {\\n r := mload(add(signature, 0x20))\\n s := mload(add(signature, 0x40))\\n v := byte(0, mload(add(signature, 0x60)))\\n }\\n\\n return recover(hash, v, r, s);\\n }\\n\\n /**\\n * @dev Overload of {ECDSA-recover-bytes32-bytes-} that receives the `v`,\\n * `r` and `s` signature fields separately.\\n */\\n function recover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) internal pure returns (address) {\\n // EIP-2 still allows signature malleability for ecrecover(). Remove this possibility and make the signature\\n // unique. Appendix F in the Ethereum Yellow paper (https://ethereum.github.io/yellowpaper/paper.pdf), defines\\n // the valid range for s in (281): 0 < s < secp256k1n \\u00f7 2 + 1, and for v in (282): v \\u2208 {27, 28}. Most\\n // signatures from current libraries generate a unique signature with an s-value in the lower half order.\\n //\\n // If your library generates malleable signatures, such as s-values in the upper range, calculate a new s-value\\n // with 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 - s1 and flip v from 27 to 28 or\\n // vice versa. If your library also generates signatures with 0/1 for v instead 27/28, add 27 to v to accept\\n // these malleable signatures as well.\\n require(uint256(s) <= 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0, \\\"ECDSA: invalid signature 's' value\\\");\\n require(v == 27 || v == 28, \\\"ECDSA: invalid signature 'v' value\\\");\\n\\n // If the signature is valid (and not malleable), return the signer address\\n address signer = ecrecover(hash, v, r, s);\\n require(signer != address(0), \\\"ECDSA: invalid signature\\\");\\n\\n return signer;\\n }\\n\\n /**\\n * @dev Returns an Ethereum Signed Message, created from a `hash`. This\\n * replicates the behavior of the\\n * https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_sign[`eth_sign`]\\n * JSON-RPC method.\\n *\\n * See {recover}.\\n */\\n function toEthSignedMessageHash(bytes32 hash) internal pure returns (bytes32) {\\n // 32 is the length in bytes of hash,\\n // enforced by the type signature above\\n return keccak256(abi.encodePacked(\\\"\\\\x19Ethereum Signed Message:\\\\n32\\\", hash));\\n }\\n}\\n\",\"keccak256\":\"0xe348c45df01e0705c50ede5063d77111a996722ffb83f0a22979338a32b06887\",\"license\":\"MIT\"},\"@openzeppelin/contracts-upgradeable/drafts/EIP712Upgradeable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity >=0.6.0 <0.8.0;\\nimport \\\"../proxy/Initializable.sol\\\";\\n\\n/**\\n * @dev https://eips.ethereum.org/EIPS/eip-712[EIP 712] is a standard for hashing and signing of typed structured data.\\n *\\n * The encoding specified in the EIP is very generic, and such a generic implementation in Solidity is not feasible,\\n * thus this contract does not implement the encoding itself. Protocols need to implement the type-specific encoding\\n * they need in their contracts using a combination of `abi.encode` and `keccak256`.\\n *\\n * This contract implements the EIP 712 domain separator ({_domainSeparatorV4}) that is used as part of the encoding\\n * scheme, and the final step of the encoding to obtain the message digest that is then signed via ECDSA\\n * ({_hashTypedDataV4}).\\n *\\n * The implementation of the domain separator was designed to be as efficient as possible while still properly updating\\n * the chain id to protect against replay attacks on an eventual fork of the chain.\\n *\\n * NOTE: This contract implements the version of the encoding known as \\\"v4\\\", as implemented by the JSON RPC method\\n * https://docs.metamask.io/guide/signing-data.html[`eth_signTypedDataV4` in MetaMask].\\n *\\n * _Available since v3.4._\\n */\\nabstract contract EIP712Upgradeable is Initializable {\\n /* solhint-disable var-name-mixedcase */\\n bytes32 private _HASHED_NAME;\\n bytes32 private _HASHED_VERSION;\\n bytes32 private constant _TYPE_HASH = keccak256(\\\"EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)\\\");\\n /* solhint-enable var-name-mixedcase */\\n\\n /**\\n * @dev Initializes the domain separator and parameter caches.\\n *\\n * The meaning of `name` and `version` is specified in\\n * https://eips.ethereum.org/EIPS/eip-712#definition-of-domainseparator[EIP 712]:\\n *\\n * - `name`: the user readable name of the signing domain, i.e. the name of the DApp or the protocol.\\n * - `version`: the current major version of the signing domain.\\n *\\n * NOTE: These parameters cannot be changed except through a xref:learn::upgrading-smart-contracts.adoc[smart\\n * contract upgrade].\\n */\\n function __EIP712_init(string memory name, string memory version) internal initializer {\\n __EIP712_init_unchained(name, version);\\n }\\n\\n function __EIP712_init_unchained(string memory name, string memory version) internal initializer {\\n bytes32 hashedName = keccak256(bytes(name));\\n bytes32 hashedVersion = keccak256(bytes(version));\\n _HASHED_NAME = hashedName;\\n _HASHED_VERSION = hashedVersion;\\n }\\n\\n /**\\n * @dev Returns the domain separator for the current chain.\\n */\\n function _domainSeparatorV4() internal view returns (bytes32) {\\n return _buildDomainSeparator(_TYPE_HASH, _EIP712NameHash(), _EIP712VersionHash());\\n }\\n\\n function _buildDomainSeparator(bytes32 typeHash, bytes32 name, bytes32 version) private view returns (bytes32) {\\n return keccak256(\\n abi.encode(\\n typeHash,\\n name,\\n version,\\n _getChainId(),\\n address(this)\\n )\\n );\\n }\\n\\n /**\\n * @dev Given an already https://eips.ethereum.org/EIPS/eip-712#definition-of-hashstruct[hashed struct], this\\n * function returns the hash of the fully encoded EIP712 message for this domain.\\n *\\n * This hash can be used together with {ECDSA-recover} to obtain the signer of a message. For example:\\n *\\n * ```solidity\\n * bytes32 digest = _hashTypedDataV4(keccak256(abi.encode(\\n * keccak256(\\\"Mail(address to,string contents)\\\"),\\n * mailTo,\\n * keccak256(bytes(mailContents))\\n * )));\\n * address signer = ECDSA.recover(digest, signature);\\n * ```\\n */\\n function _hashTypedDataV4(bytes32 structHash) internal view virtual returns (bytes32) {\\n return keccak256(abi.encodePacked(\\\"\\\\x19\\\\x01\\\", _domainSeparatorV4(), structHash));\\n }\\n\\n function _getChainId() private view returns (uint256 chainId) {\\n this; // silence state mutability warning without generating bytecode - see https://github.com/ethereum/solidity/issues/2691\\n // solhint-disable-next-line no-inline-assembly\\n assembly {\\n chainId := chainid()\\n }\\n }\\n\\n /**\\n * @dev The hash of the name parameter for the EIP712 domain.\\n *\\n * NOTE: This function reads from storage by default, but can be redefined to return a constant value if gas costs\\n * are a concern.\\n */\\n function _EIP712NameHash() internal virtual view returns (bytes32) {\\n return _HASHED_NAME;\\n }\\n\\n /**\\n * @dev The hash of the version parameter for the EIP712 domain.\\n *\\n * NOTE: This function reads from storage by default, but can be redefined to return a constant value if gas costs\\n * are a concern.\\n */\\n function _EIP712VersionHash() internal virtual view returns (bytes32) {\\n return _HASHED_VERSION;\\n }\\n uint256[50] private __gap;\\n}\\n\",\"keccak256\":\"0x6cd0bc8c149150614ca3d4a3d3d21f844a0ab3032625f34fcfcf1c2c8b351638\",\"license\":\"MIT\"},\"@openzeppelin/contracts-upgradeable/drafts/ERC20PermitUpgradeable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity >=0.6.5 <0.8.0;\\n\\nimport \\\"../token/ERC20/ERC20Upgradeable.sol\\\";\\nimport \\\"./IERC20PermitUpgradeable.sol\\\";\\nimport \\\"../cryptography/ECDSAUpgradeable.sol\\\";\\nimport \\\"../utils/CountersUpgradeable.sol\\\";\\nimport \\\"./EIP712Upgradeable.sol\\\";\\nimport \\\"../proxy/Initializable.sol\\\";\\n\\n/**\\n * @dev Implementation of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in\\n * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612].\\n *\\n * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by\\n * presenting a message signed by the account. By not relying on `{IERC20-approve}`, the token holder account doesn't\\n * need to send a transaction, and thus is not required to hold Ether at all.\\n *\\n * _Available since v3.4._\\n */\\nabstract contract ERC20PermitUpgradeable is Initializable, ERC20Upgradeable, IERC20PermitUpgradeable, EIP712Upgradeable {\\n using CountersUpgradeable for CountersUpgradeable.Counter;\\n\\n mapping (address => CountersUpgradeable.Counter) private _nonces;\\n\\n // solhint-disable-next-line var-name-mixedcase\\n bytes32 private _PERMIT_TYPEHASH;\\n\\n /**\\n * @dev Initializes the {EIP712} domain separator using the `name` parameter, and setting `version` to `\\\"1\\\"`.\\n *\\n * It's a good idea to use the same `name` that is defined as the ERC20 token name.\\n */\\n function __ERC20Permit_init(string memory name) internal initializer {\\n __Context_init_unchained();\\n __EIP712_init_unchained(name, \\\"1\\\");\\n __ERC20Permit_init_unchained(name);\\n }\\n\\n function __ERC20Permit_init_unchained(string memory name) internal initializer {\\n _PERMIT_TYPEHASH = keccak256(\\\"Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)\\\");\\n }\\n\\n /**\\n * @dev See {IERC20Permit-permit}.\\n */\\n function permit(address owner, address spender, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s) public virtual override {\\n // solhint-disable-next-line not-rely-on-time\\n require(block.timestamp <= deadline, \\\"ERC20Permit: expired deadline\\\");\\n\\n bytes32 structHash = keccak256(\\n abi.encode(\\n _PERMIT_TYPEHASH,\\n owner,\\n spender,\\n value,\\n _nonces[owner].current(),\\n deadline\\n )\\n );\\n\\n bytes32 hash = _hashTypedDataV4(structHash);\\n\\n address signer = ECDSAUpgradeable.recover(hash, v, r, s);\\n require(signer == owner, \\\"ERC20Permit: invalid signature\\\");\\n\\n _nonces[owner].increment();\\n _approve(owner, spender, value);\\n }\\n\\n /**\\n * @dev See {IERC20Permit-nonces}.\\n */\\n function nonces(address owner) public view override returns (uint256) {\\n return _nonces[owner].current();\\n }\\n\\n /**\\n * @dev See {IERC20Permit-DOMAIN_SEPARATOR}.\\n */\\n // solhint-disable-next-line func-name-mixedcase\\n function DOMAIN_SEPARATOR() external view override returns (bytes32) {\\n return _domainSeparatorV4();\\n }\\n uint256[49] private __gap;\\n}\\n\",\"keccak256\":\"0xb30c40eb91411e29d23c8184b19fd37e6c2447f685631b798af2871ede483157\",\"license\":\"MIT\"},\"@openzeppelin/contracts-upgradeable/drafts/IERC20PermitUpgradeable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity >=0.6.0 <0.8.0;\\n\\n/**\\n * @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in\\n * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612].\\n *\\n * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by\\n * presenting a message signed by the account. By not relying on `{IERC20-approve}`, the token holder account doesn't\\n * need to send a transaction, and thus is not required to hold Ether at all.\\n */\\ninterface IERC20PermitUpgradeable {\\n /**\\n * @dev Sets `value` as the allowance of `spender` over `owner`'s tokens,\\n * given `owner`'s signed approval.\\n *\\n * IMPORTANT: The same issues {IERC20-approve} has related to transaction\\n * ordering also apply here.\\n *\\n * Emits an {Approval} event.\\n *\\n * Requirements:\\n *\\n * - `spender` cannot be the zero address.\\n * - `deadline` must be a timestamp in the future.\\n * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner`\\n * over the EIP712-formatted function arguments.\\n * - the signature must use ``owner``'s current nonce (see {nonces}).\\n *\\n * For more information on the signature format, see the\\n * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP\\n * section].\\n */\\n function permit(address owner, address spender, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s) external;\\n\\n /**\\n * @dev Returns the current nonce for `owner`. This value must be\\n * included whenever a signature is generated for {permit}.\\n *\\n * Every successful call to {permit} increases ``owner``'s nonce by one. This\\n * prevents a signature from being used multiple times.\\n */\\n function nonces(address owner) external view returns (uint256);\\n\\n /**\\n * @dev Returns the domain separator used in the encoding of the signature for `permit`, as defined by {EIP712}.\\n */\\n // solhint-disable-next-line func-name-mixedcase\\n function DOMAIN_SEPARATOR() external view returns (bytes32);\\n}\\n\",\"keccak256\":\"0x30c000f3a68d252b09a738c782e0fc9dbf168b81021a195de6102f8d095681ae\",\"license\":\"MIT\"},\"@openzeppelin/contracts-upgradeable/math/SafeMathUpgradeable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity >=0.6.0 <0.8.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 SafeMathUpgradeable {\\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\",\"keccak256\":\"0x0dd1e9b19801e3e7d900fbf4182d81e1afd23ad7be39504e33df6bbcba91d724\",\"license\":\"MIT\"},\"@openzeppelin/contracts-upgradeable/proxy/Initializable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\n// solhint-disable-next-line compiler-version\\npragma solidity >=0.4.24 <0.8.0;\\n\\nimport \\\"../utils/AddressUpgradeable.sol\\\";\\n\\n/**\\n * @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed\\n * behind a proxy. Since a proxied contract can't have a constructor, it's common to move constructor logic to an\\n * external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer\\n * function so it can only be called once. The {initializer} modifier provided by this contract will have this effect.\\n *\\n * TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as\\n * possible by providing the encoded function call as the `_data` argument to {UpgradeableProxy-constructor}.\\n *\\n * CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure\\n * that all initializers are idempotent. This is not verified automatically as constructors are by Solidity.\\n */\\nabstract contract Initializable {\\n\\n /**\\n * @dev Indicates that the contract has been initialized.\\n */\\n bool private _initialized;\\n\\n /**\\n * @dev Indicates that the contract is in the process of being initialized.\\n */\\n bool private _initializing;\\n\\n /**\\n * @dev Modifier to protect an initializer function from being invoked twice.\\n */\\n modifier initializer() {\\n require(_initializing || _isConstructor() || !_initialized, \\\"Initializable: contract is already initialized\\\");\\n\\n bool isTopLevelCall = !_initializing;\\n if (isTopLevelCall) {\\n _initializing = true;\\n _initialized = true;\\n }\\n\\n _;\\n\\n if (isTopLevelCall) {\\n _initializing = false;\\n }\\n }\\n\\n /// @dev Returns true if and only if the function is running in the constructor\\n function _isConstructor() private view returns (bool) {\\n return !AddressUpgradeable.isContract(address(this));\\n }\\n}\\n\",\"keccak256\":\"0xd8e4eb08dcc1d1860fb347ba5ffd595242b9a1b66d49a47f2b4cb51c3f35017e\",\"license\":\"MIT\"},\"@openzeppelin/contracts-upgradeable/token/ERC20/ERC20BurnableUpgradeable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity >=0.6.0 <0.8.0;\\n\\nimport \\\"../../utils/ContextUpgradeable.sol\\\";\\nimport \\\"./ERC20Upgradeable.sol\\\";\\nimport \\\"../../proxy/Initializable.sol\\\";\\n\\n/**\\n * @dev Extension of {ERC20} that allows token holders to destroy both their own\\n * tokens and those that they have an allowance for, in a way that can be\\n * recognized off-chain (via event analysis).\\n */\\nabstract contract ERC20BurnableUpgradeable is Initializable, ContextUpgradeable, ERC20Upgradeable {\\n function __ERC20Burnable_init() internal initializer {\\n __Context_init_unchained();\\n __ERC20Burnable_init_unchained();\\n }\\n\\n function __ERC20Burnable_init_unchained() internal initializer {\\n }\\n using SafeMathUpgradeable for uint256;\\n\\n /**\\n * @dev Destroys `amount` tokens from the caller.\\n *\\n * See {ERC20-_burn}.\\n */\\n function burn(uint256 amount) public virtual {\\n _burn(_msgSender(), amount);\\n }\\n\\n /**\\n * @dev Destroys `amount` tokens from `account`, deducting from the caller's\\n * allowance.\\n *\\n * See {ERC20-_burn} and {ERC20-allowance}.\\n *\\n * Requirements:\\n *\\n * - the caller must have allowance for ``accounts``'s tokens of at least\\n * `amount`.\\n */\\n function burnFrom(address account, uint256 amount) public virtual {\\n uint256 decreasedAllowance = allowance(account, _msgSender()).sub(amount, \\\"ERC20: burn amount exceeds allowance\\\");\\n\\n _approve(account, _msgSender(), decreasedAllowance);\\n _burn(account, amount);\\n }\\n uint256[50] private __gap;\\n}\\n\",\"keccak256\":\"0xd0359e87fe2618573f49a95e13d9dbc31521ad64526b135618abb2a2dc362fbe\",\"license\":\"MIT\"},\"@openzeppelin/contracts-upgradeable/token/ERC20/ERC20Upgradeable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity >=0.6.0 <0.8.0;\\n\\nimport \\\"../../utils/ContextUpgradeable.sol\\\";\\nimport \\\"./IERC20Upgradeable.sol\\\";\\nimport \\\"../../math/SafeMathUpgradeable.sol\\\";\\nimport \\\"../../proxy/Initializable.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 ERC20Upgradeable is Initializable, ContextUpgradeable, IERC20Upgradeable {\\n using SafeMathUpgradeable 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 function __ERC20_init(string memory name_, string memory symbol_) internal initializer {\\n __Context_init_unchained();\\n __ERC20_init_unchained(name_, symbol_);\\n }\\n\\n function __ERC20_init_unchained(string memory name_, string memory symbol_) internal initializer {\\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 uint256[44] private __gap;\\n}\\n\",\"keccak256\":\"0x506dd0718f9ace50588c13848167df5e04ae16abb56341afb10c31ff149bc79b\",\"license\":\"MIT\"},\"@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity >=0.6.0 <0.8.0;\\n\\n/**\\n * @dev Interface of the ERC20 standard as defined in the EIP.\\n */\\ninterface IERC20Upgradeable {\\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\",\"keccak256\":\"0xa1931c47a617014f858580db625aa0dcf343796f39acd4b5b51effc092a1f0a9\",\"license\":\"MIT\"},\"@openzeppelin/contracts-upgradeable/utils/AddressUpgradeable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity >=0.6.2 <0.8.0;\\n\\n/**\\n * @dev Collection of functions related to the address type\\n */\\nlibrary AddressUpgradeable {\\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 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\",\"keccak256\":\"0xfc5ea91fa9ceb1961023b2a6c978b902888c52b90847ac7813fe3b79524165f6\",\"license\":\"MIT\"},\"@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity >=0.6.0 <0.8.0;\\nimport \\\"../proxy/Initializable.sol\\\";\\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 ContextUpgradeable is Initializable {\\n function __Context_init() internal initializer {\\n __Context_init_unchained();\\n }\\n\\n function __Context_init_unchained() internal initializer {\\n }\\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 uint256[50] private __gap;\\n}\\n\",\"keccak256\":\"0xbbf8a21b9a66c48d45ff771b8563c6df19ba451d63dfb8380a865c1e1f29d1a0\",\"license\":\"MIT\"},\"@openzeppelin/contracts-upgradeable/utils/CountersUpgradeable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity >=0.6.0 <0.8.0;\\n\\nimport \\\"../math/SafeMathUpgradeable.sol\\\";\\n\\n/**\\n * @title Counters\\n * @author Matt Condon (@shrugs)\\n * @dev Provides counters that can only be incremented or decremented by one. This can be used e.g. to track the number\\n * of elements in a mapping, issuing ERC721 ids, or counting request ids.\\n *\\n * Include with `using Counters for Counters.Counter;`\\n * Since it is not possible to overflow a 256 bit integer with increments of one, `increment` can skip the {SafeMath}\\n * overflow check, thereby saving gas. This does assume however correct usage, in that the underlying `_value` is never\\n * directly accessed.\\n */\\nlibrary CountersUpgradeable {\\n using SafeMathUpgradeable for uint256;\\n\\n struct Counter {\\n // This variable should never be directly accessed by users of the library: interactions must be restricted to\\n // the library's function. As of Solidity v0.5.2, this cannot be enforced, though there is a proposal to add\\n // this feature: see https://github.com/ethereum/solidity/issues/4637\\n uint256 _value; // default: 0\\n }\\n\\n function current(Counter storage counter) internal view returns (uint256) {\\n return counter._value;\\n }\\n\\n function increment(Counter storage counter) internal {\\n // The {SafeMath} overflow check can be skipped here, see the comment at the top\\n counter._value += 1;\\n }\\n\\n function decrement(Counter storage counter) internal {\\n counter._value = counter._value.sub(1);\\n }\\n}\\n\",\"keccak256\":\"0xe0162cc9b4d619790be38ce4c184a1cd33d41698629ae6bcac00049f24f6cce8\",\"license\":\"MIT\"},\"@openzeppelin/contracts-upgradeable/utils/EnumerableSetUpgradeable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity >=0.6.0 <0.8.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 EnumerableSetUpgradeable {\\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\",\"keccak256\":\"0x20714cf126a1a984613579156d3cbc726db8025d8400e1db1d2bb714edaba335\",\"license\":\"MIT\"},\"contracts/bridge/SynapseERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.6.12;\\n\\nimport \\\"@openzeppelin/contracts-upgradeable/token/ERC20/ERC20Upgradeable.sol\\\";\\nimport \\\"@openzeppelin/contracts-upgradeable/token/ERC20/ERC20BurnableUpgradeable.sol\\\";\\nimport \\\"@openzeppelin/contracts-upgradeable/drafts/ERC20PermitUpgradeable.sol\\\";\\nimport \\\"@openzeppelin/contracts-upgradeable/access/AccessControlUpgradeable.sol\\\";\\nimport \\\"@openzeppelin/contracts-upgradeable/proxy/Initializable.sol\\\";\\n\\ncontract SynapseERC20 is\\n Initializable,\\n ContextUpgradeable,\\n AccessControlUpgradeable,\\n ERC20BurnableUpgradeable,\\n ERC20PermitUpgradeable\\n{\\n bytes32 public constant MINTER_ROLE = keccak256(\\\"MINTER_ROLE\\\");\\n\\n /**\\n * @notice Initializes this ERC20 contract with the given parameters.\\n * @param name Token name\\n * @param symbol Token symbol\\n * @param decimals Token name\\n * @param owner admin address to be initialized with\\n */\\n function initialize(\\n string memory name,\\n string memory symbol,\\n uint8 decimals,\\n address owner\\n ) external initializer {\\n __Context_init_unchained();\\n __AccessControl_init_unchained();\\n __ERC20_init_unchained(name, symbol);\\n __ERC20Burnable_init_unchained();\\n _setupDecimals(decimals);\\n __ERC20Permit_init(name);\\n _setupRole(DEFAULT_ADMIN_ROLE, owner);\\n }\\n\\n function mint(address to, uint256 amount) external {\\n require(hasRole(MINTER_ROLE, msg.sender), \\\"Not a minter\\\");\\n _mint(to, amount);\\n }\\n}\\n\",\"keccak256\":\"0x62201e7f62c9954664d7250cd5d6997729ff226d8eb246be911e3b59b3d976f7\",\"license\":\"MIT\"}},\"version\":1}", + "bytecode": "0x608060405234801561001057600080fd5b50612213806100206000396000f3fe608060405234801561001057600080fd5b50600436106101b95760003560e01c806379cc6790116100f9578063a9059cbb11610097578063d539139311610071578063d539139314610596578063d547741f1461059e578063dd62ed3e146105ca578063de7ea79d146105f8576101b9565b8063a9059cbb146104fc578063ca15c87314610528578063d505accf14610545576101b9565b806391d14854116100d357806391d148541461049457806395d89b41146104c0578063a217fddf146104c8578063a457c2d7146104d0576101b9565b806379cc6790146104035780637ecebe001461042f5780639010d07c14610455576101b9565b8063313ce567116101665780633950935111610140578063395093511461036857806340c10f191461039457806342966c68146103c057806370a08231146103dd576101b9565b8063313ce567146103165780633644e5151461033457806336568abe1461033c576101b9565b806323b872dd1161019757806323b872dd14610295578063248a9ca3146102cb5780632f2ff15d146102e8576101b9565b806306fdde03146101be578063095ea7b31461023b57806318160ddd1461027b575b600080fd5b6101c6610736565b6040805160208082528351818301528351919283929083019185019080838360005b838110156102005781810151838201526020016101e8565b50505050905090810190601f16801561022d5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b6102676004803603604081101561025157600080fd5b506001600160a01b0381351690602001356107ea565b604080519115158252519081900360200190f35b610283610808565b60408051918252519081900360200190f35b610267600480360360608110156102ab57600080fd5b506001600160a01b0381358116916020810135909116906040013561080e565b610283600480360360208110156102e157600080fd5b5035610895565b610314600480360360408110156102fe57600080fd5b50803590602001356001600160a01b03166108aa565b005b61031e610916565b6040805160ff9092168252519081900360200190f35b61028361091f565b6103146004803603604081101561035257600080fd5b50803590602001356001600160a01b031661092e565b6102676004803603604081101561037e57600080fd5b506001600160a01b03813516906020013561098f565b610314600480360360408110156103aa57600080fd5b506001600160a01b0381351690602001356109dd565b610314600480360360208110156103d657600080fd5b5035610a62565b610283600480360360208110156103f357600080fd5b50356001600160a01b0316610a76565b6103146004803603604081101561041957600080fd5b506001600160a01b038135169060200135610a91565b6102836004803603602081101561044557600080fd5b50356001600160a01b0316610aeb565b6104786004803603604081101561046b57600080fd5b5080359060200135610b0c565b604080516001600160a01b039092168252519081900360200190f35b610267600480360360408110156104aa57600080fd5b50803590602001356001600160a01b0316610b2b565b6101c6610b43565b610283610bc2565b610267600480360360408110156104e657600080fd5b506001600160a01b038135169060200135610bc7565b6102676004803603604081101561051257600080fd5b506001600160a01b038135169060200135610c2f565b6102836004803603602081101561053e57600080fd5b5035610c43565b610314600480360360e081101561055b57600080fd5b506001600160a01b03813581169160208101359091169060408101359060608101359060ff6080820135169060a08101359060c00135610c5a565b610283610dfd565b610314600480360360408110156105b457600080fd5b50803590602001356001600160a01b0316610e21565b610283600480360360408110156105e057600080fd5b506001600160a01b0381358116916020013516610e7a565b6103146004803603608081101561060e57600080fd5b81019060208101813564010000000081111561062957600080fd5b82018360208201111561063b57600080fd5b8035906020019184600183028401116401000000008311171561065d57600080fd5b91908080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525092959493602081019350359150506401000000008111156106b057600080fd5b8201836020820111156106c257600080fd5b803590602001918460018302840111640100000000831117156106e457600080fd5b91908080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509295505050813560ff16925050602001356001600160a01b0316610ea5565b60688054604080516020601f60027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6101006001881615020190951694909404938401819004810282018101909252828152606093909290918301828280156107e05780601f106107b5576101008083540402835291602001916107e0565b820191906000526020600020905b8154815290600101906020018083116107c357829003601f168201915b5050505050905090565b60006107fe6107f7610f8a565b8484610f8e565b5060015b92915050565b60675490565b600061081b84848461107a565b61088b84610827610f8a565b610886856040518060600160405280602881526020016120d4602891396001600160a01b038a16600090815260666020526040812090610865610f8a565b6001600160a01b0316815260208101919091526040016000205491906111d7565b610f8e565b5060019392505050565b60009081526033602052604090206002015490565b6000828152603360205260409020600201546108cd906108c8610f8a565b610b2b565b6109085760405162461bcd60e51b815260040180806020018281038252602f815260200180611f99602f913960400191505060405180910390fd5b610912828261126e565b5050565b606a5460ff1690565b60006109296112d7565b905090565b610936610f8a565b6001600160a01b0316816001600160a01b0316146109855760405162461bcd60e51b815260040180806020018281038252602f8152602001806121af602f913960400191505060405180910390fd5b6109128282611312565b60006107fe61099c610f8a565b8461088685606660006109ad610f8a565b6001600160a01b03908116825260208083019390935260409182016000908120918c16815292529020549061137b565b610a077f9f2df0fed2c77648de5860a4cc508cd0818c85b8b8a1ab4ceeef8d981c8956a633610b2b565b610a58576040805162461bcd60e51b815260206004820152600c60248201527f4e6f742061206d696e7465720000000000000000000000000000000000000000604482015290519081900360640190fd5b61091282826113d5565b610a73610a6d610f8a565b826114c7565b50565b6001600160a01b031660009081526065602052604090205490565b6000610ac8826040518060600160405280602481526020016120fc60249139610ac186610abc610f8a565b610e7a565b91906111d7565b9050610adc83610ad6610f8a565b83610f8e565b610ae683836114c7565b505050565b6001600160a01b038116600090815260fd60205260408120610802906115c3565b6000828152603360205260408120610b2490836115c7565b9392505050565b6000828152603360205260408120610b2490836115d3565b60698054604080516020601f60027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6101006001881615020190951694909404938401819004810282018101909252828152606093909290918301828280156107e05780601f106107b5576101008083540402835291602001916107e0565b600081565b60006107fe610bd4610f8a565b846108868560405180606001604052806025815260200161218a6025913960666000610bfe610f8a565b6001600160a01b03908116825260208083019390935260409182016000908120918d168152925290205491906111d7565b60006107fe610c3c610f8a565b848461107a565b6000818152603360205260408120610802906115e8565b83421115610caf576040805162461bcd60e51b815260206004820152601d60248201527f45524332305065726d69743a206578706972656420646561646c696e65000000604482015290519081900360640190fd5b600060fe54888888610ce460fd60008e6001600160a01b03166001600160a01b031681526020019081526020016000206115c3565b8960405160200180878152602001866001600160a01b03168152602001856001600160a01b0316815260200184815260200183815260200182815260200196505050505050506040516020818303038152906040528051906020012090506000610d4d826115f3565b90506000610d5d8287878761165a565b9050896001600160a01b0316816001600160a01b031614610dc5576040805162461bcd60e51b815260206004820152601e60248201527f45524332305065726d69743a20696e76616c6964207369676e61747572650000604482015290519081900360640190fd5b6001600160a01b038a16600090815260fd60205260409020610de6906117f6565b610df18a8a8a610f8e565b50505050505050505050565b7f9f2df0fed2c77648de5860a4cc508cd0818c85b8b8a1ab4ceeef8d981c8956a681565b600082815260336020526040902060020154610e3f906108c8610f8a565b6109855760405162461bcd60e51b81526004018080602001828103825260308152602001806120546030913960400191505060405180910390fd5b6001600160a01b03918216600090815260666020908152604080832093909416825291909152205490565b600054610100900460ff1680610ebe5750610ebe6117ff565b80610ecc575060005460ff16155b610f075760405162461bcd60e51b815260040180806020018281038252602e815260200180612084602e913960400191505060405180910390fd5b600054610100900460ff16158015610f32576000805460ff1961ff0019909116610100171660011790555b610f3a611810565b610f42611810565b610f4c85856118b1565b610f54611810565b610f5d83611989565b610f668561199f565b610f71600083610908565b8015610f83576000805461ff00191690555b5050505050565b3390565b6001600160a01b038316610fd35760405162461bcd60e51b81526004018080602001828103825260248152602001806121666024913960400191505060405180910390fd5b6001600160a01b0382166110185760405162461bcd60e51b8152600401808060200182810382526022815260200180611fea6022913960400191505060405180910390fd5b6001600160a01b03808416600081815260666020908152604080832094871680845294825291829020859055815185815291517f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b9259281900390910190a3505050565b6001600160a01b0383166110bf5760405162461bcd60e51b81526004018080602001828103825260258152602001806121416025913960400191505060405180910390fd5b6001600160a01b0382166111045760405162461bcd60e51b8152600401808060200182810382526023815260200180611f766023913960400191505060405180910390fd5b61110f838383610ae6565b61114c8160405180606001604052806026815260200161200c602691396001600160a01b03861660009081526065602052604090205491906111d7565b6001600160a01b03808516600090815260656020526040808220939093559084168152205461117b908261137b565b6001600160a01b0380841660008181526065602090815260409182902094909455805185815290519193928716927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef92918290030190a3505050565b600081848411156112665760405162461bcd60e51b81526004018080602001828103825283818151815260200191508051906020019080838360005b8381101561122b578181015183820152602001611213565b50505050905090810190601f1680156112585780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b505050900390565b60008281526033602052604090206112869082611a91565b1561091257611293610f8a565b6001600160a01b0316816001600160a01b0316837f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a45050565b60006109297f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f611305611aa6565b61130d611aac565b611ab2565b600082815260336020526040902061132a9082611b14565b1561091257611337610f8a565b6001600160a01b0316816001600160a01b0316837ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b60405160405180910390a45050565b600082820183811015610b24576040805162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b6001600160a01b038216611430576040805162461bcd60e51b815260206004820152601f60248201527f45524332303a206d696e7420746f20746865207a65726f206164647265737300604482015290519081900360640190fd5b61143c60008383610ae6565b606754611449908261137b565b6067556001600160a01b03821660009081526065602052604090205461146f908261137b565b6001600160a01b03831660008181526065602090815260408083209490945583518581529351929391927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9281900390910190a35050565b6001600160a01b03821661150c5760405162461bcd60e51b81526004018080602001828103825260218152602001806121206021913960400191505060405180910390fd5b61151882600083610ae6565b61155581604051806060016040528060228152602001611fc8602291396001600160a01b03851660009081526065602052604090205491906111d7565b6001600160a01b03831660009081526065602052604090205560675461157b9082611b29565b6067556040805182815290516000916001600160a01b038516917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9181900360200190a35050565b5490565b6000610b248383611b86565b6000610b24836001600160a01b038416611bea565b6000610802826115c3565b60006115fd6112d7565b8260405160200180807f190100000000000000000000000000000000000000000000000000000000000081525060020183815260200182815260200192505050604051602081830303815290604052805190602001209050919050565b60007f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a08211156116bb5760405162461bcd60e51b81526004018080602001828103825260228152602001806120326022913960400191505060405180910390fd5b8360ff16601b14806116d057508360ff16601c145b61170b5760405162461bcd60e51b81526004018080602001828103825260228152602001806120b26022913960400191505060405180910390fd5b600060018686868660405160008152602001604052604051808581526020018460ff1681526020018381526020018281526020019450505050506020604051602081039080840390855afa158015611767573d6000803e3d6000fd5b50506040517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe001519150506001600160a01b0381166117ed576040805162461bcd60e51b815260206004820152601860248201527f45434453413a20696e76616c6964207369676e61747572650000000000000000604482015290519081900360640190fd5b95945050505050565b80546001019055565b600061180a30611c02565b15905090565b600054610100900460ff168061182957506118296117ff565b80611837575060005460ff16155b6118725760405162461bcd60e51b815260040180806020018281038252602e815260200180612084602e913960400191505060405180910390fd5b600054610100900460ff1615801561189d576000805460ff1961ff0019909116610100171660011790555b8015610a73576000805461ff001916905550565b600054610100900460ff16806118ca57506118ca6117ff565b806118d8575060005460ff16155b6119135760405162461bcd60e51b815260040180806020018281038252602e815260200180612084602e913960400191505060405180910390fd5b600054610100900460ff1615801561193e576000805460ff1961ff0019909116610100171660011790555b8251611951906068906020860190611ec0565b508151611965906069906020850190611ec0565b50606a805460ff191660121790558015610ae6576000805461ff0019169055505050565b606a805460ff191660ff92909216919091179055565b600054610100900460ff16806119b857506119b86117ff565b806119c6575060005460ff16155b611a015760405162461bcd60e51b815260040180806020018281038252602e815260200180612084602e913960400191505060405180910390fd5b600054610100900460ff16158015611a2c576000805460ff1961ff0019909116610100171660011790555b611a34611810565b611a73826040518060400160405280600181526020017f3100000000000000000000000000000000000000000000000000000000000000815250611c08565b611a7c82611cc8565b8015610912576000805461ff00191690555050565b6000610b24836001600160a01b038416611d8e565b60c95490565b60ca5490565b6000838383611abf611dd8565b3060405160200180868152602001858152602001848152602001838152602001826001600160a01b03168152602001955050505050506040516020818303038152906040528051906020012090509392505050565b6000610b24836001600160a01b038416611ddc565b600082821115611b80576040805162461bcd60e51b815260206004820152601e60248201527f536166654d6174683a207375627472616374696f6e206f766572666c6f770000604482015290519081900360640190fd5b50900390565b81546000908210611bc85760405162461bcd60e51b8152600401808060200182810382526022815260200180611f546022913960400191505060405180910390fd5b826000018281548110611bd757fe5b9060005260206000200154905092915050565b60009081526001919091016020526040902054151590565b3b151590565b600054610100900460ff1680611c215750611c216117ff565b80611c2f575060005460ff16155b611c6a5760405162461bcd60e51b815260040180806020018281038252602e815260200180612084602e913960400191505060405180910390fd5b600054610100900460ff16158015611c95576000805460ff1961ff0019909116610100171660011790555b825160208085019190912083519184019190912060c99190915560ca558015610ae6576000805461ff0019169055505050565b600054610100900460ff1680611ce15750611ce16117ff565b80611cef575060005460ff16155b611d2a5760405162461bcd60e51b815260040180806020018281038252602e815260200180612084602e913960400191505060405180910390fd5b600054610100900460ff16158015611d55576000805460ff1961ff0019909116610100171660011790555b7f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c960fe558015610912576000805461ff00191690555050565b6000611d9a8383611bea565b611dd057508154600181810184556000848152602080822090930184905584548482528286019093526040902091909155610802565b506000610802565b4690565b60008181526001830160205260408120548015611eb65783547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8083019190810190600090879083908110611e2d57fe5b9060005260206000200154905080876000018481548110611e4a57fe5b600091825260208083209091019290925582815260018981019092526040902090840190558654879080611e7a57fe5b60019003818190600052602060002001600090559055866001016000878152602001908152602001600020600090556001945050505050610802565b6000915050610802565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f10611f0157805160ff1916838001178555611f2e565b82800160010185558215611f2e579182015b82811115611f2e578251825591602001919060010190611f13565b50611f3a929150611f3e565b5090565b5b80821115611f3a5760008155600101611f3f56fe456e756d657261626c655365743a20696e646578206f7574206f6620626f756e647345524332303a207472616e7366657220746f20746865207a65726f2061646472657373416363657373436f6e74726f6c3a2073656e646572206d75737420626520616e2061646d696e20746f206772616e7445524332303a206275726e20616d6f756e7420657863656564732062616c616e636545524332303a20617070726f766520746f20746865207a65726f206164647265737345524332303a207472616e7366657220616d6f756e7420657863656564732062616c616e636545434453413a20696e76616c6964207369676e6174757265202773272076616c7565416363657373436f6e74726f6c3a2073656e646572206d75737420626520616e2061646d696e20746f207265766f6b65496e697469616c697a61626c653a20636f6e747261637420697320616c726561647920696e697469616c697a656445434453413a20696e76616c6964207369676e6174757265202776272076616c756545524332303a207472616e7366657220616d6f756e74206578636565647320616c6c6f77616e636545524332303a206275726e20616d6f756e74206578636565647320616c6c6f77616e636545524332303a206275726e2066726f6d20746865207a65726f206164647265737345524332303a207472616e736665722066726f6d20746865207a65726f206164647265737345524332303a20617070726f76652066726f6d20746865207a65726f206164647265737345524332303a2064656372656173656420616c6c6f77616e63652062656c6f77207a65726f416363657373436f6e74726f6c3a2063616e206f6e6c792072656e6f756e636520726f6c657320666f722073656c66a2646970667358221220e7c3753b08173a11ca96acfac750f90800b1683e662b545723723a1385793bd164736f6c634300060c0033", + "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106101b95760003560e01c806379cc6790116100f9578063a9059cbb11610097578063d539139311610071578063d539139314610596578063d547741f1461059e578063dd62ed3e146105ca578063de7ea79d146105f8576101b9565b8063a9059cbb146104fc578063ca15c87314610528578063d505accf14610545576101b9565b806391d14854116100d357806391d148541461049457806395d89b41146104c0578063a217fddf146104c8578063a457c2d7146104d0576101b9565b806379cc6790146104035780637ecebe001461042f5780639010d07c14610455576101b9565b8063313ce567116101665780633950935111610140578063395093511461036857806340c10f191461039457806342966c68146103c057806370a08231146103dd576101b9565b8063313ce567146103165780633644e5151461033457806336568abe1461033c576101b9565b806323b872dd1161019757806323b872dd14610295578063248a9ca3146102cb5780632f2ff15d146102e8576101b9565b806306fdde03146101be578063095ea7b31461023b57806318160ddd1461027b575b600080fd5b6101c6610736565b6040805160208082528351818301528351919283929083019185019080838360005b838110156102005781810151838201526020016101e8565b50505050905090810190601f16801561022d5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b6102676004803603604081101561025157600080fd5b506001600160a01b0381351690602001356107ea565b604080519115158252519081900360200190f35b610283610808565b60408051918252519081900360200190f35b610267600480360360608110156102ab57600080fd5b506001600160a01b0381358116916020810135909116906040013561080e565b610283600480360360208110156102e157600080fd5b5035610895565b610314600480360360408110156102fe57600080fd5b50803590602001356001600160a01b03166108aa565b005b61031e610916565b6040805160ff9092168252519081900360200190f35b61028361091f565b6103146004803603604081101561035257600080fd5b50803590602001356001600160a01b031661092e565b6102676004803603604081101561037e57600080fd5b506001600160a01b03813516906020013561098f565b610314600480360360408110156103aa57600080fd5b506001600160a01b0381351690602001356109dd565b610314600480360360208110156103d657600080fd5b5035610a62565b610283600480360360208110156103f357600080fd5b50356001600160a01b0316610a76565b6103146004803603604081101561041957600080fd5b506001600160a01b038135169060200135610a91565b6102836004803603602081101561044557600080fd5b50356001600160a01b0316610aeb565b6104786004803603604081101561046b57600080fd5b5080359060200135610b0c565b604080516001600160a01b039092168252519081900360200190f35b610267600480360360408110156104aa57600080fd5b50803590602001356001600160a01b0316610b2b565b6101c6610b43565b610283610bc2565b610267600480360360408110156104e657600080fd5b506001600160a01b038135169060200135610bc7565b6102676004803603604081101561051257600080fd5b506001600160a01b038135169060200135610c2f565b6102836004803603602081101561053e57600080fd5b5035610c43565b610314600480360360e081101561055b57600080fd5b506001600160a01b03813581169160208101359091169060408101359060608101359060ff6080820135169060a08101359060c00135610c5a565b610283610dfd565b610314600480360360408110156105b457600080fd5b50803590602001356001600160a01b0316610e21565b610283600480360360408110156105e057600080fd5b506001600160a01b0381358116916020013516610e7a565b6103146004803603608081101561060e57600080fd5b81019060208101813564010000000081111561062957600080fd5b82018360208201111561063b57600080fd5b8035906020019184600183028401116401000000008311171561065d57600080fd5b91908080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525092959493602081019350359150506401000000008111156106b057600080fd5b8201836020820111156106c257600080fd5b803590602001918460018302840111640100000000831117156106e457600080fd5b91908080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509295505050813560ff16925050602001356001600160a01b0316610ea5565b60688054604080516020601f60027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6101006001881615020190951694909404938401819004810282018101909252828152606093909290918301828280156107e05780601f106107b5576101008083540402835291602001916107e0565b820191906000526020600020905b8154815290600101906020018083116107c357829003601f168201915b5050505050905090565b60006107fe6107f7610f8a565b8484610f8e565b5060015b92915050565b60675490565b600061081b84848461107a565b61088b84610827610f8a565b610886856040518060600160405280602881526020016120d4602891396001600160a01b038a16600090815260666020526040812090610865610f8a565b6001600160a01b0316815260208101919091526040016000205491906111d7565b610f8e565b5060019392505050565b60009081526033602052604090206002015490565b6000828152603360205260409020600201546108cd906108c8610f8a565b610b2b565b6109085760405162461bcd60e51b815260040180806020018281038252602f815260200180611f99602f913960400191505060405180910390fd5b610912828261126e565b5050565b606a5460ff1690565b60006109296112d7565b905090565b610936610f8a565b6001600160a01b0316816001600160a01b0316146109855760405162461bcd60e51b815260040180806020018281038252602f8152602001806121af602f913960400191505060405180910390fd5b6109128282611312565b60006107fe61099c610f8a565b8461088685606660006109ad610f8a565b6001600160a01b03908116825260208083019390935260409182016000908120918c16815292529020549061137b565b610a077f9f2df0fed2c77648de5860a4cc508cd0818c85b8b8a1ab4ceeef8d981c8956a633610b2b565b610a58576040805162461bcd60e51b815260206004820152600c60248201527f4e6f742061206d696e7465720000000000000000000000000000000000000000604482015290519081900360640190fd5b61091282826113d5565b610a73610a6d610f8a565b826114c7565b50565b6001600160a01b031660009081526065602052604090205490565b6000610ac8826040518060600160405280602481526020016120fc60249139610ac186610abc610f8a565b610e7a565b91906111d7565b9050610adc83610ad6610f8a565b83610f8e565b610ae683836114c7565b505050565b6001600160a01b038116600090815260fd60205260408120610802906115c3565b6000828152603360205260408120610b2490836115c7565b9392505050565b6000828152603360205260408120610b2490836115d3565b60698054604080516020601f60027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6101006001881615020190951694909404938401819004810282018101909252828152606093909290918301828280156107e05780601f106107b5576101008083540402835291602001916107e0565b600081565b60006107fe610bd4610f8a565b846108868560405180606001604052806025815260200161218a6025913960666000610bfe610f8a565b6001600160a01b03908116825260208083019390935260409182016000908120918d168152925290205491906111d7565b60006107fe610c3c610f8a565b848461107a565b6000818152603360205260408120610802906115e8565b83421115610caf576040805162461bcd60e51b815260206004820152601d60248201527f45524332305065726d69743a206578706972656420646561646c696e65000000604482015290519081900360640190fd5b600060fe54888888610ce460fd60008e6001600160a01b03166001600160a01b031681526020019081526020016000206115c3565b8960405160200180878152602001866001600160a01b03168152602001856001600160a01b0316815260200184815260200183815260200182815260200196505050505050506040516020818303038152906040528051906020012090506000610d4d826115f3565b90506000610d5d8287878761165a565b9050896001600160a01b0316816001600160a01b031614610dc5576040805162461bcd60e51b815260206004820152601e60248201527f45524332305065726d69743a20696e76616c6964207369676e61747572650000604482015290519081900360640190fd5b6001600160a01b038a16600090815260fd60205260409020610de6906117f6565b610df18a8a8a610f8e565b50505050505050505050565b7f9f2df0fed2c77648de5860a4cc508cd0818c85b8b8a1ab4ceeef8d981c8956a681565b600082815260336020526040902060020154610e3f906108c8610f8a565b6109855760405162461bcd60e51b81526004018080602001828103825260308152602001806120546030913960400191505060405180910390fd5b6001600160a01b03918216600090815260666020908152604080832093909416825291909152205490565b600054610100900460ff1680610ebe5750610ebe6117ff565b80610ecc575060005460ff16155b610f075760405162461bcd60e51b815260040180806020018281038252602e815260200180612084602e913960400191505060405180910390fd5b600054610100900460ff16158015610f32576000805460ff1961ff0019909116610100171660011790555b610f3a611810565b610f42611810565b610f4c85856118b1565b610f54611810565b610f5d83611989565b610f668561199f565b610f71600083610908565b8015610f83576000805461ff00191690555b5050505050565b3390565b6001600160a01b038316610fd35760405162461bcd60e51b81526004018080602001828103825260248152602001806121666024913960400191505060405180910390fd5b6001600160a01b0382166110185760405162461bcd60e51b8152600401808060200182810382526022815260200180611fea6022913960400191505060405180910390fd5b6001600160a01b03808416600081815260666020908152604080832094871680845294825291829020859055815185815291517f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b9259281900390910190a3505050565b6001600160a01b0383166110bf5760405162461bcd60e51b81526004018080602001828103825260258152602001806121416025913960400191505060405180910390fd5b6001600160a01b0382166111045760405162461bcd60e51b8152600401808060200182810382526023815260200180611f766023913960400191505060405180910390fd5b61110f838383610ae6565b61114c8160405180606001604052806026815260200161200c602691396001600160a01b03861660009081526065602052604090205491906111d7565b6001600160a01b03808516600090815260656020526040808220939093559084168152205461117b908261137b565b6001600160a01b0380841660008181526065602090815260409182902094909455805185815290519193928716927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef92918290030190a3505050565b600081848411156112665760405162461bcd60e51b81526004018080602001828103825283818151815260200191508051906020019080838360005b8381101561122b578181015183820152602001611213565b50505050905090810190601f1680156112585780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b505050900390565b60008281526033602052604090206112869082611a91565b1561091257611293610f8a565b6001600160a01b0316816001600160a01b0316837f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a45050565b60006109297f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f611305611aa6565b61130d611aac565b611ab2565b600082815260336020526040902061132a9082611b14565b1561091257611337610f8a565b6001600160a01b0316816001600160a01b0316837ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b60405160405180910390a45050565b600082820183811015610b24576040805162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b6001600160a01b038216611430576040805162461bcd60e51b815260206004820152601f60248201527f45524332303a206d696e7420746f20746865207a65726f206164647265737300604482015290519081900360640190fd5b61143c60008383610ae6565b606754611449908261137b565b6067556001600160a01b03821660009081526065602052604090205461146f908261137b565b6001600160a01b03831660008181526065602090815260408083209490945583518581529351929391927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9281900390910190a35050565b6001600160a01b03821661150c5760405162461bcd60e51b81526004018080602001828103825260218152602001806121206021913960400191505060405180910390fd5b61151882600083610ae6565b61155581604051806060016040528060228152602001611fc8602291396001600160a01b03851660009081526065602052604090205491906111d7565b6001600160a01b03831660009081526065602052604090205560675461157b9082611b29565b6067556040805182815290516000916001600160a01b038516917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9181900360200190a35050565b5490565b6000610b248383611b86565b6000610b24836001600160a01b038416611bea565b6000610802826115c3565b60006115fd6112d7565b8260405160200180807f190100000000000000000000000000000000000000000000000000000000000081525060020183815260200182815260200192505050604051602081830303815290604052805190602001209050919050565b60007f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a08211156116bb5760405162461bcd60e51b81526004018080602001828103825260228152602001806120326022913960400191505060405180910390fd5b8360ff16601b14806116d057508360ff16601c145b61170b5760405162461bcd60e51b81526004018080602001828103825260228152602001806120b26022913960400191505060405180910390fd5b600060018686868660405160008152602001604052604051808581526020018460ff1681526020018381526020018281526020019450505050506020604051602081039080840390855afa158015611767573d6000803e3d6000fd5b50506040517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe001519150506001600160a01b0381166117ed576040805162461bcd60e51b815260206004820152601860248201527f45434453413a20696e76616c6964207369676e61747572650000000000000000604482015290519081900360640190fd5b95945050505050565b80546001019055565b600061180a30611c02565b15905090565b600054610100900460ff168061182957506118296117ff565b80611837575060005460ff16155b6118725760405162461bcd60e51b815260040180806020018281038252602e815260200180612084602e913960400191505060405180910390fd5b600054610100900460ff1615801561189d576000805460ff1961ff0019909116610100171660011790555b8015610a73576000805461ff001916905550565b600054610100900460ff16806118ca57506118ca6117ff565b806118d8575060005460ff16155b6119135760405162461bcd60e51b815260040180806020018281038252602e815260200180612084602e913960400191505060405180910390fd5b600054610100900460ff1615801561193e576000805460ff1961ff0019909116610100171660011790555b8251611951906068906020860190611ec0565b508151611965906069906020850190611ec0565b50606a805460ff191660121790558015610ae6576000805461ff0019169055505050565b606a805460ff191660ff92909216919091179055565b600054610100900460ff16806119b857506119b86117ff565b806119c6575060005460ff16155b611a015760405162461bcd60e51b815260040180806020018281038252602e815260200180612084602e913960400191505060405180910390fd5b600054610100900460ff16158015611a2c576000805460ff1961ff0019909116610100171660011790555b611a34611810565b611a73826040518060400160405280600181526020017f3100000000000000000000000000000000000000000000000000000000000000815250611c08565b611a7c82611cc8565b8015610912576000805461ff00191690555050565b6000610b24836001600160a01b038416611d8e565b60c95490565b60ca5490565b6000838383611abf611dd8565b3060405160200180868152602001858152602001848152602001838152602001826001600160a01b03168152602001955050505050506040516020818303038152906040528051906020012090509392505050565b6000610b24836001600160a01b038416611ddc565b600082821115611b80576040805162461bcd60e51b815260206004820152601e60248201527f536166654d6174683a207375627472616374696f6e206f766572666c6f770000604482015290519081900360640190fd5b50900390565b81546000908210611bc85760405162461bcd60e51b8152600401808060200182810382526022815260200180611f546022913960400191505060405180910390fd5b826000018281548110611bd757fe5b9060005260206000200154905092915050565b60009081526001919091016020526040902054151590565b3b151590565b600054610100900460ff1680611c215750611c216117ff565b80611c2f575060005460ff16155b611c6a5760405162461bcd60e51b815260040180806020018281038252602e815260200180612084602e913960400191505060405180910390fd5b600054610100900460ff16158015611c95576000805460ff1961ff0019909116610100171660011790555b825160208085019190912083519184019190912060c99190915560ca558015610ae6576000805461ff0019169055505050565b600054610100900460ff1680611ce15750611ce16117ff565b80611cef575060005460ff16155b611d2a5760405162461bcd60e51b815260040180806020018281038252602e815260200180612084602e913960400191505060405180910390fd5b600054610100900460ff16158015611d55576000805460ff1961ff0019909116610100171660011790555b7f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c960fe558015610912576000805461ff00191690555050565b6000611d9a8383611bea565b611dd057508154600181810184556000848152602080822090930184905584548482528286019093526040902091909155610802565b506000610802565b4690565b60008181526001830160205260408120548015611eb65783547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8083019190810190600090879083908110611e2d57fe5b9060005260206000200154905080876000018481548110611e4a57fe5b600091825260208083209091019290925582815260018981019092526040902090840190558654879080611e7a57fe5b60019003818190600052602060002001600090559055866001016000878152602001908152602001600020600090556001945050505050610802565b6000915050610802565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f10611f0157805160ff1916838001178555611f2e565b82800160010185558215611f2e579182015b82811115611f2e578251825591602001919060010190611f13565b50611f3a929150611f3e565b5090565b5b80821115611f3a5760008155600101611f3f56fe456e756d657261626c655365743a20696e646578206f7574206f6620626f756e647345524332303a207472616e7366657220746f20746865207a65726f2061646472657373416363657373436f6e74726f6c3a2073656e646572206d75737420626520616e2061646d696e20746f206772616e7445524332303a206275726e20616d6f756e7420657863656564732062616c616e636545524332303a20617070726f766520746f20746865207a65726f206164647265737345524332303a207472616e7366657220616d6f756e7420657863656564732062616c616e636545434453413a20696e76616c6964207369676e6174757265202773272076616c7565416363657373436f6e74726f6c3a2073656e646572206d75737420626520616e2061646d696e20746f207265766f6b65496e697469616c697a61626c653a20636f6e747261637420697320616c726561647920696e697469616c697a656445434453413a20696e76616c6964207369676e6174757265202776272076616c756545524332303a207472616e7366657220616d6f756e74206578636565647320616c6c6f77616e636545524332303a206275726e20616d6f756e74206578636565647320616c6c6f77616e636545524332303a206275726e2066726f6d20746865207a65726f206164647265737345524332303a207472616e736665722066726f6d20746865207a65726f206164647265737345524332303a20617070726f76652066726f6d20746865207a65726f206164647265737345524332303a2064656372656173656420616c6c6f77616e63652062656c6f77207a65726f416363657373436f6e74726f6c3a2063616e206f6e6c792072656e6f756e636520726f6c657320666f722073656c66a2646970667358221220e7c3753b08173a11ca96acfac750f90800b1683e662b545723723a1385793bd164736f6c634300060c0033", + "devdoc": { + "kind": "dev", + "methods": { + "DOMAIN_SEPARATOR()": { + "details": "See {IERC20Permit-DOMAIN_SEPARATOR}." + }, + "allowance(address,address)": { + "details": "See {IERC20-allowance}." + }, + "approve(address,uint256)": { + "details": "See {IERC20-approve}. Requirements: - `spender` cannot be the zero address." + }, + "balanceOf(address)": { + "details": "See {IERC20-balanceOf}." + }, + "burn(uint256)": { + "details": "Destroys `amount` tokens from the caller. See {ERC20-_burn}." + }, + "burnFrom(address,uint256)": { + "details": "Destroys `amount` tokens from `account`, deducting from the caller's allowance. See {ERC20-_burn} and {ERC20-allowance}. Requirements: - the caller must have allowance for ``accounts``'s tokens of at least `amount`." + }, + "decimals()": { + "details": "Returns the number of decimals used to get its user representation. For example, if `decimals` equals `2`, a balance of `505` tokens should be displayed to a user as `5,05` (`505 / 10 ** 2`). Tokens usually opt for a value of 18, imitating the relationship between Ether and Wei. This is the value {ERC20} uses, unless {_setupDecimals} is called. NOTE: This information is only used for _display_ purposes: it in no way affects any of the arithmetic of the contract, including {IERC20-balanceOf} and {IERC20-transfer}." + }, + "decreaseAllowance(address,uint256)": { + "details": "Atomically decreases the allowance granted to `spender` by the caller. This is an alternative to {approve} that can be used as a mitigation for problems described in {IERC20-approve}. Emits an {Approval} event indicating the updated allowance. Requirements: - `spender` cannot be the zero address. - `spender` must have allowance for the caller of at least `subtractedValue`." + }, + "getRoleAdmin(bytes32)": { + "details": "Returns the admin role that controls `role`. See {grantRole} and {revokeRole}. To change a role's admin, use {_setRoleAdmin}." + }, + "getRoleMember(bytes32,uint256)": { + "details": "Returns one of the accounts that have `role`. `index` must be a value between 0 and {getRoleMemberCount}, non-inclusive. Role bearers are not sorted in any particular way, and their ordering may change at any point. WARNING: When using {getRoleMember} and {getRoleMemberCount}, make sure you perform all queries on the same block. See the following https://forum.openzeppelin.com/t/iterating-over-elements-on-enumerableset-in-openzeppelin-contracts/2296[forum post] for more information." + }, + "getRoleMemberCount(bytes32)": { + "details": "Returns the number of accounts that have `role`. Can be used together with {getRoleMember} to enumerate all bearers of a role." + }, + "grantRole(bytes32,address)": { + "details": "Grants `role` to `account`. If `account` had not been already granted `role`, emits a {RoleGranted} event. Requirements: - the caller must have ``role``'s admin role." + }, + "hasRole(bytes32,address)": { + "details": "Returns `true` if `account` has been granted `role`." + }, + "increaseAllowance(address,uint256)": { + "details": "Atomically increases the allowance granted to `spender` by the caller. This is an alternative to {approve} that can be used as a mitigation for problems described in {IERC20-approve}. Emits an {Approval} event indicating the updated allowance. Requirements: - `spender` cannot be the zero address." + }, + "initialize(string,string,uint8,address)": { + "params": { + "decimals": "Token name", + "name": "Token name", + "owner": "admin address to be initialized with", + "symbol": "Token symbol" + } + }, + "name()": { + "details": "Returns the name of the token." + }, + "nonces(address)": { + "details": "See {IERC20Permit-nonces}." + }, + "permit(address,address,uint256,uint256,uint8,bytes32,bytes32)": { + "details": "See {IERC20Permit-permit}." + }, + "renounceRole(bytes32,address)": { + "details": "Revokes `role` from the calling account. Roles are often managed via {grantRole} and {revokeRole}: this function's purpose is to provide a mechanism for accounts to lose their privileges if they are compromised (such as when a trusted device is misplaced). If the calling account had been granted `role`, emits a {RoleRevoked} event. Requirements: - the caller must be `account`." + }, + "revokeRole(bytes32,address)": { + "details": "Revokes `role` from `account`. If `account` had been granted `role`, emits a {RoleRevoked} event. Requirements: - the caller must have ``role``'s admin role." + }, + "symbol()": { + "details": "Returns the symbol of the token, usually a shorter version of the name." + }, + "totalSupply()": { + "details": "See {IERC20-totalSupply}." + }, + "transfer(address,uint256)": { + "details": "See {IERC20-transfer}. Requirements: - `recipient` cannot be the zero address. - the caller must have a balance of at least `amount`." + }, + "transferFrom(address,address,uint256)": { + "details": "See {IERC20-transferFrom}. Emits an {Approval} event indicating the updated allowance. This is not required by the EIP. See the note at the beginning of {ERC20}. Requirements: - `sender` and `recipient` cannot be the zero address. - `sender` must have a balance of at least `amount`. - the caller must have allowance for ``sender``'s tokens of at least `amount`." + } + }, + "version": 1 + }, + "userdoc": { + "kind": "user", + "methods": { + "initialize(string,string,uint8,address)": { + "notice": "Initializes this ERC20 contract with the given parameters." + } + }, + "version": 1 + }, + "storageLayout": { + "storage": [ + { + "astId": 1286, + "contract": "contracts/bridge/SynapseERC20.sol:SynapseERC20", + "label": "_initialized", + "offset": 0, + "slot": "0", + "type": "t_bool" + }, + { + "astId": 1289, + "contract": "contracts/bridge/SynapseERC20.sol:SynapseERC20", + "label": "_initializing", + "offset": 1, + "slot": "0", + "type": "t_bool" + }, + { + "astId": 2325, + "contract": "contracts/bridge/SynapseERC20.sol:SynapseERC20", + "label": "__gap", + "offset": 0, + "slot": "1", + "type": "t_array(t_uint256)50_storage" + }, + { + "astId": 43, + "contract": "contracts/bridge/SynapseERC20.sol:SynapseERC20", + "label": "_roles", + "offset": 0, + "slot": "51", + "type": "t_mapping(t_bytes32,t_struct(RoleData)39_storage)" + }, + { + "astId": 306, + "contract": "contracts/bridge/SynapseERC20.sol:SynapseERC20", + "label": "__gap", + "offset": 0, + "slot": "52", + "type": "t_array(t_uint256)49_storage" + }, + { + "astId": 1449, + "contract": "contracts/bridge/SynapseERC20.sol:SynapseERC20", + "label": "_balances", + "offset": 0, + "slot": "101", + "type": "t_mapping(t_address,t_uint256)" + }, + { + "astId": 1455, + "contract": "contracts/bridge/SynapseERC20.sol:SynapseERC20", + "label": "_allowances", + "offset": 0, + "slot": "102", + "type": "t_mapping(t_address,t_mapping(t_address,t_uint256))" + }, + { + "astId": 1457, + "contract": "contracts/bridge/SynapseERC20.sol:SynapseERC20", + "label": "_totalSupply", + "offset": 0, + "slot": "103", + "type": "t_uint256" + }, + { + "astId": 1459, + "contract": "contracts/bridge/SynapseERC20.sol:SynapseERC20", + "label": "_name", + "offset": 0, + "slot": "104", + "type": "t_string_storage" + }, + { + "astId": 1461, + "contract": "contracts/bridge/SynapseERC20.sol:SynapseERC20", + "label": "_symbol", + "offset": 0, + "slot": "105", + "type": "t_string_storage" + }, + { + "astId": 1463, + "contract": "contracts/bridge/SynapseERC20.sol:SynapseERC20", + "label": "_decimals", + "offset": 0, + "slot": "106", + "type": "t_uint8" + }, + { + "astId": 1958, + "contract": "contracts/bridge/SynapseERC20.sol:SynapseERC20", + "label": "__gap", + "offset": 0, + "slot": "107", + "type": "t_array(t_uint256)44_storage" + }, + { + "astId": 1428, + "contract": "contracts/bridge/SynapseERC20.sol:SynapseERC20", + "label": "__gap", + "offset": 0, + "slot": "151", + "type": "t_array(t_uint256)50_storage" + }, + { + "astId": 562, + "contract": "contracts/bridge/SynapseERC20.sol:SynapseERC20", + "label": "_HASHED_NAME", + "offset": 0, + "slot": "201", + "type": "t_bytes32" + }, + { + "astId": 564, + "contract": "contracts/bridge/SynapseERC20.sol:SynapseERC20", + "label": "_HASHED_VERSION", + "offset": 0, + "slot": "202", + "type": "t_bytes32" + }, + { + "astId": 713, + "contract": "contracts/bridge/SynapseERC20.sol:SynapseERC20", + "label": "__gap", + "offset": 0, + "slot": "203", + "type": "t_array(t_uint256)50_storage" + }, + { + "astId": 738, + "contract": "contracts/bridge/SynapseERC20.sol:SynapseERC20", + "label": "_nonces", + "offset": 0, + "slot": "253", + "type": "t_mapping(t_address,t_struct(Counter)2336_storage)" + }, + { + "astId": 740, + "contract": "contracts/bridge/SynapseERC20.sol:SynapseERC20", + "label": "_PERMIT_TYPEHASH", + "offset": 0, + "slot": "254", + "type": "t_bytes32" + }, + { + "astId": 887, + "contract": "contracts/bridge/SynapseERC20.sol:SynapseERC20", + "label": "__gap", + "offset": 0, + "slot": "255", + "type": "t_array(t_uint256)49_storage" + } + ], + "types": { + "t_address": { + "encoding": "inplace", + "label": "address", + "numberOfBytes": "20" + }, + "t_array(t_bytes32)dyn_storage": { + "base": "t_bytes32", + "encoding": "dynamic_array", + "label": "bytes32[]", + "numberOfBytes": "32" + }, + "t_array(t_uint256)44_storage": { + "base": "t_uint256", + "encoding": "inplace", + "label": "uint256[44]", + "numberOfBytes": "1408" + }, + "t_array(t_uint256)49_storage": { + "base": "t_uint256", + "encoding": "inplace", + "label": "uint256[49]", + "numberOfBytes": "1568" + }, + "t_array(t_uint256)50_storage": { + "base": "t_uint256", + "encoding": "inplace", + "label": "uint256[50]", + "numberOfBytes": "1600" + }, + "t_bool": { + "encoding": "inplace", + "label": "bool", + "numberOfBytes": "1" + }, + "t_bytes32": { + "encoding": "inplace", + "label": "bytes32", + "numberOfBytes": "32" + }, + "t_mapping(t_address,t_mapping(t_address,t_uint256))": { + "encoding": "mapping", + "key": "t_address", + "label": "mapping(address => mapping(address => uint256))", + "numberOfBytes": "32", + "value": "t_mapping(t_address,t_uint256)" + }, + "t_mapping(t_address,t_struct(Counter)2336_storage)": { + "encoding": "mapping", + "key": "t_address", + "label": "mapping(address => struct CountersUpgradeable.Counter)", + "numberOfBytes": "32", + "value": "t_struct(Counter)2336_storage" + }, + "t_mapping(t_address,t_uint256)": { + "encoding": "mapping", + "key": "t_address", + "label": "mapping(address => uint256)", + "numberOfBytes": "32", + "value": "t_uint256" + }, + "t_mapping(t_bytes32,t_struct(RoleData)39_storage)": { + "encoding": "mapping", + "key": "t_bytes32", + "label": "mapping(bytes32 => struct AccessControlUpgradeable.RoleData)", + "numberOfBytes": "32", + "value": "t_struct(RoleData)39_storage" + }, + "t_mapping(t_bytes32,t_uint256)": { + "encoding": "mapping", + "key": "t_bytes32", + "label": "mapping(bytes32 => uint256)", + "numberOfBytes": "32", + "value": "t_uint256" + }, + "t_string_storage": { + "encoding": "bytes", + "label": "string", + "numberOfBytes": "32" + }, + "t_struct(AddressSet)2652_storage": { + "encoding": "inplace", + "label": "struct EnumerableSetUpgradeable.AddressSet", + "members": [ + { + "astId": 2651, + "contract": "contracts/bridge/SynapseERC20.sol:SynapseERC20", + "label": "_inner", + "offset": 0, + "slot": "0", + "type": "t_struct(Set)2387_storage" + } + ], + "numberOfBytes": "64" + }, + "t_struct(Counter)2336_storage": { + "encoding": "inplace", + "label": "struct CountersUpgradeable.Counter", + "members": [ + { + "astId": 2335, + "contract": "contracts/bridge/SynapseERC20.sol:SynapseERC20", + "label": "_value", + "offset": 0, + "slot": "0", + "type": "t_uint256" + } + ], + "numberOfBytes": "32" + }, + "t_struct(RoleData)39_storage": { + "encoding": "inplace", + "label": "struct AccessControlUpgradeable.RoleData", + "members": [ + { + "astId": 36, + "contract": "contracts/bridge/SynapseERC20.sol:SynapseERC20", + "label": "members", + "offset": 0, + "slot": "0", + "type": "t_struct(AddressSet)2652_storage" + }, + { + "astId": 38, + "contract": "contracts/bridge/SynapseERC20.sol:SynapseERC20", + "label": "adminRole", + "offset": 0, + "slot": "2", + "type": "t_bytes32" + } + ], + "numberOfBytes": "96" + }, + "t_struct(Set)2387_storage": { + "encoding": "inplace", + "label": "struct EnumerableSetUpgradeable.Set", + "members": [ + { + "astId": 2382, + "contract": "contracts/bridge/SynapseERC20.sol:SynapseERC20", + "label": "_values", + "offset": 0, + "slot": "0", + "type": "t_array(t_bytes32)dyn_storage" + }, + { + "astId": 2386, + "contract": "contracts/bridge/SynapseERC20.sol:SynapseERC20", + "label": "_indexes", + "offset": 0, + "slot": "1", + "type": "t_mapping(t_bytes32,t_uint256)" + } + ], + "numberOfBytes": "64" + }, + "t_uint256": { + "encoding": "inplace", + "label": "uint256", + "numberOfBytes": "32" + }, + "t_uint8": { + "encoding": "inplace", + "label": "uint8", + "numberOfBytes": "1" + } + } + } +} \ No newline at end of file diff --git a/deployments/cronos/nUSDPoolV3-LPToken.json b/deployments/cronos/nUSDPoolV3-LPToken.json new file mode 100644 index 000000000..f665d0462 --- /dev/null +++ b/deployments/cronos/nUSDPoolV3-LPToken.json @@ -0,0 +1,668 @@ +{ + "address": "0x8415D4EB17F0949e2388fdF52909db4cC0a2B082", + "abi": [ + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "Approval", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "bytes32", + "name": "previousAdminRole", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "bytes32", + "name": "newAdminRole", + "type": "bytes32" + } + ], + "name": "RoleAdminChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "sender", + "type": "address" + } + ], + "name": "RoleGranted", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "sender", + "type": "address" + } + ], + "name": "RoleRevoked", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "Transfer", + "type": "event" + }, + { + "inputs": [], + "name": "DEFAULT_ADMIN_ROLE", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "DOMAIN_SEPARATOR", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "MINTER_ROLE", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "address", + "name": "spender", + "type": "address" + } + ], + "name": "allowance", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "approve", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "balanceOf", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "burn", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "burnFrom", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "decimals", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "subtractedValue", + "type": "uint256" + } + ], + "name": "decreaseAllowance", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + } + ], + "name": "getRoleAdmin", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "internalType": "uint256", + "name": "index", + "type": "uint256" + } + ], + "name": "getRoleMember", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + } + ], + "name": "getRoleMemberCount", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "grantRole", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "hasRole", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "addedValue", + "type": "uint256" + } + ], + "name": "increaseAllowance", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "name", + "type": "string" + }, + { + "internalType": "string", + "name": "symbol", + "type": "string" + }, + { + "internalType": "uint8", + "name": "decimals", + "type": "uint8" + }, + { + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "initialize", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "mint", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "name", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "nonces", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" + }, + { + "internalType": "uint8", + "name": "v", + "type": "uint8" + }, + { + "internalType": "bytes32", + "name": "r", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "s", + "type": "bytes32" + } + ], + "name": "permit", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "renounceRole", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "revokeRole", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "symbol", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "totalSupply", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "recipient", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "transfer", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "internalType": "address", + "name": "recipient", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "transferFrom", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + } + ] +} \ No newline at end of file diff --git a/deployments/cronos/nUSDPoolV3.json b/deployments/cronos/nUSDPoolV3.json new file mode 100644 index 000000000..0f705c677 --- /dev/null +++ b/deployments/cronos/nUSDPoolV3.json @@ -0,0 +1,1001 @@ +{ + "address": "0x3b1601c386247A127287b094F9CCB585D4D0B99b", + "abi": [ + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "provider", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256[]", + "name": "tokenAmounts", + "type": "uint256[]" + }, + { + "indexed": false, + "internalType": "uint256[]", + "name": "fees", + "type": "uint256[]" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "invariant", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "lpTokenSupply", + "type": "uint256" + } + ], + "name": "AddLiquidity", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "receiver", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint8", + "name": "tokenIndex", + "type": "uint8" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amountFee", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "protocolFee", + "type": "uint256" + } + ], + "name": "FlashLoan", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "newAdminFee", + "type": "uint256" + } + ], + "name": "NewAdminFee", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "newSwapFee", + "type": "uint256" + } + ], + "name": "NewSwapFee", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "previousOwner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "OwnershipTransferred", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "Paused", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "oldA", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newA", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "initialTime", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "futureTime", + "type": "uint256" + } + ], + "name": "RampA", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "provider", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256[]", + "name": "tokenAmounts", + "type": "uint256[]" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "lpTokenSupply", + "type": "uint256" + } + ], + "name": "RemoveLiquidity", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "provider", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256[]", + "name": "tokenAmounts", + "type": "uint256[]" + }, + { + "indexed": false, + "internalType": "uint256[]", + "name": "fees", + "type": "uint256[]" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "invariant", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "lpTokenSupply", + "type": "uint256" + } + ], + "name": "RemoveLiquidityImbalance", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "provider", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "lpTokenAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "lpTokenSupply", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "boughtId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "tokensBought", + "type": "uint256" + } + ], + "name": "RemoveLiquidityOne", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "currentA", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "time", + "type": "uint256" + } + ], + "name": "StopRampA", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "buyer", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "tokensSold", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "tokensBought", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint128", + "name": "soldId", + "type": "uint128" + }, + { + "indexed": false, + "internalType": "uint128", + "name": "boughtId", + "type": "uint128" + } + ], + "name": "TokenSwap", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "Unpaused", + "type": "event" + }, + { + "inputs": [], + "name": "MAX_BPS", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256[]", + "name": "amounts", + "type": "uint256[]" + }, + { + "internalType": "uint256", + "name": "minToMint", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" + } + ], + "name": "addLiquidity", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "calculateRemoveLiquidity", + "outputs": [ + { + "internalType": "uint256[]", + "name": "", + "type": "uint256[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "tokenAmount", + "type": "uint256" + }, + { + "internalType": "uint8", + "name": "tokenIndex", + "type": "uint8" + } + ], + "name": "calculateRemoveLiquidityOneToken", + "outputs": [ + { + "internalType": "uint256", + "name": "availableTokenAmount", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint8", + "name": "tokenIndexFrom", + "type": "uint8" + }, + { + "internalType": "uint8", + "name": "tokenIndexTo", + "type": "uint8" + }, + { + "internalType": "uint256", + "name": "dx", + "type": "uint256" + } + ], + "name": "calculateSwap", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256[]", + "name": "amounts", + "type": "uint256[]" + }, + { + "internalType": "bool", + "name": "deposit", + "type": "bool" + } + ], + "name": "calculateTokenAmount", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "receiver", + "type": "address" + }, + { + "internalType": "contract IERC20", + "name": "token", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "params", + "type": "bytes" + } + ], + "name": "flashLoan", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "flashLoanFeeBPS", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getA", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getAPrecise", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "index", + "type": "uint256" + } + ], + "name": "getAdminBalance", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint8", + "name": "index", + "type": "uint8" + } + ], + "name": "getToken", + "outputs": [ + { + "internalType": "contract IERC20", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint8", + "name": "index", + "type": "uint8" + } + ], + "name": "getTokenBalance", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "tokenAddress", + "type": "address" + } + ], + "name": "getTokenIndex", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getVirtualPrice", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract IERC20[]", + "name": "_pooledTokens", + "type": "address[]" + }, + { + "internalType": "uint8[]", + "name": "decimals", + "type": "uint8[]" + }, + { + "internalType": "string", + "name": "lpTokenName", + "type": "string" + }, + { + "internalType": "string", + "name": "lpTokenSymbol", + "type": "string" + }, + { + "internalType": "uint256", + "name": "_a", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_fee", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_adminFee", + "type": "uint256" + }, + { + "internalType": "address", + "name": "lpTokenTargetAddress", + "type": "address" + } + ], + "name": "initialize", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "pause", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "paused", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "protocolFeeShareBPS", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "futureA", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "futureTime", + "type": "uint256" + } + ], + "name": "rampA", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "internalType": "uint256[]", + "name": "minAmounts", + "type": "uint256[]" + }, + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" + } + ], + "name": "removeLiquidity", + "outputs": [ + { + "internalType": "uint256[]", + "name": "", + "type": "uint256[]" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256[]", + "name": "amounts", + "type": "uint256[]" + }, + { + "internalType": "uint256", + "name": "maxBurnAmount", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" + } + ], + "name": "removeLiquidityImbalance", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "tokenAmount", + "type": "uint256" + }, + { + "internalType": "uint8", + "name": "tokenIndex", + "type": "uint8" + }, + { + "internalType": "uint256", + "name": "minAmount", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" + } + ], + "name": "removeLiquidityOneToken", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "renounceOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "newAdminFee", + "type": "uint256" + } + ], + "name": "setAdminFee", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "newFlashLoanFeeBPS", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "newProtocolFeeShareBPS", + "type": "uint256" + } + ], + "name": "setFlashLoanFees", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "newSwapFee", + "type": "uint256" + } + ], + "name": "setSwapFee", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "stopRampA", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint8", + "name": "tokenIndexFrom", + "type": "uint8" + }, + { + "internalType": "uint8", + "name": "tokenIndexTo", + "type": "uint8" + }, + { + "internalType": "uint256", + "name": "dx", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "minDy", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" + } + ], + "name": "swap", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "swapStorage", + "outputs": [ + { + "internalType": "uint256", + "name": "initialA", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "futureA", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "initialATime", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "futureATime", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "swapFee", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "adminFee", + "type": "uint256" + }, + { + "internalType": "contract LPToken", + "name": "lpToken", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "unpause", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "withdrawAdminFees", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } + ] +} \ No newline at end of file diff --git a/deployments/cronos/solcInputs/4d8253a299fa09b105ed2b87dd0189d4.json b/deployments/cronos/solcInputs/4d8253a299fa09b105ed2b87dd0189d4.json new file mode 100644 index 000000000..98ef3113c --- /dev/null +++ b/deployments/cronos/solcInputs/4d8253a299fa09b105ed2b87dd0189d4.json @@ -0,0 +1,304 @@ +{ + "language": "Solidity", + "sources": { + "contracts/amm/AaveSwap.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.6.12;\n\nimport \"./Swap.sol\";\n\n/**\n * @title AaveSwap - A StableSwap implementation in solidity, integrated with Aave.\n * @notice This contract is responsible for custody of closely pegged assets (eg. group of stablecoins)\n * and automatic market making system. Users become an LP (Liquidity Provider) by depositing their tokens\n * in desired ratios for an exchange of the pool token that represents their share of the pool.\n * Users can burn pool tokens and withdraw their share of token(s).\n *\n * Each time a swap between the pooled tokens happens, a set fee incurs which effectively gets\n * distributed to the LPs.\n *\n * In case of emergencies, admin can pause additional deposits, swaps, or single-asset withdraws - which\n * stops the ratio of the tokens in the pool from changing.\n * Users can always withdraw their tokens via multi-asset withdraws.\n *\n * @dev Most of the logic is stored as a library `SwapUtils` for the sake of reducing contract's\n * deployment size.\n */\n\ncontract AaveSwap is Swap {\n address internal AAVE_REWARDS;\n address internal AAVE_LENDING_POOL;\n address internal REWARD_TOKEN;\n address internal REWARD_RECEIVER;\n address[] internal AAVE_ASSETS;\n\n /**\n * @notice Initializes this Swap contract with the given parameters.\n * This will also clone a LPToken contract that represents users'\n * LP positions. The owner of LPToken will be this contract - which means\n * only this contract is allowed to mint/burn tokens.\n *\n * @param _pooledTokens an array of ERC20s this pool will accept\n * @param decimals the decimals to use for each pooled token,\n * eg 8 for WBTC. Cannot be larger than POOL_PRECISION_DECIMALS\n * @param lpTokenName the long-form name of the token to be deployed\n * @param lpTokenSymbol the short symbol for the token to be deployed\n * @param _a the amplification coefficient * n * (n - 1). See the\n * StableSwap paper for details\n * @param _fee default swap fee to be initialized with\n * @param _adminFee default adminFee to be initialized with\n * @param lpTokenTargetAddress the address of an existing LPToken contract to use as a target\n */\n function initialize(\n IERC20[] memory _pooledTokens,\n uint8[] memory decimals,\n string memory lpTokenName,\n string memory lpTokenSymbol,\n uint256 _a,\n uint256 _fee,\n uint256 _adminFee,\n address lpTokenTargetAddress\n ) public virtual override initializer {\n Swap.initialize(\n _pooledTokens,\n decimals,\n lpTokenName,\n lpTokenSymbol,\n _a,\n _fee,\n _adminFee,\n lpTokenTargetAddress\n );\n AAVE_REWARDS = 0x01D83Fe6A10D2f2B7AF17034343746188272cAc9;\n AAVE_LENDING_POOL = 0x4F01AeD16D97E3aB5ab2B501154DC9bb0F1A5A2C;\n REWARD_TOKEN = 0xB31f66AA3C1e785363F0875A1B74E27b85FD66c7;\n AAVE_ASSETS = [0x53f7c5869a859F0AeC3D334ee8B4Cf01E3492f21];\n REWARD_RECEIVER = msg.sender;\n }\n\n function setRewardReceiver(address _reward_receiver) external onlyOwner {\n REWARD_RECEIVER = _reward_receiver;\n }\n\n function claimAaveRewards() external {\n AAVE_REWARDS.call(\n abi.encodeWithSignature(\n \"claimRewards(address[],uint256,address)\",\n AAVE_ASSETS,\n type(uint256).max,\n REWARD_RECEIVER\n )\n );\n }\n}\n" + }, + "contracts/amm/Swap.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.6.12;\n\nimport \"@openzeppelin/contracts/math/SafeMath.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/SafeERC20.sol\";\nimport \"@openzeppelin/contracts/proxy/Clones.sol\";\nimport \"@openzeppelin/contracts-upgradeable/utils/ReentrancyGuardUpgradeable.sol\";\nimport \"./OwnerPausableUpgradeable.sol\";\nimport \"./SwapUtils.sol\";\nimport \"./AmplificationUtils.sol\";\n\n/**\n * @title Swap - A StableSwap implementation in solidity.\n * @notice This contract is responsible for custody of closely pegged assets (eg. group of stablecoins)\n * and automatic market making system. Users become an LP (Liquidity Provider) by depositing their tokens\n * in desired ratios for an exchange of the pool token that represents their share of the pool.\n * Users can burn pool tokens and withdraw their share of token(s).\n *\n * Each time a swap between the pooled tokens happens, a set fee incurs which effectively gets\n * distributed to the LPs.\n *\n * In case of emergencies, admin can pause additional deposits, swaps, or single-asset withdraws - which\n * stops the ratio of the tokens in the pool from changing.\n * Users can always withdraw their tokens via multi-asset withdraws.\n *\n * @dev Most of the logic is stored as a library `SwapUtils` for the sake of reducing contract's\n * deployment size.\n */\ncontract Swap is OwnerPausableUpgradeable, ReentrancyGuardUpgradeable {\n using SafeERC20 for IERC20;\n using SafeMath for uint256;\n using SwapUtils for SwapUtils.Swap;\n using AmplificationUtils for SwapUtils.Swap;\n\n // Struct storing data responsible for automatic market maker functionalities. In order to\n // access this data, this contract uses SwapUtils library. For more details, see SwapUtils.sol\n SwapUtils.Swap public swapStorage;\n\n // Maps token address to an index in the pool. Used to prevent duplicate tokens in the pool.\n // getTokenIndex function also relies on this mapping to retrieve token index.\n mapping(address => uint8) private tokenIndexes;\n\n /*** EVENTS ***/\n\n // events replicated from SwapUtils to make the ABI easier for dumb\n // clients\n event TokenSwap(\n address indexed buyer,\n uint256 tokensSold,\n uint256 tokensBought,\n uint128 soldId,\n uint128 boughtId\n );\n event AddLiquidity(\n address indexed provider,\n uint256[] tokenAmounts,\n uint256[] fees,\n uint256 invariant,\n uint256 lpTokenSupply\n );\n event RemoveLiquidity(\n address indexed provider,\n uint256[] tokenAmounts,\n uint256 lpTokenSupply\n );\n event RemoveLiquidityOne(\n address indexed provider,\n uint256 lpTokenAmount,\n uint256 lpTokenSupply,\n uint256 boughtId,\n uint256 tokensBought\n );\n event RemoveLiquidityImbalance(\n address indexed provider,\n uint256[] tokenAmounts,\n uint256[] fees,\n uint256 invariant,\n uint256 lpTokenSupply\n );\n event NewAdminFee(uint256 newAdminFee);\n event NewSwapFee(uint256 newSwapFee);\n event RampA(\n uint256 oldA,\n uint256 newA,\n uint256 initialTime,\n uint256 futureTime\n );\n event StopRampA(uint256 currentA, uint256 time);\n\n /**\n * @notice Initializes this Swap contract with the given parameters.\n * This will also clone a LPToken contract that represents users'\n * LP positions. The owner of LPToken will be this contract - which means\n * only this contract is allowed to mint/burn tokens.\n *\n * @param _pooledTokens an array of ERC20s this pool will accept\n * @param decimals the decimals to use for each pooled token,\n * eg 8 for WBTC. Cannot be larger than POOL_PRECISION_DECIMALS\n * @param lpTokenName the long-form name of the token to be deployed\n * @param lpTokenSymbol the short symbol for the token to be deployed\n * @param _a the amplification coefficient * n * (n - 1). See the\n * StableSwap paper for details\n * @param _fee default swap fee to be initialized with\n * @param _adminFee default adminFee to be initialized with\n * @param lpTokenTargetAddress the address of an existing LPToken contract to use as a target\n */\n function initialize(\n IERC20[] memory _pooledTokens,\n uint8[] memory decimals,\n string memory lpTokenName,\n string memory lpTokenSymbol,\n uint256 _a,\n uint256 _fee,\n uint256 _adminFee,\n address lpTokenTargetAddress\n ) public virtual initializer {\n __OwnerPausable_init();\n __ReentrancyGuard_init();\n // Check _pooledTokens and precisions parameter\n require(_pooledTokens.length > 1, \"_pooledTokens.length <= 1\");\n require(_pooledTokens.length <= 32, \"_pooledTokens.length > 32\");\n require(\n _pooledTokens.length == decimals.length,\n \"_pooledTokens decimals mismatch\"\n );\n\n uint256[] memory precisionMultipliers = new uint256[](decimals.length);\n\n for (uint8 i = 0; i < _pooledTokens.length; i++) {\n if (i > 0) {\n // Check if index is already used. Check if 0th element is a duplicate.\n require(\n tokenIndexes[address(_pooledTokens[i])] == 0 &&\n _pooledTokens[0] != _pooledTokens[i],\n \"Duplicate tokens\"\n );\n }\n require(\n address(_pooledTokens[i]) != address(0),\n \"The 0 address isn't an ERC-20\"\n );\n require(\n decimals[i] <= SwapUtils.POOL_PRECISION_DECIMALS,\n \"Token decimals exceeds max\"\n );\n precisionMultipliers[i] =\n 10 **\n uint256(SwapUtils.POOL_PRECISION_DECIMALS).sub(\n uint256(decimals[i])\n );\n tokenIndexes[address(_pooledTokens[i])] = i;\n }\n\n // Check _a, _fee, _adminFee parameters\n require(_a < AmplificationUtils.MAX_A, \"_a exceeds maximum\");\n require(_fee < SwapUtils.MAX_SWAP_FEE, \"_fee exceeds maximum\");\n require(\n _adminFee < SwapUtils.MAX_ADMIN_FEE,\n \"_adminFee exceeds maximum\"\n );\n\n // Clone and initialize a LPToken contract\n LPToken lpToken = LPToken(Clones.clone(lpTokenTargetAddress));\n require(\n lpToken.initialize(lpTokenName, lpTokenSymbol),\n \"could not init lpToken clone\"\n );\n\n // Initialize swapStorage struct\n swapStorage.lpToken = lpToken;\n swapStorage.pooledTokens = _pooledTokens;\n swapStorage.tokenPrecisionMultipliers = precisionMultipliers;\n swapStorage.balances = new uint256[](_pooledTokens.length);\n swapStorage.initialA = _a.mul(AmplificationUtils.A_PRECISION);\n swapStorage.futureA = _a.mul(AmplificationUtils.A_PRECISION);\n // swapStorage.initialATime = 0;\n // swapStorage.futureATime = 0;\n swapStorage.swapFee = _fee;\n swapStorage.adminFee = _adminFee;\n }\n\n /*** MODIFIERS ***/\n\n /**\n * @notice Modifier to check deadline against current timestamp\n * @param deadline latest timestamp to accept this transaction\n */\n modifier deadlineCheck(uint256 deadline) {\n require(block.timestamp <= deadline, \"Deadline not met\");\n _;\n }\n\n /*** VIEW FUNCTIONS ***/\n\n /**\n * @notice Return A, the amplification coefficient * n * (n - 1)\n * @dev See the StableSwap paper for details\n * @return A parameter\n */\n function getA() external view virtual returns (uint256) {\n return swapStorage.getA();\n }\n\n /**\n * @notice Return A in its raw precision form\n * @dev See the StableSwap paper for details\n * @return A parameter in its raw precision form\n */\n function getAPrecise() external view virtual returns (uint256) {\n return swapStorage.getAPrecise();\n }\n\n /**\n * @notice Return address of the pooled token at given index. Reverts if tokenIndex is out of range.\n * @param index the index of the token\n * @return address of the token at given index\n */\n function getToken(uint8 index) public view virtual returns (IERC20) {\n require(index < swapStorage.pooledTokens.length, \"Out of range\");\n return swapStorage.pooledTokens[index];\n }\n\n /**\n * @notice Return the index of the given token address. Reverts if no matching\n * token is found.\n * @param tokenAddress address of the token\n * @return the index of the given token address\n */\n function getTokenIndex(address tokenAddress)\n public\n view\n virtual\n returns (uint8)\n {\n uint8 index = tokenIndexes[tokenAddress];\n require(\n address(getToken(index)) == tokenAddress,\n \"Token does not exist\"\n );\n return index;\n }\n\n /**\n * @notice Return current balance of the pooled token at given index\n * @param index the index of the token\n * @return current balance of the pooled token at given index with token's native precision\n */\n function getTokenBalance(uint8 index)\n external\n view\n virtual\n returns (uint256)\n {\n require(index < swapStorage.pooledTokens.length, \"Index out of range\");\n return swapStorage.balances[index];\n }\n\n /**\n * @notice Get the virtual price, to help calculate profit\n * @return the virtual price, scaled to the POOL_PRECISION_DECIMALS\n */\n function getVirtualPrice() external view virtual returns (uint256) {\n return swapStorage.getVirtualPrice();\n }\n\n /**\n * @notice Calculate amount of tokens you receive on swap\n * @param tokenIndexFrom the token the user wants to sell\n * @param tokenIndexTo the token the user wants to buy\n * @param dx the amount of tokens the user wants to sell. If the token charges\n * a fee on transfers, use the amount that gets transferred after the fee.\n * @return amount of tokens the user will receive\n */\n function calculateSwap(\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx\n ) external view virtual returns (uint256) {\n return swapStorage.calculateSwap(tokenIndexFrom, tokenIndexTo, dx);\n }\n\n /**\n * @notice A simple method to calculate prices from deposits or\n * withdrawals, excluding fees but including slippage. This is\n * helpful as an input into the various \"min\" parameters on calls\n * to fight front-running\n *\n * @dev This shouldn't be used outside frontends for user estimates.\n *\n * @param amounts an array of token amounts to deposit or withdrawal,\n * corresponding to pooledTokens. The amount should be in each\n * pooled token's native precision. If a token charges a fee on transfers,\n * use the amount that gets transferred after the fee.\n * @param deposit whether this is a deposit or a withdrawal\n * @return token amount the user will receive\n */\n function calculateTokenAmount(uint256[] calldata amounts, bool deposit)\n external\n view\n virtual\n returns (uint256)\n {\n return swapStorage.calculateTokenAmount(amounts, deposit);\n }\n\n /**\n * @notice A simple method to calculate amount of each underlying\n * tokens that is returned upon burning given amount of LP tokens\n * @param amount the amount of LP tokens that would be burned on withdrawal\n * @return array of token balances that the user will receive\n */\n function calculateRemoveLiquidity(uint256 amount)\n external\n view\n virtual\n returns (uint256[] memory)\n {\n return swapStorage.calculateRemoveLiquidity(amount);\n }\n\n /**\n * @notice Calculate the amount of underlying token available to withdraw\n * when withdrawing via only single token\n * @param tokenAmount the amount of LP token to burn\n * @param tokenIndex index of which token will be withdrawn\n * @return availableTokenAmount calculated amount of underlying token\n * available to withdraw\n */\n function calculateRemoveLiquidityOneToken(\n uint256 tokenAmount,\n uint8 tokenIndex\n ) external view virtual returns (uint256 availableTokenAmount) {\n return swapStorage.calculateWithdrawOneToken(tokenAmount, tokenIndex);\n }\n\n /**\n * @notice This function reads the accumulated amount of admin fees of the token with given index\n * @param index Index of the pooled token\n * @return admin's token balance in the token's precision\n */\n function getAdminBalance(uint256 index)\n external\n view\n virtual\n returns (uint256)\n {\n return swapStorage.getAdminBalance(index);\n }\n\n /*** STATE MODIFYING FUNCTIONS ***/\n\n /**\n * @notice Swap two tokens using this pool\n * @param tokenIndexFrom the token the user wants to swap from\n * @param tokenIndexTo the token the user wants to swap to\n * @param dx the amount of tokens the user wants to swap from\n * @param minDy the min amount the user would like to receive, or revert.\n * @param deadline latest timestamp to accept this transaction\n */\n function swap(\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx,\n uint256 minDy,\n uint256 deadline\n )\n external\n virtual\n nonReentrant\n whenNotPaused\n deadlineCheck(deadline)\n returns (uint256)\n {\n return swapStorage.swap(tokenIndexFrom, tokenIndexTo, dx, minDy);\n }\n\n /**\n * @notice Add liquidity to the pool with the given amounts of tokens\n * @param amounts the amounts of each token to add, in their native precision\n * @param minToMint the minimum LP tokens adding this amount of liquidity\n * should mint, otherwise revert. Handy for front-running mitigation\n * @param deadline latest timestamp to accept this transaction\n * @return amount of LP token user minted and received\n */\n function addLiquidity(\n uint256[] calldata amounts,\n uint256 minToMint,\n uint256 deadline\n )\n external\n virtual\n nonReentrant\n whenNotPaused\n deadlineCheck(deadline)\n returns (uint256)\n {\n return swapStorage.addLiquidity(amounts, minToMint);\n }\n\n /**\n * @notice Burn LP tokens to remove liquidity from the pool. Withdraw fee that decays linearly\n * over period of 4 weeks since last deposit will apply.\n * @dev Liquidity can always be removed, even when the pool is paused.\n * @param amount the amount of LP tokens to burn\n * @param minAmounts the minimum amounts of each token in the pool\n * acceptable for this burn. Useful as a front-running mitigation\n * @param deadline latest timestamp to accept this transaction\n * @return amounts of tokens user received\n */\n function removeLiquidity(\n uint256 amount,\n uint256[] calldata minAmounts,\n uint256 deadline\n )\n external\n virtual\n nonReentrant\n deadlineCheck(deadline)\n returns (uint256[] memory)\n {\n return swapStorage.removeLiquidity(amount, minAmounts);\n }\n\n /**\n * @notice Remove liquidity from the pool all in one token. Withdraw fee that decays linearly\n * over period of 4 weeks since last deposit will apply.\n * @param tokenAmount the amount of the token you want to receive\n * @param tokenIndex the index of the token you want to receive\n * @param minAmount the minimum amount to withdraw, otherwise revert\n * @param deadline latest timestamp to accept this transaction\n * @return amount of chosen token user received\n */\n function removeLiquidityOneToken(\n uint256 tokenAmount,\n uint8 tokenIndex,\n uint256 minAmount,\n uint256 deadline\n )\n external\n virtual\n nonReentrant\n whenNotPaused\n deadlineCheck(deadline)\n returns (uint256)\n {\n return\n swapStorage.removeLiquidityOneToken(\n tokenAmount,\n tokenIndex,\n minAmount\n );\n }\n\n /**\n * @notice Remove liquidity from the pool, weighted differently than the\n * pool's current balances. Withdraw fee that decays linearly\n * over period of 4 weeks since last deposit will apply.\n * @param amounts how much of each token to withdraw\n * @param maxBurnAmount the max LP token provider is willing to pay to\n * remove liquidity. Useful as a front-running mitigation.\n * @param deadline latest timestamp to accept this transaction\n * @return amount of LP tokens burned\n */\n function removeLiquidityImbalance(\n uint256[] calldata amounts,\n uint256 maxBurnAmount,\n uint256 deadline\n )\n external\n virtual\n nonReentrant\n whenNotPaused\n deadlineCheck(deadline)\n returns (uint256)\n {\n return swapStorage.removeLiquidityImbalance(amounts, maxBurnAmount);\n }\n\n /*** ADMIN FUNCTIONS ***/\n\n /**\n * @notice Withdraw all admin fees to the contract owner\n */\n function withdrawAdminFees() external onlyOwner {\n swapStorage.withdrawAdminFees(owner());\n }\n\n /**\n * @notice Update the admin fee. Admin fee takes portion of the swap fee.\n * @param newAdminFee new admin fee to be applied on future transactions\n */\n function setAdminFee(uint256 newAdminFee) external onlyOwner {\n swapStorage.setAdminFee(newAdminFee);\n }\n\n /**\n * @notice Update the swap fee to be applied on swaps\n * @param newSwapFee new swap fee to be applied on future transactions\n */\n function setSwapFee(uint256 newSwapFee) external onlyOwner {\n swapStorage.setSwapFee(newSwapFee);\n }\n\n /**\n * @notice Start ramping up or down A parameter towards given futureA and futureTime\n * Checks if the change is too rapid, and commits the new A value only when it falls under\n * the limit range.\n * @param futureA the new A to ramp towards\n * @param futureTime timestamp when the new A should be reached\n */\n function rampA(uint256 futureA, uint256 futureTime) external onlyOwner {\n swapStorage.rampA(futureA, futureTime);\n }\n\n /**\n * @notice Stop ramping A immediately. Reverts if ramp A is already stopped.\n */\n function stopRampA() external onlyOwner {\n swapStorage.stopRampA();\n }\n}\n" + }, + "@openzeppelin/contracts/math/SafeMath.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <0.8.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" + }, + "@openzeppelin/contracts/token/ERC20/SafeERC20.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <0.8.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" + }, + "@openzeppelin/contracts/proxy/Clones.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <0.8.0;\n\n/**\n * @dev https://eips.ethereum.org/EIPS/eip-1167[EIP 1167] is a standard for\n * deploying minimal proxy contracts, also known as \"clones\".\n *\n * > To simply and cheaply clone contract functionality in an immutable way, this standard specifies\n * > a minimal bytecode implementation that delegates all calls to a known, fixed address.\n *\n * The library includes functions to deploy a proxy using either `create` (traditional deployment) or `create2`\n * (salted deterministic deployment). It also includes functions to predict the addresses of clones deployed using the\n * deterministic method.\n *\n * _Available since v3.4._\n */\nlibrary Clones {\n /**\n * @dev Deploys and returns the address of a clone that mimics the behaviour of `master`.\n *\n * This function uses the create opcode, which should never revert.\n */\n function clone(address master) internal returns (address instance) {\n // solhint-disable-next-line no-inline-assembly\n assembly {\n let ptr := mload(0x40)\n mstore(ptr, 0x3d602d80600a3d3981f3363d3d373d3d3d363d73000000000000000000000000)\n mstore(add(ptr, 0x14), shl(0x60, master))\n mstore(add(ptr, 0x28), 0x5af43d82803e903d91602b57fd5bf30000000000000000000000000000000000)\n instance := create(0, ptr, 0x37)\n }\n require(instance != address(0), \"ERC1167: create failed\");\n }\n\n /**\n * @dev Deploys and returns the address of a clone that mimics the behaviour of `master`.\n *\n * This function uses the create2 opcode and a `salt` to deterministically deploy\n * the clone. Using the same `master` and `salt` multiple time will revert, since\n * the clones cannot be deployed twice at the same address.\n */\n function cloneDeterministic(address master, bytes32 salt) internal returns (address instance) {\n // solhint-disable-next-line no-inline-assembly\n assembly {\n let ptr := mload(0x40)\n mstore(ptr, 0x3d602d80600a3d3981f3363d3d373d3d3d363d73000000000000000000000000)\n mstore(add(ptr, 0x14), shl(0x60, master))\n mstore(add(ptr, 0x28), 0x5af43d82803e903d91602b57fd5bf30000000000000000000000000000000000)\n instance := create2(0, ptr, 0x37, salt)\n }\n require(instance != address(0), \"ERC1167: create2 failed\");\n }\n\n /**\n * @dev Computes the address of a clone deployed using {Clones-cloneDeterministic}.\n */\n function predictDeterministicAddress(address master, bytes32 salt, address deployer) internal pure returns (address predicted) {\n // solhint-disable-next-line no-inline-assembly\n assembly {\n let ptr := mload(0x40)\n mstore(ptr, 0x3d602d80600a3d3981f3363d3d373d3d3d363d73000000000000000000000000)\n mstore(add(ptr, 0x14), shl(0x60, master))\n mstore(add(ptr, 0x28), 0x5af43d82803e903d91602b57fd5bf3ff00000000000000000000000000000000)\n mstore(add(ptr, 0x38), shl(0x60, deployer))\n mstore(add(ptr, 0x4c), salt)\n mstore(add(ptr, 0x6c), keccak256(ptr, 0x37))\n predicted := keccak256(add(ptr, 0x37), 0x55)\n }\n }\n\n /**\n * @dev Computes the address of a clone deployed using {Clones-cloneDeterministic}.\n */\n function predictDeterministicAddress(address master, bytes32 salt) internal view returns (address predicted) {\n return predictDeterministicAddress(master, salt, address(this));\n }\n}\n" + }, + "@openzeppelin/contracts-upgradeable/utils/ReentrancyGuardUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <0.8.0;\nimport \"../proxy/Initializable.sol\";\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 ReentrancyGuardUpgradeable is Initializable {\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 function __ReentrancyGuard_init() internal initializer {\n __ReentrancyGuard_init_unchained();\n }\n\n function __ReentrancyGuard_init_unchained() internal initializer {\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 uint256[49] private __gap;\n}\n" + }, + "contracts/amm/OwnerPausableUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.6.12;\n\nimport \"@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol\";\nimport \"@openzeppelin/contracts-upgradeable/utils/PausableUpgradeable.sol\";\n\n/**\n * @title OwnerPausable\n * @notice An ownable contract allows the owner to pause and unpause the\n * contract without a delay.\n * @dev Only methods using the provided modifiers will be paused.\n */\nabstract contract OwnerPausableUpgradeable is\n OwnableUpgradeable,\n PausableUpgradeable\n{\n function __OwnerPausable_init() internal initializer {\n __Context_init_unchained();\n __Ownable_init_unchained();\n __Pausable_init_unchained();\n }\n\n /**\n * @notice Pause the contract. Revert if already paused.\n */\n function pause() external onlyOwner {\n PausableUpgradeable._pause();\n }\n\n /**\n * @notice Unpause the contract. Revert if already unpaused.\n */\n function unpause() external onlyOwner {\n PausableUpgradeable._unpause();\n }\n}\n" + }, + "contracts/amm/SwapUtils.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.6.12;\n\nimport \"@openzeppelin/contracts/math/SafeMath.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/SafeERC20.sol\";\nimport \"./AmplificationUtils.sol\";\nimport \"./LPToken.sol\";\nimport \"./MathUtils.sol\";\n\n/**\n * @title SwapUtils library\n * @notice A library to be used within Swap.sol. Contains functions responsible for custody and AMM functionalities.\n * @dev Contracts relying on this library must initialize SwapUtils.Swap struct then use this library\n * for SwapUtils.Swap struct. Note that this library contains both functions called by users and admins.\n * Admin functions should be protected within contracts using this library.\n */\nlibrary SwapUtils {\n using SafeERC20 for IERC20;\n using SafeMath for uint256;\n using MathUtils for uint256;\n\n /*** EVENTS ***/\n\n event TokenSwap(\n address indexed buyer,\n uint256 tokensSold,\n uint256 tokensBought,\n uint128 soldId,\n uint128 boughtId\n );\n event AddLiquidity(\n address indexed provider,\n uint256[] tokenAmounts,\n uint256[] fees,\n uint256 invariant,\n uint256 lpTokenSupply\n );\n event RemoveLiquidity(\n address indexed provider,\n uint256[] tokenAmounts,\n uint256 lpTokenSupply\n );\n event RemoveLiquidityOne(\n address indexed provider,\n uint256 lpTokenAmount,\n uint256 lpTokenSupply,\n uint256 boughtId,\n uint256 tokensBought\n );\n event RemoveLiquidityImbalance(\n address indexed provider,\n uint256[] tokenAmounts,\n uint256[] fees,\n uint256 invariant,\n uint256 lpTokenSupply\n );\n event NewAdminFee(uint256 newAdminFee);\n event NewSwapFee(uint256 newSwapFee);\n\n struct Swap {\n // variables around the ramp management of A,\n // the amplification coefficient * n * (n - 1)\n // see https://www.curve.fi/stableswap-paper.pdf for details\n uint256 initialA;\n uint256 futureA;\n uint256 initialATime;\n uint256 futureATime;\n // fee calculation\n uint256 swapFee;\n uint256 adminFee;\n LPToken lpToken;\n // contract references for all tokens being pooled\n IERC20[] pooledTokens;\n // multipliers for each pooled token's precision to get to POOL_PRECISION_DECIMALS\n // for example, TBTC has 18 decimals, so the multiplier should be 1. WBTC\n // has 8, so the multiplier should be 10 ** 18 / 10 ** 8 => 10 ** 10\n uint256[] tokenPrecisionMultipliers;\n // the pool balance of each token, in the token's precision\n // the contract's actual token balance might differ\n uint256[] balances;\n }\n\n // Struct storing variables used in calculations in the\n // calculateWithdrawOneTokenDY function to avoid stack too deep errors\n struct CalculateWithdrawOneTokenDYInfo {\n uint256 d0;\n uint256 d1;\n uint256 newY;\n uint256 feePerToken;\n uint256 preciseA;\n }\n\n // Struct storing variables used in calculations in the\n // {add,remove}Liquidity functions to avoid stack too deep errors\n struct ManageLiquidityInfo {\n uint256 d0;\n uint256 d1;\n uint256 d2;\n uint256 preciseA;\n LPToken lpToken;\n uint256 totalSupply;\n uint256[] balances;\n uint256[] multipliers;\n }\n\n // the precision all pools tokens will be converted to\n uint8 public constant POOL_PRECISION_DECIMALS = 18;\n\n // the denominator used to calculate admin and LP fees. For example, an\n // LP fee might be something like tradeAmount.mul(fee).div(FEE_DENOMINATOR)\n uint256 private constant FEE_DENOMINATOR = 10**10;\n\n // Max swap fee is 1% or 100bps of each swap\n uint256 public constant MAX_SWAP_FEE = 10**8;\n\n // Max adminFee is 100% of the swapFee\n // adminFee does not add additional fee on top of swapFee\n // Instead it takes a certain % of the swapFee. Therefore it has no impact on the\n // users but only on the earnings of LPs\n uint256 public constant MAX_ADMIN_FEE = 10**10;\n\n // Constant value used as max loop limit\n uint256 private constant MAX_LOOP_LIMIT = 256;\n\n /*** VIEW & PURE FUNCTIONS ***/\n\n function _getAPrecise(Swap storage self) internal view returns (uint256) {\n return AmplificationUtils._getAPrecise(self);\n }\n\n /**\n * @notice Calculate the dy, the amount of selected token that user receives and\n * the fee of withdrawing in one token\n * @param tokenAmount the amount to withdraw in the pool's precision\n * @param tokenIndex which token will be withdrawn\n * @param self Swap struct to read from\n * @return the amount of token user will receive\n */\n function calculateWithdrawOneToken(\n Swap storage self,\n uint256 tokenAmount,\n uint8 tokenIndex\n ) external view returns (uint256) {\n (uint256 availableTokenAmount, ) = _calculateWithdrawOneToken(\n self,\n tokenAmount,\n tokenIndex,\n self.lpToken.totalSupply()\n );\n return availableTokenAmount;\n }\n\n function _calculateWithdrawOneToken(\n Swap storage self,\n uint256 tokenAmount,\n uint8 tokenIndex,\n uint256 totalSupply\n ) internal view returns (uint256, uint256) {\n uint256 dy;\n uint256 newY;\n uint256 currentY;\n\n (dy, newY, currentY) = calculateWithdrawOneTokenDY(\n self,\n tokenIndex,\n tokenAmount,\n totalSupply\n );\n\n // dy_0 (without fees)\n // dy, dy_0 - dy\n\n uint256 dySwapFee = currentY\n .sub(newY)\n .div(self.tokenPrecisionMultipliers[tokenIndex])\n .sub(dy);\n\n return (dy, dySwapFee);\n }\n\n /**\n * @notice Calculate the dy of withdrawing in one token\n * @param self Swap struct to read from\n * @param tokenIndex which token will be withdrawn\n * @param tokenAmount the amount to withdraw in the pools precision\n * @return the d and the new y after withdrawing one token\n */\n function calculateWithdrawOneTokenDY(\n Swap storage self,\n uint8 tokenIndex,\n uint256 tokenAmount,\n uint256 totalSupply\n )\n internal\n view\n returns (\n uint256,\n uint256,\n uint256\n )\n {\n // Get the current D, then solve the stableswap invariant\n // y_i for D - tokenAmount\n uint256[] memory xp = _xp(self);\n\n require(tokenIndex < xp.length, \"Token index out of range\");\n\n\n CalculateWithdrawOneTokenDYInfo memory v\n = CalculateWithdrawOneTokenDYInfo(0, 0, 0, 0, 0);\n v.preciseA = _getAPrecise(self);\n v.d0 = getD(xp, v.preciseA);\n v.d1 = v.d0.sub(tokenAmount.mul(v.d0).div(totalSupply));\n\n require(tokenAmount <= xp[tokenIndex], \"Withdraw exceeds available\");\n\n v.newY = getYD(v.preciseA, tokenIndex, xp, v.d1);\n\n uint256[] memory xpReduced = new uint256[](xp.length);\n\n v.feePerToken = _feePerToken(self.swapFee, xp.length);\n for (uint256 i = 0; i < xp.length; i++) {\n uint256 xpi = xp[i];\n // if i == tokenIndex, dxExpected = xp[i] * d1 / d0 - newY\n // else dxExpected = xp[i] - (xp[i] * d1 / d0)\n // xpReduced[i] -= dxExpected * fee / FEE_DENOMINATOR\n xpReduced[i] = xpi.sub(\n (\n (i == tokenIndex)\n ? xpi.mul(v.d1).div(v.d0).sub(v.newY)\n : xpi.sub(xpi.mul(v.d1).div(v.d0))\n )\n .mul(v.feePerToken)\n .div(FEE_DENOMINATOR)\n );\n }\n\n uint256 dy = xpReduced[tokenIndex].sub(\n getYD(v.preciseA, tokenIndex, xpReduced, v.d1)\n );\n dy = dy.sub(1).div(self.tokenPrecisionMultipliers[tokenIndex]);\n\n return (dy, v.newY, xp[tokenIndex]);\n }\n\n /**\n * @notice Calculate the price of a token in the pool with given\n * precision-adjusted balances and a particular D.\n *\n * @dev This is accomplished via solving the invariant iteratively.\n * See the StableSwap paper and Curve.fi implementation for further details.\n *\n * x_1**2 + x1 * (sum' - (A*n**n - 1) * D / (A * n**n)) = D ** (n + 1) / (n ** (2 * n) * prod' * A)\n * x_1**2 + b*x_1 = c\n * x_1 = (x_1**2 + c) / (2*x_1 + b)\n *\n * @param a the amplification coefficient * n * (n - 1). See the StableSwap paper for details.\n * @param tokenIndex Index of token we are calculating for.\n * @param xp a precision-adjusted set of pool balances. Array should be\n * the same cardinality as the pool.\n * @param d the stableswap invariant\n * @return the price of the token, in the same precision as in xp\n */\n function getYD(\n uint256 a,\n uint8 tokenIndex,\n uint256[] memory xp,\n uint256 d\n ) internal pure returns (uint256) {\n uint256 numTokens = xp.length;\n require(tokenIndex < numTokens, \"Token not found\");\n\n uint256 c = d;\n uint256 s;\n uint256 nA = a.mul(numTokens);\n\n for (uint256 i = 0; i < numTokens; i++) {\n if (i != tokenIndex) {\n s = s.add(xp[i]);\n c = c.mul(d).div(xp[i].mul(numTokens));\n // If we were to protect the division loss we would have to keep the denominator separate\n // and divide at the end. However this leads to overflow with large numTokens or/and D.\n // c = c * D * D * D * ... overflow!\n }\n }\n c = c.mul(d).mul(AmplificationUtils.A_PRECISION).div(nA.mul(numTokens));\n\n uint256 b = s.add(d.mul(AmplificationUtils.A_PRECISION).div(nA));\n uint256 yPrev;\n uint256 y = d;\n for (uint256 i = 0; i < MAX_LOOP_LIMIT; i++) {\n yPrev = y;\n y = y.mul(y).add(c).div(y.mul(2).add(b).sub(d));\n if (y.within1(yPrev)) {\n return y;\n }\n }\n revert(\"Approximation did not converge\");\n }\n\n /**\n * @notice Get D, the StableSwap invariant, based on a set of balances and a particular A.\n * @param xp a precision-adjusted set of pool balances. Array should be the same cardinality\n * as the pool.\n * @param a the amplification coefficient * n * (n - 1) in A_PRECISION.\n * See the StableSwap paper for details\n * @return the invariant, at the precision of the pool\n */\n function getD(uint256[] memory xp, uint256 a)\n internal\n pure\n returns (uint256)\n {\n uint256 numTokens = xp.length;\n uint256 s;\n for (uint256 i = 0; i < numTokens; i++) {\n s = s.add(xp[i]);\n }\n if (s == 0) {\n return 0;\n }\n\n uint256 prevD;\n uint256 d = s;\n uint256 nA = a.mul(numTokens);\n\n for (uint256 i = 0; i < MAX_LOOP_LIMIT; i++) {\n uint256 dP = d;\n for (uint256 j = 0; j < numTokens; j++) {\n dP = dP.mul(d).div(xp[j].mul(numTokens));\n // If we were to protect the division loss we would have to keep the denominator separate\n // and divide at the end. However this leads to overflow with large numTokens or/and D.\n // dP = dP * D * D * D * ... overflow!\n }\n prevD = d;\n d = nA\n .mul(s)\n .div(AmplificationUtils.A_PRECISION)\n .add(dP.mul(numTokens))\n .mul(d)\n .div(\n nA\n .sub(AmplificationUtils.A_PRECISION)\n .mul(d)\n .div(AmplificationUtils.A_PRECISION)\n .add(numTokens.add(1).mul(dP))\n );\n if (d.within1(prevD)) {\n return d;\n }\n }\n\n // Convergence should occur in 4 loops or less. If this is reached, there may be something wrong\n // with the pool. If this were to occur repeatedly, LPs should withdraw via `removeLiquidity()`\n // function which does not rely on D.\n revert(\"D does not converge\");\n }\n\n /**\n * @notice Given a set of balances and precision multipliers, return the\n * precision-adjusted balances.\n *\n * @param balances an array of token balances, in their native precisions.\n * These should generally correspond with pooled tokens.\n *\n * @param precisionMultipliers an array of multipliers, corresponding to\n * the amounts in the balances array. When multiplied together they\n * should yield amounts at the pool's precision.\n *\n * @return an array of amounts \"scaled\" to the pool's precision\n */\n function _xp(\n uint256[] memory balances,\n uint256[] memory precisionMultipliers\n ) internal pure returns (uint256[] memory) {\n uint256 numTokens = balances.length;\n require(\n numTokens == precisionMultipliers.length,\n \"Balances must match multipliers\"\n );\n uint256[] memory xp = new uint256[](numTokens);\n for (uint256 i = 0; i < numTokens; i++) {\n xp[i] = balances[i].mul(precisionMultipliers[i]);\n }\n return xp;\n }\n\n /**\n * @notice Return the precision-adjusted balances of all tokens in the pool\n * @param self Swap struct to read from\n * @return the pool balances \"scaled\" to the pool's precision, allowing\n * them to be more easily compared.\n */\n function _xp(Swap storage self) internal view returns (uint256[] memory) {\n return _xp(self.balances, self.tokenPrecisionMultipliers);\n }\n\n /**\n * @notice Get the virtual price, to help calculate profit\n * @param self Swap struct to read from\n * @return the virtual price, scaled to precision of POOL_PRECISION_DECIMALS\n */\n function getVirtualPrice(Swap storage self)\n external\n view\n returns (uint256)\n {\n uint256 d = getD(_xp(self), _getAPrecise(self));\n LPToken lpToken = self.lpToken;\n uint256 supply = lpToken.totalSupply();\n if (supply > 0) {\n return d.mul(10**uint256(POOL_PRECISION_DECIMALS)).div(supply);\n }\n return 0;\n }\n\n /**\n * @notice Calculate the new balances of the tokens given the indexes of the token\n * that is swapped from (FROM) and the token that is swapped to (TO).\n * This function is used as a helper function to calculate how much TO token\n * the user should receive on swap.\n *\n * @param preciseA precise form of amplification coefficient\n * @param tokenIndexFrom index of FROM token\n * @param tokenIndexTo index of TO token\n * @param x the new total amount of FROM token\n * @param xp balances of the tokens in the pool\n * @return the amount of TO token that should remain in the pool\n */\n function getY(\n uint256 preciseA,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 x,\n uint256[] memory xp\n ) internal pure returns (uint256) {\n uint256 numTokens = xp.length;\n require(\n tokenIndexFrom != tokenIndexTo,\n \"Can't compare token to itself\"\n );\n require(\n tokenIndexFrom < numTokens && tokenIndexTo < numTokens,\n \"Tokens must be in pool\"\n );\n\n uint256 d = getD(xp, preciseA);\n uint256 c = d;\n uint256 s;\n uint256 nA = numTokens.mul(preciseA);\n\n uint256 _x;\n for (uint256 i = 0; i < numTokens; i++) {\n if (i == tokenIndexFrom) {\n _x = x;\n } else if (i != tokenIndexTo) {\n _x = xp[i];\n } else {\n continue;\n }\n s = s.add(_x);\n c = c.mul(d).div(_x.mul(numTokens));\n // If we were to protect the division loss we would have to keep the denominator separate\n // and divide at the end. However this leads to overflow with large numTokens or/and D.\n // c = c * D * D * D * ... overflow!\n }\n c = c.mul(d).mul(AmplificationUtils.A_PRECISION).div(nA.mul(numTokens));\n uint256 b = s.add(d.mul(AmplificationUtils.A_PRECISION).div(nA));\n uint256 yPrev;\n uint256 y = d;\n\n // iterative approximation\n for (uint256 i = 0; i < MAX_LOOP_LIMIT; i++) {\n yPrev = y;\n y = y.mul(y).add(c).div(y.mul(2).add(b).sub(d));\n if (y.within1(yPrev)) {\n return y;\n }\n }\n revert(\"Approximation did not converge\");\n }\n\n /**\n * @notice Externally calculates a swap between two tokens.\n * @param self Swap struct to read from\n * @param tokenIndexFrom the token to sell\n * @param tokenIndexTo the token to buy\n * @param dx the number of tokens to sell. If the token charges a fee on transfers,\n * use the amount that gets transferred after the fee.\n * @return dy the number of tokens the user will get\n */\n function calculateSwap(\n Swap storage self,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx\n ) external view returns (uint256 dy) {\n (dy, ) = _calculateSwap(\n self,\n tokenIndexFrom,\n tokenIndexTo,\n dx,\n self.balances\n );\n }\n\n /**\n * @notice Internally calculates a swap between two tokens.\n *\n * @dev The caller is expected to transfer the actual amounts (dx and dy)\n * using the token contracts.\n *\n * @param self Swap struct to read from\n * @param tokenIndexFrom the token to sell\n * @param tokenIndexTo the token to buy\n * @param dx the number of tokens to sell. If the token charges a fee on transfers,\n * use the amount that gets transferred after the fee.\n * @return dy the number of tokens the user will get\n * @return dyFee the associated fee\n */\n function _calculateSwap(\n Swap storage self,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx,\n uint256[] memory balances\n ) internal view returns (uint256 dy, uint256 dyFee) {\n uint256[] memory multipliers = self.tokenPrecisionMultipliers;\n uint256[] memory xp = _xp(balances, multipliers);\n require(\n tokenIndexFrom < xp.length && tokenIndexTo < xp.length,\n \"Token index out of range\"\n );\n uint256 x = dx.mul(multipliers[tokenIndexFrom]).add(xp[tokenIndexFrom]);\n uint256 y = getY(\n _getAPrecise(self),\n tokenIndexFrom,\n tokenIndexTo,\n x,\n xp\n );\n dy = xp[tokenIndexTo].sub(y).sub(1);\n dyFee = dy.mul(self.swapFee).div(FEE_DENOMINATOR);\n dy = dy.sub(dyFee).div(multipliers[tokenIndexTo]);\n }\n\n /**\n * @notice A simple method to calculate amount of each underlying\n * tokens that is returned upon burning given amount of\n * LP tokens\n *\n * @param amount the amount of LP tokens that would to be burned on\n * withdrawal\n * @return array of amounts of tokens user will receive\n */\n function calculateRemoveLiquidity(Swap storage self, uint256 amount)\n external\n view\n returns (uint256[] memory)\n {\n return\n _calculateRemoveLiquidity(\n self.balances,\n amount,\n self.lpToken.totalSupply()\n );\n }\n\n function _calculateRemoveLiquidity(\n uint256[] memory balances,\n uint256 amount,\n uint256 totalSupply\n ) internal pure returns (uint256[] memory) {\n require(amount <= totalSupply, \"Cannot exceed total supply\");\n\n uint256[] memory amounts = new uint256[](balances.length);\n\n for (uint256 i = 0; i < balances.length; i++) {\n amounts[i] = balances[i].mul(amount).div(totalSupply);\n }\n return amounts;\n }\n\n /**\n * @notice A simple method to calculate prices from deposits or\n * withdrawals, excluding fees but including slippage. This is\n * helpful as an input into the various \"min\" parameters on calls\n * to fight front-running\n *\n * @dev This shouldn't be used outside frontends for user estimates.\n *\n * @param self Swap struct to read from\n * @param amounts an array of token amounts to deposit or withdrawal,\n * corresponding to pooledTokens. The amount should be in each\n * pooled token's native precision. If a token charges a fee on transfers,\n * use the amount that gets transferred after the fee.\n * @param deposit whether this is a deposit or a withdrawal\n * @return if deposit was true, total amount of lp token that will be minted and if\n * deposit was false, total amount of lp token that will be burned\n */\n function calculateTokenAmount(\n Swap storage self,\n uint256[] calldata amounts,\n bool deposit\n ) external view returns (uint256) {\n uint256 a = _getAPrecise(self);\n uint256[] memory balances = self.balances;\n uint256[] memory multipliers = self.tokenPrecisionMultipliers;\n\n uint256 d0 = getD(_xp(balances, multipliers), a);\n for (uint256 i = 0; i < balances.length; i++) {\n if (deposit) {\n balances[i] = balances[i].add(amounts[i]);\n } else {\n balances[i] = balances[i].sub(\n amounts[i],\n \"Cannot withdraw more than available\"\n );\n }\n }\n uint256 d1 = getD(_xp(balances, multipliers), a);\n uint256 totalSupply = self.lpToken.totalSupply();\n\n if (deposit) {\n return d1.sub(d0).mul(totalSupply).div(d0);\n } else {\n return d0.sub(d1).mul(totalSupply).div(d0);\n }\n }\n\n /**\n * @notice return accumulated amount of admin fees of the token with given index\n * @param self Swap struct to read from\n * @param index Index of the pooled token\n * @return admin balance in the token's precision\n */\n function getAdminBalance(Swap storage self, uint256 index)\n external\n view\n returns (uint256)\n {\n require(index < self.pooledTokens.length, \"Token index out of range\");\n return\n self.pooledTokens[index].balanceOf(address(this)).sub(\n self.balances[index]\n );\n }\n\n /**\n * @notice internal helper function to calculate fee per token multiplier used in\n * swap fee calculations\n * @param swapFee swap fee for the tokens\n * @param numTokens number of tokens pooled\n */\n function _feePerToken(uint256 swapFee, uint256 numTokens)\n internal\n pure\n returns (uint256)\n {\n return swapFee.mul(numTokens).div(numTokens.sub(1).mul(4));\n }\n\n /*** STATE MODIFYING FUNCTIONS ***/\n\n /**\n * @notice swap two tokens in the pool\n * @param self Swap struct to read from and write to\n * @param tokenIndexFrom the token the user wants to sell\n * @param tokenIndexTo the token the user wants to buy\n * @param dx the amount of tokens the user wants to sell\n * @param minDy the min amount the user would like to receive, or revert.\n * @return amount of token user received on swap\n */\n function swap(\n Swap storage self,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx,\n uint256 minDy\n ) external returns (uint256) {\n {\n IERC20 tokenFrom = self.pooledTokens[tokenIndexFrom];\n require(\n dx <= tokenFrom.balanceOf(msg.sender),\n \"Cannot swap more than you own\"\n );\n // Transfer tokens first to see if a fee was charged on transfer\n uint256 beforeBalance = tokenFrom.balanceOf(address(this));\n tokenFrom.safeTransferFrom(msg.sender, address(this), dx);\n\n // Use the actual transferred amount for AMM math\n dx = tokenFrom.balanceOf(address(this)).sub(beforeBalance);\n }\n\n uint256 dy;\n uint256 dyFee;\n uint256[] memory balances = self.balances;\n (dy, dyFee) = _calculateSwap(\n self,\n tokenIndexFrom,\n tokenIndexTo,\n dx,\n balances\n );\n require(dy >= minDy, \"Swap didn't result in min tokens\");\n\n uint256 dyAdminFee = dyFee.mul(self.adminFee).div(FEE_DENOMINATOR).div(\n self.tokenPrecisionMultipliers[tokenIndexTo]\n );\n\n self.balances[tokenIndexFrom] = balances[tokenIndexFrom].add(dx);\n self.balances[tokenIndexTo] = balances[tokenIndexTo].sub(dy).sub(\n dyAdminFee\n );\n\n self.pooledTokens[tokenIndexTo].safeTransfer(msg.sender, dy);\n\n emit TokenSwap(msg.sender, dx, dy, tokenIndexFrom, tokenIndexTo);\n\n return dy;\n }\n\n /**\n * @notice Add liquidity to the pool\n * @param self Swap struct to read from and write to\n * @param amounts the amounts of each token to add, in their native precision\n * @param minToMint the minimum LP tokens adding this amount of liquidity\n * should mint, otherwise revert. Handy for front-running mitigation\n * allowed addresses. If the pool is not in the guarded launch phase, this parameter will be ignored.\n * @return amount of LP token user received\n */\n function addLiquidity(\n Swap storage self,\n uint256[] memory amounts,\n uint256 minToMint\n ) external returns (uint256) {\n IERC20[] memory pooledTokens = self.pooledTokens;\n require(\n amounts.length == pooledTokens.length,\n \"Amounts must match pooled tokens\"\n );\n\n // current state\n ManageLiquidityInfo memory v = ManageLiquidityInfo(\n 0,\n 0,\n 0,\n _getAPrecise(self),\n self.lpToken,\n 0,\n self.balances,\n self.tokenPrecisionMultipliers\n );\n v.totalSupply = v.lpToken.totalSupply();\n\n if (v.totalSupply != 0) {\n v.d0 = getD(_xp(v.balances, v.multipliers), v.preciseA);\n }\n\n uint256[] memory newBalances = new uint256[](pooledTokens.length);\n\n for (uint256 i = 0; i < pooledTokens.length; i++) {\n require(\n v.totalSupply != 0 || amounts[i] > 0,\n \"Must supply all tokens in pool\"\n );\n\n // Transfer tokens first to see if a fee was charged on transfer\n if (amounts[i] != 0) {\n uint256 beforeBalance = pooledTokens[i].balanceOf(\n address(this)\n );\n pooledTokens[i].safeTransferFrom(\n msg.sender,\n address(this),\n amounts[i]\n );\n\n // Update the amounts[] with actual transfer amount\n amounts[i] = pooledTokens[i].balanceOf(address(this)).sub(\n beforeBalance\n );\n }\n\n newBalances[i] = v.balances[i].add(amounts[i]);\n }\n\n // invariant after change\n v.d1 = getD(_xp(newBalances, v.multipliers), v.preciseA);\n require(v.d1 > v.d0, \"D should increase\");\n\n // updated to reflect fees and calculate the user's LP tokens\n v.d2 = v.d1;\n uint256[] memory fees = new uint256[](pooledTokens.length);\n\n if (v.totalSupply != 0) {\n uint256 feePerToken = _feePerToken(\n self.swapFee,\n pooledTokens.length\n );\n for (uint256 i = 0; i < pooledTokens.length; i++) {\n uint256 idealBalance = v.d1.mul(v.balances[i]).div(v.d0);\n fees[i] = feePerToken\n .mul(idealBalance.difference(newBalances[i]))\n .div(FEE_DENOMINATOR);\n self.balances[i] = newBalances[i].sub(\n fees[i].mul(self.adminFee).div(FEE_DENOMINATOR)\n );\n newBalances[i] = newBalances[i].sub(fees[i]);\n }\n v.d2 = getD(_xp(newBalances, v.multipliers), v.preciseA);\n } else {\n // the initial depositor doesn't pay fees\n self.balances = newBalances;\n }\n\n uint256 toMint;\n if (v.totalSupply == 0) {\n toMint = v.d1;\n } else {\n toMint = v.d2.sub(v.d0).mul(v.totalSupply).div(v.d0);\n }\n\n require(toMint >= minToMint, \"Couldn't mint min requested\");\n\n // mint the user's LP tokens\n v.lpToken.mint(msg.sender, toMint);\n\n emit AddLiquidity(\n msg.sender,\n amounts,\n fees,\n v.d1,\n v.totalSupply.add(toMint)\n );\n\n return toMint;\n }\n\n /**\n * @notice Burn LP tokens to remove liquidity from the pool.\n * @dev Liquidity can always be removed, even when the pool is paused.\n * @param self Swap struct to read from and write to\n * @param amount the amount of LP tokens to burn\n * @param minAmounts the minimum amounts of each token in the pool\n * acceptable for this burn. Useful as a front-running mitigation\n * @return amounts of tokens the user received\n */\n function removeLiquidity(\n Swap storage self,\n uint256 amount,\n uint256[] calldata minAmounts\n ) external returns (uint256[] memory) {\n LPToken lpToken = self.lpToken;\n IERC20[] memory pooledTokens = self.pooledTokens;\n require(amount <= lpToken.balanceOf(msg.sender), \">LP.balanceOf\");\n require(\n minAmounts.length == pooledTokens.length,\n \"minAmounts must match poolTokens\"\n );\n\n uint256[] memory balances = self.balances;\n uint256 totalSupply = lpToken.totalSupply();\n\n uint256[] memory amounts = _calculateRemoveLiquidity(\n balances,\n amount,\n totalSupply\n );\n\n for (uint256 i = 0; i < amounts.length; i++) {\n require(amounts[i] >= minAmounts[i], \"amounts[i] < minAmounts[i]\");\n self.balances[i] = balances[i].sub(amounts[i]);\n pooledTokens[i].safeTransfer(msg.sender, amounts[i]);\n }\n\n lpToken.burnFrom(msg.sender, amount);\n\n emit RemoveLiquidity(msg.sender, amounts, totalSupply.sub(amount));\n\n return amounts;\n }\n\n /**\n * @notice Remove liquidity from the pool all in one token.\n * @param self Swap struct to read from and write to\n * @param tokenAmount the amount of the lp tokens to burn\n * @param tokenIndex the index of the token you want to receive\n * @param minAmount the minimum amount to withdraw, otherwise revert\n * @return amount chosen token that user received\n */\n function removeLiquidityOneToken(\n Swap storage self,\n uint256 tokenAmount,\n uint8 tokenIndex,\n uint256 minAmount\n ) external returns (uint256) {\n LPToken lpToken = self.lpToken;\n IERC20[] memory pooledTokens = self.pooledTokens;\n\n require(tokenAmount <= lpToken.balanceOf(msg.sender), \">LP.balanceOf\");\n require(tokenIndex < pooledTokens.length, \"Token not found\");\n\n uint256 totalSupply = lpToken.totalSupply();\n\n (uint256 dy, uint256 dyFee) = _calculateWithdrawOneToken(\n self,\n tokenAmount,\n tokenIndex,\n totalSupply\n );\n\n require(dy >= minAmount, \"dy < minAmount\");\n\n self.balances[tokenIndex] = self.balances[tokenIndex].sub(\n dy.add(dyFee.mul(self.adminFee).div(FEE_DENOMINATOR))\n );\n lpToken.burnFrom(msg.sender, tokenAmount);\n pooledTokens[tokenIndex].safeTransfer(msg.sender, dy);\n\n emit RemoveLiquidityOne(\n msg.sender,\n tokenAmount,\n totalSupply,\n tokenIndex,\n dy\n );\n\n return dy;\n }\n\n /**\n * @notice Remove liquidity from the pool, weighted differently than the\n * pool's current balances.\n *\n * @param self Swap struct to read from and write to\n * @param amounts how much of each token to withdraw\n * @param maxBurnAmount the max LP token provider is willing to pay to\n * remove liquidity. Useful as a front-running mitigation.\n * @return actual amount of LP tokens burned in the withdrawal\n */\n function removeLiquidityImbalance(\n Swap storage self,\n uint256[] memory amounts,\n uint256 maxBurnAmount\n ) public returns (uint256) {\n ManageLiquidityInfo memory v = ManageLiquidityInfo(\n 0,\n 0,\n 0,\n _getAPrecise(self),\n self.lpToken,\n 0,\n self.balances,\n self.tokenPrecisionMultipliers\n );\n v.totalSupply = v.lpToken.totalSupply();\n\n IERC20[] memory pooledTokens = self.pooledTokens;\n\n require(\n amounts.length == pooledTokens.length,\n \"Amounts should match pool tokens\"\n );\n\n require(\n maxBurnAmount <= v.lpToken.balanceOf(msg.sender) &&\n maxBurnAmount != 0,\n \">LP.balanceOf\"\n );\n\n uint256 feePerToken = _feePerToken(self.swapFee, pooledTokens.length);\n uint256[] memory fees = new uint256[](pooledTokens.length);\n {\n uint256[] memory balances1 = new uint256[](pooledTokens.length);\n v.d0 = getD(_xp(v.balances, v.multipliers), v.preciseA);\n for (uint256 i = 0; i < pooledTokens.length; i++) {\n balances1[i] = v.balances[i].sub(\n amounts[i],\n \"Cannot withdraw more than available\"\n );\n }\n v.d1 = getD(_xp(balances1, v.multipliers), v.preciseA);\n\n for (uint256 i = 0; i < pooledTokens.length; i++) {\n uint256 idealBalance = v.d1.mul(v.balances[i]).div(v.d0);\n uint256 difference = idealBalance.difference(balances1[i]);\n fees[i] = feePerToken.mul(difference).div(FEE_DENOMINATOR);\n self.balances[i] = balances1[i].sub(\n fees[i].mul(self.adminFee).div(FEE_DENOMINATOR)\n );\n balances1[i] = balances1[i].sub(fees[i]);\n }\n\n v.d2 = getD(_xp(balances1, v.multipliers), v.preciseA);\n }\n uint256 tokenAmount = v.d0.sub(v.d2).mul(v.totalSupply).div(v.d0);\n require(tokenAmount != 0, \"Burnt amount cannot be zero\");\n tokenAmount = tokenAmount.add(1);\n\n require(tokenAmount <= maxBurnAmount, \"tokenAmount > maxBurnAmount\");\n\n v.lpToken.burnFrom(msg.sender, tokenAmount);\n\n for (uint256 i = 0; i < pooledTokens.length; i++) {\n pooledTokens[i].safeTransfer(msg.sender, amounts[i]);\n }\n\n emit RemoveLiquidityImbalance(\n msg.sender,\n amounts,\n fees,\n v.d1,\n v.totalSupply.sub(tokenAmount)\n );\n\n return tokenAmount;\n }\n\n /**\n * @notice withdraw all admin fees to a given address\n * @param self Swap struct to withdraw fees from\n * @param to Address to send the fees to\n */\n function withdrawAdminFees(Swap storage self, address to) external {\n IERC20[] memory pooledTokens = self.pooledTokens;\n for (uint256 i = 0; i < pooledTokens.length; i++) {\n IERC20 token = pooledTokens[i];\n uint256 balance = token.balanceOf(address(this)).sub(\n self.balances[i]\n );\n if (balance != 0) {\n token.safeTransfer(to, balance);\n }\n }\n }\n\n /**\n * @notice Sets the admin fee\n * @dev adminFee cannot be higher than 100% of the swap fee\n * @param self Swap struct to update\n * @param newAdminFee new admin fee to be applied on future transactions\n */\n function setAdminFee(Swap storage self, uint256 newAdminFee) external {\n require(newAdminFee <= MAX_ADMIN_FEE, \"Fee is too high\");\n self.adminFee = newAdminFee;\n\n emit NewAdminFee(newAdminFee);\n }\n\n /**\n * @notice update the swap fee\n * @dev fee cannot be higher than 1% of each swap\n * @param self Swap struct to update\n * @param newSwapFee new swap fee to be applied on future transactions\n */\n function setSwapFee(Swap storage self, uint256 newSwapFee) external {\n require(newSwapFee <= MAX_SWAP_FEE, \"Fee is too high\");\n self.swapFee = newSwapFee;\n\n emit NewSwapFee(newSwapFee);\n }\n}\n" + }, + "contracts/amm/AmplificationUtils.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.6.12;\n\nimport \"@openzeppelin/contracts/token/ERC20/SafeERC20.sol\";\nimport \"./SwapUtils.sol\";\n\n/**\n * @title AmplificationUtils library\n * @notice A library to calculate and ramp the A parameter of a given `SwapUtils.Swap` struct.\n * This library assumes the struct is fully validated.\n */\nlibrary AmplificationUtils {\n using SafeMath for uint256;\n\n event RampA(\n uint256 oldA,\n uint256 newA,\n uint256 initialTime,\n uint256 futureTime\n );\n event StopRampA(uint256 currentA, uint256 time);\n\n // Constant values used in ramping A calculations\n uint256 public constant A_PRECISION = 100;\n uint256 public constant MAX_A = 10**6;\n uint256 private constant MAX_A_CHANGE = 2;\n uint256 private constant MIN_RAMP_TIME = 7 days;\n\n /**\n * @notice Return A, the amplification coefficient * n * (n - 1)\n * @dev See the StableSwap paper for details\n * @param self Swap struct to read from\n * @return A parameter\n */\n function getA(SwapUtils.Swap storage self) external view returns (uint256) {\n return _getAPrecise(self).div(A_PRECISION);\n }\n\n /**\n * @notice Return A in its raw precision\n * @dev See the StableSwap paper for details\n * @param self Swap struct to read from\n * @return A parameter in its raw precision form\n */\n function getAPrecise(SwapUtils.Swap storage self)\n external\n view\n returns (uint256)\n {\n return _getAPrecise(self);\n }\n\n /**\n * @notice Return A in its raw precision\n * @dev See the StableSwap paper for details\n * @param self Swap struct to read from\n * @return A parameter in its raw precision form\n */\n function _getAPrecise(SwapUtils.Swap storage self)\n internal\n view\n returns (uint256)\n {\n uint256 t1 = self.futureATime; // time when ramp is finished\n uint256 a1 = self.futureA; // final A value when ramp is finished\n\n if (block.timestamp < t1) {\n uint256 t0 = self.initialATime; // time when ramp is started\n uint256 a0 = self.initialA; // initial A value when ramp is started\n if (a1 > a0) {\n // a0 + (a1 - a0) * (block.timestamp - t0) / (t1 - t0)\n return\n a0.add(\n a1.sub(a0).mul(block.timestamp.sub(t0)).div(t1.sub(t0))\n );\n } else {\n // a0 - (a0 - a1) * (block.timestamp - t0) / (t1 - t0)\n return\n a0.sub(\n a0.sub(a1).mul(block.timestamp.sub(t0)).div(t1.sub(t0))\n );\n }\n } else {\n return a1;\n }\n }\n\n /**\n * @notice Start ramping up or down A parameter towards given futureA_ and futureTime_\n * Checks if the change is too rapid, and commits the new A value only when it falls under\n * the limit range.\n * @param self Swap struct to update\n * @param futureA_ the new A to ramp towards\n * @param futureTime_ timestamp when the new A should be reached\n */\n function rampA(\n SwapUtils.Swap storage self,\n uint256 futureA_,\n uint256 futureTime_\n ) external {\n require(\n block.timestamp >= self.initialATime.add(1 days),\n \"Wait 1 day before starting ramp\"\n );\n require(\n futureTime_ >= block.timestamp.add(MIN_RAMP_TIME),\n \"Insufficient ramp time\"\n );\n require(\n futureA_ > 0 && futureA_ < MAX_A,\n \"futureA_ must be > 0 and < MAX_A\"\n );\n\n uint256 initialAPrecise = _getAPrecise(self);\n uint256 futureAPrecise = futureA_.mul(A_PRECISION);\n\n if (futureAPrecise < initialAPrecise) {\n require(\n futureAPrecise.mul(MAX_A_CHANGE) >= initialAPrecise,\n \"futureA_ is too small\"\n );\n } else {\n require(\n futureAPrecise <= initialAPrecise.mul(MAX_A_CHANGE),\n \"futureA_ is too large\"\n );\n }\n\n self.initialA = initialAPrecise;\n self.futureA = futureAPrecise;\n self.initialATime = block.timestamp;\n self.futureATime = futureTime_;\n\n emit RampA(\n initialAPrecise,\n futureAPrecise,\n block.timestamp,\n futureTime_\n );\n }\n\n /**\n * @notice Stops ramping A immediately. Once this function is called, rampA()\n * cannot be called for another 24 hours\n * @param self Swap struct to update\n */\n function stopRampA(SwapUtils.Swap storage self) external {\n require(self.futureATime > block.timestamp, \"Ramp is already stopped\");\n\n uint256 currentA = _getAPrecise(self);\n self.initialA = currentA;\n self.futureA = currentA;\n self.initialATime = block.timestamp;\n self.futureATime = block.timestamp;\n\n emit StopRampA(currentA, block.timestamp);\n }\n}\n" + }, + "@openzeppelin/contracts/token/ERC20/IERC20.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <0.8.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" + }, + "@openzeppelin/contracts/utils/Address.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.2 <0.8.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" + }, + "@openzeppelin/contracts-upgradeable/proxy/Initializable.sol": { + "content": "// SPDX-License-Identifier: MIT\n\n// solhint-disable-next-line compiler-version\npragma solidity >=0.4.24 <0.8.0;\n\nimport \"../utils/AddressUpgradeable.sol\";\n\n/**\n * @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed\n * behind a proxy. Since a proxied contract can't have a constructor, it's common to move constructor logic to an\n * external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer\n * function so it can only be called once. The {initializer} modifier provided by this contract will have this effect.\n *\n * TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as\n * possible by providing the encoded function call as the `_data` argument to {UpgradeableProxy-constructor}.\n *\n * CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure\n * that all initializers are idempotent. This is not verified automatically as constructors are by Solidity.\n */\nabstract contract Initializable {\n\n /**\n * @dev Indicates that the contract has been initialized.\n */\n bool private _initialized;\n\n /**\n * @dev Indicates that the contract is in the process of being initialized.\n */\n bool private _initializing;\n\n /**\n * @dev Modifier to protect an initializer function from being invoked twice.\n */\n modifier initializer() {\n require(_initializing || _isConstructor() || !_initialized, \"Initializable: contract is already initialized\");\n\n bool isTopLevelCall = !_initializing;\n if (isTopLevelCall) {\n _initializing = true;\n _initialized = true;\n }\n\n _;\n\n if (isTopLevelCall) {\n _initializing = false;\n }\n }\n\n /// @dev Returns true if and only if the function is running in the constructor\n function _isConstructor() private view returns (bool) {\n return !AddressUpgradeable.isContract(address(this));\n }\n}\n" + }, + "@openzeppelin/contracts-upgradeable/utils/AddressUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.2 <0.8.0;\n\n/**\n * @dev Collection of functions related to the address type\n */\nlibrary AddressUpgradeable {\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 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" + }, + "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <0.8.0;\n\nimport \"../utils/ContextUpgradeable.sol\";\nimport \"../proxy/Initializable.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 OwnableUpgradeable is Initializable, ContextUpgradeable {\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 function __Ownable_init() internal initializer {\n __Context_init_unchained();\n __Ownable_init_unchained();\n }\n\n function __Ownable_init_unchained() internal initializer {\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 uint256[49] private __gap;\n}\n" + }, + "@openzeppelin/contracts-upgradeable/utils/PausableUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <0.8.0;\n\nimport \"./ContextUpgradeable.sol\";\nimport \"../proxy/Initializable.sol\";\n\n/**\n * @dev Contract module which allows children to implement an emergency stop\n * mechanism that can be triggered by an authorized account.\n *\n * This module is used through inheritance. It will make available the\n * modifiers `whenNotPaused` and `whenPaused`, which can be applied to\n * the functions of your contract. Note that they will not be pausable by\n * simply including this module, only once the modifiers are put in place.\n */\nabstract contract PausableUpgradeable is Initializable, ContextUpgradeable {\n /**\n * @dev Emitted when the pause is triggered by `account`.\n */\n event Paused(address account);\n\n /**\n * @dev Emitted when the pause is lifted by `account`.\n */\n event Unpaused(address account);\n\n bool private _paused;\n\n /**\n * @dev Initializes the contract in unpaused state.\n */\n function __Pausable_init() internal initializer {\n __Context_init_unchained();\n __Pausable_init_unchained();\n }\n\n function __Pausable_init_unchained() internal initializer {\n _paused = false;\n }\n\n /**\n * @dev Returns true if the contract is paused, and false otherwise.\n */\n function paused() public view virtual returns (bool) {\n return _paused;\n }\n\n /**\n * @dev Modifier to make a function callable only when the contract is not paused.\n *\n * Requirements:\n *\n * - The contract must not be paused.\n */\n modifier whenNotPaused() {\n require(!paused(), \"Pausable: paused\");\n _;\n }\n\n /**\n * @dev Modifier to make a function callable only when the contract is paused.\n *\n * Requirements:\n *\n * - The contract must be paused.\n */\n modifier whenPaused() {\n require(paused(), \"Pausable: not paused\");\n _;\n }\n\n /**\n * @dev Triggers stopped state.\n *\n * Requirements:\n *\n * - The contract must not be paused.\n */\n function _pause() internal virtual whenNotPaused {\n _paused = true;\n emit Paused(_msgSender());\n }\n\n /**\n * @dev Returns to normal state.\n *\n * Requirements:\n *\n * - The contract must be paused.\n */\n function _unpause() internal virtual whenPaused {\n _paused = false;\n emit Unpaused(_msgSender());\n }\n uint256[49] private __gap;\n}\n" + }, + "@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <0.8.0;\nimport \"../proxy/Initializable.sol\";\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 ContextUpgradeable is Initializable {\n function __Context_init() internal initializer {\n __Context_init_unchained();\n }\n\n function __Context_init_unchained() internal initializer {\n }\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 uint256[50] private __gap;\n}\n" + }, + "contracts/amm/LPToken.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.6.12;\n\nimport \"@openzeppelin/contracts-upgradeable/token/ERC20/ERC20BurnableUpgradeable.sol\";\nimport \"@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol\";\nimport \"./interfaces/ISwap.sol\";\n\n/**\n * @title Liquidity Provider Token\n * @notice This token is an ERC20 detailed token with added capability to be minted by the owner.\n * It is used to represent user's shares when providing liquidity to swap contracts.\n * @dev Only Swap contracts should initialize and own LPToken contracts.\n */\ncontract LPToken is ERC20BurnableUpgradeable, OwnableUpgradeable {\n using SafeMathUpgradeable for uint256;\n\n /**\n * @notice Initializes this LPToken contract with the given name and symbol\n * @dev The caller of this function will become the owner. A Swap contract should call this\n * in its initializer function.\n * @param name name of this token\n * @param symbol symbol of this token\n */\n function initialize(string memory name, string memory symbol)\n external\n initializer\n returns (bool)\n {\n __Context_init_unchained();\n __ERC20_init_unchained(name, symbol);\n __Ownable_init_unchained();\n return true;\n }\n\n /**\n * @notice Mints the given amount of LPToken to the recipient.\n * @dev only owner can call this mint function\n * @param recipient address of account to receive the tokens\n * @param amount amount of tokens to mint\n */\n function mint(address recipient, uint256 amount) external onlyOwner {\n require(amount != 0, \"LPToken: cannot mint 0\");\n _mint(recipient, amount);\n }\n\n /**\n * @dev Overrides ERC20._beforeTokenTransfer() which get called on every transfers including\n * minting and burning. * This assumes the owner is set to a Swap contract's address.\n */\n function _beforeTokenTransfer(\n address from,\n address to,\n uint256 amount\n ) internal virtual override(ERC20Upgradeable) {\n super._beforeTokenTransfer(from, to, amount);\n require(to != address(this), \"LPToken: cannot send to itself\");\n }\n}\n" + }, + "contracts/amm/MathUtils.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.6.12;\n\nimport \"@openzeppelin/contracts/math/SafeMath.sol\";\n\n/**\n * @title MathUtils library\n * @notice A library to be used in conjunction with SafeMath. Contains functions for calculating\n * differences between two uint256.\n */\nlibrary MathUtils {\n /**\n * @notice Compares a and b and returns true if the difference between a and b\n * is less than 1 or equal to each other.\n * @param a uint256 to compare with\n * @param b uint256 to compare with\n * @return True if the difference between a and b is less than 1 or equal,\n * otherwise return false\n */\n function within1(uint256 a, uint256 b) internal pure returns (bool) {\n return (difference(a, b) <= 1);\n }\n\n /**\n * @notice Calculates absolute difference between a and b\n * @param a uint256 to compare with\n * @param b uint256 to compare with\n * @return Difference between a and b\n */\n function difference(uint256 a, uint256 b) internal pure returns (uint256) {\n if (a > b) {\n return a - b;\n }\n return b - a;\n }\n}\n" + }, + "@openzeppelin/contracts-upgradeable/token/ERC20/ERC20BurnableUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <0.8.0;\n\nimport \"../../utils/ContextUpgradeable.sol\";\nimport \"./ERC20Upgradeable.sol\";\nimport \"../../proxy/Initializable.sol\";\n\n/**\n * @dev Extension of {ERC20} that allows token holders to destroy both their own\n * tokens and those that they have an allowance for, in a way that can be\n * recognized off-chain (via event analysis).\n */\nabstract contract ERC20BurnableUpgradeable is Initializable, ContextUpgradeable, ERC20Upgradeable {\n function __ERC20Burnable_init() internal initializer {\n __Context_init_unchained();\n __ERC20Burnable_init_unchained();\n }\n\n function __ERC20Burnable_init_unchained() internal initializer {\n }\n using SafeMathUpgradeable for uint256;\n\n /**\n * @dev Destroys `amount` tokens from the caller.\n *\n * See {ERC20-_burn}.\n */\n function burn(uint256 amount) public virtual {\n _burn(_msgSender(), amount);\n }\n\n /**\n * @dev Destroys `amount` tokens from `account`, deducting from the caller's\n * allowance.\n *\n * See {ERC20-_burn} and {ERC20-allowance}.\n *\n * Requirements:\n *\n * - the caller must have allowance for ``accounts``'s tokens of at least\n * `amount`.\n */\n function burnFrom(address account, uint256 amount) public virtual {\n uint256 decreasedAllowance = allowance(account, _msgSender()).sub(amount, \"ERC20: burn amount exceeds allowance\");\n\n _approve(account, _msgSender(), decreasedAllowance);\n _burn(account, amount);\n }\n uint256[50] private __gap;\n}\n" + }, + "contracts/amm/interfaces/ISwap.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.6.12;\n\nimport \"@openzeppelin/contracts/token/ERC20/ERC20.sol\";\n\ninterface ISwap {\n // pool data view functions\n function getA() external view returns (uint256);\n\n function getToken(uint8 index) external view returns (IERC20);\n\n function getTokenIndex(address tokenAddress) external view returns (uint8);\n\n function getTokenBalance(uint8 index) external view returns (uint256);\n\n function getVirtualPrice() external view returns (uint256);\n\n // min return calculation functions\n function calculateSwap(\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx\n ) external view returns (uint256);\n\n function calculateTokenAmount(uint256[] calldata amounts, bool deposit)\n external\n view\n returns (uint256);\n\n function calculateRemoveLiquidity(uint256 amount)\n external\n view\n returns (uint256[] memory);\n\n function calculateRemoveLiquidityOneToken(\n uint256 tokenAmount,\n uint8 tokenIndex\n ) external view returns (uint256 availableTokenAmount);\n\n // state modifying functions\n function initialize(\n IERC20[] memory pooledTokens,\n uint8[] memory decimals,\n string memory lpTokenName,\n string memory lpTokenSymbol,\n uint256 a,\n uint256 fee,\n uint256 adminFee,\n address lpTokenTargetAddress\n ) external;\n\n function swap(\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx,\n uint256 minDy,\n uint256 deadline\n ) external returns (uint256);\n\n function addLiquidity(\n uint256[] calldata amounts,\n uint256 minToMint,\n uint256 deadline\n ) external returns (uint256);\n\n function removeLiquidity(\n uint256 amount,\n uint256[] calldata minAmounts,\n uint256 deadline\n ) external returns (uint256[] memory);\n\n function removeLiquidityOneToken(\n uint256 tokenAmount,\n uint8 tokenIndex,\n uint256 minAmount,\n uint256 deadline\n ) external returns (uint256);\n\n function removeLiquidityImbalance(\n uint256[] calldata amounts,\n uint256 maxBurnAmount,\n uint256 deadline\n ) external returns (uint256);\n}\n" + }, + "@openzeppelin/contracts-upgradeable/token/ERC20/ERC20Upgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <0.8.0;\n\nimport \"../../utils/ContextUpgradeable.sol\";\nimport \"./IERC20Upgradeable.sol\";\nimport \"../../math/SafeMathUpgradeable.sol\";\nimport \"../../proxy/Initializable.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 ERC20Upgradeable is Initializable, ContextUpgradeable, IERC20Upgradeable {\n using SafeMathUpgradeable 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 function __ERC20_init(string memory name_, string memory symbol_) internal initializer {\n __Context_init_unchained();\n __ERC20_init_unchained(name_, symbol_);\n }\n\n function __ERC20_init_unchained(string memory name_, string memory symbol_) internal initializer {\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 uint256[44] private __gap;\n}\n" + }, + "@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <0.8.0;\n\n/**\n * @dev Interface of the ERC20 standard as defined in the EIP.\n */\ninterface IERC20Upgradeable {\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" + }, + "@openzeppelin/contracts-upgradeable/math/SafeMathUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <0.8.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 SafeMathUpgradeable {\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" + }, + "@openzeppelin/contracts/token/ERC20/ERC20.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <0.8.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_) public {\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" + }, + "@openzeppelin/contracts/utils/Context.sol": { + "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" + }, + "contracts/amm/SwapFlashLoan.sol": { + "content": "// SPDX-License-Identifier: MIT WITH AGPL-3.0-only\n\npragma solidity 0.6.12;\n\nimport \"./Swap.sol\";\nimport \"./interfaces/IFlashLoanReceiver.sol\";\n\n/**\n * @title Swap - A StableSwap implementation in solidity.\n * @notice This contract is responsible for custody of closely pegged assets (eg. group of stablecoins)\n * and automatic market making system. Users become an LP (Liquidity Provider) by depositing their tokens\n * in desired ratios for an exchange of the pool token that represents their share of the pool.\n * Users can burn pool tokens and withdraw their share of token(s).\n *\n * Each time a swap between the pooled tokens happens, a set fee incurs which effectively gets\n * distributed to the LPs.\n *\n * In case of emergencies, admin can pause additional deposits, swaps, or single-asset withdraws - which\n * stops the ratio of the tokens in the pool from changing.\n * Users can always withdraw their tokens via multi-asset withdraws.\n *\n * @dev Most of the logic is stored as a library `SwapUtils` for the sake of reducing contract's\n * deployment size.\n */\ncontract SwapFlashLoan is Swap {\n // Total fee that is charged on all flashloans in BPS. Borrowers must repay the amount plus the flash loan fee.\n // This fee is split between the protocol and the pool.\n uint256 public flashLoanFeeBPS;\n // Share of the flash loan fee that goes to the protocol in BPS. A portion of each flash loan fee is allocated\n // to the protocol rather than the pool.\n uint256 public protocolFeeShareBPS;\n // Max BPS for limiting flash loan fee settings.\n uint256 public constant MAX_BPS = 10000;\n\n /*** EVENTS ***/\n event FlashLoan(\n address indexed receiver,\n uint8 tokenIndex,\n uint256 amount,\n uint256 amountFee,\n uint256 protocolFee\n );\n\n /**\n * @notice Initializes this Swap contract with the given parameters.\n * This will also clone a LPToken contract that represents users'\n * LP positions. The owner of LPToken will be this contract - which means\n * only this contract is allowed to mint/burn tokens.\n *\n * @param _pooledTokens an array of ERC20s this pool will accept\n * @param decimals the decimals to use for each pooled token,\n * eg 8 for WBTC. Cannot be larger than POOL_PRECISION_DECIMALS\n * @param lpTokenName the long-form name of the token to be deployed\n * @param lpTokenSymbol the short symbol for the token to be deployed\n * @param _a the amplification coefficient * n * (n - 1). See the\n * StableSwap paper for details\n * @param _fee default swap fee to be initialized with\n * @param _adminFee default adminFee to be initialized with\n * @param lpTokenTargetAddress the address of an existing LPToken contract to use as a target\n */\n function initialize(\n IERC20[] memory _pooledTokens,\n uint8[] memory decimals,\n string memory lpTokenName,\n string memory lpTokenSymbol,\n uint256 _a,\n uint256 _fee,\n uint256 _adminFee,\n address lpTokenTargetAddress\n ) public virtual override initializer {\n Swap.initialize(\n _pooledTokens,\n decimals,\n lpTokenName,\n lpTokenSymbol,\n _a,\n _fee,\n _adminFee,\n lpTokenTargetAddress\n );\n flashLoanFeeBPS = 8; // 8 bps\n protocolFeeShareBPS = 0; // 0 bps\n }\n\n /*** STATE MODIFYING FUNCTIONS ***/\n\n /**\n * @notice Borrow the specified token from this pool for this transaction only. This function will call\n * `IFlashLoanReceiver(receiver).executeOperation` and the `receiver` must return the full amount of the token\n * and the associated fee by the end of the callback transaction. If the conditions are not met, this call\n * is reverted.\n * @param receiver the address of the receiver of the token. This address must implement the IFlashLoanReceiver\n * interface and the callback function `executeOperation`.\n * @param token the protocol fee in bps to be applied on the total flash loan fee\n * @param amount the total amount to borrow in this transaction\n * @param params optional data to pass along to the callback function\n */\n function flashLoan(\n address receiver,\n IERC20 token,\n uint256 amount,\n bytes memory params\n ) external nonReentrant {\n uint8 tokenIndex = getTokenIndex(address(token));\n uint256 availableLiquidityBefore = token.balanceOf(address(this));\n uint256 protocolBalanceBefore = availableLiquidityBefore.sub(\n swapStorage.balances[tokenIndex]\n );\n require(\n amount > 0 && availableLiquidityBefore >= amount,\n \"invalid amount\"\n );\n\n // Calculate the additional amount of tokens the pool should end up with\n uint256 amountFee = amount.mul(flashLoanFeeBPS).div(10000);\n // Calculate the portion of the fee that will go to the protocol\n uint256 protocolFee = amountFee.mul(protocolFeeShareBPS).div(10000);\n require(amountFee > 0, \"amount is small for a flashLoan\");\n\n // Transfer the requested amount of tokens\n token.safeTransfer(receiver, amount);\n\n // Execute callback function on receiver\n IFlashLoanReceiver(receiver).executeOperation(\n address(this),\n address(token),\n amount,\n amountFee,\n params\n );\n\n uint256 availableLiquidityAfter = token.balanceOf(address(this));\n require(\n availableLiquidityAfter >= availableLiquidityBefore.add(amountFee),\n \"flashLoan fee is not met\"\n );\n\n swapStorage.balances[tokenIndex] = availableLiquidityAfter\n .sub(protocolBalanceBefore)\n .sub(protocolFee);\n emit FlashLoan(receiver, tokenIndex, amount, amountFee, protocolFee);\n }\n\n /*** ADMIN FUNCTIONS ***/\n\n /**\n * @notice Updates the flash loan fee parameters. This function can only be called by the owner.\n * @param newFlashLoanFeeBPS the total fee in bps to be applied on future flash loans\n * @param newProtocolFeeShareBPS the protocol fee in bps to be applied on the total flash loan fee\n */\n function setFlashLoanFees(\n uint256 newFlashLoanFeeBPS,\n uint256 newProtocolFeeShareBPS\n ) external onlyOwner {\n require(\n newFlashLoanFeeBPS > 0 &&\n newFlashLoanFeeBPS <= MAX_BPS &&\n newProtocolFeeShareBPS <= MAX_BPS,\n \"fees are not in valid range\"\n );\n flashLoanFeeBPS = newFlashLoanFeeBPS;\n protocolFeeShareBPS = newProtocolFeeShareBPS;\n }\n}\n" + }, + "contracts/amm/interfaces/IFlashLoanReceiver.sol": { + "content": "// SPDX-License-Identifier: AGPL-3.0-only\n\npragma solidity 0.6.12;\n\n/**\n * @title IFlashLoanReceiver interface\n * @notice Interface for the Nerve fee IFlashLoanReceiver. Modified from Aave's IFlashLoanReceiver interface.\n * https://github.com/aave/aave-protocol/blob/4b4545fb583fd4f400507b10f3c3114f45b8a037/contracts/flashloan/interfaces/IFlashLoanReceiver.sol\n * @author Aave\n * @dev implement this interface to develop a flashloan-compatible flashLoanReceiver contract\n **/\ninterface IFlashLoanReceiver {\n function executeOperation(\n address pool,\n address token,\n uint256 amount,\n uint256 fee,\n bytes calldata params\n ) external;\n}\n" + }, + "contracts/amm/helper/FlashLoanBorrowerExample.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.6.12;\n\nimport \"@openzeppelin/contracts/math/SafeMath.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/SafeERC20.sol\";\nimport \"../interfaces/IFlashLoanReceiver.sol\";\nimport \"../interfaces/ISwapFlashLoan.sol\";\nimport \"hardhat/console.sol\";\n\ncontract FlashLoanBorrowerExample is IFlashLoanReceiver {\n using SafeMath for uint256;\n\n // Typical executeOperation function should do the 3 following actions\n // 1. Check if the flashLoan was successful\n // 2. Do actions with the borrowed tokens\n // 3. Repay the debt to the `pool`\n function executeOperation(\n address pool,\n address token,\n uint256 amount,\n uint256 fee,\n bytes calldata params\n ) external override {\n // 1. Check if the flashLoan was valid\n require(\n IERC20(token).balanceOf(address(this)) >= amount,\n \"flashloan is broken?\"\n );\n\n // 2. Do actions with the borrowed token\n bytes32 paramsHash = keccak256(params);\n if (paramsHash == keccak256(bytes(\"dontRepayDebt\"))) {\n return;\n } else if (paramsHash == keccak256(bytes(\"reentrancy_addLiquidity\"))) {\n ISwapFlashLoan(pool).addLiquidity(\n new uint256[](0),\n 0,\n block.timestamp\n );\n } else if (paramsHash == keccak256(bytes(\"reentrancy_swap\"))) {\n ISwapFlashLoan(pool).swap(1, 0, 1e6, 0, now);\n } else if (\n paramsHash == keccak256(bytes(\"reentrancy_removeLiquidity\"))\n ) {\n ISwapFlashLoan(pool).removeLiquidity(1e18, new uint256[](0), now);\n } else if (\n paramsHash == keccak256(bytes(\"reentrancy_removeLiquidityOneToken\"))\n ) {\n ISwapFlashLoan(pool).removeLiquidityOneToken(1e18, 0, 1e18, now);\n }\n\n // 3. Payback debt\n uint256 totalDebt = amount.add(fee);\n IERC20(token).transfer(pool, totalDebt);\n }\n\n function flashLoan(\n ISwapFlashLoan swap,\n IERC20 token,\n uint256 amount,\n bytes memory params\n ) external {\n swap.flashLoan(address(this), token, amount, params);\n }\n}\n" + }, + "contracts/amm/interfaces/ISwapFlashLoan.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.6.12;\n\nimport \"./ISwap.sol\";\n\ninterface ISwapFlashLoan is ISwap {\n function flashLoan(\n address receiver,\n IERC20 token,\n uint256 amount,\n bytes memory params\n ) external;\n}\n" + }, + "hardhat/console.sol": { + "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" + }, + "contracts/amm/helper/test/TestSwapReturnValues.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.6.12;\n\nimport \"../../interfaces/ISwap.sol\";\nimport \"hardhat/console.sol\";\n\ncontract TestSwapReturnValues {\n using SafeMath for uint256;\n\n ISwap public swap;\n IERC20 public lpToken;\n uint8 public n;\n\n uint256 public constant MAX_INT = 2**256 - 1;\n\n constructor(\n ISwap swapContract,\n IERC20 lpTokenContract,\n uint8 numOfTokens\n ) public {\n swap = swapContract;\n lpToken = lpTokenContract;\n n = numOfTokens;\n\n // Pre-approve tokens\n for (uint8 i; i < n; i++) {\n swap.getToken(i).approve(address(swap), MAX_INT);\n }\n lpToken.approve(address(swap), MAX_INT);\n }\n\n function test_swap(\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx,\n uint256 minDy\n ) public {\n uint256 balanceBefore =\n swap.getToken(tokenIndexTo).balanceOf(address(this));\n uint256 returnValue =\n swap.swap(tokenIndexFrom, tokenIndexTo, dx, minDy, block.timestamp);\n uint256 balanceAfter =\n swap.getToken(tokenIndexTo).balanceOf(address(this));\n\n console.log(\n \"swap: Expected %s, got %s\",\n balanceAfter.sub(balanceBefore),\n returnValue\n );\n\n require(\n returnValue == balanceAfter.sub(balanceBefore),\n \"swap()'s return value does not match received amount\"\n );\n }\n\n function test_addLiquidity(uint256[] calldata amounts, uint256 minToMint)\n public\n {\n uint256 balanceBefore = lpToken.balanceOf(address(this));\n uint256 returnValue = swap.addLiquidity(amounts, minToMint, MAX_INT);\n uint256 balanceAfter = lpToken.balanceOf(address(this));\n\n console.log(\n \"addLiquidity: Expected %s, got %s\",\n balanceAfter.sub(balanceBefore),\n returnValue\n );\n\n require(\n returnValue == balanceAfter.sub(balanceBefore),\n \"addLiquidity()'s return value does not match minted amount\"\n );\n }\n\n function test_removeLiquidity(uint256 amount, uint256[] memory minAmounts)\n public\n {\n uint256[] memory balanceBefore = new uint256[](n);\n uint256[] memory balanceAfter = new uint256[](n);\n\n for (uint8 i = 0; i < n; i++) {\n balanceBefore[i] = swap.getToken(i).balanceOf(address(this));\n }\n\n uint256[] memory returnValue =\n swap.removeLiquidity(amount, minAmounts, MAX_INT);\n\n for (uint8 i = 0; i < n; i++) {\n balanceAfter[i] = swap.getToken(i).balanceOf(address(this));\n console.log(\n \"removeLiquidity: Expected %s, got %s\",\n balanceAfter[i].sub(balanceBefore[i]),\n returnValue[i]\n );\n require(\n balanceAfter[i].sub(balanceBefore[i]) == returnValue[i],\n \"removeLiquidity()'s return value does not match received amounts of tokens\"\n );\n }\n }\n\n function test_removeLiquidityImbalance(\n uint256[] calldata amounts,\n uint256 maxBurnAmount\n ) public {\n uint256 balanceBefore = lpToken.balanceOf(address(this));\n uint256 returnValue =\n swap.removeLiquidityImbalance(amounts, maxBurnAmount, MAX_INT);\n uint256 balanceAfter = lpToken.balanceOf(address(this));\n\n console.log(\n \"removeLiquidityImbalance: Expected %s, got %s\",\n balanceBefore.sub(balanceAfter),\n returnValue\n );\n\n require(\n returnValue == balanceBefore.sub(balanceAfter),\n \"removeLiquidityImbalance()'s return value does not match burned lpToken amount\"\n );\n }\n\n function test_removeLiquidityOneToken(\n uint256 tokenAmount,\n uint8 tokenIndex,\n uint256 minAmount\n ) public {\n uint256 balanceBefore =\n swap.getToken(tokenIndex).balanceOf(address(this));\n uint256 returnValue =\n swap.removeLiquidityOneToken(\n tokenAmount,\n tokenIndex,\n minAmount,\n MAX_INT\n );\n uint256 balanceAfter =\n swap.getToken(tokenIndex).balanceOf(address(this));\n\n console.log(\n \"removeLiquidityOneToken: Expected %s, got %s\",\n balanceAfter.sub(balanceBefore),\n returnValue\n );\n\n require(\n returnValue == balanceAfter.sub(balanceBefore),\n \"removeLiquidityOneToken()'s return value does not match received token amount\"\n );\n }\n}\n" + }, + "contracts/amm/SwapDeployer.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.6.12;\n\nimport \"@openzeppelin/contracts/access/Ownable.sol\";\nimport \"@openzeppelin/contracts/proxy/Clones.sol\";\nimport \"./interfaces/ISwap.sol\";\n\ncontract SwapDeployer is Ownable {\n event NewSwapPool(\n address indexed deployer,\n address swapAddress,\n IERC20[] pooledTokens\n );\n\n constructor() public Ownable() {}\n\n function deploy(\n address swapAddress,\n IERC20[] memory _pooledTokens,\n uint8[] memory decimals,\n string memory lpTokenName,\n string memory lpTokenSymbol,\n uint256 _a,\n uint256 _fee,\n uint256 _adminFee,\n address lpTokenTargetAddress\n ) external returns (address) {\n address swapClone = Clones.clone(swapAddress);\n ISwap(swapClone).initialize(\n _pooledTokens,\n decimals,\n lpTokenName,\n lpTokenSymbol,\n _a,\n _fee,\n _adminFee,\n lpTokenTargetAddress\n );\n Ownable(swapClone).transferOwnership(owner());\n emit NewSwapPool(msg.sender, swapClone, _pooledTokens);\n return swapClone;\n }\n}\n" + }, + "@openzeppelin/contracts/access/Ownable.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <0.8.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 () internal {\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" + }, + "contracts/bridge/SynapseERC20Factory.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.6.12;\n\nimport \"@openzeppelin/contracts/access/Ownable.sol\";\nimport \"@openzeppelin/contracts/proxy/Clones.sol\";\nimport \"./interfaces/ISynapseERC20.sol\";\n\ncontract SynapseERC20Factory {\n constructor() public {}\n\n event SynapseERC20Created(address contractAddress);\n\n /**\n * @notice Deploys a new node\n * @param synapseERC20Address address of the synapseERC20Address contract to initialize with\n * @param name Token name\n * @param symbol Token symbol\n * @param decimals Token name\n * @param owner admin address to be initialized with\n * @return Address of the newest node management contract created\n **/\n function deploy(\n address synapseERC20Address,\n string memory name,\n string memory symbol,\n uint8 decimals,\n address owner\n ) external returns (address) {\n address synERC20Clone = Clones.clone(synapseERC20Address);\n ISynapseERC20(synERC20Clone).initialize(name, symbol, decimals, owner);\n\n emit SynapseERC20Created(synERC20Clone);\n\n return synERC20Clone;\n }\n}\n" + }, + "contracts/bridge/interfaces/ISynapseERC20.sol": { + "content": "// SPDX-License-Identifier: MIT\n\n\npragma solidity 0.6.12;\n\ninterface ISynapseERC20 { \n function initialize(\n string memory _name, string memory _symbol, uint8 _decimals, address owner) external;\n\n function mint(address to, uint256 amount) external;\n}\n\n" + }, + "contracts/bridge/wrappers/AvaxJewelMigration.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.6.12;\n\nimport '@openzeppelin/contracts/token/ERC20/ERC20.sol';\nimport \"@openzeppelin/contracts/token/ERC20/SafeERC20.sol\";\nimport \"@openzeppelin/contracts/access/Ownable.sol\";\n\nimport '../interfaces/ISynapseBridge.sol';\n\ninterface IERC20Mintable is IERC20 {\n function mint(address to, uint256 amount) external;\n}\n\ncontract AvaxJewelMigration is Ownable {\n using SafeERC20 for IERC20;\n using SafeERC20 for IERC20Mintable;\n\n\n ISynapseBridge constant synapseBridge = ISynapseBridge(0xC05e61d0E7a63D27546389B7aD62FdFf5A91aACE);\n // MULTICHAIN JEWEL \n IERC20 constant legacyToken = IERC20(0x4f60a160D8C2DDdaAfe16FCC57566dB84D674BD6);\n // SYNAPSE JEWEL\n IERC20 constant newToken = IERC20(0x997Ddaa07d716995DE90577C123Db411584E5E46);\n uint256 constant MAX_UINT256 = 2**256 - 1;\n\n constructor() public {\n newToken.safeApprove(address(synapseBridge), MAX_UINT256);\n }\n\n function migrate(uint256 amount) public {\n legacyToken.safeTransferFrom(msg.sender, address(this), amount);\n IERC20Mintable(address(newToken)).mint(msg.sender, amount);\n }\n\n function migrateAndBridge(uint256 amount, address to, uint256 chainId) external {\n migrate(amount);\n synapseBridge.redeem(to, chainId, newToken, amount);\n }\n\n function redeemLegacy() external onlyOwner {\n uint256 legacyBalance = legacyToken.balanceOf(address(this));\n legacyToken.safeTransfer(owner(), legacyBalance);\n }\n} " + }, + "contracts/bridge/interfaces/ISynapseBridge.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.6.12;\n\nimport '@openzeppelin/contracts/token/ERC20/SafeERC20.sol';\nimport '@openzeppelin/contracts/token/ERC20/ERC20Burnable.sol';\n\ninterface ISynapseBridge {\n using SafeERC20 for IERC20;\n\n function deposit(\n address to,\n uint256 chainId,\n IERC20 token,\n uint256 amount\n ) external;\n\n function depositAndSwap(\n address to,\n uint256 chainId,\n IERC20 token,\n uint256 amount,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 minDy,\n uint256 deadline\n ) external;\n\n function redeem(\n address to,\n uint256 chainId,\n IERC20 token,\n uint256 amount\n ) external;\n\n\n function redeemv2(\n bytes32 to,\n uint256 chainId,\n IERC20 token,\n uint256 amount\n ) external;\n\n\n function redeemAndSwap(\n address to,\n uint256 chainId,\n IERC20 token,\n uint256 amount,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 minDy,\n uint256 deadline\n ) external;\n\n function redeemAndRemove(\n address to,\n uint256 chainId,\n IERC20 token,\n uint256 amount,\n uint8 liqTokenIndex,\n uint256 liqMinAmount,\n uint256 liqDeadline\n ) external;\n}\n" + }, + "@openzeppelin/contracts/token/ERC20/ERC20Burnable.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <0.8.0;\n\nimport \"../../utils/Context.sol\";\nimport \"./ERC20.sol\";\n\n/**\n * @dev Extension of {ERC20} that allows token holders to destroy both their own\n * tokens and those that they have an allowance for, in a way that can be\n * recognized off-chain (via event analysis).\n */\nabstract contract ERC20Burnable is Context, ERC20 {\n using SafeMath for uint256;\n\n /**\n * @dev Destroys `amount` tokens from the caller.\n *\n * See {ERC20-_burn}.\n */\n function burn(uint256 amount) public virtual {\n _burn(_msgSender(), amount);\n }\n\n /**\n * @dev Destroys `amount` tokens from `account`, deducting from the caller's\n * allowance.\n *\n * See {ERC20-_burn} and {ERC20-allowance}.\n *\n * Requirements:\n *\n * - the caller must have allowance for ``accounts``'s tokens of at least\n * `amount`.\n */\n function burnFrom(address account, uint256 amount) public virtual {\n uint256 decreasedAllowance = allowance(account, _msgSender()).sub(amount, \"ERC20: burn amount exceeds allowance\");\n\n _approve(account, _msgSender(), decreasedAllowance);\n _burn(account, amount);\n }\n}\n" + }, + "contracts/bridge/wrappers/MoonriverBridgeZap.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.6.12;\n\nimport \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/SafeERC20.sol\";\nimport \"../interfaces/ISwap.sol\";\nimport \"../interfaces/ISynapseBridge.sol\";\nimport \"../interfaces/IWETH9.sol\";\n\ninterface IFrax {\n function exchangeCanonicalForOld(address bridge_token_address, uint256 token_amount) external returns (uint256);\n}\n\ncontract MoonriverBridgeZap {\n using SafeERC20 for IERC20;\n\n ISynapseBridge synapseBridge;\n address payable public immutable WETH_ADDRESS;\n IFrax private constant CANOLICAL_FRAX = IFrax(0x1A93B23281CC1CDE4C4741353F3064709A16197d);\n IERC20 private constant SYN_FRAX = IERC20(0xE96AC70907ffF3Efee79f502C985A7A21Bce407d);\n\n mapping(address => address) public swapMap;\n mapping(address => IERC20[]) public swapTokensMap;\n\n uint256 constant MAX_UINT256 = 2**256 - 1;\n\n constructor(\n address payable _wethAddress,\n address _swapOne,\n address tokenOne,\n address _swapTwo,\n address tokenTwo,\n ISynapseBridge _synapseBridge\n ) public {\n WETH_ADDRESS = _wethAddress;\n synapseBridge = _synapseBridge;\n swapMap[tokenOne] = _swapOne;\n swapMap[tokenTwo] = _swapTwo;\n IERC20(_wethAddress).safeIncreaseAllowance(address(_synapseBridge), MAX_UINT256);\n if (address(_swapOne) != address(0)) {\n {\n uint8 i;\n for (; i < 32; i++) {\n try ISwap(_swapOne).getToken(i) returns (\n IERC20 token\n ) {\n swapTokensMap[_swapOne].push(token);\n token.safeApprove(address(_swapOne), MAX_UINT256);\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n } catch {\n break;\n }\n }\n require(i > 1, \"swap must have at least 2 tokens\");\n }\n }\n if (address(_swapTwo) != address(0)) {\n {\n uint8 i;\n for (; i < 32; i++) {\n try ISwap(_swapTwo).getToken(i) returns (\n IERC20 token\n ) {\n swapTokensMap[_swapTwo].push(token);\n token.safeApprove(address(_swapTwo), MAX_UINT256);\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n } catch {\n break;\n }\n }\n require(i > 1, \"swap must have at least 2 tokens\");\n }\n }\n }\n\n /**\n * @notice Calculate amount of tokens you receive on swap\n * @param tokenIndexFrom the token the user wants to sell\n * @param tokenIndexTo the token the user wants to buy\n * @param dx the amount of tokens the user wants to sell. If the token charges\n * a fee on transfers, use the amount that gets transferred after the fee.\n * @return amount of tokens the user will receive\n */\n function calculateSwap(\n IERC20 token,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx\n ) external view virtual returns (uint256) {\n ISwap swap = ISwap(\n swapMap[address(token)]\n );\n return swap.calculateSwap(tokenIndexFrom, tokenIndexTo, dx);\n }\n\n function swapAndRedeem(\n address to,\n uint256 chainId,\n IERC20 token,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx,\n uint256 minDy,\n uint256 deadline\n ) external {\n ISwap swap = ISwap(swapMap[address(token)]);\n require(address(swap) != address(0), \"Swap is 0x00\");\n IERC20[] memory tokens = swapTokensMap[address(swap)];\n tokens[tokenIndexFrom].safeTransferFrom(\n msg.sender,\n address(this),\n dx\n );\n // swap\n\n uint256 swappedAmount = swap.swap(\n tokenIndexFrom,\n tokenIndexTo,\n dx,\n minDy,\n deadline\n );\n // deposit into bridge, gets nUSD\n if (\n token.allowance(address(this), address(synapseBridge)) <\n swappedAmount\n ) {\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n }\n synapseBridge.redeem(to, chainId, token, swappedAmount);\n }\n\n function swapAndRedeemAndSwap(\n address to,\n uint256 chainId,\n IERC20 token,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx,\n uint256 minDy,\n uint256 deadline,\n uint8 swapTokenIndexFrom,\n uint8 swapTokenIndexTo,\n uint256 swapMinDy,\n uint256 swapDeadline\n ) external {\n require(\n address(swapMap[address(token)]) != address(0),\n \"Swap is 0x00\"\n );\n IERC20[] memory tokens = swapTokensMap[\n swapMap[address(token)]\n ];\n tokens[tokenIndexFrom].safeTransferFrom(\n msg.sender,\n address(this),\n dx\n );\n // swap\n\n uint256 swappedAmount = ISwap(swapMap[address(token)]).swap(tokenIndexFrom, tokenIndexTo, dx, minDy, deadline);\n // deposit into bridge, gets nUSD\n if (\n token.allowance(address(this), address(synapseBridge)) <\n swappedAmount\n ) {\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n }\n synapseBridge.redeemAndSwap(\n to,\n chainId,\n token,\n swappedAmount,\n swapTokenIndexFrom,\n swapTokenIndexTo,\n swapMinDy,\n swapDeadline\n );\n }\n\n function swapAndRedeemAndRemove(\n address to,\n uint256 chainId,\n IERC20 token,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx,\n uint256 minDy,\n uint256 deadline,\n uint8 liqTokenIndex,\n uint256 liqMinAmount,\n uint256 liqDeadline\n ) external {\n ISwap swap = ISwap(swapMap[address(token)]);\n require(address(swap) != address(0), \"Swap is 0x00\");\n IERC20[] memory tokens = swapTokensMap[address(swap)];\n tokens[tokenIndexFrom].safeTransferFrom(\n msg.sender,\n address(this),\n dx\n );\n // swap\n\n uint256 swappedAmount = swap.swap(\n tokenIndexFrom,\n tokenIndexTo,\n dx,\n minDy,\n deadline\n );\n // deposit into bridge, gets nUSD\n if (\n token.allowance(address(this), address(synapseBridge)) <\n swappedAmount\n ) {\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n }\n synapseBridge.redeemAndRemove(\n to,\n chainId,\n token,\n swappedAmount,\n liqTokenIndex,\n liqMinAmount,\n liqDeadline\n );\n }\n\n /**\n * @notice wraps SynapseBridge redeem()\n * @param to address on other chain to redeem underlying assets to\n * @param chainId which underlying chain to bridge assets onto\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n **/\n function redeem(\n address to,\n uint256 chainId,\n IERC20 token,\n uint256 amount\n ) external {\n token.safeTransferFrom(msg.sender, address(this), amount);\n if (address(token) == address(CANOLICAL_FRAX)) {\n uint256 swappedAmount = CANOLICAL_FRAX.exchangeCanonicalForOld(address(SYN_FRAX), amount);\n if (SYN_FRAX.allowance(address(this), address(synapseBridge)) < amount) {\n SYN_FRAX.safeApprove(address(synapseBridge), MAX_UINT256);\n }\n synapseBridge.redeem(to, chainId, SYN_FRAX, swappedAmount);\n } else {\n if (token.allowance(address(this), address(synapseBridge)) < amount) {\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n }\n synapseBridge.redeem(to, chainId, token, amount);\n }\n }\n\n /**\n * @notice Wraps SynapseBridge redeemv2() function\n * @param to address on other chain to bridge assets to\n * @param chainId which chain to bridge assets onto\n * @param token ERC20 compatible token to redeem into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n **/\n function redeemv2(\n bytes32 to,\n uint256 chainId,\n IERC20 token,\n uint256 amount\n ) external {\n token.safeTransferFrom(msg.sender, address(this), amount);\n\n if (token.allowance(address(this), address(synapseBridge)) < amount) {\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n }\n synapseBridge.redeemv2(to, chainId, token, amount);\n }\n\n /**\n * @notice wraps SynapseBridge redeem()\n * @param to address on other chain to redeem underlying assets to\n * @param chainId which underlying chain to bridge assets onto\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n **/\n function deposit(\n address to,\n uint256 chainId,\n IERC20 token,\n uint256 amount\n ) external {\n token.safeTransferFrom(msg.sender, address(this), amount);\n if (token.allowance(address(this), address(synapseBridge)) < amount) {\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n }\n synapseBridge.deposit(to, chainId, token, amount);\n }\n\n /**\n * @notice Wraps SynapseBridge deposit() function to make it compatible w/ ETH -> WETH conversions\n * @param to address on other chain to bridge assets to\n * @param chainId which chain to bridge assets onto\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n **/\n function depositETH(\n address to,\n uint256 chainId,\n uint256 amount\n ) external payable {\n require(msg.value > 0 && msg.value == amount, 'INCORRECT MSG VALUE');\n IWETH9(WETH_ADDRESS).deposit{value: msg.value}();\n synapseBridge.deposit(to, chainId, IERC20(WETH_ADDRESS), amount);\n }\n\n\n\n function swapETHAndRedeem(\n address to,\n uint256 chainId,\n IERC20 token,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx,\n uint256 minDy,\n uint256 deadline\n ) external payable {\n require(WETH_ADDRESS != address(0), \"WETH 0\");\n require(msg.value > 0 && msg.value == dx, \"INCORRECT MSG VALUE\");\n ISwap swap = ISwap(swapMap[address(token)]);\n require(address(swap) != address(0), \"Swap is 0x00\");\n IWETH9(WETH_ADDRESS).deposit{value: msg.value}();\n\n // swap\n uint256 swappedAmount = swap.swap(\n tokenIndexFrom,\n tokenIndexTo,\n dx,\n minDy,\n deadline\n );\n synapseBridge.redeem(to, chainId, token, swappedAmount);\n }\n\n /**\n * @notice Wraps redeemAndSwap on SynapseBridge.sol\n * Relays to nodes that (typically) a wrapped synAsset ERC20 token has been burned and the underlying needs to be redeeemed on the native chain. This function indicates to the nodes that they should attempt to redeem the LP token for the underlying assets (E.g \"swap\" out of the LP token)\n * @param to address on other chain to redeem underlying assets to\n * @param chainId which underlying chain to bridge assets onto\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n * @param tokenIndexFrom the token the user wants to swap from\n * @param tokenIndexTo the token the user wants to swap to\n * @param minDy the min amount the user would like to receive, or revert to only minting the SynERC20 token crosschain.\n * @param deadline latest timestamp to accept this transaction\n **/\n function redeemAndSwap(\n address to,\n uint256 chainId,\n IERC20 token,\n uint256 amount,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 minDy,\n uint256 deadline\n ) external {\n token.safeTransferFrom(msg.sender, address(this), amount);\n if (token.allowance(address(this), address(synapseBridge)) < amount) {\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n }\n synapseBridge.redeemAndSwap(\n to,\n chainId,\n token,\n amount,\n tokenIndexFrom,\n tokenIndexTo,\n minDy,\n deadline\n );\n }\n\n /**\n * @notice Wraps redeemAndRemove on SynapseBridge\n * Relays to nodes that (typically) a wrapped synAsset ERC20 token has been burned and the underlying needs to be redeeemed on the native chain. This function indicates to the nodes that they should attempt to redeem the LP token for the underlying assets (E.g \"swap\" out of the LP token)\n * @param to address on other chain to redeem underlying assets to\n * @param chainId which underlying chain to bridge assets onto\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount of (typically) LP token to pass to the nodes to attempt to removeLiquidity() with to redeem for the underlying assets of the LP token\n * @param liqTokenIndex Specifies which of the underlying LP assets the nodes should attempt to redeem for\n * @param liqMinAmount Specifies the minimum amount of the underlying asset needed for the nodes to execute the redeem/swap\n * @param liqDeadline Specificies the deadline that the nodes are allowed to try to redeem/swap the LP token\n **/\n function redeemAndRemove(\n address to,\n uint256 chainId,\n IERC20 token,\n uint256 amount,\n uint8 liqTokenIndex,\n uint256 liqMinAmount,\n uint256 liqDeadline\n ) external {\n token.safeTransferFrom(msg.sender, address(this), amount);\n if (token.allowance(address(this), address(synapseBridge)) < amount) {\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n }\n synapseBridge.redeemAndRemove(\n to,\n chainId,\n token,\n amount,\n liqTokenIndex,\n liqMinAmount,\n liqDeadline\n );\n }\n}\n" + }, + "contracts/bridge/interfaces/ISwap.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.6.12;\n\nimport '@openzeppelin/contracts/token/ERC20/ERC20.sol';\n\ninterface ISwap {\n // pool data view functions\n function getA() external view returns (uint256);\n\n function getToken(uint8 index) external view returns (IERC20);\n\n function getTokenIndex(address tokenAddress) external view returns (uint8);\n\n function getTokenBalance(uint8 index) external view returns (uint256);\n\n function getVirtualPrice() external view returns (uint256);\n\n // min return calculation functions\n function calculateSwap(\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx\n ) external view returns (uint256);\n\n function calculateTokenAmount(uint256[] calldata amounts, bool deposit)\n external\n view\n returns (uint256);\n\n function calculateRemoveLiquidity(uint256 amount)\n external\n view\n returns (uint256[] memory);\n\n function calculateRemoveLiquidityOneToken(\n uint256 tokenAmount,\n uint8 tokenIndex\n ) external view returns (uint256 availableTokenAmount);\n\n // state modifying functions\n function initialize(\n IERC20[] memory pooledTokens,\n uint8[] memory decimals,\n string memory lpTokenName,\n string memory lpTokenSymbol,\n uint256 a,\n uint256 fee,\n uint256 adminFee,\n address lpTokenTargetAddress\n ) external;\n\n function swap(\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx,\n uint256 minDy,\n uint256 deadline\n ) external returns (uint256);\n\n function addLiquidity(\n uint256[] calldata amounts,\n uint256 minToMint,\n uint256 deadline\n ) external returns (uint256);\n\n function removeLiquidity(\n uint256 amount,\n uint256[] calldata minAmounts,\n uint256 deadline\n ) external returns (uint256[] memory);\n\n function removeLiquidityOneToken(\n uint256 tokenAmount,\n uint8 tokenIndex,\n uint256 minAmount,\n uint256 deadline\n ) external returns (uint256);\n\n function removeLiquidityImbalance(\n uint256[] calldata amounts,\n uint256 maxBurnAmount,\n uint256 deadline\n ) external returns (uint256);\n}\n" + }, + "contracts/bridge/interfaces/IWETH9.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.4.0;\n\ninterface IWETH9 {\n function name() external view returns (string memory);\n\n function symbol() external view returns (string memory);\n\n function decimals() external view returns (uint8);\n\n function balanceOf(address) external view returns (uint256);\n\n function allowance(address, address) external view returns (uint256);\n\n receive() external payable;\n\n function deposit() external payable;\n\n function withdraw(uint256 wad) external;\n\n function totalSupply() external view returns (uint256);\n\n function approve(address guy, uint256 wad) external returns (bool);\n\n function transfer(address dst, uint256 wad) external returns (bool);\n\n function transferFrom(\n address src,\n address dst,\n uint256 wad\n ) external returns (bool);\n}" + }, + "contracts/bridge/wrappers/L2BridgeZap.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.6.12;\n\nimport \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/SafeERC20.sol\";\nimport \"../interfaces/ISwap.sol\";\nimport \"../interfaces/ISynapseBridge.sol\";\nimport \"../interfaces/IWETH9.sol\";\n\ncontract L2BridgeZap {\n using SafeERC20 for IERC20;\n\n ISynapseBridge synapseBridge;\n address payable public immutable WETH_ADDRESS;\n\n mapping(address => address) public swapMap;\n mapping(address => IERC20[]) public swapTokensMap;\n\n uint256 constant MAX_UINT256 = 2**256 - 1;\n\n constructor(\n address payable _wethAddress,\n address _swapOne,\n address tokenOne,\n address _swapTwo,\n address tokenTwo,\n ISynapseBridge _synapseBridge\n ) public {\n WETH_ADDRESS = _wethAddress;\n synapseBridge = _synapseBridge;\n swapMap[tokenOne] = _swapOne;\n swapMap[tokenTwo] = _swapTwo;\n if (_wethAddress != address(0)) {\n IERC20(_wethAddress).safeIncreaseAllowance(address(_synapseBridge), MAX_UINT256);\n }\n if (address(_swapOne) != address(0)) {\n {\n uint8 i;\n for (; i < 32; i++) {\n try ISwap(_swapOne).getToken(i) returns (\n IERC20 token\n ) {\n swapTokensMap[_swapOne].push(token);\n token.safeApprove(address(_swapOne), MAX_UINT256);\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n } catch {\n break;\n }\n }\n require(i > 1, \"swap must have at least 2 tokens\");\n }\n }\n if (address(_swapTwo) != address(0)) {\n {\n uint8 i;\n for (; i < 32; i++) {\n try ISwap(_swapTwo).getToken(i) returns (\n IERC20 token\n ) {\n swapTokensMap[_swapTwo].push(token);\n token.safeApprove(address(_swapTwo), MAX_UINT256);\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n } catch {\n break;\n }\n }\n require(i > 1, \"swap must have at least 2 tokens\");\n }\n }\n }\n\n /**\n * @notice Calculate amount of tokens you receive on swap\n * @param tokenIndexFrom the token the user wants to sell\n * @param tokenIndexTo the token the user wants to buy\n * @param dx the amount of tokens the user wants to sell. If the token charges\n * a fee on transfers, use the amount that gets transferred after the fee.\n * @return amount of tokens the user will receive\n */\n function calculateSwap(\n IERC20 token,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx\n ) external view virtual returns (uint256) {\n ISwap swap = ISwap(\n swapMap[address(token)]\n );\n return swap.calculateSwap(tokenIndexFrom, tokenIndexTo, dx);\n }\n\n function swapAndRedeem(\n address to,\n uint256 chainId,\n IERC20 token,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx,\n uint256 minDy,\n uint256 deadline\n ) external {\n ISwap swap = ISwap(swapMap[address(token)]);\n require(address(swap) != address(0), \"Swap is 0x00\");\n IERC20[] memory tokens = swapTokensMap[address(swap)];\n tokens[tokenIndexFrom].safeTransferFrom(\n msg.sender,\n address(this),\n dx\n );\n // swap\n\n uint256 swappedAmount = swap.swap(\n tokenIndexFrom,\n tokenIndexTo,\n dx,\n minDy,\n deadline\n );\n // deposit into bridge, gets nUSD\n if (\n token.allowance(address(this), address(synapseBridge)) <\n swappedAmount\n ) {\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n }\n synapseBridge.redeem(to, chainId, token, swappedAmount);\n }\n\n function swapAndRedeemAndSwap(\n address to,\n uint256 chainId,\n IERC20 token,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx,\n uint256 minDy,\n uint256 deadline,\n uint8 swapTokenIndexFrom,\n uint8 swapTokenIndexTo,\n uint256 swapMinDy,\n uint256 swapDeadline\n ) external {\n require(\n address(swapMap[address(token)]) != address(0),\n \"Swap is 0x00\"\n );\n IERC20[] memory tokens = swapTokensMap[\n swapMap[address(token)]\n ];\n tokens[tokenIndexFrom].safeTransferFrom(\n msg.sender,\n address(this),\n dx\n );\n // swap\n\n uint256 swappedAmount = ISwap(swapMap[address(token)]).swap(tokenIndexFrom, tokenIndexTo, dx, minDy, deadline);\n // deposit into bridge, gets nUSD\n if (\n token.allowance(address(this), address(synapseBridge)) <\n swappedAmount\n ) {\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n }\n synapseBridge.redeemAndSwap(\n to,\n chainId,\n token,\n swappedAmount,\n swapTokenIndexFrom,\n swapTokenIndexTo,\n swapMinDy,\n swapDeadline\n );\n }\n\n function swapAndRedeemAndRemove(\n address to,\n uint256 chainId,\n IERC20 token,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx,\n uint256 minDy,\n uint256 deadline,\n uint8 liqTokenIndex,\n uint256 liqMinAmount,\n uint256 liqDeadline\n ) external {\n ISwap swap = ISwap(swapMap[address(token)]);\n require(address(swap) != address(0), \"Swap is 0x00\");\n IERC20[] memory tokens = swapTokensMap[address(swap)];\n tokens[tokenIndexFrom].safeTransferFrom(\n msg.sender,\n address(this),\n dx\n );\n // swap\n\n uint256 swappedAmount = swap.swap(\n tokenIndexFrom,\n tokenIndexTo,\n dx,\n minDy,\n deadline\n );\n // deposit into bridge, gets nUSD\n if (\n token.allowance(address(this), address(synapseBridge)) <\n swappedAmount\n ) {\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n }\n synapseBridge.redeemAndRemove(\n to,\n chainId,\n token,\n swappedAmount,\n liqTokenIndex,\n liqMinAmount,\n liqDeadline\n );\n }\n\n /**\n * @notice wraps SynapseBridge redeem()\n * @param to address on other chain to redeem underlying assets to\n * @param chainId which underlying chain to bridge assets onto\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n **/\n function redeem(\n address to,\n uint256 chainId,\n IERC20 token,\n uint256 amount\n ) external {\n token.safeTransferFrom(msg.sender, address(this), amount);\n if (token.allowance(address(this), address(synapseBridge)) < amount) {\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n }\n synapseBridge.redeem(to, chainId, token, amount);\n }\n\n /**\n * @notice wraps SynapseBridge redeem()\n * @param to address on other chain to redeem underlying assets to\n * @param chainId which underlying chain to bridge assets onto\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n **/\n function deposit(\n address to,\n uint256 chainId,\n IERC20 token,\n uint256 amount\n ) external {\n token.safeTransferFrom(msg.sender, address(this), amount);\n if (token.allowance(address(this), address(synapseBridge)) < amount) {\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n }\n synapseBridge.deposit(to, chainId, token, amount);\n }\n\n /**\n * @notice Wraps SynapseBridge deposit() function to make it compatible w/ ETH -> WETH conversions\n * @param to address on other chain to bridge assets to\n * @param chainId which chain to bridge assets onto\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n **/\n function depositETH(\n address to,\n uint256 chainId,\n uint256 amount\n ) external payable {\n require(msg.value > 0 && msg.value == amount, 'INCORRECT MSG VALUE');\n IWETH9(WETH_ADDRESS).deposit{value: msg.value}();\n synapseBridge.deposit(to, chainId, IERC20(WETH_ADDRESS), amount);\n }\n\n\n /**\n * @notice Wraps SynapseBridge depositAndSwap() function to make it compatible w/ ETH -> WETH conversions\n * @param to address on other chain to bridge assets to\n * @param chainId which chain to bridge assets onto\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n * @param tokenIndexFrom the token the user wants to swap from\n * @param tokenIndexTo the token the user wants to swap to\n * @param minDy the min amount the user would like to receive, or revert to only minting the SynERC20 token crosschain.\n * @param deadline latest timestamp to accept this transaction\n **/\n function depositETHAndSwap(\n address to,\n uint256 chainId,\n uint256 amount,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 minDy,\n uint256 deadline\n ) external payable {\n require(msg.value > 0 && msg.value == amount, 'INCORRECT MSG VALUE');\n IWETH9(WETH_ADDRESS).deposit{value: msg.value}();\n synapseBridge.depositAndSwap(to, chainId, IERC20(WETH_ADDRESS), amount, tokenIndexFrom, tokenIndexTo, minDy, deadline);\n }\n\n\n function swapETHAndRedeem(\n address to,\n uint256 chainId,\n IERC20 token,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx,\n uint256 minDy,\n uint256 deadline\n ) external payable {\n require(WETH_ADDRESS != address(0), \"WETH 0\");\n require(msg.value > 0 && msg.value == dx, \"INCORRECT MSG VALUE\");\n ISwap swap = ISwap(swapMap[address(token)]);\n require(address(swap) != address(0), \"Swap is 0x00\");\n IWETH9(WETH_ADDRESS).deposit{value: msg.value}();\n\n // swap\n uint256 swappedAmount = swap.swap(\n tokenIndexFrom,\n tokenIndexTo,\n dx,\n minDy,\n deadline\n );\n synapseBridge.redeem(to, chainId, token, swappedAmount);\n }\n\n\n function swapETHAndRedeemAndSwap(\n address to,\n uint256 chainId,\n IERC20 token,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx,\n uint256 minDy,\n uint256 deadline,\n uint8 swapTokenIndexFrom,\n uint8 swapTokenIndexTo,\n uint256 swapMinDy,\n uint256 swapDeadline\n ) external payable {\n require(WETH_ADDRESS != address(0), \"WETH 0\");\n require(msg.value > 0 && msg.value == dx, \"INCORRECT MSG VALUE\");\n ISwap swap = ISwap(swapMap[address(token)]);\n require(address(swap) != address(0), \"Swap is 0x00\");\n IWETH9(WETH_ADDRESS).deposit{value: msg.value}();\n\n // swap\n uint256 swappedAmount = swap.swap(\n tokenIndexFrom,\n tokenIndexTo,\n dx,\n minDy,\n deadline\n );\n synapseBridge.redeemAndSwap(to, chainId, token, swappedAmount,swapTokenIndexFrom,\n swapTokenIndexTo,\n swapMinDy,\n swapDeadline);\n }\n\n\n /**\n * @notice Wraps redeemAndSwap on SynapseBridge.sol\n * Relays to nodes that (typically) a wrapped synAsset ERC20 token has been burned and the underlying needs to be redeeemed on the native chain. This function indicates to the nodes that they should attempt to redeem the LP token for the underlying assets (E.g \"swap\" out of the LP token)\n * @param to address on other chain to redeem underlying assets to\n * @param chainId which underlying chain to bridge assets onto\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n * @param tokenIndexFrom the token the user wants to swap from\n * @param tokenIndexTo the token the user wants to swap to\n * @param minDy the min amount the user would like to receive, or revert to only minting the SynERC20 token crosschain.\n * @param deadline latest timestamp to accept this transaction\n **/\n function redeemAndSwap(\n address to,\n uint256 chainId,\n IERC20 token,\n uint256 amount,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 minDy,\n uint256 deadline\n ) external {\n token.safeTransferFrom(msg.sender, address(this), amount);\n if (token.allowance(address(this), address(synapseBridge)) < amount) {\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n }\n synapseBridge.redeemAndSwap(\n to,\n chainId,\n token,\n amount,\n tokenIndexFrom,\n tokenIndexTo,\n minDy,\n deadline\n );\n }\n\n /**\n * @notice Wraps redeemAndRemove on SynapseBridge\n * Relays to nodes that (typically) a wrapped synAsset ERC20 token has been burned and the underlying needs to be redeeemed on the native chain. This function indicates to the nodes that they should attempt to redeem the LP token for the underlying assets (E.g \"swap\" out of the LP token)\n * @param to address on other chain to redeem underlying assets to\n * @param chainId which underlying chain to bridge assets onto\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount of (typically) LP token to pass to the nodes to attempt to removeLiquidity() with to redeem for the underlying assets of the LP token\n * @param liqTokenIndex Specifies which of the underlying LP assets the nodes should attempt to redeem for\n * @param liqMinAmount Specifies the minimum amount of the underlying asset needed for the nodes to execute the redeem/swap\n * @param liqDeadline Specificies the deadline that the nodes are allowed to try to redeem/swap the LP token\n **/\n function redeemAndRemove(\n address to,\n uint256 chainId,\n IERC20 token,\n uint256 amount,\n uint8 liqTokenIndex,\n uint256 liqMinAmount,\n uint256 liqDeadline\n ) external {\n token.safeTransferFrom(msg.sender, address(this), amount);\n if (token.allowance(address(this), address(synapseBridge)) < amount) {\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n }\n synapseBridge.redeemAndRemove(\n to,\n chainId,\n token,\n amount,\n liqTokenIndex,\n liqMinAmount,\n liqDeadline\n );\n }\n\n /**\n * @notice Wraps SynapseBridge redeemv2() function\n * @param to address on other chain to bridge assets to\n * @param chainId which chain to bridge assets onto\n * @param token ERC20 compatible token to redeem into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n **/\n function redeemv2(\n bytes32 to,\n uint256 chainId,\n IERC20 token,\n uint256 amount\n ) external {\n token.safeTransferFrom(msg.sender, address(this), amount);\n\n if (token.allowance(address(this), address(synapseBridge)) < amount) {\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n }\n synapseBridge.redeemv2(to, chainId, token, amount);\n }\n}\n" + }, + "contracts/bridge/wrappers/L1BridgeZap.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.6.12;\n\nimport '@openzeppelin/contracts/token/ERC20/IERC20.sol';\nimport '@openzeppelin/contracts/token/ERC20/SafeERC20.sol';\nimport '../interfaces/ISwap.sol';\nimport '../interfaces/ISynapseBridge.sol';\nimport \"../interfaces/IWETH9.sol\";\n\n\n/**\n * @title L1BridgeZap\n * @notice This contract is responsible for handling user Zaps into the SynapseBridge contract, through the Synapse Swap contracts. It does so\n * It does so by combining the action of addLiquidity() to the base swap pool, and then calling either deposit() or depositAndSwap() on the bridge.\n * This is done in hopes of automating portions of the bridge user experience to users, while keeping the SynapseBridge contract logic small.\n *\n * @dev This contract should be deployed with a base Swap.sol address and a SynapseBridge.sol address, otherwise, it will not function.\n */\ncontract L1BridgeZap {\n using SafeERC20 for IERC20;\n\n uint256 constant MAX_UINT256 = 2**256 - 1;\n \n ISwap baseSwap;\n ISynapseBridge synapseBridge;\n IERC20[] public baseTokens;\n address payable public immutable WETH_ADDRESS;\n \n\n /**\n * @notice Constructs the contract, approves each token inside of baseSwap to be used by baseSwap (needed for addLiquidity())\n */\n constructor(address payable _wethAddress, ISwap _baseSwap, ISynapseBridge _synapseBridge) public {\n WETH_ADDRESS = _wethAddress;\n baseSwap = _baseSwap;\n synapseBridge = _synapseBridge;\n IERC20(_wethAddress).safeIncreaseAllowance(address(_synapseBridge), MAX_UINT256);\n if (address(_baseSwap) != address(0)) {\n {\n uint8 i;\n for (; i < 32; i++) {\n try _baseSwap.getToken(i) returns (IERC20 token) {\n baseTokens.push(token);\n token.safeIncreaseAllowance(address(_baseSwap), MAX_UINT256);\n } catch {\n break;\n }\n }\n require(i > 1, 'baseSwap must have at least 2 tokens');\n }\n }\n }\n \n /**\n * @notice Wraps SynapseBridge deposit() function to make it compatible w/ ETH -> WETH conversions\n * @param to address on other chain to bridge assets to\n * @param chainId which chain to bridge assets onto\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n **/\n function depositETH(\n address to,\n uint256 chainId,\n uint256 amount\n ) external payable {\n require(msg.value > 0 && msg.value == amount, 'INCORRECT MSG VALUE');\n IWETH9(WETH_ADDRESS).deposit{value: msg.value}();\n synapseBridge.deposit(to, chainId, IERC20(WETH_ADDRESS), amount);\n }\n\n /**\n * @notice Wraps SynapseBridge depositAndSwap() function to make it compatible w/ ETH -> WETH conversions\n * @param to address on other chain to bridge assets to\n * @param chainId which chain to bridge assets onto\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n * @param tokenIndexFrom the token the user wants to swap from\n * @param tokenIndexTo the token the user wants to swap to\n * @param minDy the min amount the user would like to receive, or revert to only minting the SynERC20 token crosschain.\n * @param deadline latest timestamp to accept this transaction\n **/\n function depositETHAndSwap(\n address to,\n uint256 chainId,\n uint256 amount,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 minDy,\n uint256 deadline\n ) external payable {\n require(msg.value > 0 && msg.value == amount, 'INCORRECT MSG VALUE');\n IWETH9(WETH_ADDRESS).deposit{value: msg.value}();\n synapseBridge.depositAndSwap(to, chainId, IERC20(WETH_ADDRESS), amount, tokenIndexFrom, tokenIndexTo, minDy, deadline);\n }\n\n\n /**\n * @notice A simple method to calculate prices from deposits or\n * withdrawals, excluding fees but including slippage. This is\n * helpful as an input into the various \"min\" parameters on calls\n * to fight front-running\n *\n * @dev This shouldn't be used outside frontends for user estimates.\n *\n * @param amounts an array of token amounts to deposit or withdrawal,\n * corresponding to pooledTokens. The amount should be in each\n * pooled token's native precision.\n * @param deposit whether this is a deposit or a withdrawal\n * @return token amount the user will receive\n */\n function calculateTokenAmount(uint256[] calldata amounts, bool deposit)\n external\n view\n virtual\n returns (uint256)\n {\n return baseSwap.calculateTokenAmount(amounts, deposit);\n }\n\n /**\n * @notice Calculate the amount of underlying token available to withdraw\n * when withdrawing via only single token\n * @param tokenAmount the amount of LP token to burn\n * @param tokenIndex index of which token will be withdrawn\n * @return availableTokenAmount calculated amount of underlying token\n * available to withdraw\n */\n function calculateRemoveLiquidityOneToken(\n uint256 tokenAmount,\n uint8 tokenIndex\n ) external view virtual returns (uint256 availableTokenAmount) {\n return baseSwap.calculateRemoveLiquidityOneToken(tokenAmount, tokenIndex);\n }\n\n\n /**\n * @notice Combines adding liquidity to the given Swap, and calls deposit() on the bridge using that LP token\n * @param to address on other chain to bridge assets to\n * @param chainId which chain to bridge assets onto\n * @param token ERC20 compatible token to deposit into the bridge\n * @param liquidityAmounts the amounts of each token to add, in their native precision\n * @param minToMint the minimum LP tokens adding this amount of liquidity\n * should mint, otherwise revert. Handy for front-running mitigation\n * @param deadline latest timestamp to accept this transaction\n **/\n function zapAndDeposit(\n address to,\n uint256 chainId,\n IERC20 token,\n uint256[] calldata liquidityAmounts,\n uint256 minToMint,\n uint256 deadline\n ) external {\n // add liquidity\n for (uint256 i = 0; i < baseTokens.length; i++) {\n if (liquidityAmounts[i] != 0) {\n baseTokens[i].safeTransferFrom(\n msg.sender,\n address(this),\n liquidityAmounts[i]\n );\n }\n }\n\n uint256 liqAdded = baseSwap.addLiquidity(\n liquidityAmounts,\n minToMint,\n deadline\n );\n // deposit into bridge, gets nUSD\n if (token.allowance(address(this), address(synapseBridge)) < liqAdded) {\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n }\n synapseBridge.deposit(to, chainId, token, liqAdded);\n }\n\n /**\n * @notice Combines adding liquidity to the given Swap, and calls depositAndSwap() on the bridge using that LP token\n * @param to address on other chain to bridge assets to\n * @param chainId which chain to bridge assets onto\n * @param token ERC20 compatible token to deposit into the bridge\n * @param liquidityAmounts the amounts of each token to add, in their native precision\n * @param minToMint the minimum LP tokens adding this amount of liquidity\n * should mint, otherwise revert. Handy for front-running mitigation\n * @param liqDeadline latest timestamp to accept this transaction\n * @param tokenIndexFrom the token the user wants to swap from\n * @param tokenIndexTo the token the user wants to swap to\n * @param minDy the min amount the user would like to receive, or revert to only minting the SynERC20 token crosschain.\n * @param swapDeadline latest timestamp to accept this transaction\n **/\n function zapAndDepositAndSwap(\n address to,\n uint256 chainId,\n IERC20 token,\n uint256[] calldata liquidityAmounts,\n uint256 minToMint,\n uint256 liqDeadline,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 minDy,\n uint256 swapDeadline\n ) external {\n // add liquidity\n for (uint256 i = 0; i < baseTokens.length; i++) {\n if (liquidityAmounts[i] != 0) {\n baseTokens[i].safeTransferFrom(\n msg.sender,\n address(this),\n liquidityAmounts[i]\n );\n }\n }\n\n uint256 liqAdded = baseSwap.addLiquidity(\n liquidityAmounts,\n minToMint,\n liqDeadline\n );\n // deposit into bridge, bridge attemps to swap into desired asset\n if (token.allowance(address(this), address(synapseBridge)) < liqAdded) {\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n }\n synapseBridge.depositAndSwap(\n to,\n chainId,\n token,\n liqAdded,\n tokenIndexFrom,\n tokenIndexTo,\n minDy,\n swapDeadline\n );\n }\n\n /**\n * @notice Wraps SynapseBridge deposit() function\n * @param to address on other chain to bridge assets to\n * @param chainId which chain to bridge assets onto\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n **/\n function deposit(\n address to,\n uint256 chainId,\n IERC20 token,\n uint256 amount\n ) external {\n token.safeTransferFrom(msg.sender, address(this), amount);\n\n if (token.allowance(address(this), address(synapseBridge)) < amount) {\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n }\n synapseBridge.deposit(to, chainId, token, amount);\n }\n \n /**\n * @notice Wraps SynapseBridge depositAndSwap() function\n * @param to address on other chain to bridge assets to\n * @param chainId which chain to bridge assets onto\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n * @param tokenIndexFrom the token the user wants to swap from\n * @param tokenIndexTo the token the user wants to swap to\n * @param minDy the min amount the user would like to receive, or revert to only minting the SynERC20 token crosschain.\n * @param deadline latest timestamp to accept this transaction\n **/\n function depositAndSwap(\n address to,\n uint256 chainId,\n IERC20 token,\n uint256 amount,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 minDy,\n uint256 deadline\n ) external {\n token.safeTransferFrom(msg.sender, address(this), amount);\n \n if (token.allowance(address(this), address(synapseBridge)) < amount) {\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n }\n synapseBridge.depositAndSwap(to, chainId, token, amount, tokenIndexFrom, tokenIndexTo, minDy, deadline);\n }\n\n\n /**\n * @notice Wraps SynapseBridge redeem() function\n * @param to address on other chain to bridge assets to\n * @param chainId which chain to bridge assets onto\n * @param token ERC20 compatible token to redeem into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n **/\n function redeem(\n address to,\n uint256 chainId,\n IERC20 token,\n uint256 amount\n ) external {\n token.safeTransferFrom(msg.sender, address(this), amount);\n\n if (token.allowance(address(this), address(synapseBridge)) < amount) {\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n }\n synapseBridge.redeem(to, chainId, token, amount);\n }\n\n /**\n * @notice Wraps SynapseBridge redeemv2() function\n * @param to address on other chain to bridge assets to\n * @param chainId which chain to bridge assets onto\n * @param token ERC20 compatible token to redeem into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n **/\n function redeemv2(\n bytes32 to,\n uint256 chainId,\n IERC20 token,\n uint256 amount\n ) external {\n token.safeTransferFrom(msg.sender, address(this), amount);\n\n if (token.allowance(address(this), address(synapseBridge)) < amount) {\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n }\n synapseBridge.redeemv2(to, chainId, token, amount);\n }\n\n}\n" + }, + "contracts/bridge/wrappers/MigratorBridgeZap.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.6.12;\n\nimport '@openzeppelin/contracts/token/ERC20/IERC20.sol';\nimport '@openzeppelin/contracts/token/ERC20/SafeERC20.sol';\nimport '@openzeppelin/contracts/math/SafeMath.sol';\n\nimport '../interfaces/ISynapseBridge.sol';\nimport '../interfaces/IERC20Migrator.sol';\n\ncontract MigratorBridgeZap {\n using SafeERC20 for IERC20;\n using SafeMath for uint256;\n \n ISynapseBridge constant synapseBridge = ISynapseBridge(0xd123f70AE324d34A9E76b67a27bf77593bA8749f);\n IERC20Migrator constant erc20Migrator = IERC20Migrator(0xf0284FB86adA5E4D82555C529677eEA3B2C3E022); \n IERC20 constant legacyToken = IERC20(0x42F6f551ae042cBe50C739158b4f0CAC0Edb9096);\n IERC20 constant newToken = IERC20(0xa4080f1778e69467E905B8d6F72f6e441f9e9484);\n uint256 constant MAX_UINT256 = 2**256 - 1;\n\n constructor() public {\n legacyToken.safeApprove(address(erc20Migrator), MAX_UINT256);\n newToken.safeApprove(address(synapseBridge), MAX_UINT256);\n }\n\n function migrate(uint256 amount) external {\n legacyToken.safeTransferFrom(msg.sender, address(this), amount);\n erc20Migrator.migrate(amount);\n newToken.safeTransfer(msg.sender, amount.mul(5).div(2));\n }\n\n function migrateAndBridge(uint256 amount, address to, uint256 chainId) external {\n legacyToken.safeTransferFrom(msg.sender, address(this), amount);\n erc20Migrator.migrate(amount);\n synapseBridge.redeem(to, chainId, newToken, amount.mul(5).div(2));\n }\n}" + }, + "contracts/bridge/interfaces/IERC20Migrator.sol": { + "content": "// SPDX-License-Identifier: MIT\n\n\npragma solidity 0.6.12;\n\ninterface IERC20Migrator { \n function migrate(uint256 amount) external;\n}\n\n" + }, + "contracts/bridge/wrappers/JewelBridgeSwap.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.6.12;\n\nimport '@openzeppelin/contracts/token/ERC20/ERC20.sol';\nimport \"@openzeppelin/contracts/token/ERC20/SafeERC20.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/ERC20Burnable.sol\";\nimport \"@openzeppelin/contracts/math/SafeMath.sol\";\n\ninterface IERC20Mintable is IERC20 {\n function mint(address to, uint256 amount) external;\n}\n\ncontract JewelBridgeSwap {\n using SafeERC20 for IERC20;\n using SafeERC20 for IERC20Mintable;\n using SafeMath for uint256;\n\n // Maps token address to an index in the pool. Used to prevent duplicate tokens in the pool.\n // getTokenIndex function also relies on this mapping to retrieve token index.\n mapping(address => uint8) private tokenIndexes;\n IERC20[2] pooledTokens;\n \n constructor(IERC20 tokenA, IERC20 mintableTokenB) public {\n pooledTokens[0] = tokenA;\n pooledTokens[1] = mintableTokenB;\n tokenIndexes[address(tokenA)] = 0;\n tokenIndexes[address(mintableTokenB)] = 1;\n }\n\n /**\n * @notice Return address of the pooled token at given index. Reverts if tokenIndex is out of range.\n * @param index the index of the token\n * @return address of the token at given index\n */\n function getToken(uint8 index) public view returns (IERC20) {\n require(index < pooledTokens.length, \"Out of range\");\n return pooledTokens[index];\n }\n\n /**\n * @notice Return the index of the given token address. Reverts if no matching\n * token is found.\n * @param tokenAddress address of the token\n * @return the index of the given token address\n */\n function getTokenIndex(address tokenAddress)\n public\n view\n returns (uint8)\n {\n uint8 index = tokenIndexes[tokenAddress];\n require(\n address(getToken(index)) == tokenAddress,\n \"Token does not exist\"\n );\n return index;\n }\n\n /**\n * @notice Calculate amount of tokens you receive on swap\n * @param tokenIndexFrom the token the user wants to sell\n * @param tokenIndexTo the token the user wants to buy\n * @param dx the amount of tokens the user wants to swap. \n * @return amount of tokens the user will receive\n */\n function calculateSwap(\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx\n ) external view returns (uint256) {\n return dx;\n }\n\n /**\n * @notice Swap two tokens using this pool\n * @param tokenIndexFrom the token the user wants to swap from\n * @param tokenIndexTo the token the user wants to swap to\n * @param dx the amount of tokens the user wants to swap from\n * @param minDy the min amount the user would like to receive, or revert.\n * @param deadline latest timestamp to accept this transaction\n */\n function swap(\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx,\n uint256 minDy,\n uint256 deadline\n )\n external\n returns (uint256)\n {\n {\n IERC20 tokenFrom = pooledTokens[tokenIndexFrom];\n require(\n dx <= tokenFrom.balanceOf(msg.sender),\n \"Cannot swap more than you own\"\n );\n // Transfer tokens first to see if a fee was charged on transfer\n uint256 beforeBalance = tokenFrom.balanceOf(address(this));\n tokenFrom.safeTransferFrom(msg.sender, address(this), dx);\n\n // Use the actual transferred amount for AMM math\n dx = tokenFrom.balanceOf(address(this)).sub(beforeBalance);\n }\n\n // redeem JEWEL for synJEWEL\n if (tokenIndexFrom == 0 && tokenIndexTo == 1) {\n IERC20Mintable(address(pooledTokens[tokenIndexTo])).mint(msg.sender, dx);\n return dx;\n // redeem synJEWEL for JEWEL\n } else if (tokenIndexFrom == 1 && tokenIndexTo == 0) {\n ERC20Burnable(address(pooledTokens[tokenIndexFrom])).burn(dx);\n pooledTokens[tokenIndexTo].safeTransfer(msg.sender, dx);\n return dx;\n } else {\n revert(\"Unsupported indexes\");\n }\n }\n}" + }, + "contracts/bridge/testing/SynapseToken.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity >=0.6.0 <0.8.0;\n\n\nimport \"@openzeppelin/contracts/token/ERC20/ERC20.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/ERC20Burnable.sol\";\nimport \"@openzeppelin/contracts/access/AccessControl.sol\";\nimport \"@openzeppelin/contracts/drafts/ERC20Permit.sol\";\n\ncontract Synapse is ERC20, ERC20Burnable, AccessControl, ERC20Permit {\n bytes32 public constant MINTER_ROLE = keccak256(\"MINTER_ROLE\");\n\n constructor() public ERC20(\"Synapse\", \"SYN\") ERC20Permit(\"Synapse\") {\n _setupRole(DEFAULT_ADMIN_ROLE, msg.sender);\n _setupRole(MINTER_ROLE, msg.sender);\n }\n\n function mint(address to, uint256 amount) external {\n require(hasRole(MINTER_ROLE, msg.sender));\n _mint(to, amount);\n }\n}" + }, + "@openzeppelin/contracts/access/AccessControl.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <0.8.0;\n\nimport \"../utils/EnumerableSet.sol\";\nimport \"../utils/Address.sol\";\nimport \"../utils/Context.sol\";\n\n/**\n * @dev Contract module that allows children to implement role-based access\n * control mechanisms.\n *\n * Roles are referred to by their `bytes32` identifier. These should be exposed\n * in the external API and be unique. The best way to achieve this is by\n * using `public constant` hash digests:\n *\n * ```\n * bytes32 public constant MY_ROLE = keccak256(\"MY_ROLE\");\n * ```\n *\n * Roles can be used to represent a set of permissions. To restrict access to a\n * function call, use {hasRole}:\n *\n * ```\n * function foo() public {\n * require(hasRole(MY_ROLE, msg.sender));\n * ...\n * }\n * ```\n *\n * Roles can be granted and revoked dynamically via the {grantRole} and\n * {revokeRole} functions. Each role has an associated admin role, and only\n * accounts that have a role's admin role can call {grantRole} and {revokeRole}.\n *\n * By default, the admin role for all roles is `DEFAULT_ADMIN_ROLE`, which means\n * that only accounts with this role will be able to grant or revoke other\n * roles. More complex role relationships can be created by using\n * {_setRoleAdmin}.\n *\n * WARNING: The `DEFAULT_ADMIN_ROLE` is also its own admin: it has permission to\n * grant and revoke this role. Extra precautions should be taken to secure\n * accounts that have been granted it.\n */\nabstract contract AccessControl is Context {\n using EnumerableSet for EnumerableSet.AddressSet;\n using Address for address;\n\n struct RoleData {\n EnumerableSet.AddressSet members;\n bytes32 adminRole;\n }\n\n mapping (bytes32 => RoleData) private _roles;\n\n bytes32 public constant DEFAULT_ADMIN_ROLE = 0x00;\n\n /**\n * @dev Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole`\n *\n * `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite\n * {RoleAdminChanged} not being emitted signaling this.\n *\n * _Available since v3.1._\n */\n event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole);\n\n /**\n * @dev Emitted when `account` is granted `role`.\n *\n * `sender` is the account that originated the contract call, an admin role\n * bearer except when using {_setupRole}.\n */\n event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender);\n\n /**\n * @dev Emitted when `account` is revoked `role`.\n *\n * `sender` is the account that originated the contract call:\n * - if using `revokeRole`, it is the admin role bearer\n * - if using `renounceRole`, it is the role bearer (i.e. `account`)\n */\n event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender);\n\n /**\n * @dev Returns `true` if `account` has been granted `role`.\n */\n function hasRole(bytes32 role, address account) public view returns (bool) {\n return _roles[role].members.contains(account);\n }\n\n /**\n * @dev Returns the number of accounts that have `role`. Can be used\n * together with {getRoleMember} to enumerate all bearers of a role.\n */\n function getRoleMemberCount(bytes32 role) public view returns (uint256) {\n return _roles[role].members.length();\n }\n\n /**\n * @dev Returns one of the accounts that have `role`. `index` must be a\n * value between 0 and {getRoleMemberCount}, non-inclusive.\n *\n * Role bearers are not sorted in any particular way, and their ordering may\n * change at any point.\n *\n * WARNING: When using {getRoleMember} and {getRoleMemberCount}, make sure\n * you perform all queries on the same block. See the following\n * https://forum.openzeppelin.com/t/iterating-over-elements-on-enumerableset-in-openzeppelin-contracts/2296[forum post]\n * for more information.\n */\n function getRoleMember(bytes32 role, uint256 index) public view returns (address) {\n return _roles[role].members.at(index);\n }\n\n /**\n * @dev Returns the admin role that controls `role`. See {grantRole} and\n * {revokeRole}.\n *\n * To change a role's admin, use {_setRoleAdmin}.\n */\n function getRoleAdmin(bytes32 role) public view returns (bytes32) {\n return _roles[role].adminRole;\n }\n\n /**\n * @dev Grants `role` to `account`.\n *\n * If `account` had not been already granted `role`, emits a {RoleGranted}\n * event.\n *\n * Requirements:\n *\n * - the caller must have ``role``'s admin role.\n */\n function grantRole(bytes32 role, address account) public virtual {\n require(hasRole(_roles[role].adminRole, _msgSender()), \"AccessControl: sender must be an admin to grant\");\n\n _grantRole(role, account);\n }\n\n /**\n * @dev Revokes `role` from `account`.\n *\n * If `account` had been granted `role`, emits a {RoleRevoked} event.\n *\n * Requirements:\n *\n * - the caller must have ``role``'s admin role.\n */\n function revokeRole(bytes32 role, address account) public virtual {\n require(hasRole(_roles[role].adminRole, _msgSender()), \"AccessControl: sender must be an admin to revoke\");\n\n _revokeRole(role, account);\n }\n\n /**\n * @dev Revokes `role` from the calling account.\n *\n * Roles are often managed via {grantRole} and {revokeRole}: this function's\n * purpose is to provide a mechanism for accounts to lose their privileges\n * if they are compromised (such as when a trusted device is misplaced).\n *\n * If the calling account had been granted `role`, emits a {RoleRevoked}\n * event.\n *\n * Requirements:\n *\n * - the caller must be `account`.\n */\n function renounceRole(bytes32 role, address account) public virtual {\n require(account == _msgSender(), \"AccessControl: can only renounce roles for self\");\n\n _revokeRole(role, account);\n }\n\n /**\n * @dev Grants `role` to `account`.\n *\n * If `account` had not been already granted `role`, emits a {RoleGranted}\n * event. Note that unlike {grantRole}, this function doesn't perform any\n * checks on the calling account.\n *\n * [WARNING]\n * ====\n * This function should only be called from the constructor when setting\n * up the initial roles for the system.\n *\n * Using this function in any other way is effectively circumventing the admin\n * system imposed by {AccessControl}.\n * ====\n */\n function _setupRole(bytes32 role, address account) internal virtual {\n _grantRole(role, account);\n }\n\n /**\n * @dev Sets `adminRole` as ``role``'s admin role.\n *\n * Emits a {RoleAdminChanged} event.\n */\n function _setRoleAdmin(bytes32 role, bytes32 adminRole) internal virtual {\n emit RoleAdminChanged(role, _roles[role].adminRole, adminRole);\n _roles[role].adminRole = adminRole;\n }\n\n function _grantRole(bytes32 role, address account) private {\n if (_roles[role].members.add(account)) {\n emit RoleGranted(role, account, _msgSender());\n }\n }\n\n function _revokeRole(bytes32 role, address account) private {\n if (_roles[role].members.remove(account)) {\n emit RoleRevoked(role, account, _msgSender());\n }\n }\n}\n" + }, + "@openzeppelin/contracts/drafts/ERC20Permit.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.5 <0.8.0;\n\nimport \"../token/ERC20/ERC20.sol\";\nimport \"./IERC20Permit.sol\";\nimport \"../cryptography/ECDSA.sol\";\nimport \"../utils/Counters.sol\";\nimport \"./EIP712.sol\";\n\n/**\n * @dev Implementation of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in\n * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612].\n *\n * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by\n * presenting a message signed by the account. By not relying on `{IERC20-approve}`, the token holder account doesn't\n * need to send a transaction, and thus is not required to hold Ether at all.\n *\n * _Available since v3.4._\n */\nabstract contract ERC20Permit is ERC20, IERC20Permit, EIP712 {\n using Counters for Counters.Counter;\n\n mapping (address => Counters.Counter) private _nonces;\n\n // solhint-disable-next-line var-name-mixedcase\n bytes32 private immutable _PERMIT_TYPEHASH = keccak256(\"Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)\");\n\n /**\n * @dev Initializes the {EIP712} domain separator using the `name` parameter, and setting `version` to `\"1\"`.\n *\n * It's a good idea to use the same `name` that is defined as the ERC20 token name.\n */\n constructor(string memory name) internal EIP712(name, \"1\") {\n }\n\n /**\n * @dev See {IERC20Permit-permit}.\n */\n function permit(address owner, address spender, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s) public virtual override {\n // solhint-disable-next-line not-rely-on-time\n require(block.timestamp <= deadline, \"ERC20Permit: expired deadline\");\n\n bytes32 structHash = keccak256(\n abi.encode(\n _PERMIT_TYPEHASH,\n owner,\n spender,\n value,\n _nonces[owner].current(),\n deadline\n )\n );\n\n bytes32 hash = _hashTypedDataV4(structHash);\n\n address signer = ECDSA.recover(hash, v, r, s);\n require(signer == owner, \"ERC20Permit: invalid signature\");\n\n _nonces[owner].increment();\n _approve(owner, spender, value);\n }\n\n /**\n * @dev See {IERC20Permit-nonces}.\n */\n function nonces(address owner) public view override returns (uint256) {\n return _nonces[owner].current();\n }\n\n /**\n * @dev See {IERC20Permit-DOMAIN_SEPARATOR}.\n */\n // solhint-disable-next-line func-name-mixedcase\n function DOMAIN_SEPARATOR() external view override returns (bytes32) {\n return _domainSeparatorV4();\n }\n}\n" + }, + "@openzeppelin/contracts/utils/EnumerableSet.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <0.8.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" + }, + "@openzeppelin/contracts/drafts/IERC20Permit.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <0.8.0;\n\n/**\n * @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in\n * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612].\n *\n * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by\n * presenting a message signed by the account. By not relying on `{IERC20-approve}`, the token holder account doesn't\n * need to send a transaction, and thus is not required to hold Ether at all.\n */\ninterface IERC20Permit {\n /**\n * @dev Sets `value` as the allowance of `spender` over `owner`'s tokens,\n * given `owner`'s signed approval.\n *\n * IMPORTANT: The same issues {IERC20-approve} has related to transaction\n * ordering also apply here.\n *\n * Emits an {Approval} event.\n *\n * Requirements:\n *\n * - `spender` cannot be the zero address.\n * - `deadline` must be a timestamp in the future.\n * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner`\n * over the EIP712-formatted function arguments.\n * - the signature must use ``owner``'s current nonce (see {nonces}).\n *\n * For more information on the signature format, see the\n * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP\n * section].\n */\n function permit(address owner, address spender, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s) external;\n\n /**\n * @dev Returns the current nonce for `owner`. This value must be\n * included whenever a signature is generated for {permit}.\n *\n * Every successful call to {permit} increases ``owner``'s nonce by one. This\n * prevents a signature from being used multiple times.\n */\n function nonces(address owner) external view returns (uint256);\n\n /**\n * @dev Returns the domain separator used in the encoding of the signature for `permit`, as defined by {EIP712}.\n */\n // solhint-disable-next-line func-name-mixedcase\n function DOMAIN_SEPARATOR() external view returns (bytes32);\n}\n" + }, + "@openzeppelin/contracts/cryptography/ECDSA.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <0.8.0;\n\n/**\n * @dev Elliptic Curve Digital Signature Algorithm (ECDSA) operations.\n *\n * These functions can be used to verify that a message was signed by the holder\n * of the private keys of a given address.\n */\nlibrary ECDSA {\n /**\n * @dev Returns the address that signed a hashed message (`hash`) with\n * `signature`. This address can then be used for verification purposes.\n *\n * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:\n * this function rejects them by requiring the `s` value to be in the lower\n * half order, and the `v` value to be either 27 or 28.\n *\n * IMPORTANT: `hash` _must_ be the result of a hash operation for the\n * verification to be secure: it is possible to craft signatures that\n * recover to arbitrary addresses for non-hashed data. A safe way to ensure\n * this is by receiving a hash of the original message (which may otherwise\n * be too long), and then calling {toEthSignedMessageHash} on it.\n */\n function recover(bytes32 hash, bytes memory signature) internal pure returns (address) {\n // Check the signature length\n if (signature.length != 65) {\n revert(\"ECDSA: invalid signature length\");\n }\n\n // Divide the signature in r, s and v variables\n bytes32 r;\n bytes32 s;\n uint8 v;\n\n // ecrecover takes the signature parameters, and the only way to get them\n // currently is to use assembly.\n // solhint-disable-next-line no-inline-assembly\n assembly {\n r := mload(add(signature, 0x20))\n s := mload(add(signature, 0x40))\n v := byte(0, mload(add(signature, 0x60)))\n }\n\n return recover(hash, v, r, s);\n }\n\n /**\n * @dev Overload of {ECDSA-recover-bytes32-bytes-} that receives the `v`,\n * `r` and `s` signature fields separately.\n */\n function recover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) internal pure returns (address) {\n // EIP-2 still allows signature malleability for ecrecover(). Remove this possibility and make the signature\n // unique. Appendix F in the Ethereum Yellow paper (https://ethereum.github.io/yellowpaper/paper.pdf), defines\n // the valid range for s in (281): 0 < s < secp256k1n ÷ 2 + 1, and for v in (282): v ∈ {27, 28}. Most\n // signatures from current libraries generate a unique signature with an s-value in the lower half order.\n //\n // If your library generates malleable signatures, such as s-values in the upper range, calculate a new s-value\n // with 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 - s1 and flip v from 27 to 28 or\n // vice versa. If your library also generates signatures with 0/1 for v instead 27/28, add 27 to v to accept\n // these malleable signatures as well.\n require(uint256(s) <= 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0, \"ECDSA: invalid signature 's' value\");\n require(v == 27 || v == 28, \"ECDSA: invalid signature 'v' value\");\n\n // If the signature is valid (and not malleable), return the signer address\n address signer = ecrecover(hash, v, r, s);\n require(signer != address(0), \"ECDSA: invalid signature\");\n\n return signer;\n }\n\n /**\n * @dev Returns an Ethereum Signed Message, created from a `hash`. This\n * replicates the behavior of the\n * https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_sign[`eth_sign`]\n * JSON-RPC method.\n *\n * See {recover}.\n */\n function toEthSignedMessageHash(bytes32 hash) internal pure returns (bytes32) {\n // 32 is the length in bytes of hash,\n // enforced by the type signature above\n return keccak256(abi.encodePacked(\"\\x19Ethereum Signed Message:\\n32\", hash));\n }\n}\n" + }, + "@openzeppelin/contracts/utils/Counters.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <0.8.0;\n\nimport \"../math/SafeMath.sol\";\n\n/**\n * @title Counters\n * @author Matt Condon (@shrugs)\n * @dev Provides counters that can only be incremented or decremented by one. This can be used e.g. to track the number\n * of elements in a mapping, issuing ERC721 ids, or counting request ids.\n *\n * Include with `using Counters for Counters.Counter;`\n * Since it is not possible to overflow a 256 bit integer with increments of one, `increment` can skip the {SafeMath}\n * overflow check, thereby saving gas. This does assume however correct usage, in that the underlying `_value` is never\n * directly accessed.\n */\nlibrary Counters {\n using SafeMath for uint256;\n\n struct Counter {\n // This variable should never be directly accessed by users of the library: interactions must be restricted to\n // the library's function. As of Solidity v0.5.2, this cannot be enforced, though there is a proposal to add\n // this feature: see https://github.com/ethereum/solidity/issues/4637\n uint256 _value; // default: 0\n }\n\n function current(Counter storage counter) internal view returns (uint256) {\n return counter._value;\n }\n\n function increment(Counter storage counter) internal {\n // The {SafeMath} overflow check can be skipped here, see the comment at the top\n counter._value += 1;\n }\n\n function decrement(Counter storage counter) internal {\n counter._value = counter._value.sub(1);\n }\n}\n" + }, + "@openzeppelin/contracts/drafts/EIP712.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <0.8.0;\n\n/**\n * @dev https://eips.ethereum.org/EIPS/eip-712[EIP 712] is a standard for hashing and signing of typed structured data.\n *\n * The encoding specified in the EIP is very generic, and such a generic implementation in Solidity is not feasible,\n * thus this contract does not implement the encoding itself. Protocols need to implement the type-specific encoding\n * they need in their contracts using a combination of `abi.encode` and `keccak256`.\n *\n * This contract implements the EIP 712 domain separator ({_domainSeparatorV4}) that is used as part of the encoding\n * scheme, and the final step of the encoding to obtain the message digest that is then signed via ECDSA\n * ({_hashTypedDataV4}).\n *\n * The implementation of the domain separator was designed to be as efficient as possible while still properly updating\n * the chain id to protect against replay attacks on an eventual fork of the chain.\n *\n * NOTE: This contract implements the version of the encoding known as \"v4\", as implemented by the JSON RPC method\n * https://docs.metamask.io/guide/signing-data.html[`eth_signTypedDataV4` in MetaMask].\n *\n * _Available since v3.4._\n */\nabstract contract EIP712 {\n /* solhint-disable var-name-mixedcase */\n // Cache the domain separator as an immutable value, but also store the chain id that it corresponds to, in order to\n // invalidate the cached domain separator if the chain id changes.\n bytes32 private immutable _CACHED_DOMAIN_SEPARATOR;\n uint256 private immutable _CACHED_CHAIN_ID;\n\n bytes32 private immutable _HASHED_NAME;\n bytes32 private immutable _HASHED_VERSION;\n bytes32 private immutable _TYPE_HASH;\n /* solhint-enable var-name-mixedcase */\n\n /**\n * @dev Initializes the domain separator and parameter caches.\n *\n * The meaning of `name` and `version` is specified in\n * https://eips.ethereum.org/EIPS/eip-712#definition-of-domainseparator[EIP 712]:\n *\n * - `name`: the user readable name of the signing domain, i.e. the name of the DApp or the protocol.\n * - `version`: the current major version of the signing domain.\n *\n * NOTE: These parameters cannot be changed except through a xref:learn::upgrading-smart-contracts.adoc[smart\n * contract upgrade].\n */\n constructor(string memory name, string memory version) internal {\n bytes32 hashedName = keccak256(bytes(name));\n bytes32 hashedVersion = keccak256(bytes(version));\n bytes32 typeHash = keccak256(\"EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)\");\n _HASHED_NAME = hashedName;\n _HASHED_VERSION = hashedVersion;\n _CACHED_CHAIN_ID = _getChainId();\n _CACHED_DOMAIN_SEPARATOR = _buildDomainSeparator(typeHash, hashedName, hashedVersion);\n _TYPE_HASH = typeHash;\n }\n\n /**\n * @dev Returns the domain separator for the current chain.\n */\n function _domainSeparatorV4() internal view virtual returns (bytes32) {\n if (_getChainId() == _CACHED_CHAIN_ID) {\n return _CACHED_DOMAIN_SEPARATOR;\n } else {\n return _buildDomainSeparator(_TYPE_HASH, _HASHED_NAME, _HASHED_VERSION);\n }\n }\n\n function _buildDomainSeparator(bytes32 typeHash, bytes32 name, bytes32 version) private view returns (bytes32) {\n return keccak256(\n abi.encode(\n typeHash,\n name,\n version,\n _getChainId(),\n address(this)\n )\n );\n }\n\n /**\n * @dev Given an already https://eips.ethereum.org/EIPS/eip-712#definition-of-hashstruct[hashed struct], this\n * function returns the hash of the fully encoded EIP712 message for this domain.\n *\n * This hash can be used together with {ECDSA-recover} to obtain the signer of a message. For example:\n *\n * ```solidity\n * bytes32 digest = _hashTypedDataV4(keccak256(abi.encode(\n * keccak256(\"Mail(address to,string contents)\"),\n * mailTo,\n * keccak256(bytes(mailContents))\n * )));\n * address signer = ECDSA.recover(digest, signature);\n * ```\n */\n function _hashTypedDataV4(bytes32 structHash) internal view virtual returns (bytes32) {\n return keccak256(abi.encodePacked(\"\\x19\\x01\", _domainSeparatorV4(), structHash));\n }\n\n function _getChainId() private view returns (uint256 chainId) {\n this; // silence state mutability warning without generating bytecode - see https://github.com/ethereum/solidity/issues/2691\n // solhint-disable-next-line no-inline-assembly\n assembly {\n chainId := chainid()\n }\n }\n}\n" + }, + "contracts/bridge/mocks/ERC20Mock.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.6.12;\n\nimport \"@openzeppelin/contracts/token/ERC20/ERC20.sol\";\n\ncontract ERC20Mock is ERC20 {\n constructor(\n string memory name,\n string memory symbol,\n uint256 supply\n ) public ERC20(name, symbol) {\n _mint(msg.sender, supply);\n }\n\n function mint(address to, uint256 amount) external {\n _mint(to, amount);\n }\n}" + }, + "contracts/bridge/interfaces/IMetaSwapDeposit.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.6.12;\nimport '@openzeppelin/contracts/token/ERC20/ERC20.sol';\n\n/**\n * @title IMetaSwapDeposit interface\n * @notice Interface for the meta swap contract.\n * @dev implement this interface to develop a a factory-patterned ECDSA node management contract\n **/\ninterface IMetaSwapDeposit {\n // min return calculation functions\n function calculateSwap(\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx\n ) external view returns (uint256);\n\n function swap(\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx,\n uint256 minDy,\n uint256 deadline\n ) external returns (uint256);\n\n function getToken(uint256 index) external view returns (IERC20);\n}\n" + }, + "contracts/amm/interfaces/IMetaSwapDeposit.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.6.12;\n\nimport \"@openzeppelin/contracts/token/ERC20/ERC20.sol\";\nimport \"./ISwap.sol\";\nimport \"./IMetaSwap.sol\";\n\ninterface IMetaSwapDeposit {\n function initialize(\n ISwap baseSwap_,\n IMetaSwap metaSwap_,\n IERC20 metaLPToken_\n ) external;\n}\n" + }, + "contracts/amm/interfaces/IMetaSwap.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.6.12;\n\nimport \"@openzeppelin/contracts/token/ERC20/ERC20.sol\";\n\ninterface IMetaSwap {\n // pool data view functions\n function getA() external view returns (uint256);\n\n function getToken(uint8 index) external view returns (IERC20);\n\n function getTokenIndex(address tokenAddress) external view returns (uint8);\n\n function getTokenBalance(uint8 index) external view returns (uint256);\n\n function getVirtualPrice() external view returns (uint256);\n\n function isGuarded() external view returns (bool);\n\n // min return calculation functions\n function calculateSwap(\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx\n ) external view returns (uint256);\n\n function calculateSwapUnderlying(\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx\n ) external view returns (uint256);\n\n function calculateTokenAmount(uint256[] calldata amounts, bool deposit)\n external\n view\n returns (uint256);\n\n function calculateRemoveLiquidity(uint256 amount)\n external\n view\n returns (uint256[] memory);\n\n function calculateRemoveLiquidityOneToken(\n uint256 tokenAmount,\n uint8 tokenIndex\n ) external view returns (uint256 availableTokenAmount);\n\n // state modifying functions\n function initializeMetaSwap(\n IERC20[] memory pooledTokens,\n uint8[] memory decimals,\n string memory lpTokenName,\n string memory lpTokenSymbol,\n uint256 a,\n uint256 fee,\n uint256 adminFee,\n address lpTokenTargetAddress,\n address baseSwap\n ) external;\n\n function swap(\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx,\n uint256 minDy,\n uint256 deadline\n ) external returns (uint256);\n\n function swapUnderlying(\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx,\n uint256 minDy,\n uint256 deadline\n ) external returns (uint256);\n\n function addLiquidity(\n uint256[] calldata amounts,\n uint256 minToMint,\n uint256 deadline\n ) external returns (uint256);\n\n function removeLiquidity(\n uint256 amount,\n uint256[] calldata minAmounts,\n uint256 deadline\n ) external returns (uint256[] memory);\n\n function removeLiquidityOneToken(\n uint256 tokenAmount,\n uint8 tokenIndex,\n uint256 minAmount,\n uint256 deadline\n ) external returns (uint256);\n\n function removeLiquidityImbalance(\n uint256[] calldata amounts,\n uint256 maxBurnAmount,\n uint256 deadline\n ) external returns (uint256);\n\n function swapStorage()\n external\n view\n returns (\n uint256 initialA,\n uint256 futureA,\n uint256 initialATime,\n uint256 futureATime,\n uint256 swapFee,\n uint256 adminFee,\n address lpToken\n );\n}\n" + }, + "contracts/amm/helper/GenericERC20.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.6.12;\n\nimport \"@openzeppelin/contracts/token/ERC20/ERC20.sol\";\nimport \"@openzeppelin/contracts/access/Ownable.sol\";\n\n/**\n * @title Generic ERC20 token\n * @notice This contract simulates a generic ERC20 token that is mintable and burnable.\n */\ncontract GenericERC20 is ERC20, Ownable {\n /**\n * @notice Deploy this contract with given name, symbol, and decimals\n * @dev the caller of this constructor will become the owner of this contract\n * @param name_ name of this token\n * @param symbol_ symbol of this token\n * @param decimals_ number of decimals this token will be based on\n */\n constructor(\n string memory name_,\n string memory symbol_,\n uint8 decimals_\n ) public ERC20(name_, symbol_) {\n _setupDecimals(decimals_);\n }\n\n /**\n * @notice Mints given amount of tokens to recipient\n * @dev only owner can call this mint function\n * @param recipient address of account to receive the tokens\n * @param amount amount of tokens to mint\n */\n function mint(address recipient, uint256 amount) external onlyOwner {\n require(amount != 0, \"amount == 0\");\n _mint(recipient, amount);\n }\n}\n" + }, + "contracts/bridge/wrappers/HarmonyBridgeZap.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.6.12;\n\nimport \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/SafeERC20.sol\";\nimport \"../interfaces/ISwap.sol\";\nimport \"../interfaces/ISynapseBridge.sol\";\nimport \"../interfaces/IWETH9.sol\";\n\ninterface IFrax {\n function exchangeCanonicalForOld(address bridge_token_address, uint256 token_amount) external returns (uint256);\n}\n\ncontract HarmonyBridgeZap {\n using SafeERC20 for IERC20;\n\n ISynapseBridge synapseBridge;\n address payable public immutable WETH_ADDRESS;\n IFrax private constant CANOLICAL_FRAX = IFrax(0xFa7191D292d5633f702B0bd7E3E3BcCC0e633200);\n IERC20 private constant SYN_FRAX = IERC20(0x1852F70512298d56e9c8FDd905e02581E04ddb2a);\n\n mapping(address => address) public swapMap;\n mapping(address => IERC20[]) public swapTokensMap;\n\n uint256 constant MAX_UINT256 = 2**256 - 1;\n\n constructor(\n address payable _wethAddress,\n address _swapOne,\n address tokenOne,\n address _swapTwo,\n address tokenTwo,\n address _swapThree,\n address tokenThree,\n address _swapFour,\n address tokenFour,\n ISynapseBridge _synapseBridge\n ) public {\n WETH_ADDRESS = _wethAddress;\n synapseBridge = _synapseBridge;\n swapMap[tokenOne] = _swapOne;\n swapMap[tokenTwo] = _swapTwo;\n swapMap[tokenThree] = _swapThree;\n swapMap[tokenFour] = _swapFour;\n\n if (address(_swapOne) != address(0)) {\n {\n uint8 i;\n for (; i < 32; i++) {\n try ISwap(_swapOne).getToken(i) returns (\n IERC20 token\n ) {\n swapTokensMap[_swapOne].push(token);\n token.safeApprove(address(_swapOne), MAX_UINT256);\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n } catch {\n break;\n }\n }\n require(i > 1, \"swap must have at least 2 tokens\");\n }\n }\n if (address(_swapTwo) != address(0)) {\n {\n uint8 i;\n for (; i < 32; i++) {\n try ISwap(_swapTwo).getToken(i) returns (\n IERC20 token\n ) {\n swapTokensMap[_swapTwo].push(token);\n token.safeApprove(address(_swapTwo), MAX_UINT256);\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n } catch {\n break;\n }\n }\n require(i > 1, \"swap must have at least 2 tokens\");\n }\n }\n\n if (address(_swapThree) != address(0)) {\n {\n uint8 i;\n for (; i < 32; i++) {\n try ISwap(_swapThree).getToken(i) returns (\n IERC20 token\n ) {\n swapTokensMap[_swapThree].push(token);\n token.safeApprove(address(_swapThree), MAX_UINT256);\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n } catch {\n break;\n }\n }\n require(i > 1, \"swap must have at least 2 tokens\");\n }\n }\n\n if (address(_swapFour) != address(0)) {\n {\n uint8 i;\n for (; i < 32; i++) {\n try ISwap(_swapFour).getToken(i) returns (\n IERC20 token\n ) {\n swapTokensMap[_swapFour].push(token);\n token.safeApprove(address(_swapFour), MAX_UINT256);\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n } catch {\n break;\n }\n }\n require(i > 1, \"swap must have at least 2 tokens\");\n }\n }\n }\n\n /**\n * @notice Calculate amount of tokens you receive on swap\n * @param tokenIndexFrom the token the user wants to sell\n * @param tokenIndexTo the token the user wants to buy\n * @param dx the amount of tokens the user wants to sell. If the token charges\n * a fee on transfers, use the amount that gets transferred after the fee.\n * @return amount of tokens the user will receive\n */\n function calculateSwap(\n IERC20 token,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx\n ) external view virtual returns (uint256) {\n ISwap swap = ISwap(\n swapMap[address(token)]\n );\n return swap.calculateSwap(tokenIndexFrom, tokenIndexTo, dx);\n }\n\n function swapAndRedeem(\n address to,\n uint256 chainId,\n IERC20 token,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx,\n uint256 minDy,\n uint256 deadline\n ) external {\n ISwap swap = ISwap(swapMap[address(token)]);\n require(address(swap) != address(0), \"Swap is 0x00\");\n IERC20[] memory tokens = swapTokensMap[address(swap)];\n tokens[tokenIndexFrom].safeTransferFrom(\n msg.sender,\n address(this),\n dx\n );\n // swap\n\n uint256 swappedAmount = swap.swap(\n tokenIndexFrom,\n tokenIndexTo,\n dx,\n minDy,\n deadline\n );\n // deposit into bridge, gets nUSD\n if (\n token.allowance(address(this), address(synapseBridge)) <\n swappedAmount\n ) {\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n }\n synapseBridge.redeem(to, chainId, token, swappedAmount);\n }\n\n function swapAndRedeemAndSwap(\n address to,\n uint256 chainId,\n IERC20 token,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx,\n uint256 minDy,\n uint256 deadline,\n uint8 swapTokenIndexFrom,\n uint8 swapTokenIndexTo,\n uint256 swapMinDy,\n uint256 swapDeadline\n ) external {\n require(\n address(swapMap[address(token)]) != address(0),\n \"Swap is 0x00\"\n );\n IERC20[] memory tokens = swapTokensMap[\n swapMap[address(token)]\n ];\n tokens[tokenIndexFrom].safeTransferFrom(\n msg.sender,\n address(this),\n dx\n );\n // swap\n\n uint256 swappedAmount = ISwap(swapMap[address(token)]).swap(tokenIndexFrom, tokenIndexTo, dx, minDy, deadline);\n // deposit into bridge, gets nUSD\n if (\n token.allowance(address(this), address(synapseBridge)) <\n swappedAmount\n ) {\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n }\n synapseBridge.redeemAndSwap(\n to,\n chainId,\n token,\n swappedAmount,\n swapTokenIndexFrom,\n swapTokenIndexTo,\n swapMinDy,\n swapDeadline\n );\n }\n\n function swapAndRedeemAndRemove(\n address to,\n uint256 chainId,\n IERC20 token,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx,\n uint256 minDy,\n uint256 deadline,\n uint8 liqTokenIndex,\n uint256 liqMinAmount,\n uint256 liqDeadline\n ) external {\n ISwap swap = ISwap(swapMap[address(token)]);\n require(address(swap) != address(0), \"Swap is 0x00\");\n IERC20[] memory tokens = swapTokensMap[address(swap)];\n tokens[tokenIndexFrom].safeTransferFrom(\n msg.sender,\n address(this),\n dx\n );\n // swap\n\n uint256 swappedAmount = swap.swap(\n tokenIndexFrom,\n tokenIndexTo,\n dx,\n minDy,\n deadline\n );\n // deposit into bridge, gets nUSD\n if (\n token.allowance(address(this), address(synapseBridge)) <\n swappedAmount\n ) {\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n }\n synapseBridge.redeemAndRemove(\n to,\n chainId,\n token,\n swappedAmount,\n liqTokenIndex,\n liqMinAmount,\n liqDeadline\n );\n }\n\n /**\n * @notice wraps SynapseBridge redeem()\n * @param to address on other chain to redeem underlying assets to\n * @param chainId which underlying chain to bridge assets onto\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n **/\n function redeem(\n address to,\n uint256 chainId,\n IERC20 token,\n uint256 amount\n ) external {\n token.safeTransferFrom(msg.sender, address(this), amount);\n if (address(token) == address(CANOLICAL_FRAX)) {\n uint256 swappedAmount = CANOLICAL_FRAX.exchangeCanonicalForOld(address(SYN_FRAX), amount);\n if (SYN_FRAX.allowance(address(this), address(synapseBridge)) < amount) {\n SYN_FRAX.safeApprove(address(synapseBridge), MAX_UINT256);\n }\n synapseBridge.redeem(to, chainId, SYN_FRAX, swappedAmount);\n } else {\n if (token.allowance(address(this), address(synapseBridge)) < amount) {\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n }\n synapseBridge.redeem(to, chainId, token, amount);\n }\n \n }\n\n /**\n * @notice Wraps SynapseBridge redeemv2() function\n * @param to address on other chain to bridge assets to\n * @param chainId which chain to bridge assets onto\n * @param token ERC20 compatible token to redeem into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n **/\n function redeemv2(\n bytes32 to,\n uint256 chainId,\n IERC20 token,\n uint256 amount\n ) external {\n token.safeTransferFrom(msg.sender, address(this), amount);\n\n if (token.allowance(address(this), address(synapseBridge)) < amount) {\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n }\n synapseBridge.redeemv2(to, chainId, token, amount);\n }\n\n /**\n * @notice wraps SynapseBridge redeem()\n * @param to address on other chain to redeem underlying assets to\n * @param chainId which underlying chain to bridge assets onto\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n **/\n function deposit(\n address to,\n uint256 chainId,\n IERC20 token,\n uint256 amount\n ) external {\n token.safeTransferFrom(msg.sender, address(this), amount);\n if (token.allowance(address(this), address(synapseBridge)) < amount) {\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n }\n synapseBridge.deposit(to, chainId, token, amount);\n }\n\n function swapETHAndRedeem(\n address to,\n uint256 chainId,\n IERC20 token,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx,\n uint256 minDy,\n uint256 deadline\n ) external payable {\n require(WETH_ADDRESS != address(0), \"WETH 0\");\n require(msg.value > 0 && msg.value == dx, \"INCORRECT MSG VALUE\");\n ISwap swap = ISwap(swapMap[address(token)]);\n require(address(swap) != address(0), \"Swap is 0x00\");\n IWETH9(WETH_ADDRESS).deposit{value: msg.value}();\n\n // swap\n uint256 swappedAmount = swap.swap(\n tokenIndexFrom,\n tokenIndexTo,\n dx,\n minDy,\n deadline\n );\n synapseBridge.redeem(to, chainId, token, swappedAmount);\n }\n\n /**\n * @notice Wraps redeemAndSwap on SynapseBridge.sol\n * Relays to nodes that (typically) a wrapped synAsset ERC20 token has been burned and the underlying needs to be redeeemed on the native chain. This function indicates to the nodes that they should attempt to redeem the LP token for the underlying assets (E.g \"swap\" out of the LP token)\n * @param to address on other chain to redeem underlying assets to\n * @param chainId which underlying chain to bridge assets onto\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n * @param tokenIndexFrom the token the user wants to swap from\n * @param tokenIndexTo the token the user wants to swap to\n * @param minDy the min amount the user would like to receive, or revert to only minting the SynERC20 token crosschain.\n * @param deadline latest timestamp to accept this transaction\n **/\n function redeemAndSwap(\n address to,\n uint256 chainId,\n IERC20 token,\n uint256 amount,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 minDy,\n uint256 deadline\n ) external {\n token.safeTransferFrom(msg.sender, address(this), amount);\n if (token.allowance(address(this), address(synapseBridge)) < amount) {\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n }\n synapseBridge.redeemAndSwap(\n to,\n chainId,\n token,\n amount,\n tokenIndexFrom,\n tokenIndexTo,\n minDy,\n deadline\n );\n }\n\n /**\n * @notice Wraps redeemAndRemove on SynapseBridge\n * Relays to nodes that (typically) a wrapped synAsset ERC20 token has been burned and the underlying needs to be redeeemed on the native chain. This function indicates to the nodes that they should attempt to redeem the LP token for the underlying assets (E.g \"swap\" out of the LP token)\n * @param to address on other chain to redeem underlying assets to\n * @param chainId which underlying chain to bridge assets onto\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount of (typically) LP token to pass to the nodes to attempt to removeLiquidity() with to redeem for the underlying assets of the LP token\n * @param liqTokenIndex Specifies which of the underlying LP assets the nodes should attempt to redeem for\n * @param liqMinAmount Specifies the minimum amount of the underlying asset needed for the nodes to execute the redeem/swap\n * @param liqDeadline Specificies the deadline that the nodes are allowed to try to redeem/swap the LP token\n **/\n function redeemAndRemove(\n address to,\n uint256 chainId,\n IERC20 token,\n uint256 amount,\n uint8 liqTokenIndex,\n uint256 liqMinAmount,\n uint256 liqDeadline\n ) external {\n token.safeTransferFrom(msg.sender, address(this), amount);\n if (token.allowance(address(this), address(synapseBridge)) < amount) {\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n }\n synapseBridge.redeemAndRemove(\n to,\n chainId,\n token,\n amount,\n liqTokenIndex,\n liqMinAmount,\n liqDeadline\n );\n }\n}\n" + }, + "contracts/bridge/wrappers/AvalancheBridgeZap.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.6.12;\n\nimport \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/SafeERC20.sol\";\nimport \"../interfaces/ISwap.sol\";\nimport \"../interfaces/ISynapseBridge.sol\";\nimport \"../interfaces/IWETH9.sol\";\n\ncontract AvalancheBridgeZap {\n using SafeERC20 for IERC20;\n\n ISynapseBridge synapseBridge;\n address payable public immutable WETH_ADDRESS;\n\n mapping(address => address) public swapMap;\n mapping(address => IERC20[]) public swapTokensMap;\n\n uint256 constant MAX_UINT256 = 2**256 - 1;\n\n constructor(\n address payable _wethAddress,\n address _swapOne,\n address tokenOne,\n address _swapTwo,\n address tokenTwo,\n ISynapseBridge _synapseBridge\n ) public {\n WETH_ADDRESS = _wethAddress;\n synapseBridge = _synapseBridge;\n swapMap[tokenOne] = _swapOne;\n swapMap[tokenTwo] = _swapTwo;\n if (_wethAddress != address(0)) {\n IERC20(_wethAddress).safeIncreaseAllowance(address(_synapseBridge), MAX_UINT256);\n }\n if (address(_swapOne) != address(0)) {\n {\n uint8 i;\n for (; i < 32; i++) {\n try ISwap(_swapOne).getToken(i) returns (\n IERC20 token\n ) {\n swapTokensMap[_swapOne].push(token);\n token.safeApprove(address(_swapOne), MAX_UINT256);\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n } catch {\n break;\n }\n }\n require(i > 1, \"swap must have at least 2 tokens\");\n }\n }\n if (address(_swapTwo) != address(0)) {\n {\n uint8 i;\n for (; i < 32; i++) {\n try ISwap(_swapTwo).getToken(i) returns (\n IERC20 token\n ) {\n swapTokensMap[_swapTwo].push(token);\n token.safeApprove(address(_swapTwo), MAX_UINT256);\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n } catch {\n break;\n }\n }\n require(i > 1, \"swap must have at least 2 tokens\");\n }\n }\n }\n\n /**\n * @notice Calculate amount of tokens you receive on swap\n * @param tokenIndexFrom the token the user wants to sell\n * @param tokenIndexTo the token the user wants to buy\n * @param dx the amount of tokens the user wants to sell. If the token charges\n * a fee on transfers, use the amount that gets transferred after the fee.\n * @return amount of tokens the user will receive\n */\n function calculateSwap(\n IERC20 token,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx\n ) external view virtual returns (uint256) {\n ISwap swap = ISwap(\n swapMap[address(token)]\n );\n return swap.calculateSwap(tokenIndexFrom, tokenIndexTo, dx);\n }\n\n function swapAndRedeem(\n address to,\n uint256 chainId,\n IERC20 token,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx,\n uint256 minDy,\n uint256 deadline\n ) external {\n ISwap swap = ISwap(swapMap[address(token)]);\n require(address(swap) != address(0), \"Swap is 0x00\");\n IERC20[] memory tokens = swapTokensMap[address(swap)];\n tokens[tokenIndexFrom].safeTransferFrom(\n msg.sender,\n address(this),\n dx\n );\n // swap\n\n uint256 swappedAmount = swap.swap(\n tokenIndexFrom,\n tokenIndexTo,\n dx,\n minDy,\n deadline\n );\n // deposit into bridge, gets nUSD\n if (\n token.allowance(address(this), address(synapseBridge)) <\n swappedAmount\n ) {\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n }\n synapseBridge.redeem(to, chainId, token, swappedAmount);\n }\n\n function swapAndRedeemAndSwap(\n address to,\n uint256 chainId,\n IERC20 token,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx,\n uint256 minDy,\n uint256 deadline,\n uint8 swapTokenIndexFrom,\n uint8 swapTokenIndexTo,\n uint256 swapMinDy,\n uint256 swapDeadline\n ) external {\n require(\n address(swapMap[address(token)]) != address(0),\n \"Swap is 0x00\"\n );\n IERC20[] memory tokens = swapTokensMap[\n swapMap[address(token)]\n ];\n tokens[tokenIndexFrom].safeTransferFrom(\n msg.sender,\n address(this),\n dx\n );\n // swap\n\n uint256 swappedAmount = ISwap(swapMap[address(token)]).swap(tokenIndexFrom, tokenIndexTo, dx, minDy, deadline);\n // deposit into bridge, gets nUSD\n if (\n token.allowance(address(this), address(synapseBridge)) <\n swappedAmount\n ) {\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n }\n synapseBridge.redeemAndSwap(\n to,\n chainId,\n token,\n swappedAmount,\n swapTokenIndexFrom,\n swapTokenIndexTo,\n swapMinDy,\n swapDeadline\n );\n }\n\n function swapAndRedeemAndRemove(\n address to,\n uint256 chainId,\n IERC20 token,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx,\n uint256 minDy,\n uint256 deadline,\n uint8 liqTokenIndex,\n uint256 liqMinAmount,\n uint256 liqDeadline\n ) external {\n ISwap swap = ISwap(swapMap[address(token)]);\n require(address(swap) != address(0), \"Swap is 0x00\");\n IERC20[] memory tokens = swapTokensMap[address(swap)];\n tokens[tokenIndexFrom].safeTransferFrom(\n msg.sender,\n address(this),\n dx\n );\n // swap\n\n uint256 swappedAmount = swap.swap(\n tokenIndexFrom,\n tokenIndexTo,\n dx,\n minDy,\n deadline\n );\n // deposit into bridge, gets nUSD\n if (\n token.allowance(address(this), address(synapseBridge)) <\n swappedAmount\n ) {\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n }\n synapseBridge.redeemAndRemove(\n to,\n chainId,\n token,\n swappedAmount,\n liqTokenIndex,\n liqMinAmount,\n liqDeadline\n );\n }\n\n /**\n * @notice wraps SynapseBridge redeem()\n * @param to address on other chain to redeem underlying assets to\n * @param chainId which underlying chain to bridge assets onto\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n **/\n function redeem(\n address to,\n uint256 chainId,\n IERC20 token,\n uint256 amount\n ) external {\n token.safeTransferFrom(msg.sender, address(this), amount);\n if (token.allowance(address(this), address(synapseBridge)) < amount) {\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n }\n synapseBridge.redeem(to, chainId, token, amount);\n }\n\n /**\n * @notice wraps SynapseBridge redeem()\n * @param to address on other chain to redeem underlying assets to\n * @param chainId which underlying chain to bridge assets onto\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n **/\n function deposit(\n address to,\n uint256 chainId,\n IERC20 token,\n uint256 amount\n ) external {\n token.safeTransferFrom(msg.sender, address(this), amount);\n if (token.allowance(address(this), address(synapseBridge)) < amount) {\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n }\n synapseBridge.deposit(to, chainId, token, amount);\n }\n\n /**\n * @notice Wraps SynapseBridge deposit() function to make it compatible w/ ETH -> WETH conversions\n * @param to address on other chain to bridge assets to\n * @param chainId which chain to bridge assets onto\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n **/\n function depositETH(\n address to,\n uint256 chainId,\n uint256 amount\n ) external payable {\n require(msg.value > 0 && msg.value == amount, 'INCORRECT MSG VALUE');\n IWETH9(WETH_ADDRESS).deposit{value: msg.value}();\n synapseBridge.deposit(to, chainId, IERC20(WETH_ADDRESS), amount);\n }\n\n\n function swapETHAndRedeem(\n address to,\n uint256 chainId,\n IERC20 token,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx,\n uint256 minDy,\n uint256 deadline\n ) external payable {\n require(WETH_ADDRESS != address(0), \"WETH 0\");\n require(msg.value > 0 && msg.value == dx, \"INCORRECT MSG VALUE\");\n ISwap swap = ISwap(swapMap[address(token)]);\n require(address(swap) != address(0), \"Swap is 0x00\");\n IWETH9(WETH_ADDRESS).deposit{value: msg.value}();\n\n // swap\n uint256 swappedAmount = swap.swap(\n tokenIndexFrom,\n tokenIndexTo,\n dx,\n minDy,\n deadline\n );\n synapseBridge.redeem(to, chainId, token, swappedAmount);\n }\n\n\n function swapETHAndRedeemAndSwap(\n address to,\n uint256 chainId,\n IERC20 token,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx,\n uint256 minDy,\n uint256 deadline,\n uint8 swapTokenIndexFrom,\n uint8 swapTokenIndexTo,\n uint256 swapMinDy,\n uint256 swapDeadline\n ) external payable {\n require(WETH_ADDRESS != address(0), \"WETH 0\");\n require(msg.value > 0 && msg.value == dx, \"INCORRECT MSG VALUE\");\n ISwap swap = ISwap(swapMap[address(token)]);\n require(address(swap) != address(0), \"Swap is 0x00\");\n IWETH9(WETH_ADDRESS).deposit{value: msg.value}();\n\n // swap\n uint256 swappedAmount = swap.swap(\n tokenIndexFrom,\n tokenIndexTo,\n dx,\n minDy,\n deadline\n );\n synapseBridge.redeemAndSwap(to, chainId, token, swappedAmount,swapTokenIndexFrom,\n swapTokenIndexTo,\n swapMinDy,\n swapDeadline);\n }\n\n\n /**\n * @notice Wraps redeemAndSwap on SynapseBridge.sol\n * Relays to nodes that (typically) a wrapped synAsset ERC20 token has been burned and the underlying needs to be redeeemed on the native chain. This function indicates to the nodes that they should attempt to redeem the LP token for the underlying assets (E.g \"swap\" out of the LP token)\n * @param to address on other chain to redeem underlying assets to\n * @param chainId which underlying chain to bridge assets onto\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n * @param tokenIndexFrom the token the user wants to swap from\n * @param tokenIndexTo the token the user wants to swap to\n * @param minDy the min amount the user would like to receive, or revert to only minting the SynERC20 token crosschain.\n * @param deadline latest timestamp to accept this transaction\n **/\n function redeemAndSwap(\n address to,\n uint256 chainId,\n IERC20 token,\n uint256 amount,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 minDy,\n uint256 deadline\n ) external {\n token.safeTransferFrom(msg.sender, address(this), amount);\n if (token.allowance(address(this), address(synapseBridge)) < amount) {\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n }\n synapseBridge.redeemAndSwap(\n to,\n chainId,\n token,\n amount,\n tokenIndexFrom,\n tokenIndexTo,\n minDy,\n deadline\n );\n }\n\n /**\n * @notice Wraps redeemAndRemove on SynapseBridge\n * Relays to nodes that (typically) a wrapped synAsset ERC20 token has been burned and the underlying needs to be redeeemed on the native chain. This function indicates to the nodes that they should attempt to redeem the LP token for the underlying assets (E.g \"swap\" out of the LP token)\n * @param to address on other chain to redeem underlying assets to\n * @param chainId which underlying chain to bridge assets onto\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount of (typically) LP token to pass to the nodes to attempt to removeLiquidity() with to redeem for the underlying assets of the LP token\n * @param liqTokenIndex Specifies which of the underlying LP assets the nodes should attempt to redeem for\n * @param liqMinAmount Specifies the minimum amount of the underlying asset needed for the nodes to execute the redeem/swap\n * @param liqDeadline Specificies the deadline that the nodes are allowed to try to redeem/swap the LP token\n **/\n function redeemAndRemove(\n address to,\n uint256 chainId,\n IERC20 token,\n uint256 amount,\n uint8 liqTokenIndex,\n uint256 liqMinAmount,\n uint256 liqDeadline\n ) external {\n token.safeTransferFrom(msg.sender, address(this), amount);\n if (token.allowance(address(this), address(synapseBridge)) < amount) {\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n }\n synapseBridge.redeemAndRemove(\n to,\n chainId,\n token,\n amount,\n liqTokenIndex,\n liqMinAmount,\n liqDeadline\n );\n }\n\n /**\n * @notice Wraps SynapseBridge redeemv2() function\n * @param to address on other chain to bridge assets to\n * @param chainId which chain to bridge assets onto\n * @param token ERC20 compatible token to redeem into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n **/\n function redeemv2(\n bytes32 to,\n uint256 chainId,\n IERC20 token,\n uint256 amount\n ) external {\n token.safeTransferFrom(msg.sender, address(this), amount);\n\n if (token.allowance(address(this), address(synapseBridge)) < amount) {\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n }\n synapseBridge.redeemv2(to, chainId, token, amount);\n }\n}\n" + }, + "contracts/bridge/SynapseBridge.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.6.12;\n\nimport \"@openzeppelin/contracts-upgradeable/proxy/Initializable.sol\";\nimport \"@openzeppelin/contracts-upgradeable/access/AccessControlUpgradeable.sol\";\nimport \"@openzeppelin/contracts-upgradeable/utils/ReentrancyGuardUpgradeable.sol\";\nimport \"@openzeppelin/contracts-upgradeable/utils/PausableUpgradeable.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/SafeERC20.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/ERC20Burnable.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport \"@openzeppelin/contracts/math/SafeMath.sol\";\n\nimport \"./interfaces/ISwap.sol\";\nimport \"./interfaces/IWETH9.sol\";\n\ninterface IERC20Mintable is IERC20 {\n function mint(address to, uint256 amount) external;\n}\n\ncontract SynapseBridge is\n Initializable,\n AccessControlUpgradeable,\n ReentrancyGuardUpgradeable,\n PausableUpgradeable\n{\n using SafeERC20 for IERC20;\n using SafeERC20 for IERC20Mintable;\n using SafeMath for uint256;\n\n bytes32 public constant NODEGROUP_ROLE = keccak256(\"NODEGROUP_ROLE\");\n bytes32 public constant GOVERNANCE_ROLE = keccak256(\"GOVERNANCE_ROLE\");\n\n mapping(address => uint256) private fees;\n\n uint256 public startBlockNumber;\n uint256 public constant bridgeVersion = 6;\n uint256 public chainGasAmount;\n address payable public WETH_ADDRESS;\n\n mapping(bytes32 => bool) private kappaMap;\n\n receive() external payable {}\n\n function initialize() external initializer {\n startBlockNumber = block.number;\n _setupRole(DEFAULT_ADMIN_ROLE, msg.sender);\n __AccessControl_init();\n }\n\n function setChainGasAmount(uint256 amount) external {\n require(hasRole(GOVERNANCE_ROLE, msg.sender), \"Not governance\");\n chainGasAmount = amount;\n }\n\n function setWethAddress(address payable _wethAddress) external {\n require(hasRole(DEFAULT_ADMIN_ROLE, msg.sender), \"Not admin\");\n WETH_ADDRESS = _wethAddress;\n }\n\n function addKappas(bytes32[] calldata kappas) external {\n require(hasRole(GOVERNANCE_ROLE, msg.sender), \"Not governance\");\n for (uint256 i = 0; i < kappas.length; ++i) {\n kappaMap[kappas[i]] = true;\n }\n }\n\n event TokenDeposit(\n address indexed to,\n uint256 chainId,\n IERC20 token,\n uint256 amount\n );\n event TokenRedeem(\n address indexed to,\n uint256 chainId,\n IERC20 token,\n uint256 amount\n );\n event TokenWithdraw(\n address indexed to,\n IERC20 token,\n uint256 amount,\n uint256 fee,\n bytes32 indexed kappa\n );\n event TokenMint(\n address indexed to,\n IERC20Mintable token,\n uint256 amount,\n uint256 fee,\n bytes32 indexed kappa\n );\n event TokenDepositAndSwap(\n address indexed to,\n uint256 chainId,\n IERC20 token,\n uint256 amount,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 minDy,\n uint256 deadline\n );\n event TokenMintAndSwap(\n address indexed to,\n IERC20Mintable token,\n uint256 amount,\n uint256 fee,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 minDy,\n uint256 deadline,\n bool swapSuccess,\n bytes32 indexed kappa\n );\n event TokenRedeemAndSwap(\n address indexed to,\n uint256 chainId,\n IERC20 token,\n uint256 amount,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 minDy,\n uint256 deadline\n );\n event TokenRedeemAndRemove(\n address indexed to,\n uint256 chainId,\n IERC20 token,\n uint256 amount,\n uint8 swapTokenIndex,\n uint256 swapMinAmount,\n uint256 swapDeadline\n );\n event TokenWithdrawAndRemove(\n address indexed to,\n IERC20 token,\n uint256 amount,\n uint256 fee,\n uint8 swapTokenIndex,\n uint256 swapMinAmount,\n uint256 swapDeadline,\n bool swapSuccess,\n bytes32 indexed kappa\n );\n\n // v2 events\n event TokenRedeemV2(\n bytes32 indexed to,\n uint256 chainId,\n IERC20 token,\n uint256 amount\n );\n\n // VIEW FUNCTIONS ***/\n function getFeeBalance(address tokenAddress)\n external\n view\n returns (uint256)\n {\n return fees[tokenAddress];\n }\n\n function kappaExists(bytes32 kappa) external view returns (bool) {\n return kappaMap[kappa];\n }\n\n // FEE FUNCTIONS ***/\n /**\n * * @notice withdraw specified ERC20 token fees to a given address\n * * @param token ERC20 token in which fees acccumulated to transfer\n * * @param to Address to send the fees to\n */\n function withdrawFees(IERC20 token, address to) external whenNotPaused {\n require(hasRole(GOVERNANCE_ROLE, msg.sender), \"Not governance\");\n require(to != address(0), \"Address is 0x000\");\n if (fees[address(token)] != 0) {\n token.safeTransfer(to, fees[address(token)]);\n fees[address(token)] = 0;\n }\n }\n\n // PAUSABLE FUNCTIONS ***/\n function pause() external {\n require(hasRole(GOVERNANCE_ROLE, msg.sender), \"Not governance\");\n _pause();\n }\n\n function unpause() external {\n require(hasRole(GOVERNANCE_ROLE, msg.sender), \"Not governance\");\n _unpause();\n }\n\n /**\n * @notice Relays to nodes to transfers an ERC20 token cross-chain\n * @param to address on other chain to bridge assets to\n * @param chainId which chain to bridge assets onto\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n **/\n function deposit(\n address to,\n uint256 chainId,\n IERC20 token,\n uint256 amount\n ) external nonReentrant whenNotPaused {\n emit TokenDeposit(to, chainId, token, amount);\n token.safeTransferFrom(msg.sender, address(this), amount);\n }\n\n /**\n * @notice Relays to nodes that (typically) a wrapped synAsset ERC20 token has been burned and the underlying needs to be redeeemed on the native chain\n * @param to address on other chain to redeem underlying assets to\n * @param chainId which underlying chain to bridge assets onto\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n **/\n function redeem(\n address to,\n uint256 chainId,\n ERC20Burnable token,\n uint256 amount\n ) external nonReentrant whenNotPaused {\n emit TokenRedeem(to, chainId, token, amount);\n token.burnFrom(msg.sender, amount);\n }\n\n /**\n * @notice Function to be called by the node group to withdraw the underlying assets from the contract\n * @param to address on chain to send underlying assets to\n * @param token ERC20 compatible token to withdraw from the bridge\n * @param amount Amount in native token decimals to withdraw\n * @param fee Amount in native token decimals to save to the contract as fees\n * @param kappa kappa\n **/\n function withdraw(\n address to,\n IERC20 token,\n uint256 amount,\n uint256 fee,\n bytes32 kappa\n ) external nonReentrant whenNotPaused {\n require(\n hasRole(NODEGROUP_ROLE, msg.sender),\n \"Caller is not a node group\"\n );\n require(amount > fee, \"Amount must be greater than fee\");\n require(!kappaMap[kappa], \"Kappa is already present\");\n kappaMap[kappa] = true;\n fees[address(token)] = fees[address(token)].add(fee);\n if (address(token) == WETH_ADDRESS && WETH_ADDRESS != address(0)) {\n IWETH9(WETH_ADDRESS).withdraw(amount.sub(fee));\n (bool success, ) = to.call{value: amount.sub(fee)}(\"\");\n require(success, \"ETH_TRANSFER_FAILED\");\n emit TokenWithdraw(to, token, amount, fee, kappa);\n } else {\n emit TokenWithdraw(to, token, amount, fee, kappa);\n token.safeTransfer(to, amount.sub(fee));\n }\n }\n\n /**\n * @notice Nodes call this function to mint a SynERC20 (or any asset that the bridge is given minter access to). This is called by the nodes after a TokenDeposit event is emitted.\n * @dev This means the SynapseBridge.sol contract must have minter access to the token attempting to be minted\n * @param to address on other chain to redeem underlying assets to\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain post-fees\n * @param fee Amount in native token decimals to save to the contract as fees\n * @param kappa kappa\n **/\n function mint(\n address payable to,\n IERC20Mintable token,\n uint256 amount,\n uint256 fee,\n bytes32 kappa\n ) external nonReentrant whenNotPaused {\n require(\n hasRole(NODEGROUP_ROLE, msg.sender),\n \"Caller is not a node group\"\n );\n require(amount > fee, \"Amount must be greater than fee\");\n require(!kappaMap[kappa], \"Kappa is already present\");\n kappaMap[kappa] = true;\n fees[address(token)] = fees[address(token)].add(fee);\n emit TokenMint(to, token, amount.sub(fee), fee, kappa);\n token.mint(address(this), amount);\n IERC20(token).safeTransfer(to, amount.sub(fee));\n if (chainGasAmount != 0 && address(this).balance > chainGasAmount) {\n to.call.value(chainGasAmount)(\"\");\n }\n }\n\n /**\n * @notice Relays to nodes to both transfer an ERC20 token cross-chain, and then have the nodes execute a swap through a liquidity pool on behalf of the user.\n * @param to address on other chain to bridge assets to\n * @param chainId which chain to bridge assets onto\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n * @param tokenIndexFrom the token the user wants to swap from\n * @param tokenIndexTo the token the user wants to swap to\n * @param minDy the min amount the user would like to receive, or revert to only minting the SynERC20 token crosschain.\n * @param deadline latest timestamp to accept this transaction\n **/\n function depositAndSwap(\n address to,\n uint256 chainId,\n IERC20 token,\n uint256 amount,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 minDy,\n uint256 deadline\n ) external nonReentrant whenNotPaused {\n emit TokenDepositAndSwap(\n to,\n chainId,\n token,\n amount,\n tokenIndexFrom,\n tokenIndexTo,\n minDy,\n deadline\n );\n token.safeTransferFrom(msg.sender, address(this), amount);\n }\n\n /**\n * @notice Relays to nodes that (typically) a wrapped synAsset ERC20 token has been burned and the underlying needs to be redeeemed on the native chain. This function indicates to the nodes that they should attempt to redeem the LP token for the underlying assets (E.g \"swap\" out of the LP token)\n * @param to address on other chain to redeem underlying assets to\n * @param chainId which underlying chain to bridge assets onto\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n * @param tokenIndexFrom the token the user wants to swap from\n * @param tokenIndexTo the token the user wants to swap to\n * @param minDy the min amount the user would like to receive, or revert to only minting the SynERC20 token crosschain.\n * @param deadline latest timestamp to accept this transaction\n **/\n function redeemAndSwap(\n address to,\n uint256 chainId,\n ERC20Burnable token,\n uint256 amount,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 minDy,\n uint256 deadline\n ) external nonReentrant whenNotPaused {\n emit TokenRedeemAndSwap(\n to,\n chainId,\n token,\n amount,\n tokenIndexFrom,\n tokenIndexTo,\n minDy,\n deadline\n );\n token.burnFrom(msg.sender, amount);\n }\n\n /**\n * @notice Relays to nodes that (typically) a wrapped synAsset ERC20 token has been burned and the underlying needs to be redeeemed on the native chain. This function indicates to the nodes that they should attempt to redeem the LP token for the underlying assets (E.g \"swap\" out of the LP token)\n * @param to address on other chain to redeem underlying assets to\n * @param chainId which underlying chain to bridge assets onto\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n * @param swapTokenIndex Specifies which of the underlying LP assets the nodes should attempt to redeem for\n * @param swapMinAmount Specifies the minimum amount of the underlying asset needed for the nodes to execute the redeem/swap\n * @param swapDeadline Specificies the deadline that the nodes are allowed to try to redeem/swap the LP token\n **/\n function redeemAndRemove(\n address to,\n uint256 chainId,\n ERC20Burnable token,\n uint256 amount,\n uint8 swapTokenIndex,\n uint256 swapMinAmount,\n uint256 swapDeadline\n ) external nonReentrant whenNotPaused {\n emit TokenRedeemAndRemove(\n to,\n chainId,\n token,\n amount,\n swapTokenIndex,\n swapMinAmount,\n swapDeadline\n );\n token.burnFrom(msg.sender, amount);\n }\n\n /**\n * @notice Nodes call this function to mint a SynERC20 (or any asset that the bridge is given minter access to), and then attempt to swap the SynERC20 into the desired destination asset. This is called by the nodes after a TokenDepositAndSwap event is emitted.\n * @dev This means the BridgeDeposit.sol contract must have minter access to the token attempting to be minted\n * @param to address on other chain to redeem underlying assets to\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain post-fees\n * @param fee Amount in native token decimals to save to the contract as fees\n * @param pool Destination chain's pool to use to swap SynERC20 -> Asset. The nodes determine this by using PoolConfig.sol.\n * @param tokenIndexFrom Index of the SynERC20 asset in the pool\n * @param tokenIndexTo Index of the desired final asset\n * @param minDy Minumum amount (in final asset decimals) that must be swapped for, otherwise the user will receive the SynERC20.\n * @param deadline Epoch time of the deadline that the swap is allowed to be executed.\n * @param kappa kappa\n **/\n function mintAndSwap(\n address payable to,\n IERC20Mintable token,\n uint256 amount,\n uint256 fee,\n ISwap pool,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 minDy,\n uint256 deadline,\n bytes32 kappa\n ) external nonReentrant whenNotPaused {\n require(\n hasRole(NODEGROUP_ROLE, msg.sender),\n \"Caller is not a node group\"\n );\n require(amount > fee, \"Amount must be greater than fee\");\n require(!kappaMap[kappa], \"Kappa is already present\");\n kappaMap[kappa] = true;\n fees[address(token)] = fees[address(token)].add(fee);\n // Transfer gas airdrop\n if (chainGasAmount != 0 && address(this).balance > chainGasAmount) {\n to.call.value(chainGasAmount)(\"\");\n }\n // first check to make sure more will be given than min amount required\n uint256 expectedOutput = ISwap(pool).calculateSwap(\n tokenIndexFrom,\n tokenIndexTo,\n amount.sub(fee)\n );\n\n if (expectedOutput >= minDy) {\n // proceed with swap\n token.mint(address(this), amount);\n token.safeIncreaseAllowance(address(pool), amount);\n try\n ISwap(pool).swap(\n tokenIndexFrom,\n tokenIndexTo,\n amount.sub(fee),\n minDy,\n deadline\n )\n returns (uint256 finalSwappedAmount) {\n // Swap succeeded, transfer swapped asset\n IERC20 swappedTokenTo = ISwap(pool).getToken(tokenIndexTo);\n if (\n address(swappedTokenTo) == WETH_ADDRESS &&\n WETH_ADDRESS != address(0)\n ) {\n IWETH9(WETH_ADDRESS).withdraw(finalSwappedAmount);\n (bool success, ) = to.call{value: finalSwappedAmount}(\"\");\n require(success, \"ETH_TRANSFER_FAILED\");\n emit TokenMintAndSwap(\n to,\n token,\n finalSwappedAmount,\n fee,\n tokenIndexFrom,\n tokenIndexTo,\n minDy,\n deadline,\n true,\n kappa\n );\n } else {\n swappedTokenTo.safeTransfer(to, finalSwappedAmount);\n emit TokenMintAndSwap(\n to,\n token,\n finalSwappedAmount,\n fee,\n tokenIndexFrom,\n tokenIndexTo,\n minDy,\n deadline,\n true,\n kappa\n );\n }\n } catch {\n IERC20(token).safeTransfer(to, amount.sub(fee));\n emit TokenMintAndSwap(\n to,\n token,\n amount.sub(fee),\n fee,\n tokenIndexFrom,\n tokenIndexTo,\n minDy,\n deadline,\n false,\n kappa\n );\n }\n } else {\n token.mint(address(this), amount);\n IERC20(token).safeTransfer(to, amount.sub(fee));\n emit TokenMintAndSwap(\n to,\n token,\n amount.sub(fee),\n fee,\n tokenIndexFrom,\n tokenIndexTo,\n minDy,\n deadline,\n false,\n kappa\n );\n }\n }\n\n /**\n * @notice Function to be called by the node group to withdraw the underlying assets from the contract\n * @param to address on chain to send underlying assets to\n * @param token ERC20 compatible token to withdraw from the bridge\n * @param amount Amount in native token decimals to withdraw\n * @param fee Amount in native token decimals to save to the contract as fees\n * @param pool Destination chain's pool to use to swap SynERC20 -> Asset. The nodes determine this by using PoolConfig.sol.\n * @param swapTokenIndex Specifies which of the underlying LP assets the nodes should attempt to redeem for\n * @param swapMinAmount Specifies the minimum amount of the underlying asset needed for the nodes to execute the redeem/swap\n * @param swapDeadline Specificies the deadline that the nodes are allowed to try to redeem/swap the LP token\n * @param kappa kappa\n **/\n function withdrawAndRemove(\n address to,\n IERC20 token,\n uint256 amount,\n uint256 fee,\n ISwap pool,\n uint8 swapTokenIndex,\n uint256 swapMinAmount,\n uint256 swapDeadline,\n bytes32 kappa\n ) external nonReentrant whenNotPaused {\n require(\n hasRole(NODEGROUP_ROLE, msg.sender),\n \"Caller is not a node group\"\n );\n require(amount > fee, \"Amount must be greater than fee\");\n require(!kappaMap[kappa], \"Kappa is already present\");\n kappaMap[kappa] = true;\n fees[address(token)] = fees[address(token)].add(fee);\n // first check to make sure more will be given than min amount required\n uint256 expectedOutput = ISwap(pool).calculateRemoveLiquidityOneToken(\n amount.sub(fee),\n swapTokenIndex\n );\n\n if (expectedOutput >= swapMinAmount) {\n token.safeIncreaseAllowance(address(pool), amount.sub(fee));\n try\n ISwap(pool).removeLiquidityOneToken(\n amount.sub(fee),\n swapTokenIndex,\n swapMinAmount,\n swapDeadline\n )\n returns (uint256 finalSwappedAmount) {\n // Swap succeeded, transfer swapped asset\n IERC20 swappedTokenTo = ISwap(pool).getToken(swapTokenIndex);\n swappedTokenTo.safeTransfer(to, finalSwappedAmount);\n emit TokenWithdrawAndRemove(\n to,\n token,\n finalSwappedAmount,\n fee,\n swapTokenIndex,\n swapMinAmount,\n swapDeadline,\n true,\n kappa\n );\n } catch {\n IERC20(token).safeTransfer(to, amount.sub(fee));\n emit TokenWithdrawAndRemove(\n to,\n token,\n amount.sub(fee),\n fee,\n swapTokenIndex,\n swapMinAmount,\n swapDeadline,\n false,\n kappa\n );\n }\n } else {\n token.safeTransfer(to, amount.sub(fee));\n emit TokenWithdrawAndRemove(\n to,\n token,\n amount.sub(fee),\n fee,\n swapTokenIndex,\n swapMinAmount,\n swapDeadline,\n false,\n kappa\n );\n }\n }\n\n // BRIDGE FUNCTIONS TO HANDLE DIFF ADDRESSES\n /**\n * @notice Relays to nodes that (typically) a wrapped synAsset ERC20 token has been burned and the underlying needs to be redeeemed on the native chain\n * @param to address on other chain to redeem underlying assets to\n * @param chainId which underlying chain to bridge assets onto\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n **/\n function redeemV2(\n bytes32 to,\n uint256 chainId,\n ERC20Burnable token,\n uint256 amount\n ) external nonReentrant whenNotPaused {\n emit TokenRedeemV2(to, chainId, token, amount);\n token.burnFrom(msg.sender, amount);\n }\n}\n" + }, + "@openzeppelin/contracts-upgradeable/access/AccessControlUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <0.8.0;\n\nimport \"../utils/EnumerableSetUpgradeable.sol\";\nimport \"../utils/AddressUpgradeable.sol\";\nimport \"../utils/ContextUpgradeable.sol\";\nimport \"../proxy/Initializable.sol\";\n\n/**\n * @dev Contract module that allows children to implement role-based access\n * control mechanisms.\n *\n * Roles are referred to by their `bytes32` identifier. These should be exposed\n * in the external API and be unique. The best way to achieve this is by\n * using `public constant` hash digests:\n *\n * ```\n * bytes32 public constant MY_ROLE = keccak256(\"MY_ROLE\");\n * ```\n *\n * Roles can be used to represent a set of permissions. To restrict access to a\n * function call, use {hasRole}:\n *\n * ```\n * function foo() public {\n * require(hasRole(MY_ROLE, msg.sender));\n * ...\n * }\n * ```\n *\n * Roles can be granted and revoked dynamically via the {grantRole} and\n * {revokeRole} functions. Each role has an associated admin role, and only\n * accounts that have a role's admin role can call {grantRole} and {revokeRole}.\n *\n * By default, the admin role for all roles is `DEFAULT_ADMIN_ROLE`, which means\n * that only accounts with this role will be able to grant or revoke other\n * roles. More complex role relationships can be created by using\n * {_setRoleAdmin}.\n *\n * WARNING: The `DEFAULT_ADMIN_ROLE` is also its own admin: it has permission to\n * grant and revoke this role. Extra precautions should be taken to secure\n * accounts that have been granted it.\n */\nabstract contract AccessControlUpgradeable is Initializable, ContextUpgradeable {\n function __AccessControl_init() internal initializer {\n __Context_init_unchained();\n __AccessControl_init_unchained();\n }\n\n function __AccessControl_init_unchained() internal initializer {\n }\n using EnumerableSetUpgradeable for EnumerableSetUpgradeable.AddressSet;\n using AddressUpgradeable for address;\n\n struct RoleData {\n EnumerableSetUpgradeable.AddressSet members;\n bytes32 adminRole;\n }\n\n mapping (bytes32 => RoleData) private _roles;\n\n bytes32 public constant DEFAULT_ADMIN_ROLE = 0x00;\n\n /**\n * @dev Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole`\n *\n * `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite\n * {RoleAdminChanged} not being emitted signaling this.\n *\n * _Available since v3.1._\n */\n event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole);\n\n /**\n * @dev Emitted when `account` is granted `role`.\n *\n * `sender` is the account that originated the contract call, an admin role\n * bearer except when using {_setupRole}.\n */\n event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender);\n\n /**\n * @dev Emitted when `account` is revoked `role`.\n *\n * `sender` is the account that originated the contract call:\n * - if using `revokeRole`, it is the admin role bearer\n * - if using `renounceRole`, it is the role bearer (i.e. `account`)\n */\n event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender);\n\n /**\n * @dev Returns `true` if `account` has been granted `role`.\n */\n function hasRole(bytes32 role, address account) public view returns (bool) {\n return _roles[role].members.contains(account);\n }\n\n /**\n * @dev Returns the number of accounts that have `role`. Can be used\n * together with {getRoleMember} to enumerate all bearers of a role.\n */\n function getRoleMemberCount(bytes32 role) public view returns (uint256) {\n return _roles[role].members.length();\n }\n\n /**\n * @dev Returns one of the accounts that have `role`. `index` must be a\n * value between 0 and {getRoleMemberCount}, non-inclusive.\n *\n * Role bearers are not sorted in any particular way, and their ordering may\n * change at any point.\n *\n * WARNING: When using {getRoleMember} and {getRoleMemberCount}, make sure\n * you perform all queries on the same block. See the following\n * https://forum.openzeppelin.com/t/iterating-over-elements-on-enumerableset-in-openzeppelin-contracts/2296[forum post]\n * for more information.\n */\n function getRoleMember(bytes32 role, uint256 index) public view returns (address) {\n return _roles[role].members.at(index);\n }\n\n /**\n * @dev Returns the admin role that controls `role`. See {grantRole} and\n * {revokeRole}.\n *\n * To change a role's admin, use {_setRoleAdmin}.\n */\n function getRoleAdmin(bytes32 role) public view returns (bytes32) {\n return _roles[role].adminRole;\n }\n\n /**\n * @dev Grants `role` to `account`.\n *\n * If `account` had not been already granted `role`, emits a {RoleGranted}\n * event.\n *\n * Requirements:\n *\n * - the caller must have ``role``'s admin role.\n */\n function grantRole(bytes32 role, address account) public virtual {\n require(hasRole(_roles[role].adminRole, _msgSender()), \"AccessControl: sender must be an admin to grant\");\n\n _grantRole(role, account);\n }\n\n /**\n * @dev Revokes `role` from `account`.\n *\n * If `account` had been granted `role`, emits a {RoleRevoked} event.\n *\n * Requirements:\n *\n * - the caller must have ``role``'s admin role.\n */\n function revokeRole(bytes32 role, address account) public virtual {\n require(hasRole(_roles[role].adminRole, _msgSender()), \"AccessControl: sender must be an admin to revoke\");\n\n _revokeRole(role, account);\n }\n\n /**\n * @dev Revokes `role` from the calling account.\n *\n * Roles are often managed via {grantRole} and {revokeRole}: this function's\n * purpose is to provide a mechanism for accounts to lose their privileges\n * if they are compromised (such as when a trusted device is misplaced).\n *\n * If the calling account had been granted `role`, emits a {RoleRevoked}\n * event.\n *\n * Requirements:\n *\n * - the caller must be `account`.\n */\n function renounceRole(bytes32 role, address account) public virtual {\n require(account == _msgSender(), \"AccessControl: can only renounce roles for self\");\n\n _revokeRole(role, account);\n }\n\n /**\n * @dev Grants `role` to `account`.\n *\n * If `account` had not been already granted `role`, emits a {RoleGranted}\n * event. Note that unlike {grantRole}, this function doesn't perform any\n * checks on the calling account.\n *\n * [WARNING]\n * ====\n * This function should only be called from the constructor when setting\n * up the initial roles for the system.\n *\n * Using this function in any other way is effectively circumventing the admin\n * system imposed by {AccessControl}.\n * ====\n */\n function _setupRole(bytes32 role, address account) internal virtual {\n _grantRole(role, account);\n }\n\n /**\n * @dev Sets `adminRole` as ``role``'s admin role.\n *\n * Emits a {RoleAdminChanged} event.\n */\n function _setRoleAdmin(bytes32 role, bytes32 adminRole) internal virtual {\n emit RoleAdminChanged(role, _roles[role].adminRole, adminRole);\n _roles[role].adminRole = adminRole;\n }\n\n function _grantRole(bytes32 role, address account) private {\n if (_roles[role].members.add(account)) {\n emit RoleGranted(role, account, _msgSender());\n }\n }\n\n function _revokeRole(bytes32 role, address account) private {\n if (_roles[role].members.remove(account)) {\n emit RoleRevoked(role, account, _msgSender());\n }\n }\n uint256[49] private __gap;\n}\n" + }, + "@openzeppelin/contracts-upgradeable/utils/EnumerableSetUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <0.8.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 EnumerableSetUpgradeable {\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" + }, + "contracts/bridge/MoonriverSynapseBridge.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.6.12;\n\nimport \"@openzeppelin/contracts-upgradeable/proxy/Initializable.sol\";\nimport \"@openzeppelin/contracts-upgradeable/access/AccessControlUpgradeable.sol\";\nimport \"@openzeppelin/contracts-upgradeable/utils/ReentrancyGuardUpgradeable.sol\";\nimport \"@openzeppelin/contracts-upgradeable/utils/PausableUpgradeable.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/SafeERC20.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/ERC20Burnable.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport \"@openzeppelin/contracts/math/SafeMath.sol\";\n\nimport \"./interfaces/ISwap.sol\";\nimport \"./interfaces/IWETH9.sol\";\n\ninterface IERC20Mintable is IERC20 {\n function mint(address to, uint256 amount) external;\n}\n\ninterface IFrax {\n function exchangeOldForCanonical(\n address bridge_token_address,\n uint256 token_amount\n ) external returns (uint256);\n}\n\ncontract MRSynapseBridge is\n Initializable,\n AccessControlUpgradeable,\n ReentrancyGuardUpgradeable,\n PausableUpgradeable\n{\n using SafeERC20 for IERC20;\n using SafeERC20 for IERC20Mintable;\n using SafeMath for uint256;\n\n bytes32 public constant NODEGROUP_ROLE = keccak256(\"NODEGROUP_ROLE\");\n bytes32 public constant GOVERNANCE_ROLE = keccak256(\"GOVERNANCE_ROLE\");\n\n mapping(address => uint256) private fees;\n\n uint256 public startBlockNumber;\n uint256 public constant bridgeVersion = 6;\n uint256 public chainGasAmount;\n address payable public WETH_ADDRESS;\n\n mapping(bytes32 => bool) private kappaMap;\n\n receive() external payable {}\n\n function initialize() external initializer {\n startBlockNumber = block.number;\n _setupRole(DEFAULT_ADMIN_ROLE, msg.sender);\n __AccessControl_init();\n }\n\n function setChainGasAmount(uint256 amount) external {\n require(hasRole(GOVERNANCE_ROLE, msg.sender), \"Not governance\");\n chainGasAmount = amount;\n }\n\n function setWethAddress(address payable _wethAddress) external {\n require(hasRole(DEFAULT_ADMIN_ROLE, msg.sender), \"Not admin\");\n WETH_ADDRESS = _wethAddress;\n }\n\n function addKappas(bytes32[] calldata kappas) external {\n require(hasRole(GOVERNANCE_ROLE, msg.sender), \"Not governance\");\n for (uint256 i = 0; i < kappas.length; ++i) {\n kappaMap[kappas[i]] = true;\n }\n }\n\n event TokenDeposit(\n address indexed to,\n uint256 chainId,\n IERC20 token,\n uint256 amount\n );\n event TokenRedeem(\n address indexed to,\n uint256 chainId,\n IERC20 token,\n uint256 amount\n );\n event TokenWithdraw(\n address indexed to,\n IERC20 token,\n uint256 amount,\n uint256 fee,\n bytes32 indexed kappa\n );\n event TokenMint(\n address indexed to,\n IERC20Mintable token,\n uint256 amount,\n uint256 fee,\n bytes32 indexed kappa\n );\n event TokenDepositAndSwap(\n address indexed to,\n uint256 chainId,\n IERC20 token,\n uint256 amount,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 minDy,\n uint256 deadline\n );\n event TokenMintAndSwap(\n address indexed to,\n IERC20Mintable token,\n uint256 amount,\n uint256 fee,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 minDy,\n uint256 deadline,\n bool swapSuccess,\n bytes32 indexed kappa\n );\n event TokenRedeemAndSwap(\n address indexed to,\n uint256 chainId,\n IERC20 token,\n uint256 amount,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 minDy,\n uint256 deadline\n );\n event TokenRedeemAndRemove(\n address indexed to,\n uint256 chainId,\n IERC20 token,\n uint256 amount,\n uint8 swapTokenIndex,\n uint256 swapMinAmount,\n uint256 swapDeadline\n );\n event TokenWithdrawAndRemove(\n address indexed to,\n IERC20 token,\n uint256 amount,\n uint256 fee,\n uint8 swapTokenIndex,\n uint256 swapMinAmount,\n uint256 swapDeadline,\n bool swapSuccess,\n bytes32 indexed kappa\n );\n\n // v2 events\n event TokenRedeemV2(\n bytes32 indexed to,\n uint256 chainId,\n IERC20 token,\n uint256 amount\n );\n\n // VIEW FUNCTIONS ***/\n function getFeeBalance(address tokenAddress)\n external\n view\n returns (uint256)\n {\n return fees[tokenAddress];\n }\n\n function kappaExists(bytes32 kappa) external view returns (bool) {\n return kappaMap[kappa];\n }\n\n // FEE FUNCTIONS ***/\n /**\n * * @notice withdraw specified ERC20 token fees to a given address\n * * @param token ERC20 token in which fees acccumulated to transfer\n * * @param to Address to send the fees to\n */\n function withdrawFees(IERC20 token, address to) external whenNotPaused {\n require(hasRole(GOVERNANCE_ROLE, msg.sender), \"Not governance\");\n require(to != address(0), \"Address is 0x000\");\n if (fees[address(token)] != 0) {\n token.safeTransfer(to, fees[address(token)]);\n fees[address(token)] = 0;\n }\n }\n\n // PAUSABLE FUNCTIONS ***/\n function pause() external {\n require(hasRole(GOVERNANCE_ROLE, msg.sender), \"Not governance\");\n _pause();\n }\n\n function unpause() external {\n require(hasRole(GOVERNANCE_ROLE, msg.sender), \"Not governance\");\n _unpause();\n }\n\n /**\n * @notice Relays to nodes to transfers an ERC20 token cross-chain\n * @param to address on other chain to bridge assets to\n * @param chainId which chain to bridge assets onto\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n **/\n function deposit(\n address to,\n uint256 chainId,\n IERC20 token,\n uint256 amount\n ) external nonReentrant whenNotPaused {\n emit TokenDeposit(to, chainId, token, amount);\n token.safeTransferFrom(msg.sender, address(this), amount);\n }\n\n /**\n * @notice Relays to nodes that (typically) a wrapped synAsset ERC20 token has been burned and the underlying needs to be redeeemed on the native chain\n * @param to address on other chain to redeem underlying assets to\n * @param chainId which underlying chain to bridge assets onto\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n **/\n function redeem(\n address to,\n uint256 chainId,\n ERC20Burnable token,\n uint256 amount\n ) external nonReentrant whenNotPaused {\n emit TokenRedeem(to, chainId, token, amount);\n token.burnFrom(msg.sender, amount);\n }\n\n /**\n * @notice Function to be called by the node group to withdraw the underlying assets from the contract\n * @param to address on chain to send underlying assets to\n * @param token ERC20 compatible token to withdraw from the bridge\n * @param amount Amount in native token decimals to withdraw\n * @param fee Amount in native token decimals to save to the contract as fees\n * @param kappa kappa\n **/\n function withdraw(\n address to,\n IERC20 token,\n uint256 amount,\n uint256 fee,\n bytes32 kappa\n ) external nonReentrant whenNotPaused {\n require(\n hasRole(NODEGROUP_ROLE, msg.sender),\n \"Caller is not a node group\"\n );\n require(amount > fee, \"Amount must be greater than fee\");\n require(!kappaMap[kappa], \"Kappa is already present\");\n kappaMap[kappa] = true;\n fees[address(token)] = fees[address(token)].add(fee);\n if (address(token) == WETH_ADDRESS && WETH_ADDRESS != address(0)) {\n IWETH9(WETH_ADDRESS).withdraw(amount.sub(fee));\n (bool success, ) = to.call{value: amount.sub(fee)}(\"\");\n require(success, \"ETH_TRANSFER_FAILED\");\n emit TokenWithdraw(to, token, amount, fee, kappa);\n } else {\n emit TokenWithdraw(to, token, amount, fee, kappa);\n token.safeTransfer(to, amount.sub(fee));\n }\n }\n\n /**\n * @notice Nodes call this function to mint a SynERC20 (or any asset that the bridge is given minter access to). This is called by the nodes after a TokenDeposit event is emitted.\n * @dev This means the SynapseBridge.sol contract must have minter access to the token attempting to be minted\n * @param to address on other chain to redeem underlying assets to\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain post-fees\n * @param fee Amount in native token decimals to save to the contract as fees\n * @param kappa kappa\n **/\n function mint(\n address payable to,\n IERC20Mintable token,\n uint256 amount,\n uint256 fee,\n bytes32 kappa\n ) external nonReentrant whenNotPaused {\n require(\n hasRole(NODEGROUP_ROLE, msg.sender),\n \"Caller is not a node group\"\n );\n require(amount > fee, \"Amount must be greater than fee\");\n require(!kappaMap[kappa], \"Kappa is already present\");\n kappaMap[kappa] = true;\n fees[address(token)] = fees[address(token)].add(fee);\n emit TokenMint(to, token, amount.sub(fee), fee, kappa);\n token.mint(address(this), amount);\n // checks if synFRAX\n if (address(token) == 0xE96AC70907ffF3Efee79f502C985A7A21Bce407d) {\n token.safeIncreaseAllowance(\n 0x1A93B23281CC1CDE4C4741353F3064709A16197d,\n amount.sub(fee)\n );\n try\n IFrax(0x1A93B23281CC1CDE4C4741353F3064709A16197d)\n .exchangeOldForCanonical(address(token), amount.sub(fee))\n returns (uint256 canolical_tokens_out) {\n IERC20(0x1A93B23281CC1CDE4C4741353F3064709A16197d).safeTransfer(\n to,\n canolical_tokens_out\n );\n } catch {\n IERC20(token).safeTransfer(to, amount.sub(fee));\n }\n } else {\n IERC20(token).safeTransfer(to, amount.sub(fee));\n }\n if (chainGasAmount != 0 && address(this).balance > chainGasAmount) {\n to.call.value(chainGasAmount)(\"\");\n }\n }\n\n /**\n * @notice Relays to nodes to both transfer an ERC20 token cross-chain, and then have the nodes execute a swap through a liquidity pool on behalf of the user.\n * @param to address on other chain to bridge assets to\n * @param chainId which chain to bridge assets onto\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n * @param tokenIndexFrom the token the user wants to swap from\n * @param tokenIndexTo the token the user wants to swap to\n * @param minDy the min amount the user would like to receive, or revert to only minting the SynERC20 token crosschain.\n * @param deadline latest timestamp to accept this transaction\n **/\n function depositAndSwap(\n address to,\n uint256 chainId,\n IERC20 token,\n uint256 amount,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 minDy,\n uint256 deadline\n ) external nonReentrant whenNotPaused {\n emit TokenDepositAndSwap(\n to,\n chainId,\n token,\n amount,\n tokenIndexFrom,\n tokenIndexTo,\n minDy,\n deadline\n );\n token.safeTransferFrom(msg.sender, address(this), amount);\n }\n\n /**\n * @notice Relays to nodes that (typically) a wrapped synAsset ERC20 token has been burned and the underlying needs to be redeeemed on the native chain. This function indicates to the nodes that they should attempt to redeem the LP token for the underlying assets (E.g \"swap\" out of the LP token)\n * @param to address on other chain to redeem underlying assets to\n * @param chainId which underlying chain to bridge assets onto\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n * @param tokenIndexFrom the token the user wants to swap from\n * @param tokenIndexTo the token the user wants to swap to\n * @param minDy the min amount the user would like to receive, or revert to only minting the SynERC20 token crosschain.\n * @param deadline latest timestamp to accept this transaction\n **/\n function redeemAndSwap(\n address to,\n uint256 chainId,\n ERC20Burnable token,\n uint256 amount,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 minDy,\n uint256 deadline\n ) external nonReentrant whenNotPaused {\n emit TokenRedeemAndSwap(\n to,\n chainId,\n token,\n amount,\n tokenIndexFrom,\n tokenIndexTo,\n minDy,\n deadline\n );\n token.burnFrom(msg.sender, amount);\n }\n\n /**\n * @notice Relays to nodes that (typically) a wrapped synAsset ERC20 token has been burned and the underlying needs to be redeeemed on the native chain. This function indicates to the nodes that they should attempt to redeem the LP token for the underlying assets (E.g \"swap\" out of the LP token)\n * @param to address on other chain to redeem underlying assets to\n * @param chainId which underlying chain to bridge assets onto\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n * @param swapTokenIndex Specifies which of the underlying LP assets the nodes should attempt to redeem for\n * @param swapMinAmount Specifies the minimum amount of the underlying asset needed for the nodes to execute the redeem/swap\n * @param swapDeadline Specificies the deadline that the nodes are allowed to try to redeem/swap the LP token\n **/\n function redeemAndRemove(\n address to,\n uint256 chainId,\n ERC20Burnable token,\n uint256 amount,\n uint8 swapTokenIndex,\n uint256 swapMinAmount,\n uint256 swapDeadline\n ) external nonReentrant whenNotPaused {\n emit TokenRedeemAndRemove(\n to,\n chainId,\n token,\n amount,\n swapTokenIndex,\n swapMinAmount,\n swapDeadline\n );\n token.burnFrom(msg.sender, amount);\n }\n\n /**\n * @notice Nodes call this function to mint a SynERC20 (or any asset that the bridge is given minter access to), and then attempt to swap the SynERC20 into the desired destination asset. This is called by the nodes after a TokenDepositAndSwap event is emitted.\n * @dev This means the BridgeDeposit.sol contract must have minter access to the token attempting to be minted\n * @param to address on other chain to redeem underlying assets to\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain post-fees\n * @param fee Amount in native token decimals to save to the contract as fees\n * @param pool Destination chain's pool to use to swap SynERC20 -> Asset. The nodes determine this by using PoolConfig.sol.\n * @param tokenIndexFrom Index of the SynERC20 asset in the pool\n * @param tokenIndexTo Index of the desired final asset\n * @param minDy Minumum amount (in final asset decimals) that must be swapped for, otherwise the user will receive the SynERC20.\n * @param deadline Epoch time of the deadline that the swap is allowed to be executed.\n * @param kappa kappa\n **/\n function mintAndSwap(\n address payable to,\n IERC20Mintable token,\n uint256 amount,\n uint256 fee,\n ISwap pool,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 minDy,\n uint256 deadline,\n bytes32 kappa\n ) external nonReentrant whenNotPaused {\n require(\n hasRole(NODEGROUP_ROLE, msg.sender),\n \"Caller is not a node group\"\n );\n require(amount > fee, \"Amount must be greater than fee\");\n require(!kappaMap[kappa], \"Kappa is already present\");\n kappaMap[kappa] = true;\n fees[address(token)] = fees[address(token)].add(fee);\n // Transfer gas airdrop\n if (chainGasAmount != 0 && address(this).balance > chainGasAmount) {\n to.call.value(chainGasAmount)(\"\");\n }\n // first check to make sure more will be given than min amount required\n uint256 expectedOutput = ISwap(pool).calculateSwap(\n tokenIndexFrom,\n tokenIndexTo,\n amount.sub(fee)\n );\n\n if (expectedOutput >= minDy) {\n // proceed with swap\n token.mint(address(this), amount);\n token.safeIncreaseAllowance(address(pool), amount);\n try\n ISwap(pool).swap(\n tokenIndexFrom,\n tokenIndexTo,\n amount.sub(fee),\n minDy,\n deadline\n )\n returns (uint256 finalSwappedAmount) {\n // Swap succeeded, transfer swapped asset\n IERC20 swappedTokenTo = ISwap(pool).getToken(tokenIndexTo);\n if (\n address(swappedTokenTo) == WETH_ADDRESS &&\n WETH_ADDRESS != address(0)\n ) {\n IWETH9(WETH_ADDRESS).withdraw(finalSwappedAmount);\n (bool success, ) = to.call{value: finalSwappedAmount}(\"\");\n require(success, \"ETH_TRANSFER_FAILED\");\n emit TokenMintAndSwap(\n to,\n token,\n finalSwappedAmount,\n fee,\n tokenIndexFrom,\n tokenIndexTo,\n minDy,\n deadline,\n true,\n kappa\n );\n } else {\n swappedTokenTo.safeTransfer(to, finalSwappedAmount);\n emit TokenMintAndSwap(\n to,\n token,\n finalSwappedAmount,\n fee,\n tokenIndexFrom,\n tokenIndexTo,\n minDy,\n deadline,\n true,\n kappa\n );\n }\n } catch {\n IERC20(token).safeTransfer(to, amount.sub(fee));\n emit TokenMintAndSwap(\n to,\n token,\n amount.sub(fee),\n fee,\n tokenIndexFrom,\n tokenIndexTo,\n minDy,\n deadline,\n false,\n kappa\n );\n }\n } else {\n token.mint(address(this), amount);\n IERC20(token).safeTransfer(to, amount.sub(fee));\n emit TokenMintAndSwap(\n to,\n token,\n amount.sub(fee),\n fee,\n tokenIndexFrom,\n tokenIndexTo,\n minDy,\n deadline,\n false,\n kappa\n );\n }\n }\n\n /**\n * @notice Function to be called by the node group to withdraw the underlying assets from the contract\n * @param to address on chain to send underlying assets to\n * @param token ERC20 compatible token to withdraw from the bridge\n * @param amount Amount in native token decimals to withdraw\n * @param fee Amount in native token decimals to save to the contract as fees\n * @param pool Destination chain's pool to use to swap SynERC20 -> Asset. The nodes determine this by using PoolConfig.sol.\n * @param swapTokenIndex Specifies which of the underlying LP assets the nodes should attempt to redeem for\n * @param swapMinAmount Specifies the minimum amount of the underlying asset needed for the nodes to execute the redeem/swap\n * @param swapDeadline Specificies the deadline that the nodes are allowed to try to redeem/swap the LP token\n * @param kappa kappa\n **/\n function withdrawAndRemove(\n address to,\n IERC20 token,\n uint256 amount,\n uint256 fee,\n ISwap pool,\n uint8 swapTokenIndex,\n uint256 swapMinAmount,\n uint256 swapDeadline,\n bytes32 kappa\n ) external nonReentrant whenNotPaused {\n require(\n hasRole(NODEGROUP_ROLE, msg.sender),\n \"Caller is not a node group\"\n );\n require(amount > fee, \"Amount must be greater than fee\");\n require(!kappaMap[kappa], \"Kappa is already present\");\n kappaMap[kappa] = true;\n fees[address(token)] = fees[address(token)].add(fee);\n // first check to make sure more will be given than min amount required\n uint256 expectedOutput = ISwap(pool).calculateRemoveLiquidityOneToken(\n amount.sub(fee),\n swapTokenIndex\n );\n\n if (expectedOutput >= swapMinAmount) {\n token.safeIncreaseAllowance(address(pool), amount.sub(fee));\n try\n ISwap(pool).removeLiquidityOneToken(\n amount.sub(fee),\n swapTokenIndex,\n swapMinAmount,\n swapDeadline\n )\n returns (uint256 finalSwappedAmount) {\n // Swap succeeded, transfer swapped asset\n IERC20 swappedTokenTo = ISwap(pool).getToken(swapTokenIndex);\n swappedTokenTo.safeTransfer(to, finalSwappedAmount);\n emit TokenWithdrawAndRemove(\n to,\n token,\n finalSwappedAmount,\n fee,\n swapTokenIndex,\n swapMinAmount,\n swapDeadline,\n true,\n kappa\n );\n } catch {\n IERC20(token).safeTransfer(to, amount.sub(fee));\n emit TokenWithdrawAndRemove(\n to,\n token,\n amount.sub(fee),\n fee,\n swapTokenIndex,\n swapMinAmount,\n swapDeadline,\n false,\n kappa\n );\n }\n } else {\n token.safeTransfer(to, amount.sub(fee));\n emit TokenWithdrawAndRemove(\n to,\n token,\n amount.sub(fee),\n fee,\n swapTokenIndex,\n swapMinAmount,\n swapDeadline,\n false,\n kappa\n );\n }\n }\n\n // BRIDGE FUNCTIONS TO HANDLE DIFF ADDRESSES\n /**\n * @notice Relays to nodes that (typically) a wrapped synAsset ERC20 token has been burned and the underlying needs to be redeeemed on the native chain\n * @param to address on other chain to redeem underlying assets to\n * @param chainId which underlying chain to bridge assets onto\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n **/\n function redeemV2(\n bytes32 to,\n uint256 chainId,\n ERC20Burnable token,\n uint256 amount\n ) external nonReentrant whenNotPaused {\n emit TokenRedeemV2(to, chainId, token, amount);\n token.burnFrom(msg.sender, amount);\n }\n}\n" + }, + "contracts/bridge/HarmonySynapseBridge.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.6.12;\n\nimport \"@openzeppelin/contracts-upgradeable/proxy/Initializable.sol\";\nimport \"@openzeppelin/contracts-upgradeable/access/AccessControlUpgradeable.sol\";\nimport \"@openzeppelin/contracts-upgradeable/utils/ReentrancyGuardUpgradeable.sol\";\nimport \"@openzeppelin/contracts-upgradeable/utils/PausableUpgradeable.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/SafeERC20.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/ERC20Burnable.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport \"@openzeppelin/contracts/math/SafeMath.sol\";\n\nimport \"./interfaces/ISwap.sol\";\nimport \"./interfaces/IWETH9.sol\";\n\ninterface IERC20Mintable is IERC20 {\n function mint(address to, uint256 amount) external;\n}\n\ninterface IFrax {\n function exchangeOldForCanonical(\n address bridge_token_address,\n uint256 token_amount\n ) external returns (uint256);\n}\n\ncontract HarmonySynapseBridge is\n Initializable,\n AccessControlUpgradeable,\n ReentrancyGuardUpgradeable,\n PausableUpgradeable\n{\n using SafeERC20 for IERC20;\n using SafeERC20 for IERC20Mintable;\n using SafeMath for uint256;\n\n bytes32 public constant NODEGROUP_ROLE = keccak256(\"NODEGROUP_ROLE\");\n bytes32 public constant GOVERNANCE_ROLE = keccak256(\"GOVERNANCE_ROLE\");\n\n mapping(address => uint256) private fees;\n\n uint256 public startBlockNumber;\n uint256 public constant bridgeVersion = 6;\n uint256 public chainGasAmount;\n address payable public WETH_ADDRESS;\n\n mapping(bytes32 => bool) private kappaMap;\n\n receive() external payable {}\n\n function initialize() external initializer {\n startBlockNumber = block.number;\n _setupRole(DEFAULT_ADMIN_ROLE, msg.sender);\n __AccessControl_init();\n }\n\n function setChainGasAmount(uint256 amount) external {\n require(hasRole(GOVERNANCE_ROLE, msg.sender), \"Not governance\");\n chainGasAmount = amount;\n }\n\n function setWethAddress(address payable _wethAddress) external {\n require(hasRole(DEFAULT_ADMIN_ROLE, msg.sender), \"Not admin\");\n WETH_ADDRESS = _wethAddress;\n }\n\n function addKappas(bytes32[] calldata kappas) external {\n require(hasRole(GOVERNANCE_ROLE, msg.sender), \"Not governance\");\n for (uint256 i = 0; i < kappas.length; ++i) {\n kappaMap[kappas[i]] = true;\n }\n }\n\n event TokenDeposit(\n address indexed to,\n uint256 chainId,\n IERC20 token,\n uint256 amount\n );\n event TokenRedeem(\n address indexed to,\n uint256 chainId,\n IERC20 token,\n uint256 amount\n );\n event TokenWithdraw(\n address indexed to,\n IERC20 token,\n uint256 amount,\n uint256 fee,\n bytes32 indexed kappa\n );\n event TokenMint(\n address indexed to,\n IERC20Mintable token,\n uint256 amount,\n uint256 fee,\n bytes32 indexed kappa\n );\n event TokenDepositAndSwap(\n address indexed to,\n uint256 chainId,\n IERC20 token,\n uint256 amount,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 minDy,\n uint256 deadline\n );\n event TokenMintAndSwap(\n address indexed to,\n IERC20Mintable token,\n uint256 amount,\n uint256 fee,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 minDy,\n uint256 deadline,\n bool swapSuccess,\n bytes32 indexed kappa\n );\n event TokenRedeemAndSwap(\n address indexed to,\n uint256 chainId,\n IERC20 token,\n uint256 amount,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 minDy,\n uint256 deadline\n );\n event TokenRedeemAndRemove(\n address indexed to,\n uint256 chainId,\n IERC20 token,\n uint256 amount,\n uint8 swapTokenIndex,\n uint256 swapMinAmount,\n uint256 swapDeadline\n );\n event TokenWithdrawAndRemove(\n address indexed to,\n IERC20 token,\n uint256 amount,\n uint256 fee,\n uint8 swapTokenIndex,\n uint256 swapMinAmount,\n uint256 swapDeadline,\n bool swapSuccess,\n bytes32 indexed kappa\n );\n\n // v2 events\n event TokenRedeemV2(\n bytes32 indexed to,\n uint256 chainId,\n IERC20 token,\n uint256 amount\n );\n\n // VIEW FUNCTIONS ***/\n function getFeeBalance(address tokenAddress)\n external\n view\n returns (uint256)\n {\n return fees[tokenAddress];\n }\n\n function kappaExists(bytes32 kappa) external view returns (bool) {\n return kappaMap[kappa];\n }\n\n // FEE FUNCTIONS ***/\n /**\n * * @notice withdraw specified ERC20 token fees to a given address\n * * @param token ERC20 token in which fees acccumulated to transfer\n * * @param to Address to send the fees to\n */\n function withdrawFees(IERC20 token, address to) external whenNotPaused {\n require(hasRole(GOVERNANCE_ROLE, msg.sender), \"Not governance\");\n require(to != address(0), \"Address is 0x000\");\n if (fees[address(token)] != 0) {\n token.safeTransfer(to, fees[address(token)]);\n fees[address(token)] = 0;\n }\n }\n\n // PAUSABLE FUNCTIONS ***/\n function pause() external {\n require(hasRole(GOVERNANCE_ROLE, msg.sender), \"Not governance\");\n _pause();\n }\n\n function unpause() external {\n require(hasRole(GOVERNANCE_ROLE, msg.sender), \"Not governance\");\n _unpause();\n }\n\n /**\n * @notice Relays to nodes to transfers an ERC20 token cross-chain\n * @param to address on other chain to bridge assets to\n * @param chainId which chain to bridge assets onto\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n **/\n function deposit(\n address to,\n uint256 chainId,\n IERC20 token,\n uint256 amount\n ) external nonReentrant whenNotPaused {\n emit TokenDeposit(to, chainId, token, amount);\n token.safeTransferFrom(msg.sender, address(this), amount);\n }\n\n /**\n * @notice Relays to nodes that (typically) a wrapped synAsset ERC20 token has been burned and the underlying needs to be redeeemed on the native chain\n * @param to address on other chain to redeem underlying assets to\n * @param chainId which underlying chain to bridge assets onto\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n **/\n function redeem(\n address to,\n uint256 chainId,\n ERC20Burnable token,\n uint256 amount\n ) external nonReentrant whenNotPaused {\n emit TokenRedeem(to, chainId, token, amount);\n token.burnFrom(msg.sender, amount);\n }\n\n /**\n * @notice Function to be called by the node group to withdraw the underlying assets from the contract\n * @param to address on chain to send underlying assets to\n * @param token ERC20 compatible token to withdraw from the bridge\n * @param amount Amount in native token decimals to withdraw\n * @param fee Amount in native token decimals to save to the contract as fees\n * @param kappa kappa\n **/\n function withdraw(\n address to,\n IERC20 token,\n uint256 amount,\n uint256 fee,\n bytes32 kappa\n ) external nonReentrant whenNotPaused {\n require(\n hasRole(NODEGROUP_ROLE, msg.sender),\n \"Caller is not a node group\"\n );\n require(amount > fee, \"Amount must be greater than fee\");\n require(!kappaMap[kappa], \"Kappa is already present\");\n kappaMap[kappa] = true;\n fees[address(token)] = fees[address(token)].add(fee);\n if (address(token) == WETH_ADDRESS && WETH_ADDRESS != address(0)) {\n IWETH9(WETH_ADDRESS).withdraw(amount.sub(fee));\n (bool success, ) = to.call{value: amount.sub(fee)}(\"\");\n require(success, \"ETH_TRANSFER_FAILED\");\n emit TokenWithdraw(to, token, amount, fee, kappa);\n } else {\n emit TokenWithdraw(to, token, amount, fee, kappa);\n token.safeTransfer(to, amount.sub(fee));\n }\n }\n\n /**\n * @notice Nodes call this function to mint a SynERC20 (or any asset that the bridge is given minter access to). This is called by the nodes after a TokenDeposit event is emitted.\n * @dev This means the SynapseBridge.sol contract must have minter access to the token attempting to be minted\n * @param to address on other chain to redeem underlying assets to\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain post-fees\n * @param fee Amount in native token decimals to save to the contract as fees\n * @param kappa kappa\n **/\n function mint(\n address payable to,\n IERC20Mintable token,\n uint256 amount,\n uint256 fee,\n bytes32 kappa\n ) external nonReentrant whenNotPaused {\n require(\n hasRole(NODEGROUP_ROLE, msg.sender),\n \"Caller is not a node group\"\n );\n require(amount > fee, \"Amount must be greater than fee\");\n require(!kappaMap[kappa], \"Kappa is already present\");\n kappaMap[kappa] = true;\n fees[address(token)] = fees[address(token)].add(fee);\n emit TokenMint(to, token, amount.sub(fee), fee, kappa);\n token.mint(address(this), amount);\n // checks if synFRAX\n if (address(token) == 0x1852F70512298d56e9c8FDd905e02581E04ddb2a) {\n if (\n token.allowance(\n address(this),\n 0xFa7191D292d5633f702B0bd7E3E3BcCC0e633200\n ) < amount.sub(fee)\n ) {\n token.safeApprove(\n address(0xFa7191D292d5633f702B0bd7E3E3BcCC0e633200),\n 0\n );\n token.safeApprove(\n address(0xFa7191D292d5633f702B0bd7E3E3BcCC0e633200),\n type(uint256).max\n );\n }\n try\n IFrax(0xFa7191D292d5633f702B0bd7E3E3BcCC0e633200)\n .exchangeOldForCanonical(address(token), amount.sub(fee))\n returns (uint256 canolical_tokens_out) {\n IERC20(0xFa7191D292d5633f702B0bd7E3E3BcCC0e633200).safeTransfer(\n to,\n canolical_tokens_out\n );\n } catch {\n IERC20(token).safeTransfer(to, amount.sub(fee));\n }\n } else {\n IERC20(token).safeTransfer(to, amount.sub(fee));\n }\n if (chainGasAmount != 0 && address(this).balance > chainGasAmount) {\n to.call.value(chainGasAmount)(\"\");\n }\n }\n\n /**\n * @notice Relays to nodes to both transfer an ERC20 token cross-chain, and then have the nodes execute a swap through a liquidity pool on behalf of the user.\n * @param to address on other chain to bridge assets to\n * @param chainId which chain to bridge assets onto\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n * @param tokenIndexFrom the token the user wants to swap from\n * @param tokenIndexTo the token the user wants to swap to\n * @param minDy the min amount the user would like to receive, or revert to only minting the SynERC20 token crosschain.\n * @param deadline latest timestamp to accept this transaction\n **/\n function depositAndSwap(\n address to,\n uint256 chainId,\n IERC20 token,\n uint256 amount,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 minDy,\n uint256 deadline\n ) external nonReentrant whenNotPaused {\n emit TokenDepositAndSwap(\n to,\n chainId,\n token,\n amount,\n tokenIndexFrom,\n tokenIndexTo,\n minDy,\n deadline\n );\n token.safeTransferFrom(msg.sender, address(this), amount);\n }\n\n /**\n * @notice Relays to nodes that (typically) a wrapped synAsset ERC20 token has been burned and the underlying needs to be redeeemed on the native chain. This function indicates to the nodes that they should attempt to redeem the LP token for the underlying assets (E.g \"swap\" out of the LP token)\n * @param to address on other chain to redeem underlying assets to\n * @param chainId which underlying chain to bridge assets onto\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n * @param tokenIndexFrom the token the user wants to swap from\n * @param tokenIndexTo the token the user wants to swap to\n * @param minDy the min amount the user would like to receive, or revert to only minting the SynERC20 token crosschain.\n * @param deadline latest timestamp to accept this transaction\n **/\n function redeemAndSwap(\n address to,\n uint256 chainId,\n ERC20Burnable token,\n uint256 amount,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 minDy,\n uint256 deadline\n ) external nonReentrant whenNotPaused {\n emit TokenRedeemAndSwap(\n to,\n chainId,\n token,\n amount,\n tokenIndexFrom,\n tokenIndexTo,\n minDy,\n deadline\n );\n token.burnFrom(msg.sender, amount);\n }\n\n /**\n * @notice Relays to nodes that (typically) a wrapped synAsset ERC20 token has been burned and the underlying needs to be redeeemed on the native chain. This function indicates to the nodes that they should attempt to redeem the LP token for the underlying assets (E.g \"swap\" out of the LP token)\n * @param to address on other chain to redeem underlying assets to\n * @param chainId which underlying chain to bridge assets onto\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n * @param swapTokenIndex Specifies which of the underlying LP assets the nodes should attempt to redeem for\n * @param swapMinAmount Specifies the minimum amount of the underlying asset needed for the nodes to execute the redeem/swap\n * @param swapDeadline Specificies the deadline that the nodes are allowed to try to redeem/swap the LP token\n **/\n function redeemAndRemove(\n address to,\n uint256 chainId,\n ERC20Burnable token,\n uint256 amount,\n uint8 swapTokenIndex,\n uint256 swapMinAmount,\n uint256 swapDeadline\n ) external nonReentrant whenNotPaused {\n emit TokenRedeemAndRemove(\n to,\n chainId,\n token,\n amount,\n swapTokenIndex,\n swapMinAmount,\n swapDeadline\n );\n token.burnFrom(msg.sender, amount);\n }\n\n /**\n * @notice Nodes call this function to mint a SynERC20 (or any asset that the bridge is given minter access to), and then attempt to swap the SynERC20 into the desired destination asset. This is called by the nodes after a TokenDepositAndSwap event is emitted.\n * @dev This means the BridgeDeposit.sol contract must have minter access to the token attempting to be minted\n * @param to address on other chain to redeem underlying assets to\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain post-fees\n * @param fee Amount in native token decimals to save to the contract as fees\n * @param pool Destination chain's pool to use to swap SynERC20 -> Asset. The nodes determine this by using PoolConfig.sol.\n * @param tokenIndexFrom Index of the SynERC20 asset in the pool\n * @param tokenIndexTo Index of the desired final asset\n * @param minDy Minumum amount (in final asset decimals) that must be swapped for, otherwise the user will receive the SynERC20.\n * @param deadline Epoch time of the deadline that the swap is allowed to be executed.\n * @param kappa kappa\n **/\n function mintAndSwap(\n address payable to,\n IERC20Mintable token,\n uint256 amount,\n uint256 fee,\n ISwap pool,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 minDy,\n uint256 deadline,\n bytes32 kappa\n ) external nonReentrant whenNotPaused {\n require(\n hasRole(NODEGROUP_ROLE, msg.sender),\n \"Caller is not a node group\"\n );\n require(amount > fee, \"Amount must be greater than fee\");\n require(!kappaMap[kappa], \"Kappa is already present\");\n kappaMap[kappa] = true;\n fees[address(token)] = fees[address(token)].add(fee);\n // Transfer gas airdrop\n if (chainGasAmount != 0 && address(this).balance > chainGasAmount) {\n to.call.value(chainGasAmount)(\"\");\n }\n // first check to make sure more will be given than min amount required\n uint256 expectedOutput = ISwap(pool).calculateSwap(\n tokenIndexFrom,\n tokenIndexTo,\n amount.sub(fee)\n );\n\n if (expectedOutput >= minDy) {\n // proceed with swap\n token.mint(address(this), amount);\n token.safeIncreaseAllowance(address(pool), amount);\n try\n ISwap(pool).swap(\n tokenIndexFrom,\n tokenIndexTo,\n amount.sub(fee),\n minDy,\n deadline\n )\n returns (uint256 finalSwappedAmount) {\n // Swap succeeded, transfer swapped asset\n IERC20 swappedTokenTo = ISwap(pool).getToken(tokenIndexTo);\n if (\n address(swappedTokenTo) == WETH_ADDRESS &&\n WETH_ADDRESS != address(0)\n ) {\n IWETH9(WETH_ADDRESS).withdraw(finalSwappedAmount);\n (bool success, ) = to.call{value: finalSwappedAmount}(\"\");\n require(success, \"ETH_TRANSFER_FAILED\");\n emit TokenMintAndSwap(\n to,\n token,\n finalSwappedAmount,\n fee,\n tokenIndexFrom,\n tokenIndexTo,\n minDy,\n deadline,\n true,\n kappa\n );\n } else {\n swappedTokenTo.safeTransfer(to, finalSwappedAmount);\n emit TokenMintAndSwap(\n to,\n token,\n finalSwappedAmount,\n fee,\n tokenIndexFrom,\n tokenIndexTo,\n minDy,\n deadline,\n true,\n kappa\n );\n }\n } catch {\n IERC20(token).safeTransfer(to, amount.sub(fee));\n emit TokenMintAndSwap(\n to,\n token,\n amount.sub(fee),\n fee,\n tokenIndexFrom,\n tokenIndexTo,\n minDy,\n deadline,\n false,\n kappa\n );\n }\n } else {\n token.mint(address(this), amount);\n IERC20(token).safeTransfer(to, amount.sub(fee));\n emit TokenMintAndSwap(\n to,\n token,\n amount.sub(fee),\n fee,\n tokenIndexFrom,\n tokenIndexTo,\n minDy,\n deadline,\n false,\n kappa\n );\n }\n }\n\n /**\n * @notice Function to be called by the node group to withdraw the underlying assets from the contract\n * @param to address on chain to send underlying assets to\n * @param token ERC20 compatible token to withdraw from the bridge\n * @param amount Amount in native token decimals to withdraw\n * @param fee Amount in native token decimals to save to the contract as fees\n * @param pool Destination chain's pool to use to swap SynERC20 -> Asset. The nodes determine this by using PoolConfig.sol.\n * @param swapTokenIndex Specifies which of the underlying LP assets the nodes should attempt to redeem for\n * @param swapMinAmount Specifies the minimum amount of the underlying asset needed for the nodes to execute the redeem/swap\n * @param swapDeadline Specificies the deadline that the nodes are allowed to try to redeem/swap the LP token\n * @param kappa kappa\n **/\n function withdrawAndRemove(\n address to,\n IERC20 token,\n uint256 amount,\n uint256 fee,\n ISwap pool,\n uint8 swapTokenIndex,\n uint256 swapMinAmount,\n uint256 swapDeadline,\n bytes32 kappa\n ) external nonReentrant whenNotPaused {\n require(\n hasRole(NODEGROUP_ROLE, msg.sender),\n \"Caller is not a node group\"\n );\n require(amount > fee, \"Amount must be greater than fee\");\n require(!kappaMap[kappa], \"Kappa is already present\");\n kappaMap[kappa] = true;\n fees[address(token)] = fees[address(token)].add(fee);\n // first check to make sure more will be given than min amount required\n uint256 expectedOutput = ISwap(pool).calculateRemoveLiquidityOneToken(\n amount.sub(fee),\n swapTokenIndex\n );\n\n if (expectedOutput >= swapMinAmount) {\n token.safeIncreaseAllowance(address(pool), amount.sub(fee));\n try\n ISwap(pool).removeLiquidityOneToken(\n amount.sub(fee),\n swapTokenIndex,\n swapMinAmount,\n swapDeadline\n )\n returns (uint256 finalSwappedAmount) {\n // Swap succeeded, transfer swapped asset\n IERC20 swappedTokenTo = ISwap(pool).getToken(swapTokenIndex);\n swappedTokenTo.safeTransfer(to, finalSwappedAmount);\n emit TokenWithdrawAndRemove(\n to,\n token,\n finalSwappedAmount,\n fee,\n swapTokenIndex,\n swapMinAmount,\n swapDeadline,\n true,\n kappa\n );\n } catch {\n IERC20(token).safeTransfer(to, amount.sub(fee));\n emit TokenWithdrawAndRemove(\n to,\n token,\n amount.sub(fee),\n fee,\n swapTokenIndex,\n swapMinAmount,\n swapDeadline,\n false,\n kappa\n );\n }\n } else {\n token.safeTransfer(to, amount.sub(fee));\n emit TokenWithdrawAndRemove(\n to,\n token,\n amount.sub(fee),\n fee,\n swapTokenIndex,\n swapMinAmount,\n swapDeadline,\n false,\n kappa\n );\n }\n }\n\n // BRIDGE FUNCTIONS TO HANDLE DIFF ADDRESSES\n /**\n * @notice Relays to nodes that (typically) a wrapped synAsset ERC20 token has been burned and the underlying needs to be redeeemed on the native chain\n * @param to address on other chain to redeem underlying assets to\n * @param chainId which underlying chain to bridge assets onto\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n **/\n function redeemV2(\n bytes32 to,\n uint256 chainId,\n ERC20Burnable token,\n uint256 amount\n ) external nonReentrant whenNotPaused {\n emit TokenRedeemV2(to, chainId, token, amount);\n token.burnFrom(msg.sender, amount);\n }\n}\n" + }, + "contracts/bridge/SynapseERC20.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.6.12;\n\nimport \"@openzeppelin/contracts-upgradeable/token/ERC20/ERC20Upgradeable.sol\";\nimport \"@openzeppelin/contracts-upgradeable/token/ERC20/ERC20BurnableUpgradeable.sol\";\nimport \"@openzeppelin/contracts-upgradeable/drafts/ERC20PermitUpgradeable.sol\";\nimport \"@openzeppelin/contracts-upgradeable/access/AccessControlUpgradeable.sol\";\nimport \"@openzeppelin/contracts-upgradeable/proxy/Initializable.sol\";\n\ncontract SynapseERC20 is\n Initializable,\n ContextUpgradeable,\n AccessControlUpgradeable,\n ERC20BurnableUpgradeable,\n ERC20PermitUpgradeable\n{\n bytes32 public constant MINTER_ROLE = keccak256(\"MINTER_ROLE\");\n\n /**\n * @notice Initializes this ERC20 contract with the given parameters.\n * @param name Token name\n * @param symbol Token symbol\n * @param decimals Token name\n * @param owner admin address to be initialized with\n */\n function initialize(\n string memory name,\n string memory symbol,\n uint8 decimals,\n address owner\n ) external initializer {\n __Context_init_unchained();\n __AccessControl_init_unchained();\n __ERC20_init_unchained(name, symbol);\n __ERC20Burnable_init_unchained();\n _setupDecimals(decimals);\n __ERC20Permit_init(name);\n _setupRole(DEFAULT_ADMIN_ROLE, owner);\n }\n\n function mint(address to, uint256 amount) external {\n require(hasRole(MINTER_ROLE, msg.sender), \"Not a minter\");\n _mint(to, amount);\n }\n}\n" + }, + "@openzeppelin/contracts-upgradeable/drafts/ERC20PermitUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.5 <0.8.0;\n\nimport \"../token/ERC20/ERC20Upgradeable.sol\";\nimport \"./IERC20PermitUpgradeable.sol\";\nimport \"../cryptography/ECDSAUpgradeable.sol\";\nimport \"../utils/CountersUpgradeable.sol\";\nimport \"./EIP712Upgradeable.sol\";\nimport \"../proxy/Initializable.sol\";\n\n/**\n * @dev Implementation of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in\n * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612].\n *\n * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by\n * presenting a message signed by the account. By not relying on `{IERC20-approve}`, the token holder account doesn't\n * need to send a transaction, and thus is not required to hold Ether at all.\n *\n * _Available since v3.4._\n */\nabstract contract ERC20PermitUpgradeable is Initializable, ERC20Upgradeable, IERC20PermitUpgradeable, EIP712Upgradeable {\n using CountersUpgradeable for CountersUpgradeable.Counter;\n\n mapping (address => CountersUpgradeable.Counter) private _nonces;\n\n // solhint-disable-next-line var-name-mixedcase\n bytes32 private _PERMIT_TYPEHASH;\n\n /**\n * @dev Initializes the {EIP712} domain separator using the `name` parameter, and setting `version` to `\"1\"`.\n *\n * It's a good idea to use the same `name` that is defined as the ERC20 token name.\n */\n function __ERC20Permit_init(string memory name) internal initializer {\n __Context_init_unchained();\n __EIP712_init_unchained(name, \"1\");\n __ERC20Permit_init_unchained(name);\n }\n\n function __ERC20Permit_init_unchained(string memory name) internal initializer {\n _PERMIT_TYPEHASH = keccak256(\"Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)\");\n }\n\n /**\n * @dev See {IERC20Permit-permit}.\n */\n function permit(address owner, address spender, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s) public virtual override {\n // solhint-disable-next-line not-rely-on-time\n require(block.timestamp <= deadline, \"ERC20Permit: expired deadline\");\n\n bytes32 structHash = keccak256(\n abi.encode(\n _PERMIT_TYPEHASH,\n owner,\n spender,\n value,\n _nonces[owner].current(),\n deadline\n )\n );\n\n bytes32 hash = _hashTypedDataV4(structHash);\n\n address signer = ECDSAUpgradeable.recover(hash, v, r, s);\n require(signer == owner, \"ERC20Permit: invalid signature\");\n\n _nonces[owner].increment();\n _approve(owner, spender, value);\n }\n\n /**\n * @dev See {IERC20Permit-nonces}.\n */\n function nonces(address owner) public view override returns (uint256) {\n return _nonces[owner].current();\n }\n\n /**\n * @dev See {IERC20Permit-DOMAIN_SEPARATOR}.\n */\n // solhint-disable-next-line func-name-mixedcase\n function DOMAIN_SEPARATOR() external view override returns (bytes32) {\n return _domainSeparatorV4();\n }\n uint256[49] private __gap;\n}\n" + }, + "@openzeppelin/contracts-upgradeable/drafts/IERC20PermitUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <0.8.0;\n\n/**\n * @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in\n * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612].\n *\n * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by\n * presenting a message signed by the account. By not relying on `{IERC20-approve}`, the token holder account doesn't\n * need to send a transaction, and thus is not required to hold Ether at all.\n */\ninterface IERC20PermitUpgradeable {\n /**\n * @dev Sets `value` as the allowance of `spender` over `owner`'s tokens,\n * given `owner`'s signed approval.\n *\n * IMPORTANT: The same issues {IERC20-approve} has related to transaction\n * ordering also apply here.\n *\n * Emits an {Approval} event.\n *\n * Requirements:\n *\n * - `spender` cannot be the zero address.\n * - `deadline` must be a timestamp in the future.\n * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner`\n * over the EIP712-formatted function arguments.\n * - the signature must use ``owner``'s current nonce (see {nonces}).\n *\n * For more information on the signature format, see the\n * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP\n * section].\n */\n function permit(address owner, address spender, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s) external;\n\n /**\n * @dev Returns the current nonce for `owner`. This value must be\n * included whenever a signature is generated for {permit}.\n *\n * Every successful call to {permit} increases ``owner``'s nonce by one. This\n * prevents a signature from being used multiple times.\n */\n function nonces(address owner) external view returns (uint256);\n\n /**\n * @dev Returns the domain separator used in the encoding of the signature for `permit`, as defined by {EIP712}.\n */\n // solhint-disable-next-line func-name-mixedcase\n function DOMAIN_SEPARATOR() external view returns (bytes32);\n}\n" + }, + "@openzeppelin/contracts-upgradeable/cryptography/ECDSAUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <0.8.0;\n\n/**\n * @dev Elliptic Curve Digital Signature Algorithm (ECDSA) operations.\n *\n * These functions can be used to verify that a message was signed by the holder\n * of the private keys of a given address.\n */\nlibrary ECDSAUpgradeable {\n /**\n * @dev Returns the address that signed a hashed message (`hash`) with\n * `signature`. This address can then be used for verification purposes.\n *\n * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:\n * this function rejects them by requiring the `s` value to be in the lower\n * half order, and the `v` value to be either 27 or 28.\n *\n * IMPORTANT: `hash` _must_ be the result of a hash operation for the\n * verification to be secure: it is possible to craft signatures that\n * recover to arbitrary addresses for non-hashed data. A safe way to ensure\n * this is by receiving a hash of the original message (which may otherwise\n * be too long), and then calling {toEthSignedMessageHash} on it.\n */\n function recover(bytes32 hash, bytes memory signature) internal pure returns (address) {\n // Check the signature length\n if (signature.length != 65) {\n revert(\"ECDSA: invalid signature length\");\n }\n\n // Divide the signature in r, s and v variables\n bytes32 r;\n bytes32 s;\n uint8 v;\n\n // ecrecover takes the signature parameters, and the only way to get them\n // currently is to use assembly.\n // solhint-disable-next-line no-inline-assembly\n assembly {\n r := mload(add(signature, 0x20))\n s := mload(add(signature, 0x40))\n v := byte(0, mload(add(signature, 0x60)))\n }\n\n return recover(hash, v, r, s);\n }\n\n /**\n * @dev Overload of {ECDSA-recover-bytes32-bytes-} that receives the `v`,\n * `r` and `s` signature fields separately.\n */\n function recover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) internal pure returns (address) {\n // EIP-2 still allows signature malleability for ecrecover(). Remove this possibility and make the signature\n // unique. Appendix F in the Ethereum Yellow paper (https://ethereum.github.io/yellowpaper/paper.pdf), defines\n // the valid range for s in (281): 0 < s < secp256k1n ÷ 2 + 1, and for v in (282): v ∈ {27, 28}. Most\n // signatures from current libraries generate a unique signature with an s-value in the lower half order.\n //\n // If your library generates malleable signatures, such as s-values in the upper range, calculate a new s-value\n // with 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 - s1 and flip v from 27 to 28 or\n // vice versa. If your library also generates signatures with 0/1 for v instead 27/28, add 27 to v to accept\n // these malleable signatures as well.\n require(uint256(s) <= 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0, \"ECDSA: invalid signature 's' value\");\n require(v == 27 || v == 28, \"ECDSA: invalid signature 'v' value\");\n\n // If the signature is valid (and not malleable), return the signer address\n address signer = ecrecover(hash, v, r, s);\n require(signer != address(0), \"ECDSA: invalid signature\");\n\n return signer;\n }\n\n /**\n * @dev Returns an Ethereum Signed Message, created from a `hash`. This\n * replicates the behavior of the\n * https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_sign[`eth_sign`]\n * JSON-RPC method.\n *\n * See {recover}.\n */\n function toEthSignedMessageHash(bytes32 hash) internal pure returns (bytes32) {\n // 32 is the length in bytes of hash,\n // enforced by the type signature above\n return keccak256(abi.encodePacked(\"\\x19Ethereum Signed Message:\\n32\", hash));\n }\n}\n" + }, + "@openzeppelin/contracts-upgradeable/utils/CountersUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <0.8.0;\n\nimport \"../math/SafeMathUpgradeable.sol\";\n\n/**\n * @title Counters\n * @author Matt Condon (@shrugs)\n * @dev Provides counters that can only be incremented or decremented by one. This can be used e.g. to track the number\n * of elements in a mapping, issuing ERC721 ids, or counting request ids.\n *\n * Include with `using Counters for Counters.Counter;`\n * Since it is not possible to overflow a 256 bit integer with increments of one, `increment` can skip the {SafeMath}\n * overflow check, thereby saving gas. This does assume however correct usage, in that the underlying `_value` is never\n * directly accessed.\n */\nlibrary CountersUpgradeable {\n using SafeMathUpgradeable for uint256;\n\n struct Counter {\n // This variable should never be directly accessed by users of the library: interactions must be restricted to\n // the library's function. As of Solidity v0.5.2, this cannot be enforced, though there is a proposal to add\n // this feature: see https://github.com/ethereum/solidity/issues/4637\n uint256 _value; // default: 0\n }\n\n function current(Counter storage counter) internal view returns (uint256) {\n return counter._value;\n }\n\n function increment(Counter storage counter) internal {\n // The {SafeMath} overflow check can be skipped here, see the comment at the top\n counter._value += 1;\n }\n\n function decrement(Counter storage counter) internal {\n counter._value = counter._value.sub(1);\n }\n}\n" + }, + "@openzeppelin/contracts-upgradeable/drafts/EIP712Upgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <0.8.0;\nimport \"../proxy/Initializable.sol\";\n\n/**\n * @dev https://eips.ethereum.org/EIPS/eip-712[EIP 712] is a standard for hashing and signing of typed structured data.\n *\n * The encoding specified in the EIP is very generic, and such a generic implementation in Solidity is not feasible,\n * thus this contract does not implement the encoding itself. Protocols need to implement the type-specific encoding\n * they need in their contracts using a combination of `abi.encode` and `keccak256`.\n *\n * This contract implements the EIP 712 domain separator ({_domainSeparatorV4}) that is used as part of the encoding\n * scheme, and the final step of the encoding to obtain the message digest that is then signed via ECDSA\n * ({_hashTypedDataV4}).\n *\n * The implementation of the domain separator was designed to be as efficient as possible while still properly updating\n * the chain id to protect against replay attacks on an eventual fork of the chain.\n *\n * NOTE: This contract implements the version of the encoding known as \"v4\", as implemented by the JSON RPC method\n * https://docs.metamask.io/guide/signing-data.html[`eth_signTypedDataV4` in MetaMask].\n *\n * _Available since v3.4._\n */\nabstract contract EIP712Upgradeable is Initializable {\n /* solhint-disable var-name-mixedcase */\n bytes32 private _HASHED_NAME;\n bytes32 private _HASHED_VERSION;\n bytes32 private constant _TYPE_HASH = keccak256(\"EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)\");\n /* solhint-enable var-name-mixedcase */\n\n /**\n * @dev Initializes the domain separator and parameter caches.\n *\n * The meaning of `name` and `version` is specified in\n * https://eips.ethereum.org/EIPS/eip-712#definition-of-domainseparator[EIP 712]:\n *\n * - `name`: the user readable name of the signing domain, i.e. the name of the DApp or the protocol.\n * - `version`: the current major version of the signing domain.\n *\n * NOTE: These parameters cannot be changed except through a xref:learn::upgrading-smart-contracts.adoc[smart\n * contract upgrade].\n */\n function __EIP712_init(string memory name, string memory version) internal initializer {\n __EIP712_init_unchained(name, version);\n }\n\n function __EIP712_init_unchained(string memory name, string memory version) internal initializer {\n bytes32 hashedName = keccak256(bytes(name));\n bytes32 hashedVersion = keccak256(bytes(version));\n _HASHED_NAME = hashedName;\n _HASHED_VERSION = hashedVersion;\n }\n\n /**\n * @dev Returns the domain separator for the current chain.\n */\n function _domainSeparatorV4() internal view returns (bytes32) {\n return _buildDomainSeparator(_TYPE_HASH, _EIP712NameHash(), _EIP712VersionHash());\n }\n\n function _buildDomainSeparator(bytes32 typeHash, bytes32 name, bytes32 version) private view returns (bytes32) {\n return keccak256(\n abi.encode(\n typeHash,\n name,\n version,\n _getChainId(),\n address(this)\n )\n );\n }\n\n /**\n * @dev Given an already https://eips.ethereum.org/EIPS/eip-712#definition-of-hashstruct[hashed struct], this\n * function returns the hash of the fully encoded EIP712 message for this domain.\n *\n * This hash can be used together with {ECDSA-recover} to obtain the signer of a message. For example:\n *\n * ```solidity\n * bytes32 digest = _hashTypedDataV4(keccak256(abi.encode(\n * keccak256(\"Mail(address to,string contents)\"),\n * mailTo,\n * keccak256(bytes(mailContents))\n * )));\n * address signer = ECDSA.recover(digest, signature);\n * ```\n */\n function _hashTypedDataV4(bytes32 structHash) internal view virtual returns (bytes32) {\n return keccak256(abi.encodePacked(\"\\x19\\x01\", _domainSeparatorV4(), structHash));\n }\n\n function _getChainId() private view returns (uint256 chainId) {\n this; // silence state mutability warning without generating bytecode - see https://github.com/ethereum/solidity/issues/2691\n // solhint-disable-next-line no-inline-assembly\n assembly {\n chainId := chainid()\n }\n }\n\n /**\n * @dev The hash of the name parameter for the EIP712 domain.\n *\n * NOTE: This function reads from storage by default, but can be redefined to return a constant value if gas costs\n * are a concern.\n */\n function _EIP712NameHash() internal virtual view returns (bytes32) {\n return _HASHED_NAME;\n }\n\n /**\n * @dev The hash of the version parameter for the EIP712 domain.\n *\n * NOTE: This function reads from storage by default, but can be redefined to return a constant value if gas costs\n * are a concern.\n */\n function _EIP712VersionHash() internal virtual view returns (bytes32) {\n return _HASHED_VERSION;\n }\n uint256[50] private __gap;\n}\n" + }, + "contracts/auxiliary/DummyWethProxy.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.6.12;\nimport \"@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol\";\nimport \"@openzeppelin/contracts-upgradeable/proxy/Initializable.sol\";\n\ninterface IWETH9 {\n function name() external view returns (string memory);\n\n function symbol() external view returns (string memory);\n\n function decimals() external view returns (uint8);\n\n function balanceOf(address) external view returns (uint256);\n\n function allowance(address, address) external view returns (uint256);\n\n receive() external payable;\n\n function deposit() external payable;\n\n function withdraw(uint256 wad) external;\n\n function totalSupply() external view returns (uint256);\n\n function approve(address guy, uint256 wad) external returns (bool);\n\n function transfer(address dst, uint256 wad) external returns (bool);\n\n function transferFrom(\n address src,\n address dst,\n uint256 wad\n ) external returns (bool);\n}\n\ncontract DummyWethProxy is Initializable, OwnableUpgradeable {\n function initialize() external initializer {\n __Ownable_init();\n }\n\n IWETH9 public WETH;\n\n function setWETHAddress(address payable _weth) external onlyOwner {\n WETH = IWETH9(_weth);\n }\n\n function withdrawToSelf(uint256 amount) external {\n WETH.withdraw(amount);\n }\n\n function rescue(uint256 amount) external onlyOwner {\n WETH.transfer(owner(), amount);\n }\n\n receive() external payable {}\n\n fallback() external payable {}\n}\n" + }, + "contracts/amm/helper/test/TestMathUtils.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.6.12;\n\nimport \"../../MathUtils.sol\";\n\ncontract TestMathUtils {\n using MathUtils for uint256;\n\n function difference(uint256 a, uint256 b) public pure returns (uint256) {\n return a.difference(b);\n }\n\n function within1(uint256 a, uint256 b) public pure returns (bool) {\n return a.within1(b);\n }\n}\n" + }, + "contracts/bridge/ERC20Migrator.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.6.12;\n\nimport \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/SafeERC20.sol\";\nimport \"@openzeppelin/contracts/math/SafeMath.sol\";\n\n/**\n * @title ERC20Migrator\n * @dev This contract can be used to migrate an ERC20 token from one\n * contract to another, where each token holder has to opt-in to the migration.\n * To opt-in, users must approve for this contract the number of tokens they\n * want to migrate. Once the allowance is set up, anyone can trigger the\n * migration to the new token contract. In this way, token holders \"turn in\"\n * their old balance and will be minted an equal amount in the new token.\n * The new token contract must be mintable.\n * ```\n */\n\ninterface IERC20Mintable is IERC20 {\n function mint(address to, uint256 amount) external;\n}\n\ncontract ERC20Migrator {\n using SafeERC20 for IERC20;\n using SafeMath for uint256;\n\n // Address of the old token contract\n IERC20 private _legacyToken;\n\n // Address of the new token contract\n IERC20Mintable private _newToken;\n\n /**\n * @param legacyToken address of the old token contract\n */\n constructor(IERC20 legacyToken, IERC20Mintable newToken) public {\n _legacyToken = legacyToken;\n _newToken = newToken;\n }\n\n /**\n * @dev Returns the legacy token that is being migrated.\n */\n function legacyToken() external view returns (IERC20) {\n return _legacyToken;\n }\n\n /**\n * @dev Returns the new token to which we are migrating.\n */\n function newToken() external view returns (IERC20) {\n return _newToken;\n }\n\n /**\n * @dev Transfers part of an account's balance in the old token to this\n * contract, and mints the same amount of new tokens for that account.\n * @param amount amount of tokens to be migrated\n */\n function migrate(uint256 amount) external {\n _legacyToken.safeTransferFrom(msg.sender, address(this), amount);\n uint256 amountToMint = amount.mul(5).div(2);\n _newToken.mint(msg.sender, amountToMint);\n }\n}\n" + }, + "contracts/bridge/ECDSANodeManagement.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.6.12;\n\nimport \"./utils/AddressArrayUtils.sol\";\nimport \"@openzeppelin/contracts/math/SafeMath.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/SafeERC20.sol\";\n\ncontract ECDSANodeManagement {\n using AddressArrayUtils for address[];\n using SafeMath for uint256;\n using SafeERC20 for IERC20;\n\n // Status of the keep.\n // Active means the keep is active.\n // Closed means the keep was closed happily.\n // Terminated means the keep was closed due to misbehavior.\n enum Status {\n Active,\n Closed,\n Terminated\n }\n\n // Address of the keep's owner.\n address public owner;\n\n // List of keep members' addresses.\n address[] public members;\n\n // Minimum number of honest keep members required to produce a signature.\n uint256 public honestThreshold;\n\n // Keep's ECDSA public key serialized to 64-bytes, where X and Y coordinates\n // are padded with zeros to 32-byte each.\n bytes public publicKey;\n\n // The timestamp at which keep has been created and key generation process\n // started.\n uint256 internal keyGenerationStartTimestamp;\n\n // Map stores public key by member addresses. All members should submit the\n // same public key.\n mapping(address => bytes) internal submittedPublicKeys;\n\n // The current status of the keep.\n // If the keep is Active members monitor it and support requests from the\n // keep owner.\n // If the owner decides to close the keep the flag is set to Closed.\n // If the owner seizes member bonds the flag is set to Terminated.\n Status internal status;\n\n // Flags execution of contract initialization.\n bool internal isInitialized;\n\n // Notification that the submitted public key does not match a key submitted\n // by other member. The event contains address of the member who tried to\n // submit a public key and a conflicting public key submitted already by other\n // member.\n event ConflictingPublicKeySubmitted(\n address indexed submittingMember,\n bytes conflictingPublicKey\n );\n\n // Notification that keep's ECDSA public key has been successfully established.\n event PublicKeyPublished(bytes publicKey);\n\n // Notification that the keep was closed by the owner.\n // Members no longer need to support this keep.\n event KeepClosed();\n\n // Notification that the keep has been terminated by the owner.\n // Members no longer need to support this keep.\n event KeepTerminated();\n\n /// @notice Returns keep's ECDSA public key.\n /// @return Keep's ECDSA public key.\n function getPublicKey() external view returns (bytes memory) {\n return publicKey;\n }\n\n /// @notice Submits a public key to the keep.\n /// @dev Public key is published successfully if all members submit the same\n /// value. In case of conflicts with others members submissions it will emit\n /// `ConflictingPublicKeySubmitted` event. When all submitted keys match\n /// it will store the key as keep's public key and emit a `PublicKeyPublished`\n /// event.\n /// @param _publicKey Signer's public key.\n function submitPublicKey(bytes calldata _publicKey) external onlyMember {\n require(\n !hasMemberSubmittedPublicKey(msg.sender),\n \"Member already submitted a public key\"\n );\n\n require(_publicKey.length == 64, \"Public key must be 64 bytes long\");\n\n submittedPublicKeys[msg.sender] = _publicKey;\n\n // Check if public keys submitted by all keep members are the same as\n // the currently submitted one.\n uint256 matchingPublicKeysCount = 0;\n for (uint256 i = 0; i < members.length; i++) {\n if (\n keccak256(submittedPublicKeys[members[i]]) !=\n keccak256(_publicKey)\n ) {\n // Emit an event only if compared member already submitted a value.\n if (hasMemberSubmittedPublicKey(members[i])) {\n emit ConflictingPublicKeySubmitted(\n msg.sender,\n submittedPublicKeys[members[i]]\n );\n }\n } else {\n matchingPublicKeysCount++;\n }\n }\n\n if (matchingPublicKeysCount != members.length) {\n return;\n }\n\n // All submitted signatures match.\n publicKey = _publicKey;\n emit PublicKeyPublished(_publicKey);\n }\n\n /// @notice Gets the owner of the keep.\n /// @return Address of the keep owner.\n function getOwner() external view returns (address) {\n return owner;\n }\n\n /// @notice Gets the timestamp the keep was opened at.\n /// @return Timestamp the keep was opened at.\n function getOpenedTimestamp() external view returns (uint256) {\n return keyGenerationStartTimestamp;\n }\n\n /// @notice Closes keep when owner decides that they no longer need it.\n /// Releases bonds to the keep members.\n /// @dev The function can be called only by the owner of the keep and only\n /// if the keep has not been already closed.\n function closeKeep() public onlyOwner onlyWhenActive {\n markAsClosed();\n }\n\n /// @notice Returns true if the keep is active.\n /// @return true if the keep is active, false otherwise.\n function isActive() public view returns (bool) {\n return status == Status.Active;\n }\n\n /// @notice Returns true if the keep is closed and members no longer support\n /// this keep.\n /// @return true if the keep is closed, false otherwise.\n function isClosed() public view returns (bool) {\n return status == Status.Closed;\n }\n\n /// @notice Returns true if the keep has been terminated.\n /// Keep is terminated when bonds are seized and members no longer support\n /// this keep.\n /// @return true if the keep has been terminated, false otherwise.\n function isTerminated() public view returns (bool) {\n return status == Status.Terminated;\n }\n\n /// @notice Returns members of the keep.\n /// @return List of the keep members' addresses.\n function getMembers() public view returns (address[] memory) {\n return members;\n }\n\n /// @notice Initialization function.\n /// @dev We use clone factory to create new keep. That is why this contract\n /// doesn't have a constructor. We provide keep parameters for each instance\n /// function after cloning instances from the master contract.\n /// Initialization must happen in the same transaction in which the clone is\n /// created.\n /// @param _owner Address of the keep owner.\n /// @param _members Addresses of the keep members.\n /// @param _honestThreshold Minimum number of honest keep members.\n function initialize(\n address _owner,\n address[] memory _members,\n uint256 _honestThreshold\n ) public {\n require(!isInitialized, \"Contract already initialized\");\n require(_owner != address(0));\n owner = _owner;\n members = _members;\n honestThreshold = _honestThreshold;\n\n status = Status.Active;\n isInitialized = true;\n\n /* solium-disable-next-line security/no-block-members*/\n keyGenerationStartTimestamp = block.timestamp;\n }\n\n /// @notice Checks if the member already submitted a public key.\n /// @param _member Address of the member.\n /// @return True if member already submitted a public key, else false.\n function hasMemberSubmittedPublicKey(address _member)\n internal\n view\n returns (bool)\n {\n return submittedPublicKeys[_member].length != 0;\n }\n\n /// @notice Marks the keep as closed.\n /// Keep can be marked as closed only when there is no signing in progress\n /// or the requested signing process has timed out.\n function markAsClosed() internal {\n status = Status.Closed;\n emit KeepClosed();\n }\n\n /// @notice Marks the keep as terminated.\n /// Keep can be marked as terminated only when there is no signing in progress\n /// or the requested signing process has timed out.\n function markAsTerminated() internal {\n status = Status.Terminated;\n emit KeepTerminated();\n }\n\n /// @notice Coverts a public key to an ethereum address.\n /// @param _publicKey Public key provided as 64-bytes concatenation of\n /// X and Y coordinates (32-bytes each).\n /// @return Ethereum address.\n function publicKeyToAddress(bytes memory _publicKey)\n internal\n pure\n returns (address)\n {\n // We hash the public key and then truncate last 20 bytes of the digest\n // which is the ethereum address.\n return address(uint160(uint256(keccak256(_publicKey))));\n }\n\n /// @notice Terminates the keep.\n function terminateKeep() internal {\n markAsTerminated();\n }\n\n /// @notice Checks if the caller is the keep's owner.\n /// @dev Throws an error if called by any account other than owner.\n modifier onlyOwner() {\n require(owner == msg.sender, \"Caller is not the keep owner\");\n _;\n }\n\n /// @notice Checks if the caller is a keep member.\n /// @dev Throws an error if called by any account other than one of the members.\n modifier onlyMember() {\n require(members.contains(msg.sender), \"Caller is not the keep member\");\n _;\n }\n\n /// @notice Checks if the keep is currently active.\n /// @dev Throws an error if called when the keep has been already closed.\n modifier onlyWhenActive() {\n require(isActive(), \"Keep is not active\");\n _;\n }\n}\n" + }, + "contracts/bridge/utils/AddressArrayUtils.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.6.12;\n\nlibrary AddressArrayUtils {\n function contains(address[] memory self, address _address)\n internal\n pure\n returns (bool)\n {\n for (uint256 i = 0; i < self.length; i++) {\n if (_address == self[i]) {\n return true;\n }\n }\n return false;\n }\n}" + }, + "contracts/bridge/testing/NodeEnv.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.6.12;\npragma experimental ABIEncoderV2;\n\nimport '@openzeppelin/contracts/access/AccessControl.sol';\nimport \"../utils/EnumerableStringMap.sol\";\n\n/**\n * @title NodeEnv contract\n * @author Synapse Authors\n * @notice This contract implements a key-value store for storing variables on which synapse nodes must coordinate\n * methods are purposely arbitrary to allow these fields to be defined in synapse improvement proposals.\n * @notice This token is used for configuring different tokens on the bridge and mapping them across chains.\n**/\ncontract NodeEnv is AccessControl {\n using EnumerableStringMap for EnumerableStringMap.StringToStringMap;\n // BRIDGEMANAGER_ROLE owns the bridge. They are the only user that can call setters on this contract\n bytes32 public constant BRIDGEMANAGER_ROLE = keccak256('BRIDGEMANAGER_ROLE');\n // _config stores the config\n EnumerableStringMap.StringToStringMap private _config; // key is tokenAddress,chainID\n\n // ConfigUpdate is emitted when the config is updated by the user\n event ConfigUpdate(\n string key\n );\n\n constructor() public {\n _setupRole(DEFAULT_ADMIN_ROLE, msg.sender);\n _setupRole(BRIDGEMANAGER_ROLE, msg.sender);\n }\n\n /**\n * @notice get the length of the config\n *\n * @dev this is useful for enumerating through all keys in the env\n */\n function keyCount()\n external\n view\n returns (uint256){\n return _config.length();\n }\n\n /**\n * @notice gets the key/value pair by it's index\n *\n * Requirements:\n *\n * - `index` must be strictly less than {length}.\n */\n function keyValueByIndex(uint256 index) external view returns(string memory, string memory){\n return _config.at(index);\n }\n\n /**\n * @notice gets the value associated with the key\n */\n function get(string calldata _key) external view returns(string memory){\n string memory key = _key;\n return _config.get(key);\n }\n\n /**\n * @notice sets the key\n *\n * @dev caller must have bridge manager role\n */\n function set(string calldata _key, string calldata _value) external returns(bool) {\n require(\n hasRole(BRIDGEMANAGER_ROLE, msg.sender),\n 'Caller is not Bridge Manager'\n );\n string memory key = _key;\n string memory value = _value;\n\n return _config.set(key, value);\n }\n}" + }, + "contracts/bridge/utils/EnumerableStringMap.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.6.12;\n\nimport \"@openzeppelin/contracts/utils/EnumerableSet.sol\";\n\n/**\n * @title EnumerableStringMap\n * @dev Library for managing an enumerable variant of Solidity's\n * https://solidity.readthedocs.io/en/latest/types.html#mapping-types[`mapping`]\n * type.\n *\n * Maps have the following properties:\n *\n * - Entries are added, removed, and checked for existence in constant time\n * (O(1)).\n * - Entries are enumerated in O(n). No guarantees are made on the ordering.\n *\n * this isn't a terribly gas efficient implementation because it emphasizes usability over gas efficiency\n * by allowing arbitrary length string memorys. If Gettetrs/Setters are going to be used frequently in contracts\n * consider using the OpenZeppeling Bytes32 implementation\n *\n * this also differs from the OpenZeppelin implementation by keccac256 hashing the string memorys\n * so we can use enumerable bytes32 set\n */\nlibrary EnumerableStringMap {\n using EnumerableSet for EnumerableSet.Bytes32Set;\n\n // To implement this library for multiple types with as little code\n // repetition as possible, we write it in terms of a generic Map type with\n // bytes32 keys and values.\n // The Map implementation uses private functions, and user-facing\n // implementations (such as Uint256ToAddressMap) are just wrappers around\n // the underlying Map.\n // This means that we can only create new EnumerableMaps for types that fit\n // in bytes32.\n\n struct Map {\n // Storage of keys as a set\n EnumerableSet.Bytes32Set _keys;\n // Mapping of keys to resulting values to allow key lookup in the set\n mapping(bytes32 => string) _hashKeyMap;\n // values\n mapping(bytes32 => string) _values;\n }\n\n /**\n * @dev Adds a key-value pair to a map, or updates the value for an existing\n * key. O(1).\n *\n * Returns true if the key was added to the map, that is if it was not\n * already present.\n */\n function _set(\n Map storage map,\n string memory key,\n string memory value\n ) private returns (bool) {\n bytes32 keyHash = keccak256(abi.encodePacked(key));\n map._values[keyHash] = value;\n map._hashKeyMap[keyHash] = key;\n return map._keys.add(keyHash);\n }\n\n /**\n * @dev Removes a key-value pair from a map. O(1).\n *\n * Returns true if the key was removed from the map, that is if it was present.\n */\n function _remove(Map storage map, bytes32 keyHash) private returns (bool) {\n delete map._values[keyHash];\n delete map._hashKeyMap[keyHash];\n return map._keys.remove(keyHash);\n }\n\n /**\n * @dev Returns true if the key is in the map. O(1).\n */\n function _contains(Map storage map, bytes32 keyHash) private view returns (bool) {\n return map._keys.contains(keyHash);\n }\n\n /**\n * @dev Returns the number of key-value pairs in the map. O(1).\n */\n function _length(Map storage map) private view returns (uint256) {\n return map._keys.length();\n }\n\n /**\n * @dev Returns the key-value pair stored at position `index` in the map. O(1).\n *\n * Note that there are no guarantees on the ordering of entries inside the\n * array, and it may change when more entries are added or removed.\n *\n * Requirements:\n *\n * - `index` must be strictly less than {length}.\n */\n function _at(Map storage map, uint256 index) private view returns (string memory, string memory) {\n bytes32 keyHash = map._keys.at(index);\n return (map._hashKeyMap[keyHash], map._values[keyHash]);\n }\n\n /**\n * @dev Tries to returns the value associated with `key`. O(1).\n * Does not revert if `key` is not in the map.\n */\n function _tryGet(Map storage map, bytes32 keyHash) private view returns (bool, string memory) {\n string memory value = map._values[keyHash];\n if (keccak256(bytes(value)) == keccak256(bytes(\"\"))) {\n return (_contains(map, keyHash), \"\");\n } else {\n return (true, value);\n }\n }\n\n /**\n * @dev Returns the value associated with `key`. O(1).\n *\n * Requirements:\n *\n * - `key` must be in the map.\n */\n function _get(Map storage map, bytes32 keyHash) private view returns (string memory) {\n string memory value = map._values[keyHash];\n require(_contains(map, keyHash), \"EnumerableMap: nonexistent key\");\n return value;\n }\n\n // StringToStringMap\n struct StringToStringMap {\n Map _inner;\n }\n\n /**\n * @dev Adds a key-value pair to a map, or updates the value for an existing\n * key. O(1).\n *\n * Returns true if the key was added to the map, that is if it was not\n * already present.\n */\n function set(\n StringToStringMap storage map,\n string memory key,\n string memory value\n ) internal returns (bool) {\n return _set(map._inner, key, value);\n }\n\n /**\n * @dev Removes a value from a set. O(1).\n *\n * Returns true if the key was removed from the map, that is if it was present.\n */\n function remove(StringToStringMap storage map, string memory key) internal returns (bool) {\n return _remove(map._inner, keccak256(abi.encodePacked(key)));\n }\n\n /**\n * @dev Returns true if the key is in the map. O(1).\n */\n function contains(StringToStringMap storage map, string memory key) internal view returns (bool) {\n return _contains(map._inner, keccak256(abi.encodePacked(key)));\n }\n\n /**\n * @dev Returns the number of elements in the map. O(1).\n */\n function length(StringToStringMap storage map) internal view returns (uint256) {\n return _length(map._inner);\n }\n\n /**\n * @dev Returns the element stored at position `index` in the set. O(1).\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(StringToStringMap storage map, uint256 index) internal view returns (string memory, string memory) {\n return _at(map._inner, index);\n }\n\n /**\n * @dev Tries to returns the value associated with `key`. O(1).\n * Does not revert if `key` is not in the map.\n *\n * _Available since v3.4._\n */\n function tryGet(StringToStringMap storage map, uint256 key) internal view returns (bool, string memory) {\n (bool success, string memory value) = _tryGet(map._inner, bytes32(key));\n return (success, value);\n }\n\n /**\n * @dev Returns the value associated with `key`. O(1).\n *\n * Requirements:\n *\n * - `key` must be in the map.\n */\n function get(StringToStringMap storage map, string memory key) internal view returns (string memory) {\n return _get(map._inner, keccak256(abi.encodePacked(key)));\n }\n}" + }, + "contracts/bridge/PoolConfig.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.6.12;\npragma experimental ABIEncoderV2;\n\nimport \"@openzeppelin/contracts/access/AccessControl.sol\";\n\ncontract PoolConfig is AccessControl {\n bytes32 public constant BRIDGEMANAGER_ROLE =\n keccak256(\"BRIDGEMANAGER_ROLE\");\n mapping(address => mapping(uint256 => Pool)) private _pool; // key is tokenAddress,chainID\n\n struct Pool {\n address tokenAddress;\n uint256 chainId;\n address poolAddress;\n bool metaswap;\n }\n\n constructor() public {\n _setupRole(DEFAULT_ADMIN_ROLE, msg.sender);\n _setupRole(BRIDGEMANAGER_ROLE, msg.sender);\n }\n\n function getPoolConfig(address tokenAddress, uint256 chainID)\n external\n view\n returns (Pool memory)\n {\n return _pool[tokenAddress][chainID];\n }\n\n function setPoolConfig(\n address tokenAddress,\n uint256 chainID,\n address poolAddress,\n bool metaswap\n ) external returns (Pool memory) {\n require(\n hasRole(BRIDGEMANAGER_ROLE, msg.sender),\n \"Caller is not Bridge Manager\"\n );\n Pool memory newPool = Pool(\n tokenAddress,\n chainID,\n poolAddress,\n metaswap\n );\n _pool[tokenAddress][chainID] = newPool;\n return newPool;\n }\n}\n" + }, + "contracts/bridge/BridgeConfigV3.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.6.12;\npragma experimental ABIEncoderV2;\n\nimport \"@openzeppelin/contracts/access/AccessControl.sol\";\nimport \"@openzeppelin/contracts/math/SafeMath.sol\";\n\n/**\n * @title BridgeConfig contract\n * @notice This token is used for configuring different tokens on the bridge and mapping them across chains.\n **/\n\ncontract BridgeConfigV3 is AccessControl {\n using SafeMath for uint256;\n bytes32 public constant BRIDGEMANAGER_ROLE =\n keccak256(\"BRIDGEMANAGER_ROLE\");\n bytes32[] private _allTokenIDs;\n mapping(bytes32 => Token[]) private _allTokens; // key is tokenID\n mapping(uint256 => mapping(string => bytes32)) private _tokenIDMap; // key is chainID,tokenAddress\n mapping(bytes32 => mapping(uint256 => Token)) private _tokens; // key is tokenID,chainID\n mapping(address => mapping(uint256 => Pool)) private _pool; // key is tokenAddress,chainID\n mapping(uint256 => uint256) private _maxGasPrice; // key is tokenID,chainID\n uint256 public constant bridgeConfigVersion = 3;\n\n // the denominator used to calculate fees. For example, an\n // LP fee might be something like tradeAmount.mul(fee).div(FEE_DENOMINATOR)\n uint256 private constant FEE_DENOMINATOR = 10**10;\n\n // this struct must be initialized using setTokenConfig for each token that directly interacts with the bridge\n struct Token {\n uint256 chainId;\n string tokenAddress;\n uint8 tokenDecimals;\n uint256 maxSwap;\n uint256 minSwap;\n uint256 swapFee;\n uint256 maxSwapFee;\n uint256 minSwapFee;\n bool hasUnderlying;\n bool isUnderlying;\n }\n\n struct Pool {\n address tokenAddress;\n uint256 chainId;\n address poolAddress;\n bool metaswap;\n }\n\n constructor() public {\n _setupRole(DEFAULT_ADMIN_ROLE, msg.sender);\n }\n\n /**\n * @notice Returns a list of all existing token IDs converted to strings\n */\n function getAllTokenIDs() public view returns (string[] memory result) {\n uint256 length = _allTokenIDs.length;\n result = new string[](length);\n for (uint256 i = 0; i < length; ++i) {\n result[i] = toString(_allTokenIDs[i]);\n }\n }\n\n function _getTokenID(string memory tokenAddress, uint256 chainID)\n internal\n view\n returns (string memory)\n {\n return toString(_tokenIDMap[chainID][tokenAddress]);\n }\n\n function getTokenID(string memory tokenAddress, uint256 chainID)\n public\n view\n returns (string memory)\n {\n return _getTokenID(_toLower(tokenAddress), chainID);\n }\n\n /**\n * @notice Returns the token ID (string) of the cross-chain token inputted\n * @param tokenAddress address of token to get ID for\n * @param chainID chainID of which to get token ID for\n */\n function getTokenID(address tokenAddress, uint256 chainID)\n public\n view\n returns (string memory)\n {\n return _getTokenID(_toLower(toString(tokenAddress)), chainID);\n }\n\n /**\n * @notice Returns the full token config struct\n * @param tokenID String input of the token ID for the token\n * @param chainID Chain ID of which token address + config to get\n */\n function getToken(string memory tokenID, uint256 chainID)\n public\n view\n returns (Token memory token)\n {\n return _tokens[toBytes32(tokenID)][chainID];\n }\n\n /**\n * @notice Returns the full token config struct\n * @param tokenID String input of the token ID for the token\n * @param chainID Chain ID of which token address + config to get\n */\n function getTokenByID(string memory tokenID, uint256 chainID)\n public\n view\n returns (Token memory token)\n {\n return _tokens[toBytes32(tokenID)][chainID];\n }\n\n /**\n * @notice Returns token config struct, given an address and chainID\n * @param tokenAddress Matches the token ID by using a combo of address + chain ID\n * @param chainID Chain ID of which token to get config for\n */\n function getTokenByAddress(string memory tokenAddress, uint256 chainID)\n public\n view\n returns (Token memory token)\n {\n return _tokens[_tokenIDMap[chainID][_toLower(tokenAddress)]][chainID];\n }\n\n function getTokenByEVMAddress(address tokenAddress, uint256 chainID)\n public\n view\n returns (Token memory token)\n {\n return\n _tokens[_tokenIDMap[chainID][_toLower(toString(tokenAddress))]][\n chainID\n ];\n }\n\n /**\n * @notice Returns true if the token has an underlying token -- meaning the token is deposited into the bridge\n * @param tokenID String to check if it is a withdraw/underlying token\n */\n function hasUnderlyingToken(string memory tokenID)\n public\n view\n returns (bool)\n {\n bytes32 bytesTokenID = toBytes32(tokenID);\n Token[] memory _mcTokens = _allTokens[bytesTokenID];\n for (uint256 i = 0; i < _mcTokens.length; ++i) {\n if (_mcTokens[i].hasUnderlying) {\n return true;\n }\n }\n return false;\n }\n\n /**\n * @notice Returns which token is the underlying token to withdraw\n * @param tokenID string token ID\n */\n function getUnderlyingToken(string memory tokenID)\n public\n view\n returns (Token memory token)\n {\n bytes32 bytesTokenID = toBytes32(tokenID);\n Token[] memory _mcTokens = _allTokens[bytesTokenID];\n for (uint256 i = 0; i < _mcTokens.length; ++i) {\n if (_mcTokens[i].isUnderlying) {\n return _mcTokens[i];\n }\n }\n }\n\n /**\n @notice Public function returning if token ID exists given a string\n */\n function isTokenIDExist(string memory tokenID) public view returns (bool) {\n return _isTokenIDExist(toBytes32(tokenID));\n }\n\n /**\n @notice Internal function returning if token ID exists given bytes32 version of the ID\n */\n function _isTokenIDExist(bytes32 tokenID) internal view returns (bool) {\n for (uint256 i = 0; i < _allTokenIDs.length; ++i) {\n if (_allTokenIDs[i] == tokenID) {\n return true;\n }\n }\n return false;\n }\n\n /**\n * @notice Internal function which handles logic of setting token ID and dealing with mappings\n * @param tokenID bytes32 version of ID\n * @param chainID which chain to set the token config for\n * @param tokenToAdd Token object to set the mapping to\n */\n function _setTokenConfig(\n bytes32 tokenID,\n uint256 chainID,\n Token memory tokenToAdd\n ) internal returns (bool) {\n _tokens[tokenID][chainID] = tokenToAdd;\n if (!_isTokenIDExist(tokenID)) {\n _allTokenIDs.push(tokenID);\n }\n\n Token[] storage _mcTokens = _allTokens[tokenID];\n for (uint256 i = 0; i < _mcTokens.length; ++i) {\n if (_mcTokens[i].chainId == chainID) {\n string memory oldToken = _mcTokens[i].tokenAddress;\n if (!compareStrings(tokenToAdd.tokenAddress, oldToken)) {\n _mcTokens[i].tokenAddress = tokenToAdd.tokenAddress;\n _tokenIDMap[chainID][oldToken] = keccak256(\"\");\n _tokenIDMap[chainID][tokenToAdd.tokenAddress] = tokenID;\n }\n }\n }\n _mcTokens.push(tokenToAdd);\n _tokenIDMap[chainID][tokenToAdd.tokenAddress] = tokenID;\n return true;\n }\n\n /**\n * @notice Main write function of this contract - Handles creating the struct and passing it to the internal logic function\n * @param tokenID string ID to set the token config object form\n * @param chainID chain ID to use for the token config object\n * @param tokenAddress token address of the token on the given chain\n * @param tokenDecimals decimals of token\n * @param maxSwap maximum amount of token allowed to be transferred at once - in native token decimals\n * @param minSwap minimum amount of token needed to be transferred at once - in native token decimals\n * @param swapFee percent based swap fee -- 10e6 == 10bps\n * @param maxSwapFee max swap fee to be charged - in native token decimals\n * @param minSwapFee min swap fee to be charged - in native token decimals - especially useful for mainnet ETH\n * @param hasUnderlying bool which represents whether this is a global mint token or one to withdraw()\n * @param isUnderlying bool which represents if this token is the one to withdraw on the given chain\n */\n function setTokenConfig(\n string calldata tokenID,\n uint256 chainID,\n address tokenAddress,\n uint8 tokenDecimals,\n uint256 maxSwap,\n uint256 minSwap,\n uint256 swapFee,\n uint256 maxSwapFee,\n uint256 minSwapFee,\n bool hasUnderlying,\n bool isUnderlying\n ) public returns (bool) {\n require(hasRole(BRIDGEMANAGER_ROLE, msg.sender));\n return\n setTokenConfig(\n tokenID,\n chainID,\n toString(tokenAddress),\n tokenDecimals,\n maxSwap,\n minSwap,\n swapFee,\n maxSwapFee,\n minSwapFee,\n hasUnderlying,\n isUnderlying\n );\n }\n\n /**\n * @notice Main write function of this contract - Handles creating the struct and passing it to the internal logic function\n * @param tokenID string ID to set the token config object form\n * @param chainID chain ID to use for the token config object\n * @param tokenAddress token address of the token on the given chain\n * @param tokenDecimals decimals of token\n * @param maxSwap maximum amount of token allowed to be transferred at once - in native token decimals\n * @param minSwap minimum amount of token needed to be transferred at once - in native token decimals\n * @param swapFee percent based swap fee -- 10e6 == 10bps\n * @param maxSwapFee max swap fee to be charged - in native token decimals\n * @param minSwapFee min swap fee to be charged - in native token decimals - especially useful for mainnet ETH\n * @param hasUnderlying bool which represents whether this is a global mint token or one to withdraw()\n * @param isUnderlying bool which represents if this token is the one to withdraw on the given chain\n */\n function setTokenConfig(\n string calldata tokenID,\n uint256 chainID,\n string memory tokenAddress,\n uint8 tokenDecimals,\n uint256 maxSwap,\n uint256 minSwap,\n uint256 swapFee,\n uint256 maxSwapFee,\n uint256 minSwapFee,\n bool hasUnderlying,\n bool isUnderlying\n ) public returns (bool) {\n require(hasRole(BRIDGEMANAGER_ROLE, msg.sender));\n Token memory tokenToAdd;\n tokenToAdd.tokenAddress = _toLower(tokenAddress);\n tokenToAdd.tokenDecimals = tokenDecimals;\n tokenToAdd.maxSwap = maxSwap;\n tokenToAdd.minSwap = minSwap;\n tokenToAdd.swapFee = swapFee;\n tokenToAdd.maxSwapFee = maxSwapFee;\n tokenToAdd.minSwapFee = minSwapFee;\n tokenToAdd.hasUnderlying = hasUnderlying;\n tokenToAdd.isUnderlying = isUnderlying;\n tokenToAdd.chainId = chainID;\n\n return _setTokenConfig(toBytes32(tokenID), chainID, tokenToAdd);\n }\n\n function _calculateSwapFee(\n string memory tokenAddress,\n uint256 chainID,\n uint256 amount\n ) internal view returns (uint256) {\n Token memory token = _tokens[_tokenIDMap[chainID][tokenAddress]][\n chainID\n ];\n uint256 calculatedSwapFee = amount.mul(token.swapFee).div(\n FEE_DENOMINATOR\n );\n if (\n calculatedSwapFee > token.minSwapFee &&\n calculatedSwapFee < token.maxSwapFee\n ) {\n return calculatedSwapFee;\n } else if (calculatedSwapFee > token.maxSwapFee) {\n return token.maxSwapFee;\n } else {\n return token.minSwapFee;\n }\n }\n\n /**\n * @notice Calculates bridge swap fee based on the destination chain's token transfer.\n * @dev This means the fee should be calculated based on the chain that the nodes emit a tx on\n * @param tokenAddress address of the destination token to query token config for\n * @param chainID destination chain ID to query the token config for\n * @param amount in native token decimals\n * @return Fee calculated in token decimals\n */\n function calculateSwapFee(\n string memory tokenAddress,\n uint256 chainID,\n uint256 amount\n ) external view returns (uint256) {\n return _calculateSwapFee(_toLower(tokenAddress), chainID, amount);\n }\n\n /**\n * @notice Calculates bridge swap fee based on the destination chain's token transfer.\n * @dev This means the fee should be calculated based on the chain that the nodes emit a tx on\n * @param tokenAddress address of the destination token to query token config for\n * @param chainID destination chain ID to query the token config for\n * @param amount in native token decimals\n * @return Fee calculated in token decimals\n */\n function calculateSwapFee(\n address tokenAddress,\n uint256 chainID,\n uint256 amount\n ) external view returns (uint256) {\n return\n _calculateSwapFee(\n _toLower(toString(tokenAddress)),\n chainID,\n amount\n );\n }\n\n // GAS PRICING\n\n /**\n * @notice sets the max gas price for a chain\n */\n function setMaxGasPrice(uint256 chainID, uint256 maxPrice) public {\n require(hasRole(BRIDGEMANAGER_ROLE, msg.sender));\n _maxGasPrice[chainID] = maxPrice;\n }\n\n /**\n * @notice gets the max gas price for a chain\n */\n function getMaxGasPrice(uint256 chainID) public view returns (uint256) {\n return _maxGasPrice[chainID];\n }\n\n // POOL CONFIG\n\n function getPoolConfig(address tokenAddress, uint256 chainID)\n external\n view\n returns (Pool memory)\n {\n return _pool[tokenAddress][chainID];\n }\n\n function setPoolConfig(\n address tokenAddress,\n uint256 chainID,\n address poolAddress,\n bool metaswap\n ) external returns (Pool memory) {\n require(\n hasRole(BRIDGEMANAGER_ROLE, msg.sender),\n \"Caller is not Bridge Manager\"\n );\n Pool memory newPool = Pool(\n tokenAddress,\n chainID,\n poolAddress,\n metaswap\n );\n _pool[tokenAddress][chainID] = newPool;\n return newPool;\n }\n\n // UTILITY FUNCTIONS\n\n function toString(bytes32 data) internal pure returns (string memory) {\n uint8 i = 0;\n while (i < 32 && data[i] != 0) {\n ++i;\n }\n bytes memory bs = new bytes(i);\n for (uint8 j = 0; j < i; ++j) {\n bs[j] = data[j];\n }\n return string(bs);\n }\n\n // toBytes32 converts a string to a bytes 32\n function toBytes32(string memory str)\n internal\n pure\n returns (bytes32 result)\n {\n require(bytes(str).length <= 32);\n assembly {\n result := mload(add(str, 32))\n }\n }\n\n function toString(address x) internal pure returns (string memory) {\n bytes memory s = new bytes(40);\n for (uint256 i = 0; i < 20; i++) {\n bytes1 b = bytes1(uint8(uint256(uint160(x)) / (2**(8 * (19 - i)))));\n bytes1 hi = bytes1(uint8(b) / 16);\n bytes1 lo = bytes1(uint8(b) - 16 * uint8(hi));\n s[2 * i] = char(hi);\n s[2 * i + 1] = char(lo);\n }\n\n string memory addrPrefix = \"0x\";\n\n return concat(addrPrefix, string(s));\n }\n\n function concat(string memory _x, string memory _y)\n internal\n pure\n returns (string memory)\n {\n bytes memory _xBytes = bytes(_x);\n bytes memory _yBytes = bytes(_y);\n\n string memory _tmpValue = new string(_xBytes.length + _yBytes.length);\n bytes memory _newValue = bytes(_tmpValue);\n\n uint256 i;\n uint256 j;\n\n for (i = 0; i < _xBytes.length; i++) {\n _newValue[j++] = _xBytes[i];\n }\n\n for (i = 0; i < _yBytes.length; i++) {\n _newValue[j++] = _yBytes[i];\n }\n\n return string(_newValue);\n }\n\n function char(bytes1 b) internal pure returns (bytes1 c) {\n if (uint8(b) < 10) {\n c = bytes1(uint8(b) + 0x30);\n } else {\n c = bytes1(uint8(b) + 0x57);\n }\n }\n\n function compareStrings(string memory a, string memory b)\n internal\n pure\n returns (bool)\n {\n return (keccak256(abi.encodePacked((a))) ==\n keccak256(abi.encodePacked((b))));\n }\n\n function _toLower(string memory str) internal pure returns (string memory) {\n bytes memory bStr = bytes(str);\n bytes memory bLower = new bytes(bStr.length);\n for (uint256 i = 0; i < bStr.length; i++) {\n // Uppercase character...\n if ((uint8(bStr[i]) >= 65) && (uint8(bStr[i]) <= 90)) {\n // So we add 32 to make it lowercase\n bLower[i] = bytes1(uint8(bStr[i]) + 32);\n } else {\n bLower[i] = bStr[i];\n }\n }\n return string(bLower);\n }\n}\n" + }, + "contracts/bridge/wrappers/GMXWrapper.sol": { + "content": "// SPDX-License-Identifier: MIT\n\nimport '@openzeppelin/contracts/math/SafeMath.sol';\n\npragma solidity 0.6.12;\n\ninterface IGMX {\n function burn(address _account, uint256 _amount) external;\n function balanceOf(address account) external view returns (uint256);\n function mint(address _account, uint256 _amount) external;\n}\n\ncontract GMXWrapper {\n using SafeMath for uint256;\n\n address constant public gmx = 0x62edc0692BD897D2295872a9FFCac5425011c661;\n address constant public bridge = 0xC05e61d0E7a63D27546389B7aD62FdFf5A91aACE;\n\n function transfer(address _recipient, uint256 _amount) external returns (bool) {\n require(msg.sender == bridge);\n _transfer(msg.sender, _recipient, _amount);\n return true;\n }\n\n function _transfer(address _sender, address _recipient, uint256 _amount) private {\n require(_sender != address(0), \"BaseToken: transfer from the zero address\");\n require(_recipient != address(0), \"BaseToken: transfer to the zero address\");\n IGMX(gmx).burn(_sender, _amount);\n IGMX(gmx).mint(_recipient, _amount);\n }\n\n function mint(address _addr, uint256 _amount) external {\n require(msg.sender == bridge);\n uint256 preMint = IGMX(gmx).balanceOf(_addr);\n IGMX(gmx).mint(_addr, _amount);\n uint256 postMint = IGMX(gmx).balanceOf(_addr);\n require(preMint.add(_amount) == postMint, \"Mint incomplete\");\n }\n\n function burnFrom(address _addr, uint256 _amount) external {\n require(msg.sender == bridge);\n uint256 preBurn = IGMX(gmx).balanceOf(_addr);\n IGMX(gmx).burn(_addr, _amount);\n uint256 postBurn = IGMX(gmx).balanceOf(_addr);\n require(postBurn.add(_amount) == preBurn, \"Burn incomplete\");\n }\n}" + }, + "contracts/amm/SwapEthWrapper.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.6.12;\n\nimport \"@openzeppelin/contracts/math/SafeMath.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/SafeERC20.sol\";\nimport \"./Swap.sol\";\nimport \"./interfaces/IWETH9.sol\";\n\n/**\n * @title SwapEthWrapper\n * @notice A wrapper contract for Swap contracts that have WETH as one of the pooled tokens.\n * @author Jongseung Lim (@weeb_mcgee)\n */\ncontract SwapEthWrapper {\n using SafeERC20 for IERC20;\n using SafeMath for uint256;\n\n // constants\n uint8 private constant MAX_UINT8 = 2**8 - 1;\n uint256 private constant MAX_UINT256 = 2**256 - 1;\n\n // immutables\n Swap public immutable SWAP;\n LPToken public immutable LP_TOKEN;\n address payable public immutable WETH_ADDRESS;\n address public immutable OWNER;\n uint8 public immutable WETH_INDEX;\n\n IERC20[] public pooledTokens;\n\n /**\n * @notice Deploys this contract with given WETH9 address and Swap address. It will attempt to\n * fetch information about the given Swap pool. If the Swap pool does not contain WETH9,\n * this call will be reverted. Owner address must be given so that `rescue()` function\n * can be limited.\n * @param wethAddress address to the WETH9 contract\n * @param swap address to the Swap contract that has WETH9 as one of the tokens\n * @param owner address that will be allowed to call `rescue()`\n */\n constructor(\n address payable wethAddress,\n Swap swap,\n address owner\n ) public {\n (, , , , , , LPToken lpToken) = swap.swapStorage();\n uint8 wethIndex = MAX_UINT8;\n\n for (uint8 i = 0; i < MAX_UINT8; i++) {\n try swap.getToken(i) returns (IERC20 token) {\n pooledTokens.push(token);\n if (address(token) == wethAddress) {\n wethIndex = i;\n }\n // Approve pooled tokens to be used by Swap\n token.approve(address(swap), MAX_UINT256);\n } catch {\n break;\n }\n }\n require(wethIndex != MAX_UINT8, \"WETH was not found in the swap pool\");\n\n // Set immutable variables\n WETH_INDEX = wethIndex;\n WETH_ADDRESS = wethAddress;\n SWAP = swap;\n LP_TOKEN = lpToken;\n OWNER = owner;\n\n // Approve LPToken to be used by Swap\n lpToken.approve(address(swap), MAX_UINT256);\n }\n\n /**\n * @notice Add liquidity to the pool with the given amounts of tokens.\n * @dev The msg.value of this call should match the value in amounts array\n * in position of WETH9.\n * @param amounts the amounts of each token to add, in their native precision\n * @param minToMint the minimum LP tokens adding this amount of liquidity\n * should mint, otherwise revert. Handy for front-running mitigation\n * @param deadline latest timestamp to accept this transaction\n * @return amount of LP token user minted and received\n */\n function addLiquidity(\n uint256[] memory amounts,\n uint256 minToMint,\n uint256 deadline\n ) external payable returns (uint256) {\n // If using ETH, deposit them to WETH.\n require(msg.value == amounts[WETH_INDEX], \"INCORRECT_MSG_VALUE\");\n if (msg.value > 0) {\n IWETH9(WETH_ADDRESS).deposit{value: msg.value}();\n }\n // Go through amounts array and transfer respective tokens to this contract.\n for (uint256 i = 0; i < amounts.length; i++) {\n uint256 amount = amounts[i];\n if (i != WETH_INDEX && amount > 0) {\n pooledTokens[i].safeTransferFrom(\n msg.sender,\n address(this),\n amount\n );\n }\n }\n // Add the assets to the pool\n uint256 lpTokenAmount = SWAP.addLiquidity(amounts, minToMint, deadline);\n // Send the LPToken to msg.sender\n IERC20(address(LP_TOKEN)).safeTransfer(msg.sender, lpTokenAmount);\n return lpTokenAmount;\n }\n\n /**\n * @notice Burn LP tokens to remove liquidity from the pool.\n * @dev Liquidity can always be removed, even when the pool is paused. Caller\n * will receive ETH instead of WETH9.\n * @param amount the amount of LP tokens to burn\n * @param minAmounts the minimum amounts of each token in the pool\n * acceptable for this burn. Useful as a front-running mitigation\n * @param deadline latest timestamp to accept this transaction\n * @return amounts of tokens user received\n */\n function removeLiquidity(\n uint256 amount,\n uint256[] calldata minAmounts,\n uint256 deadline\n ) external returns (uint256[] memory) {\n // Transfer LPToken from msg.sender to this contract.\n IERC20(address(LP_TOKEN)).safeTransferFrom(\n msg.sender,\n address(this),\n amount\n );\n // Remove liquidity\n uint256[] memory amounts = SWAP.removeLiquidity(\n amount,\n minAmounts,\n deadline\n );\n // Send the tokens back to the user\n for (uint256 i = 0; i < amounts.length; i++) {\n if (i != WETH_INDEX) {\n pooledTokens[i].safeTransfer(msg.sender, amounts[i]);\n } else {\n IWETH9(WETH_ADDRESS).withdraw(amounts[i]);\n // slither-disable-next-line arbitrary-send\n (bool success, ) = msg.sender.call{value: amounts[i]}(\"\");\n require(success, \"ETH_TRANSFER_FAILED\");\n }\n }\n return amounts;\n }\n\n /**\n * @notice Remove liquidity from the pool all in one token.\n * @dev Caller will receive ETH instead of WETH9.\n * @param tokenAmount the amount of the token you want to receive\n * @param tokenIndex the index of the token you want to receive\n * @param minAmount the minimum amount to withdraw, otherwise revert\n * @param deadline latest timestamp to accept this transaction\n * @return amount of chosen token user received\n */\n function removeLiquidityOneToken(\n uint256 tokenAmount,\n uint8 tokenIndex,\n uint256 minAmount,\n uint256 deadline\n ) external returns (uint256) {\n // Transfer LPToken from msg.sender to this contract.\n IERC20(address(LP_TOKEN)).safeTransferFrom(\n msg.sender,\n address(this),\n tokenAmount\n );\n // Withdraw via single token\n uint256 amount = SWAP.removeLiquidityOneToken(\n tokenAmount,\n tokenIndex,\n minAmount,\n deadline\n );\n // Transfer the token to msg.sender accordingly\n if (tokenIndex != WETH_INDEX) {\n pooledTokens[tokenIndex].safeTransfer(msg.sender, amount);\n } else {\n IWETH9(WETH_ADDRESS).withdraw(amount);\n // slither-disable-next-line arbitrary-send\n (bool success, ) = msg.sender.call{value: amount}(\"\");\n require(success, \"ETH_TRANSFER_FAILED\");\n }\n return amount;\n }\n\n /**\n * @notice Remove liquidity from the pool, weighted differently than the\n * pool's current balances.\n * @dev Caller will receive ETH instead of WETH9.\n * @param amounts how much of each token to withdraw\n * @param maxBurnAmount the max LP token provider is willing to pay to\n * remove liquidity. Useful as a front-running mitigation.\n * @param deadline latest timestamp to accept this transaction\n * @return amount of LP tokens burned\n */\n function removeLiquidityImbalance(\n uint256[] calldata amounts,\n uint256 maxBurnAmount,\n uint256 deadline\n ) external returns (uint256) {\n // Transfer LPToken from msg.sender to this contract.\n IERC20(address(LP_TOKEN)).safeTransferFrom(\n msg.sender,\n address(this),\n maxBurnAmount\n );\n // Withdraw in imbalanced ratio\n uint256 burnedLpTokenAmount = SWAP.removeLiquidityImbalance(\n amounts,\n maxBurnAmount,\n deadline\n );\n // Send the tokens back to the user\n for (uint256 i = 0; i < amounts.length; i++) {\n if (i != WETH_INDEX) {\n pooledTokens[i].safeTransfer(msg.sender, amounts[i]);\n } else {\n IWETH9(WETH_ADDRESS).withdraw(amounts[i]);\n // slither-disable-next-line arbitrary-send\n (bool success, ) = msg.sender.call{value: amounts[i]}(\"\");\n require(success, \"ETH_TRANSFER_FAILED\");\n }\n }\n // Send any extra LP tokens back as well\n uint256 extraLpTokenAmount = maxBurnAmount.sub(burnedLpTokenAmount);\n if (extraLpTokenAmount > 0) {\n IERC20(address(LP_TOKEN)).safeTransfer(\n msg.sender,\n extraLpTokenAmount\n );\n }\n return burnedLpTokenAmount;\n }\n\n /**\n * @notice Swap two tokens using the underlying pool. If tokenIndexFrom\n * represents WETH9 in the pool, the caller must set msg.value equal to dx.\n * If the user is swapping to WETH9 in the pool, the user will receive ETH instead.\n * @param tokenIndexFrom the token the user wants to swap from\n * @param tokenIndexTo the token the user wants to swap to\n * @param dx the amount of tokens the user wants to swap from\n * @param minDy the min amount the user would like to receive, or revert.\n * @param deadline latest timestamp to accept this transaction\n */\n function swap(\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx,\n uint256 minDy,\n uint256 deadline\n ) external payable returns (uint256) {\n // Transfer tokens from msg.sender to this contract\n if (tokenIndexFrom != WETH_INDEX) {\n IERC20(pooledTokens[tokenIndexFrom]).safeTransferFrom(\n msg.sender,\n address(this),\n dx\n );\n } else {\n require(msg.value == dx, \"INCORRECT_MSG_VALUE\");\n IWETH9(WETH_ADDRESS).deposit{value: msg.value}();\n }\n // Execute swap\n uint256 dy = SWAP.swap(\n tokenIndexFrom,\n tokenIndexTo,\n dx,\n minDy,\n deadline\n );\n // Transfer the swapped tokens to msg.sender\n if (tokenIndexTo != WETH_INDEX) {\n IERC20(pooledTokens[tokenIndexTo]).safeTransfer(msg.sender, dy);\n } else {\n IWETH9(WETH_ADDRESS).withdraw(dy);\n // slither-disable-next-line arbitrary-send\n (bool success, ) = msg.sender.call{value: dy}(\"\");\n require(success, \"ETH_TRANSFER_FAILED\");\n }\n return dy;\n }\n\n /**\n * @notice Rescues any of the ETH, the pooled tokens, or the LPToken that may be stuck\n * in this contract. Only the OWNER can call this function.\n */\n function rescue() external {\n require(msg.sender == OWNER, \"CALLED_BY_NON_OWNER\");\n IERC20[] memory tokens = pooledTokens;\n for (uint256 i = 0; i < tokens.length; i++) {\n tokens[i].safeTransfer(\n msg.sender,\n tokens[i].balanceOf(address(this))\n );\n }\n IERC20 lpToken_ = IERC20(address(LP_TOKEN));\n lpToken_.safeTransfer(msg.sender, lpToken_.balanceOf(address(this)));\n // slither-disable-next-line arbitrary-send\n (bool success, ) = msg.sender.call{value: address(this).balance}(\"\");\n require(success, \"ETH_TRANSFER_FAILED\");\n }\n\n receive() external payable {}\n\n // VIEW FUNCTIONS\n\n /**\n * @notice A simple method to calculate prices from deposits or\n * withdrawals, excluding fees but including slippage. This is\n * helpful as an input into the various \"min\" parameters on calls\n * to fight front-running\n *\n * @dev This shouldn't be used outside frontends for user estimates.\n *\n * @param amounts an array of token amounts to deposit or withdrawal,\n * corresponding to pooledTokens. The amount should be in each\n * pooled token's native precision. If a token charges a fee on transfers,\n * use the amount that gets transferred after the fee.\n * @param deposit whether this is a deposit or a withdrawal\n * @return token amount the user will receive\n */\n function calculateTokenAmount(uint256[] calldata amounts, bool deposit)\n external\n view\n returns (uint256)\n {\n return SWAP.calculateTokenAmount(amounts, deposit);\n }\n\n /**\n * @notice A simple method to calculate amount of each underlying\n * tokens that is returned upon burning given amount of LP tokens\n * @param amount the amount of LP tokens that would be burned on withdrawal\n * @return array of token balances that the user will receive\n */\n function calculateRemoveLiquidity(uint256 amount)\n external\n view\n returns (uint256[] memory)\n {\n return SWAP.calculateRemoveLiquidity(amount);\n }\n\n /**\n * @notice Calculate the amount of underlying token available to withdraw\n * when withdrawing via only single token\n * @param tokenAmount the amount of LP token to burn\n * @param tokenIndex index of which token will be withdrawn\n * @return availableTokenAmount calculated amount of underlying token\n * available to withdraw\n */\n function calculateRemoveLiquidityOneToken(\n uint256 tokenAmount,\n uint8 tokenIndex\n ) external view returns (uint256 availableTokenAmount) {\n return SWAP.calculateRemoveLiquidityOneToken(tokenAmount, tokenIndex);\n }\n}\n" + }, + "contracts/amm/interfaces/IWETH9.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.4.0;\n\ninterface IWETH9 {\n function name() external view returns (string memory);\n\n function symbol() external view returns (string memory);\n\n function decimals() external view returns (uint8);\n\n function balanceOf(address) external view returns (uint256);\n\n function allowance(address, address) external view returns (uint256);\n\n receive() external payable;\n\n function deposit() external payable;\n\n function withdraw(uint256 wad) external;\n\n function totalSupply() external view returns (uint256);\n\n function approve(address guy, uint256 wad) external returns (bool);\n\n function transfer(address dst, uint256 wad) external returns (bool);\n\n function transferFrom(\n address src,\n address dst,\n uint256 wad\n ) external returns (bool);\n}\n" + }, + "contracts/amm/helper/BaseSwapDeposit.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.6.12;\n\nimport \"@openzeppelin/contracts/math/SafeMath.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/SafeERC20.sol\";\nimport \"../interfaces/ISwap.sol\";\nimport \"@openzeppelin/contracts/utils/ReentrancyGuard.sol\";\n\ncontract BaseSwapDeposit is ReentrancyGuard {\n using SafeERC20 for IERC20;\n using SafeMath for uint256;\n\n ISwap public baseSwap;\n IERC20[] public baseTokens;\n\n uint256 constant MAX_UINT256 = 2**256 - 1;\n\n constructor(ISwap _baseSwap) public {\n baseSwap = _baseSwap;\n // Check and approve base level tokens to be deposited to the base Swap contract\n {\n uint8 i;\n for (; i < 32; i++) {\n try _baseSwap.getToken(i) returns (IERC20 token) {\n baseTokens.push(token);\n token.safeApprove(address(_baseSwap), MAX_UINT256);\n } catch {\n break;\n }\n }\n require(i > 1, \"baseSwap must have at least 2 tokens\");\n }\n }\n\n // Mutative functions\n\n /**\n * @notice Swap two underlying tokens using the meta pool and the base pool\n * @param tokenIndexFrom the token the user wants to swap from\n * @param tokenIndexTo the token the user wants to swap to\n * @param dx the amount of tokens the user wants to swap from\n * @param minDy the min amount the user would like to receive, or revert.\n * @param deadline latest timestamp to accept this transaction\n */\n function swap(\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx,\n uint256 minDy,\n uint256 deadline\n ) external nonReentrant returns (uint256) {\n baseTokens[tokenIndexFrom].safeTransferFrom(msg.sender, address(this), dx);\n uint256 tokenToAmount =\n baseSwap.swap(\n tokenIndexFrom,\n tokenIndexTo,\n dx,\n minDy,\n deadline\n );\n baseTokens[tokenIndexTo].safeTransfer(msg.sender, tokenToAmount);\n return tokenToAmount;\n }\n\n /**\n * @notice Calculate amount of tokens you receive on swap\n * @param tokenIndexFrom the token the user wants to sell\n * @param tokenIndexTo the token the user wants to buy\n * @param dx the amount of tokens the user wants to sell. If the token charges\n * a fee on transfers, use the amount that gets transferred after the fee.\n * @return amount of tokens the user will receive\n */\n function calculateSwap(\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx\n ) external view returns (uint256) {\n return\n baseSwap.calculateSwap(tokenIndexFrom, tokenIndexTo, dx);\n }\n\n /**\n * @notice Returns the address of the pooled token at given index. Reverts if tokenIndex is out of range.\n * @param index the index of the token\n * @return address of the token at given index\n */\n function getToken(uint256 index) external view returns (IERC20) {\n require(index < baseTokens.length, \"index out of range\");\n return baseTokens[index];\n }\n\n}" + }, + "@openzeppelin/contracts/utils/ReentrancyGuard.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <0.8.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 () internal {\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" + }, + "contracts/amm/AaveSwapWrapper.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.6.12;\n\nimport \"@openzeppelin/contracts/math/SafeMath.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/SafeERC20.sol\";\nimport \"./Swap.sol\";\n\ninterface ILendingPool {\n /**\n * @dev Deposits an `amount` of underlying asset into the reserve, receiving in return overlying aTokens.\n * - E.g. User deposits 100 USDC and gets in return 100 aUSDC\n * @param asset The address of the underlying asset to deposit\n * @param amount The amount to be deposited\n * @param onBehalfOf The address that will receive the aTokens, same as msg.sender if the user\n * wants to receive them on his own wallet, or a different address if the beneficiary of aTokens\n * is a different wallet\n * @param referralCode Code used to register the integrator originating the operation, for potential rewards.\n * 0 if the action is executed directly by the user, without any middle-man\n **/\n function deposit(\n address asset,\n uint256 amount,\n address onBehalfOf,\n uint16 referralCode\n ) external;\n\n /**\n * @dev Withdraws an `amount` of underlying asset from the reserve, burning the equivalent aTokens owned\n * E.g. User has 100 aUSDC, calls withdraw() and receives 100 USDC, burning the 100 aUSDC\n * @param asset The address of the underlying asset to withdraw\n * @param amount The underlying amount to be withdrawn\n * - Send the value type(uint256).max in order to withdraw the whole aToken balance\n * @param to Address that will receive the underlying, same as msg.sender if the user\n * wants to receive it on his own wallet, or a different address if the beneficiary is a\n * different wallet\n * @return The final amount withdrawn\n **/\n function withdraw(\n address asset,\n uint256 amount,\n address to\n ) external returns (uint256);\n}\n\n/**\n * @title AaveSwapWrapper\n * @notice A wrapper contract for interacting with aTokens\n */\ncontract AaveSwapWrapper {\n using SafeERC20 for IERC20;\n using SafeMath for uint256;\n mapping(uint8 => bool) private isUnderlyingIndex;\n\n // constants\n uint8 private constant MAX_UINT8 = 2**8 - 1;\n uint256 private constant MAX_UINT256 = 2**256 - 1;\n\n // immutables\n Swap public immutable SWAP;\n LPToken public immutable LP_TOKEN;\n address public immutable OWNER;\n IERC20[] public POOLED_TOKENS;\n IERC20[] public UNDERLYING_TOKENS;\n ILendingPool public LENDING_POOL;\n\n constructor(\n Swap swap,\n IERC20[] memory underlyingTokens,\n address lendingPool,\n address owner\n ) public {\n (, , , , , , LPToken lpToken) = swap.swapStorage();\n for (uint8 i = 0; i < MAX_UINT8; i++) {\n try swap.getToken(i) returns (IERC20 token) {\n POOLED_TOKENS.push(token);\n // Approve pooled tokens to be used by Swap\n token.approve(address(swap), MAX_UINT256);\n } catch {\n break;\n }\n }\n\n for (uint8 i = 0; i < POOLED_TOKENS.length; i++) {\n if (POOLED_TOKENS[i] == underlyingTokens[i]) {\n isUnderlyingIndex[i] = true;\n } else {\n isUnderlyingIndex[i] = false;\n underlyingTokens[i].approve(lendingPool, MAX_UINT256);\n }\n }\n\n // Set immutable variables\n SWAP = swap;\n LP_TOKEN = lpToken;\n OWNER = owner;\n UNDERLYING_TOKENS = underlyingTokens;\n LENDING_POOL = ILendingPool(lendingPool);\n\n // Approve LPToken to be used by Swap\n lpToken.approve(address(swap), MAX_UINT256);\n }\n\n /**\n * @notice Add liquidity to the pool with the given amounts of tokens.\n * @param amounts the amounts of each token to add, in their native precision\n * @param minToMint the minimum LP tokens adding this amount of liquidity\n * should mint, otherwise revert. Handy for front-running mitigation\n * @param deadline latest timestamp to accept this transaction\n * @return amount of LP token user minted and received\n */\n function addLiquidity(\n uint256[] memory amounts,\n uint256 minToMint,\n uint256 deadline\n ) external returns (uint256) {\n // Go through amounts array and transfer respective tokens to this contract.\n for (uint8 i = 0; i < amounts.length; i++) {\n uint256 amount = amounts[i];\n if (amount > 0) {\n UNDERLYING_TOKENS[i].safeTransferFrom(\n msg.sender,\n address(this),\n amount\n );\n if (isUnderlyingIndex[i] == false) {\n LENDING_POOL.deposit(\n address(UNDERLYING_TOKENS[i]),\n amount,\n address(this),\n 0\n );\n }\n }\n }\n\n // Add the assets to the pool\n uint256 lpTokenAmount = SWAP.addLiquidity(amounts, minToMint, deadline);\n // Send the LPToken to msg.sender\n IERC20(address(LP_TOKEN)).safeTransfer(msg.sender, lpTokenAmount);\n return lpTokenAmount;\n }\n\n /**\n * @notice Burn LP tokens to remove liquidity from the pool.\n * @dev Liquidity can always be removed, even when the pool is paused. Caller\n * will receive ETH instead of WETH9.\n * @param amount the amount of LP tokens to burn\n * @param minAmounts the minimum amounts of each token in the pool\n * acceptable for this burn. Useful as a front-running mitigation\n * @param deadline latest timestamp to accept this transaction\n * @return amounts of tokens user received\n */\n function removeLiquidity(\n uint256 amount,\n uint256[] calldata minAmounts,\n uint256 deadline\n ) external returns (uint256[] memory) {\n // Transfer LPToken from msg.sender to this contract.\n IERC20(address(LP_TOKEN)).safeTransferFrom(\n msg.sender,\n address(this),\n amount\n );\n // Remove liquidity\n uint256[] memory amounts = SWAP.removeLiquidity(\n amount,\n minAmounts,\n deadline\n );\n // Send the tokens back to the user\n for (uint8 i = 0; i < amounts.length; i++) {\n if (isUnderlyingIndex[i] == true) {\n UNDERLYING_TOKENS[i].safeTransfer(msg.sender, amounts[i]);\n } else {\n LENDING_POOL.withdraw(\n address(UNDERLYING_TOKENS[i]),\n amounts[i],\n msg.sender\n );\n // underlyingTokens[i].safeTransfer(msg.sender, amounts[i]);\n }\n }\n return amounts;\n }\n\n /**\n * @notice Remove liquidity from the pool all in one token.\n * @dev Caller will receive ETH instead of WETH9.\n * @param tokenAmount the amount of the token you want to receive\n * @param tokenIndex the index of the token you want to receive\n * @param minAmount the minimum amount to withdraw, otherwise revert\n * @param deadline latest timestamp to accept this transaction\n * @return amount of chosen token user received\n */\n function removeLiquidityOneToken(\n uint256 tokenAmount,\n uint8 tokenIndex,\n uint256 minAmount,\n uint256 deadline\n ) external returns (uint256) {\n // Transfer LPToken from msg.sender to this contract.\n IERC20(address(LP_TOKEN)).safeTransferFrom(\n msg.sender,\n address(this),\n tokenAmount\n );\n // Withdraw via single token\n uint256 amount = SWAP.removeLiquidityOneToken(\n tokenAmount,\n tokenIndex,\n minAmount,\n deadline\n );\n // Transfer the token to msg.sender accordingly\n if (isUnderlyingIndex[tokenIndex] == true) {\n UNDERLYING_TOKENS[tokenIndex].safeTransfer(msg.sender, amount);\n } else {\n LENDING_POOL.withdraw(\n address(UNDERLYING_TOKENS[tokenIndex]),\n amount,\n msg.sender\n );\n }\n return amount;\n }\n\n /**\n * @notice Swap two tokens using the underlying pool. If tokenIndexFrom\n * represents WETH9 in the pool, the caller must set msg.value equal to dx.\n * If the user is swapping to WETH9 in the pool, the user will receive ETH instead.\n * @param tokenIndexFrom the token the user wants to swap from\n * @param tokenIndexTo the token the user wants to swap to\n * @param dx the amount of tokens the user wants to swap from\n * @param minDy the min amount the user would like to receive, or revert.\n * @param deadline latest timestamp to accept this transaction\n */\n function swap(\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx,\n uint256 minDy,\n uint256 deadline\n ) external returns (uint256) {\n // Transfer tokens from msg.sender to this contract\n UNDERLYING_TOKENS[tokenIndexFrom].safeTransferFrom(\n msg.sender,\n address(this),\n dx\n );\n if (isUnderlyingIndex[tokenIndexFrom] == false) {\n LENDING_POOL.deposit(\n address(UNDERLYING_TOKENS[tokenIndexFrom]),\n dx,\n address(this),\n 0\n );\n }\n // Execute swap\n uint256 dy = SWAP.swap(\n tokenIndexFrom,\n tokenIndexTo,\n dx,\n minDy,\n deadline\n );\n // Transfer the swapped tokens to msg.sender\n if (isUnderlyingIndex[tokenIndexTo] == false) {\n LENDING_POOL.withdraw(\n address(UNDERLYING_TOKENS[tokenIndexTo]),\n dy,\n msg.sender\n );\n } else {\n UNDERLYING_TOKENS[tokenIndexTo].safeTransfer(msg.sender, dy);\n }\n return dy;\n }\n\n /**\n * @notice Rescues any of the ETH, the pooled tokens, or the LPToken that may be stuck\n * in this contract. Only the OWNER can call this function.\n */\n function rescue() external {\n require(msg.sender == OWNER, \"CALLED_BY_NON_OWNER\");\n IERC20[] memory tokens = POOLED_TOKENS;\n for (uint256 i = 0; i < tokens.length; i++) {\n tokens[i].safeTransfer(\n msg.sender,\n tokens[i].balanceOf(address(this))\n );\n }\n\n for (uint256 i = 0; i < UNDERLYING_TOKENS.length; i++) {\n UNDERLYING_TOKENS[i].safeTransfer(\n msg.sender,\n UNDERLYING_TOKENS[i].balanceOf(address(this))\n );\n }\n\n IERC20 lpToken_ = IERC20(address(LP_TOKEN));\n lpToken_.safeTransfer(msg.sender, lpToken_.balanceOf(address(this)));\n }\n\n // VIEW FUNCTIONS\n\n /**\n * @notice Calculate amount of tokens you receive on swap\n * @param tokenIndexFrom the token the user wants to sell\n * @param tokenIndexTo the token the user wants to buy\n * @param dx the amount of tokens the user wants to sell. If the token charges\n * a fee on transfers, use the amount that gets transferred after the fee.\n * @return amount of tokens the user will receive\n */\n function calculateSwap(\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx\n ) external view virtual returns (uint256) {\n return SWAP.calculateSwap(tokenIndexFrom, tokenIndexTo, dx);\n }\n\n /**\n * @notice A simple method to calculate prices from deposits or\n * withdrawals, excluding fees but including slippage. This is\n * helpful as an input into the various \"min\" parameters on calls\n * to fight front-running\n *\n * @dev This shouldn't be used outside frontends for user estimates.\n *\n * @param amounts an array of token amounts to deposit or withdrawal,\n * corresponding to pooledTokens. The amount should be in each\n * pooled token's native precision. If a token charges a fee on transfers,\n * use the amount that gets transferred after the fee.\n * @param deposit whether this is a deposit or a withdrawal\n * @return token amount the user will receive\n */\n function calculateTokenAmount(uint256[] calldata amounts, bool deposit)\n external\n view\n returns (uint256)\n {\n return SWAP.calculateTokenAmount(amounts, deposit);\n }\n\n /**\n * @notice A simple method to calculate amount of each underlying\n * tokens that is returned upon burning given amount of LP tokens\n * @param amount the amount of LP tokens that would be burned on withdrawal\n * @return array of token balances that the user will receive\n */\n function calculateRemoveLiquidity(uint256 amount)\n external\n view\n returns (uint256[] memory)\n {\n return SWAP.calculateRemoveLiquidity(amount);\n }\n\n /**\n * @notice Calculate the amount of underlying token available to withdraw\n * when withdrawing via only single token\n * @param tokenAmount the amount of LP token to burn\n * @param tokenIndex index of which token will be withdrawn\n * @return availableTokenAmount calculated amount of underlying token\n * available to withdraw\n */\n function calculateRemoveLiquidityOneToken(\n uint256 tokenAmount,\n uint8 tokenIndex\n ) external view returns (uint256 availableTokenAmount) {\n return SWAP.calculateRemoveLiquidityOneToken(tokenAmount, tokenIndex);\n }\n\n /**\n * @notice Return address of the pooled token at given index. Reverts if tokenIndex is out of range.\n * @param index the index of the token\n * @return address of the token at given index\n */\n function getToken(uint8 index) public view virtual returns (IERC20) {\n if (index < UNDERLYING_TOKENS.length) {\n return UNDERLYING_TOKENS[index];\n } else {\n revert();\n }\n }\n}\n" + }, + "contracts/bridge/ECDSAFactory.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.6.12;\n\nimport \"@openzeppelin/contracts/access/Ownable.sol\";\nimport \"@openzeppelin/contracts/proxy/Clones.sol\";\nimport \"./interfaces/IECDSANodeManagement.sol\";\n\ncontract ECDSAFactory is Ownable {\n event ECDSANodeGroupCreated(\n address indexed keepAddress,\n address[] members,\n address indexed owner,\n uint256 honestThreshold\n );\n\n struct LatestNodeGroup {\n address keepAddress;\n address[] members;\n address owner;\n uint256 honestThreshold;\n }\n\n LatestNodeGroup public latestNodeGroup;\n\n constructor() public Ownable() {}\n\n /// @notice Returns members of the keep.\n /// @return List of the keep members' addresses.\n function getMembers() public view returns (address[] memory) {\n return latestNodeGroup.members;\n }\n\n /**\n @notice Deploys a new node \n @param nodeMgmtAddress address of the ECDSANodeManagement contract to initialize with\n @param owner Owner of the ECDSANodeManagement contract who can determine if the node group is closed or active\n @param members Array of node group members addresses\n @param honestThreshold Number of signers to process a transaction \n @return Address of the newest node management contract created\n **/\n function deploy(\n address nodeMgmtAddress,\n address owner,\n address[] memory members,\n uint256 honestThreshold\n ) external onlyOwner returns (address) {\n address nodeClone = Clones.clone(nodeMgmtAddress);\n IECDSANodeManagement(nodeClone).initialize(\n owner,\n members,\n honestThreshold\n );\n\n latestNodeGroup.keepAddress = nodeClone;\n latestNodeGroup.members = members;\n latestNodeGroup.owner = owner;\n latestNodeGroup.honestThreshold = honestThreshold;\n\n emit ECDSANodeGroupCreated(nodeClone, members, owner, honestThreshold);\n return nodeClone;\n }\n}\n" + }, + "contracts/bridge/interfaces/IECDSANodeManagement.sol": { + "content": "// SPDX-License-Identifier: MIT\n\n\npragma solidity 0.6.12;\n\n/**\n * @title IECDSANodeManagement interface\n * @notice Interface for the ECDSA node management interface.\n * @dev implement this interface to develop a a factory-patterned ECDSA node management contract\n **/\ninterface IECDSANodeManagement { \n function initialize(\n address _owner,\n address[] memory _members,\n uint256 _honestThreshold) external;\n}\n\n" + }, + "contracts/auxiliary/DummyWeth.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.6.12;\nimport \"@openzeppelin/contracts/access/Ownable.sol\";\n\ninterface IWETH9 {\n function name() external view returns (string memory);\n\n function symbol() external view returns (string memory);\n\n function decimals() external view returns (uint8);\n\n function balanceOf(address) external view returns (uint256);\n\n function allowance(address, address) external view returns (uint256);\n\n receive() external payable;\n\n function deposit() external payable;\n\n function withdraw(uint256 wad) external;\n\n function totalSupply() external view returns (uint256);\n\n function approve(address guy, uint256 wad) external returns (bool);\n\n function transfer(address dst, uint256 wad) external returns (bool);\n\n function transferFrom(\n address src,\n address dst,\n uint256 wad\n ) external returns (bool);\n}\n\ncontract DummyWeth is Ownable {\n IWETH9 public WETH;\n\n function setWETHAddress(address payable _weth) external onlyOwner {\n WETH = IWETH9(_weth);\n }\n\n function withdrawToSelf(uint256 amount) external {\n WETH.withdraw(amount);\n }\n\n function rescue(uint256 amount) external onlyOwner {\n WETH.transfer(owner(), amount);\n }\n\n receive() external payable {}\n\n fallback() external payable {}\n}\n" + } + }, + "settings": { + "optimizer": { + "enabled": true, + "runs": 10000 + }, + "outputSelection": { + "*": { + "*": [ + "abi", + "evm.bytecode", + "evm.deployedBytecode", + "evm.methodIdentifiers", + "metadata", + "devdoc", + "userdoc", + "storageLayout", + "evm.gasEstimates", + "devdoc", + "userdoc" + ], + "": [ + "ast" + ] + } + }, + "metadata": { + "useLiteralContent": true + } + } +} \ No newline at end of file diff --git a/deployments/dfk/.chainId b/deployments/dfk/.chainId new file mode 100644 index 000000000..c18fc11a7 --- /dev/null +++ b/deployments/dfk/.chainId @@ -0,0 +1 @@ +53935 \ No newline at end of file diff --git a/deployments/dfk/AVAX.json b/deployments/dfk/AVAX.json new file mode 100644 index 000000000..c671cfca6 --- /dev/null +++ b/deployments/dfk/AVAX.json @@ -0,0 +1,668 @@ +{ + "address": "0xB57B60DeBDB0b8172bb6316a9164bd3C695F133a", + "abi": [ + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "Approval", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "bytes32", + "name": "previousAdminRole", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "bytes32", + "name": "newAdminRole", + "type": "bytes32" + } + ], + "name": "RoleAdminChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "sender", + "type": "address" + } + ], + "name": "RoleGranted", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "sender", + "type": "address" + } + ], + "name": "RoleRevoked", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "Transfer", + "type": "event" + }, + { + "inputs": [], + "name": "DEFAULT_ADMIN_ROLE", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "DOMAIN_SEPARATOR", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "MINTER_ROLE", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "address", + "name": "spender", + "type": "address" + } + ], + "name": "allowance", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "approve", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "balanceOf", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "burn", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "burnFrom", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "decimals", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "subtractedValue", + "type": "uint256" + } + ], + "name": "decreaseAllowance", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + } + ], + "name": "getRoleAdmin", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "internalType": "uint256", + "name": "index", + "type": "uint256" + } + ], + "name": "getRoleMember", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + } + ], + "name": "getRoleMemberCount", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "grantRole", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "hasRole", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "addedValue", + "type": "uint256" + } + ], + "name": "increaseAllowance", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "name", + "type": "string" + }, + { + "internalType": "string", + "name": "symbol", + "type": "string" + }, + { + "internalType": "uint8", + "name": "decimals", + "type": "uint8" + }, + { + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "initialize", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "mint", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "name", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "nonces", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" + }, + { + "internalType": "uint8", + "name": "v", + "type": "uint8" + }, + { + "internalType": "bytes32", + "name": "r", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "s", + "type": "bytes32" + } + ], + "name": "permit", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "renounceRole", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "revokeRole", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "symbol", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "totalSupply", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "recipient", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "transfer", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "internalType": "address", + "name": "recipient", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "transferFrom", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + } + ] +} \ No newline at end of file diff --git a/deployments/dfk/DefaultProxyAdmin.json b/deployments/dfk/DefaultProxyAdmin.json new file mode 100644 index 000000000..ff8809550 --- /dev/null +++ b/deployments/dfk/DefaultProxyAdmin.json @@ -0,0 +1,258 @@ +{ + "address": "0x587AEf47a56224B5775Ff289Fb259d59F35ADdF9", + "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "previousOwner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "OwnershipTransferred", + "type": "event" + }, + { + "inputs": [ + { + "internalType": "contract TransparentUpgradeableProxy", + "name": "proxy", + "type": "address" + }, + { + "internalType": "address", + "name": "newAdmin", + "type": "address" + } + ], + "name": "changeProxyAdmin", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract TransparentUpgradeableProxy", + "name": "proxy", + "type": "address" + } + ], + "name": "getProxyAdmin", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract TransparentUpgradeableProxy", + "name": "proxy", + "type": "address" + } + ], + "name": "getProxyImplementation", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "renounceOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract TransparentUpgradeableProxy", + "name": "proxy", + "type": "address" + }, + { + "internalType": "address", + "name": "implementation", + "type": "address" + } + ], + "name": "upgrade", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract TransparentUpgradeableProxy", + "name": "proxy", + "type": "address" + }, + { + "internalType": "address", + "name": "implementation", + "type": "address" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "upgradeAndCall", + "outputs": [], + "stateMutability": "payable", + "type": "function" + } + ], + "transactionHash": "0xdb6eee1796951ff3b2336d7d0c4c094b95c6c5577a182b5d99484b8bf8b9691e", + "receipt": { + "to": null, + "from": "0x235AF07E770f474d24F5bf73074735892371b40D", + "contractAddress": "0x587AEf47a56224B5775Ff289Fb259d59F35ADdF9", + "transactionIndex": 0, + "gasUsed": "671461", + "logsBloom": "0x00000000000000200000000000000000000000000000000000800000000000000040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000020000004000000000000800000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000002000000000000000000000000400000000000", + "blockHash": "0xccce3fde3f929fc1182d8db52766ac0f6c15d9ed04292729e57a3ac654868362", + "transactionHash": "0xdb6eee1796951ff3b2336d7d0c4c094b95c6c5577a182b5d99484b8bf8b9691e", + "logs": [ + { + "transactionIndex": 0, + "blockNumber": 64, + "transactionHash": "0xdb6eee1796951ff3b2336d7d0c4c094b95c6c5577a182b5d99484b8bf8b9691e", + "address": "0x587AEf47a56224B5775Ff289Fb259d59F35ADdF9", + "topics": [ + "0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000001bfe50bb2a8a75fefa46892db10313898ddbff8f" + ], + "data": "0x", + "logIndex": 0, + "blockHash": "0xccce3fde3f929fc1182d8db52766ac0f6c15d9ed04292729e57a3ac654868362" + } + ], + "blockNumber": 64, + "cumulativeGasUsed": "671461", + "status": 1, + "byzantium": true + }, + "args": [ + "0x1BFE50bb2A8a75fefa46892dB10313898dDbFf8F" + ], + "solcInputHash": "1635d55d57a0a2552952c0d22586ed23", + "metadata": "{\"compiler\":{\"version\":\"0.7.6+commit.7338295f\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"previousOwner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"inputs\":[{\"internalType\":\"contract TransparentUpgradeableProxy\",\"name\":\"proxy\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"newAdmin\",\"type\":\"address\"}],\"name\":\"changeProxyAdmin\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contract TransparentUpgradeableProxy\",\"name\":\"proxy\",\"type\":\"address\"}],\"name\":\"getProxyAdmin\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contract TransparentUpgradeableProxy\",\"name\":\"proxy\",\"type\":\"address\"}],\"name\":\"getProxyImplementation\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"renounceOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contract TransparentUpgradeableProxy\",\"name\":\"proxy\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"implementation\",\"type\":\"address\"}],\"name\":\"upgrade\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contract TransparentUpgradeableProxy\",\"name\":\"proxy\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"implementation\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"upgradeAndCall\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"}],\"devdoc\":{\"details\":\"This is an auxiliary contract meant to be assigned as the admin of a {TransparentUpgradeableProxy}. For an explanation of why you would want to use this see the documentation for {TransparentUpgradeableProxy}.\",\"kind\":\"dev\",\"methods\":{\"changeProxyAdmin(address,address)\":{\"details\":\"Changes the admin of `proxy` to `newAdmin`. Requirements: - This contract must be the current admin of `proxy`.\"},\"getProxyAdmin(address)\":{\"details\":\"Returns the current admin of `proxy`. Requirements: - This contract must be the admin of `proxy`.\"},\"getProxyImplementation(address)\":{\"details\":\"Returns the current implementation of `proxy`. Requirements: - This contract must be the admin of `proxy`.\"},\"owner()\":{\"details\":\"Returns the address of the current owner.\"},\"renounceOwnership()\":{\"details\":\"Leaves the contract without owner. It will not be possible to call `onlyOwner` functions anymore. Can only be called by the current owner. NOTE: Renouncing ownership will leave the contract without an owner, thereby removing any functionality that is only available to the owner.\"},\"transferOwnership(address)\":{\"details\":\"Transfers ownership of the contract to a new account (`newOwner`). Can only be called by the current owner.\"},\"upgrade(address,address)\":{\"details\":\"Upgrades `proxy` to `implementation`. See {TransparentUpgradeableProxy-upgradeTo}. Requirements: - This contract must be the admin of `proxy`.\"},\"upgradeAndCall(address,address,bytes)\":{\"details\":\"Upgrades `proxy` to `implementation` and calls a function on the new implementation. See {TransparentUpgradeableProxy-upgradeToAndCall}. Requirements: - This contract must be the admin of `proxy`.\"}},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"solc_0.7/openzeppelin/proxy/ProxyAdmin.sol\":\"ProxyAdmin\"},\"evmVersion\":\"istanbul\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":999999},\"remappings\":[]},\"sources\":{\"solc_0.7/openzeppelin/GSN/Context.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.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\",\"keccak256\":\"0x910a2e625b71168563edf9eeef55a50d6d699acfe27ceba3921f291829a8f938\",\"license\":\"MIT\"},\"solc_0.7/openzeppelin/access/Ownable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\nimport \\\"../GSN/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 */\\ncontract 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 (address initialOwner) {\\n _owner = initialOwner;\\n emit OwnershipTransferred(address(0), initialOwner);\\n }\\n\\n /**\\n * @dev Returns the address of the current owner.\\n */\\n function owner() public view 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\",\"keccak256\":\"0x85eb3b8575f16937ed27e36fae8b617d9e3e7a7e49f04e10d52dad66d0fa9e75\",\"license\":\"MIT\"},\"solc_0.7/openzeppelin/proxy/Proxy.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\n/**\\n * @dev This abstract contract provides a fallback function that delegates all calls to another contract using the EVM\\n * instruction `delegatecall`. We refer to the second contract as the _implementation_ behind the proxy, and it has to\\n * be specified by overriding the virtual {_implementation} function.\\n * \\n * Additionally, delegation to the implementation can be triggered manually through the {_fallback} function, or to a\\n * different contract through the {_delegate} function.\\n * \\n * The success and return data of the delegated call will be returned back to the caller of the proxy.\\n */\\nabstract contract Proxy {\\n /**\\n * @dev Delegates the current call to `implementation`.\\n * \\n * This function does not return to its internall call site, it will return directly to the external caller.\\n */\\n function _delegate(address implementation) internal {\\n // solhint-disable-next-line no-inline-assembly\\n assembly {\\n // Copy msg.data. We take full control of memory in this inline assembly\\n // block because it will not return to Solidity code. We overwrite the\\n // Solidity scratch pad at memory position 0.\\n calldatacopy(0, 0, calldatasize())\\n\\n // Call the implementation.\\n // out and outsize are 0 because we don't know the size yet.\\n let result := delegatecall(gas(), implementation, 0, calldatasize(), 0, 0)\\n\\n // Copy the returned data.\\n returndatacopy(0, 0, returndatasize())\\n\\n switch result\\n // delegatecall returns 0 on error.\\n case 0 { revert(0, returndatasize()) }\\n default { return(0, returndatasize()) }\\n }\\n }\\n\\n /**\\n * @dev This is a virtual function that should be overriden so it returns the address to which the fallback function\\n * and {_fallback} should delegate.\\n */\\n function _implementation() internal virtual view returns (address);\\n\\n /**\\n * @dev Delegates the current call to the address returned by `_implementation()`.\\n * \\n * This function does not return to its internall call site, it will return directly to the external caller.\\n */\\n function _fallback() internal {\\n _beforeFallback();\\n _delegate(_implementation());\\n }\\n\\n /**\\n * @dev Fallback function that delegates calls to the address returned by `_implementation()`. Will run if no other\\n * function in the contract matches the call data.\\n */\\n fallback () payable external {\\n _fallback();\\n }\\n\\n /**\\n * @dev Fallback function that delegates calls to the address returned by `_implementation()`. Will run if call data\\n * is empty.\\n */\\n receive () payable external {\\n _fallback();\\n }\\n\\n /**\\n * @dev Hook that is called before falling back to the implementation. Can happen as part of a manual `_fallback`\\n * call, or as part of the Solidity `fallback` or `receive` functions.\\n * \\n * If overriden should call `super._beforeFallback()`.\\n */\\n function _beforeFallback() internal virtual {\\n }\\n}\\n\",\"keccak256\":\"0xc33f9858a67e34c77831163d5611d21fc627dfd2c303806a98a6c9db5a01b034\",\"license\":\"MIT\"},\"solc_0.7/openzeppelin/proxy/ProxyAdmin.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\nimport \\\"../access/Ownable.sol\\\";\\nimport \\\"./TransparentUpgradeableProxy.sol\\\";\\n\\n/**\\n * @dev This is an auxiliary contract meant to be assigned as the admin of a {TransparentUpgradeableProxy}. For an\\n * explanation of why you would want to use this see the documentation for {TransparentUpgradeableProxy}.\\n */\\ncontract ProxyAdmin is Ownable {\\n\\n constructor(address owner) Ownable(owner) {}\\n\\n /**\\n * @dev Returns the current implementation of `proxy`.\\n *\\n * Requirements:\\n *\\n * - This contract must be the admin of `proxy`.\\n */\\n function getProxyImplementation(TransparentUpgradeableProxy proxy) public view returns (address) {\\n // We need to manually run the static call since the getter cannot be flagged as view\\n // bytes4(keccak256(\\\"implementation()\\\")) == 0x5c60da1b\\n (bool success, bytes memory returndata) = address(proxy).staticcall(hex\\\"5c60da1b\\\");\\n require(success);\\n return abi.decode(returndata, (address));\\n }\\n\\n /**\\n * @dev Returns the current admin of `proxy`.\\n *\\n * Requirements:\\n *\\n * - This contract must be the admin of `proxy`.\\n */\\n function getProxyAdmin(TransparentUpgradeableProxy proxy) public view returns (address) {\\n // We need to manually run the static call since the getter cannot be flagged as view\\n // bytes4(keccak256(\\\"admin()\\\")) == 0xf851a440\\n (bool success, bytes memory returndata) = address(proxy).staticcall(hex\\\"f851a440\\\");\\n require(success);\\n return abi.decode(returndata, (address));\\n }\\n\\n /**\\n * @dev Changes the admin of `proxy` to `newAdmin`.\\n *\\n * Requirements:\\n *\\n * - This contract must be the current admin of `proxy`.\\n */\\n function changeProxyAdmin(TransparentUpgradeableProxy proxy, address newAdmin) public onlyOwner {\\n proxy.changeAdmin(newAdmin);\\n }\\n\\n /**\\n * @dev Upgrades `proxy` to `implementation`. See {TransparentUpgradeableProxy-upgradeTo}.\\n *\\n * Requirements:\\n *\\n * - This contract must be the admin of `proxy`.\\n */\\n function upgrade(TransparentUpgradeableProxy proxy, address implementation) public onlyOwner {\\n proxy.upgradeTo(implementation);\\n }\\n\\n /**\\n * @dev Upgrades `proxy` to `implementation` and calls a function on the new implementation. See\\n * {TransparentUpgradeableProxy-upgradeToAndCall}.\\n *\\n * Requirements:\\n *\\n * - This contract must be the admin of `proxy`.\\n */\\n function upgradeAndCall(TransparentUpgradeableProxy proxy, address implementation, bytes memory data) public payable onlyOwner {\\n proxy.upgradeToAndCall{value: msg.value}(implementation, data);\\n }\\n}\\n\",\"keccak256\":\"0xae77885dd899a14e94f172e4e9ec7ef4b2ced0472904626c59b46150a26b5714\",\"license\":\"MIT\"},\"solc_0.7/openzeppelin/proxy/TransparentUpgradeableProxy.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\nimport \\\"./UpgradeableProxy.sol\\\";\\n\\n/**\\n * @dev This contract implements a proxy that is upgradeable by an admin.\\n * \\n * To avoid https://medium.com/nomic-labs-blog/malicious-backdoors-in-ethereum-proxies-62629adf3357[proxy selector\\n * clashing], which can potentially be used in an attack, this contract uses the\\n * https://blog.openzeppelin.com/the-transparent-proxy-pattern/[transparent proxy pattern]. This pattern implies two\\n * things that go hand in hand:\\n * \\n * 1. If any account other than the admin calls the proxy, the call will be forwarded to the implementation, even if\\n * that call matches one of the admin functions exposed by the proxy itself.\\n * 2. If the admin calls the proxy, it can access the admin functions, but its calls will never be forwarded to the\\n * implementation. If the admin tries to call a function on the implementation it will fail with an error that says\\n * \\\"admin cannot fallback to proxy target\\\".\\n * \\n * These properties mean that the admin account can only be used for admin actions like upgrading the proxy or changing\\n * the admin, so it's best if it's a dedicated account that is not used for anything else. This will avoid headaches due\\n * to sudden errors when trying to call a function from the proxy implementation.\\n * \\n * Our recommendation is for the dedicated account to be an instance of the {ProxyAdmin} contract. If set up this way,\\n * you should think of the `ProxyAdmin` instance as the real administrative inerface of your proxy.\\n */\\ncontract TransparentUpgradeableProxy is UpgradeableProxy {\\n /**\\n * @dev Initializes an upgradeable proxy managed by `_admin`, backed by the implementation at `_logic`, and\\n * optionally initialized with `_data` as explained in {UpgradeableProxy-constructor}.\\n */\\n constructor(address initialLogic, address initialAdmin, bytes memory _data) payable UpgradeableProxy(initialLogic, _data) {\\n assert(_ADMIN_SLOT == bytes32(uint256(keccak256(\\\"eip1967.proxy.admin\\\")) - 1));\\n _setAdmin(initialAdmin);\\n }\\n\\n /**\\n * @dev Emitted when the admin account has changed.\\n */\\n event AdminChanged(address previousAdmin, address newAdmin);\\n\\n /**\\n * @dev Storage slot with the admin of the contract.\\n * This is the keccak-256 hash of \\\"eip1967.proxy.admin\\\" subtracted by 1, and is\\n * validated in the constructor.\\n */\\n bytes32 private constant _ADMIN_SLOT = 0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103;\\n\\n /**\\n * @dev Modifier used internally that will delegate the call to the implementation unless the sender is the admin.\\n */\\n modifier ifAdmin() {\\n if (msg.sender == _admin()) {\\n _;\\n } else {\\n _fallback();\\n }\\n }\\n\\n /**\\n * @dev Returns the current admin.\\n * \\n * NOTE: Only the admin can call this function. See {ProxyAdmin-getProxyAdmin}.\\n * \\n * TIP: To get this value clients can read directly from the storage slot shown below (specified by EIP1967) using the\\n * https://eth.wiki/json-rpc/API#eth_getstorageat[`eth_getStorageAt`] RPC call.\\n * `0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103`\\n */\\n function admin() external ifAdmin returns (address) {\\n return _admin();\\n }\\n\\n /**\\n * @dev Returns the current implementation.\\n * \\n * NOTE: Only the admin can call this function. See {ProxyAdmin-getProxyImplementation}.\\n * \\n * TIP: To get this value clients can read directly from the storage slot shown below (specified by EIP1967) using the\\n * https://eth.wiki/json-rpc/API#eth_getstorageat[`eth_getStorageAt`] RPC call.\\n * `0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc`\\n */\\n function implementation() external ifAdmin returns (address) {\\n return _implementation();\\n }\\n\\n /**\\n * @dev Changes the admin of the proxy.\\n * \\n * Emits an {AdminChanged} event.\\n * \\n * NOTE: Only the admin can call this function. See {ProxyAdmin-changeProxyAdmin}.\\n */\\n function changeAdmin(address newAdmin) external ifAdmin {\\n require(newAdmin != address(0), \\\"TransparentUpgradeableProxy: new admin is the zero address\\\");\\n emit AdminChanged(_admin(), newAdmin);\\n _setAdmin(newAdmin);\\n }\\n\\n /**\\n * @dev Upgrade the implementation of the proxy.\\n * \\n * NOTE: Only the admin can call this function. See {ProxyAdmin-upgrade}.\\n */\\n function upgradeTo(address newImplementation) external ifAdmin {\\n _upgradeTo(newImplementation);\\n }\\n\\n /**\\n * @dev Upgrade the implementation of the proxy, and then call a function from the new implementation as specified\\n * by `data`, which should be an encoded function call. This is useful to initialize new storage variables in the\\n * proxied contract.\\n * \\n * NOTE: Only the admin can call this function. See {ProxyAdmin-upgradeAndCall}.\\n */\\n function upgradeToAndCall(address newImplementation, bytes calldata data) external payable ifAdmin {\\n _upgradeTo(newImplementation);\\n // solhint-disable-next-line avoid-low-level-calls\\n (bool success,) = newImplementation.delegatecall(data);\\n require(success);\\n }\\n\\n /**\\n * @dev Returns the current admin.\\n */\\n function _admin() internal view returns (address adm) {\\n bytes32 slot = _ADMIN_SLOT;\\n // solhint-disable-next-line no-inline-assembly\\n assembly {\\n adm := sload(slot)\\n }\\n }\\n\\n /**\\n * @dev Stores a new address in the EIP1967 admin slot.\\n */\\n function _setAdmin(address newAdmin) private {\\n bytes32 slot = _ADMIN_SLOT;\\n\\n // solhint-disable-next-line no-inline-assembly\\n assembly {\\n sstore(slot, newAdmin)\\n }\\n }\\n\\n /**\\n * @dev Makes sure the admin cannot access the fallback function. See {Proxy-_beforeFallback}.\\n */\\n function _beforeFallback() internal override virtual {\\n require(msg.sender != _admin(), \\\"TransparentUpgradeableProxy: admin cannot fallback to proxy target\\\");\\n super._beforeFallback();\\n }\\n}\\n\",\"keccak256\":\"0xd6cecbe00dc78355aff1a16d83487bb73c54701004d61a2e48cdb81e2bcacc26\",\"license\":\"MIT\"},\"solc_0.7/openzeppelin/proxy/UpgradeableProxy.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\nimport \\\"./Proxy.sol\\\";\\nimport \\\"../utils/Address.sol\\\";\\n\\n/**\\n * @dev This contract implements an upgradeable proxy. It is upgradeable because calls are delegated to an\\n * implementation address that can be changed. This address is stored in storage in the location specified by\\n * https://eips.ethereum.org/EIPS/eip-1967[EIP1967], so that it doesn't conflict with the storage layout of the\\n * implementation behind the proxy.\\n * \\n * Upgradeability is only provided internally through {_upgradeTo}. For an externally upgradeable proxy see\\n * {TransparentUpgradeableProxy}.\\n */\\ncontract UpgradeableProxy is Proxy {\\n /**\\n * @dev Initializes the upgradeable proxy with an initial implementation specified by `_logic`.\\n * \\n * If `_data` is nonempty, it's used as data in a delegate call to `_logic`. This will typically be an encoded\\n * function call, and allows initializating the storage of the proxy like a Solidity constructor.\\n */\\n constructor(address _logic, bytes memory _data) payable {\\n assert(_IMPLEMENTATION_SLOT == bytes32(uint256(keccak256(\\\"eip1967.proxy.implementation\\\")) - 1));\\n _setImplementation(_logic);\\n if(_data.length > 0) {\\n // solhint-disable-next-line avoid-low-level-calls\\n (bool success,) = _logic.delegatecall(_data);\\n require(success);\\n }\\n }\\n\\n /**\\n * @dev Emitted when the implementation is upgraded.\\n */\\n event Upgraded(address indexed implementation);\\n\\n /**\\n * @dev Storage slot with the address of the current implementation.\\n * This is the keccak-256 hash of \\\"eip1967.proxy.implementation\\\" subtracted by 1, and is\\n * validated in the constructor.\\n */\\n bytes32 private constant _IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc;\\n\\n /**\\n * @dev Returns the current implementation address.\\n */\\n function _implementation() internal override view returns (address impl) {\\n bytes32 slot = _IMPLEMENTATION_SLOT;\\n // solhint-disable-next-line no-inline-assembly\\n assembly {\\n impl := sload(slot)\\n }\\n }\\n\\n /**\\n * @dev Upgrades the proxy to a new implementation.\\n * \\n * Emits an {Upgraded} event.\\n */\\n function _upgradeTo(address newImplementation) internal {\\n _setImplementation(newImplementation);\\n emit Upgraded(newImplementation);\\n }\\n\\n /**\\n * @dev Stores a new address in the EIP1967 implementation slot.\\n */\\n function _setImplementation(address newImplementation) private {\\n require(Address.isContract(newImplementation), \\\"UpgradeableProxy: new implementation is not a contract\\\");\\n\\n bytes32 slot = _IMPLEMENTATION_SLOT;\\n\\n // solhint-disable-next-line no-inline-assembly\\n assembly {\\n sstore(slot, newImplementation)\\n }\\n }\\n}\\n\",\"keccak256\":\"0xd68f4c11941712db79a61b9dca81a5db663cfacec3d7bb19f8d2c23bb1ab8afe\",\"license\":\"MIT\"},\"solc_0.7/openzeppelin/utils/Address.sol\":{\"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 // According to EIP-1052, 0x0 is the value returned for not-yet created accounts\\n // and 0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470 is returned\\n // for accounts without code, i.e. `keccak256('')`\\n bytes32 codehash;\\n bytes32 accountHash = 0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470;\\n // solhint-disable-next-line no-inline-assembly\\n assembly { codehash := extcodehash(account) }\\n return (codehash != accountHash && codehash != 0x0);\\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 return _functionCallWithValue(target, data, value, errorMessage);\\n }\\n\\n function _functionCallWithValue(address target, bytes memory data, uint256 weiValue, string memory errorMessage) private returns (bytes memory) {\\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: weiValue }(data);\\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\",\"keccak256\":\"0x698f929f1097637d051976b322a2d532c27df022b09010e8d091e2888a5ebdf8\",\"license\":\"MIT\"}},\"version\":1}", + "bytecode": "0x608060405234801561001057600080fd5b50604051610b54380380610b548339818101604052602081101561003357600080fd5b5051600080546001600160a01b0319166001600160a01b03831690811782556040518392907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908290a35050610ac68061008e6000396000f3fe60806040526004361061007b5760003560e01c80639623609d1161004e5780639623609d1461015d57806399a88ec414610229578063f2fde38b14610271578063f3b7dead146102b15761007b565b8063204e1c7a14610080578063715018a6146100e95780637eff275e146101005780638da5cb5b14610148575b600080fd5b34801561008c57600080fd5b506100c0600480360360208110156100a357600080fd5b503573ffffffffffffffffffffffffffffffffffffffff166102f1565b6040805173ffffffffffffffffffffffffffffffffffffffff9092168252519081900360200190f35b3480156100f557600080fd5b506100fe6103a9565b005b34801561010c57600080fd5b506100fe6004803603604081101561012357600080fd5b5073ffffffffffffffffffffffffffffffffffffffff813581169160200135166104a9565b34801561015457600080fd5b506100c06105bf565b6100fe6004803603606081101561017357600080fd5b73ffffffffffffffffffffffffffffffffffffffff82358116926020810135909116918101906060810160408201356401000000008111156101b457600080fd5b8201836020820111156101c657600080fd5b803590602001918460018302840111640100000000831117156101e857600080fd5b91908080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509295506105db945050505050565b34801561023557600080fd5b506100fe6004803603604081101561024c57600080fd5b5073ffffffffffffffffffffffffffffffffffffffff8135811691602001351661075d565b34801561027d57600080fd5b506100fe6004803603602081101561029457600080fd5b503573ffffffffffffffffffffffffffffffffffffffff16610857565b3480156102bd57600080fd5b506100c0600480360360208110156102d457600080fd5b503573ffffffffffffffffffffffffffffffffffffffff166109e1565b60008060008373ffffffffffffffffffffffffffffffffffffffff1660405180807f5c60da1b000000000000000000000000000000000000000000000000000000008152506004019050600060405180830381855afa9150503d8060008114610376576040519150601f19603f3d011682016040523d82523d6000602084013e61037b565b606091505b50915091508161038a57600080fd5b80806020019051602081101561039f57600080fd5b5051949350505050565b6103b1610a66565b60005473ffffffffffffffffffffffffffffffffffffffff90811691161461043a57604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b6000805460405173ffffffffffffffffffffffffffffffffffffffff909116907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908390a3600080547fffffffffffffffffffffffff0000000000000000000000000000000000000000169055565b6104b1610a66565b60005473ffffffffffffffffffffffffffffffffffffffff90811691161461053a57604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b8173ffffffffffffffffffffffffffffffffffffffff16638f283970826040518263ffffffff1660e01b8152600401808273ffffffffffffffffffffffffffffffffffffffff168152602001915050600060405180830381600087803b1580156105a357600080fd5b505af11580156105b7573d6000803e3d6000fd5b505050505050565b60005473ffffffffffffffffffffffffffffffffffffffff1690565b6105e3610a66565b60005473ffffffffffffffffffffffffffffffffffffffff90811691161461066c57604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b8273ffffffffffffffffffffffffffffffffffffffff16634f1ef2863484846040518463ffffffff1660e01b8152600401808373ffffffffffffffffffffffffffffffffffffffff16815260200180602001828103825283818151815260200191508051906020019080838360005b838110156106f35781810151838201526020016106db565b50505050905090810190601f1680156107205780820380516001836020036101000a031916815260200191505b5093505050506000604051808303818588803b15801561073f57600080fd5b505af1158015610753573d6000803e3d6000fd5b5050505050505050565b610765610a66565b60005473ffffffffffffffffffffffffffffffffffffffff9081169116146107ee57604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b8173ffffffffffffffffffffffffffffffffffffffff16633659cfe6826040518263ffffffff1660e01b8152600401808273ffffffffffffffffffffffffffffffffffffffff168152602001915050600060405180830381600087803b1580156105a357600080fd5b61085f610a66565b60005473ffffffffffffffffffffffffffffffffffffffff9081169116146108e857604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b73ffffffffffffffffffffffffffffffffffffffff8116610954576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526026815260200180610a6b6026913960400191505060405180910390fd5b6000805460405173ffffffffffffffffffffffffffffffffffffffff808516939216917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a3600080547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff92909216919091179055565b60008060008373ffffffffffffffffffffffffffffffffffffffff1660405180807ff851a440000000000000000000000000000000000000000000000000000000008152506004019050600060405180830381855afa9150503d8060008114610376576040519150601f19603f3d011682016040523d82523d6000602084013e61037b565b339056fe4f776e61626c653a206e6577206f776e657220697320746865207a65726f2061646472657373a264697066735822122033c7eab8e5a7904ed291c191ebc004b4929d46e0bcbd0fea73fa80b0475d931164736f6c63430007060033", + "deployedBytecode": "0x60806040526004361061007b5760003560e01c80639623609d1161004e5780639623609d1461015d57806399a88ec414610229578063f2fde38b14610271578063f3b7dead146102b15761007b565b8063204e1c7a14610080578063715018a6146100e95780637eff275e146101005780638da5cb5b14610148575b600080fd5b34801561008c57600080fd5b506100c0600480360360208110156100a357600080fd5b503573ffffffffffffffffffffffffffffffffffffffff166102f1565b6040805173ffffffffffffffffffffffffffffffffffffffff9092168252519081900360200190f35b3480156100f557600080fd5b506100fe6103a9565b005b34801561010c57600080fd5b506100fe6004803603604081101561012357600080fd5b5073ffffffffffffffffffffffffffffffffffffffff813581169160200135166104a9565b34801561015457600080fd5b506100c06105bf565b6100fe6004803603606081101561017357600080fd5b73ffffffffffffffffffffffffffffffffffffffff82358116926020810135909116918101906060810160408201356401000000008111156101b457600080fd5b8201836020820111156101c657600080fd5b803590602001918460018302840111640100000000831117156101e857600080fd5b91908080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509295506105db945050505050565b34801561023557600080fd5b506100fe6004803603604081101561024c57600080fd5b5073ffffffffffffffffffffffffffffffffffffffff8135811691602001351661075d565b34801561027d57600080fd5b506100fe6004803603602081101561029457600080fd5b503573ffffffffffffffffffffffffffffffffffffffff16610857565b3480156102bd57600080fd5b506100c0600480360360208110156102d457600080fd5b503573ffffffffffffffffffffffffffffffffffffffff166109e1565b60008060008373ffffffffffffffffffffffffffffffffffffffff1660405180807f5c60da1b000000000000000000000000000000000000000000000000000000008152506004019050600060405180830381855afa9150503d8060008114610376576040519150601f19603f3d011682016040523d82523d6000602084013e61037b565b606091505b50915091508161038a57600080fd5b80806020019051602081101561039f57600080fd5b5051949350505050565b6103b1610a66565b60005473ffffffffffffffffffffffffffffffffffffffff90811691161461043a57604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b6000805460405173ffffffffffffffffffffffffffffffffffffffff909116907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908390a3600080547fffffffffffffffffffffffff0000000000000000000000000000000000000000169055565b6104b1610a66565b60005473ffffffffffffffffffffffffffffffffffffffff90811691161461053a57604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b8173ffffffffffffffffffffffffffffffffffffffff16638f283970826040518263ffffffff1660e01b8152600401808273ffffffffffffffffffffffffffffffffffffffff168152602001915050600060405180830381600087803b1580156105a357600080fd5b505af11580156105b7573d6000803e3d6000fd5b505050505050565b60005473ffffffffffffffffffffffffffffffffffffffff1690565b6105e3610a66565b60005473ffffffffffffffffffffffffffffffffffffffff90811691161461066c57604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b8273ffffffffffffffffffffffffffffffffffffffff16634f1ef2863484846040518463ffffffff1660e01b8152600401808373ffffffffffffffffffffffffffffffffffffffff16815260200180602001828103825283818151815260200191508051906020019080838360005b838110156106f35781810151838201526020016106db565b50505050905090810190601f1680156107205780820380516001836020036101000a031916815260200191505b5093505050506000604051808303818588803b15801561073f57600080fd5b505af1158015610753573d6000803e3d6000fd5b5050505050505050565b610765610a66565b60005473ffffffffffffffffffffffffffffffffffffffff9081169116146107ee57604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b8173ffffffffffffffffffffffffffffffffffffffff16633659cfe6826040518263ffffffff1660e01b8152600401808273ffffffffffffffffffffffffffffffffffffffff168152602001915050600060405180830381600087803b1580156105a357600080fd5b61085f610a66565b60005473ffffffffffffffffffffffffffffffffffffffff9081169116146108e857604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b73ffffffffffffffffffffffffffffffffffffffff8116610954576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526026815260200180610a6b6026913960400191505060405180910390fd5b6000805460405173ffffffffffffffffffffffffffffffffffffffff808516939216917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a3600080547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff92909216919091179055565b60008060008373ffffffffffffffffffffffffffffffffffffffff1660405180807ff851a440000000000000000000000000000000000000000000000000000000008152506004019050600060405180830381855afa9150503d8060008114610376576040519150601f19603f3d011682016040523d82523d6000602084013e61037b565b339056fe4f776e61626c653a206e6577206f776e657220697320746865207a65726f2061646472657373a264697066735822122033c7eab8e5a7904ed291c191ebc004b4929d46e0bcbd0fea73fa80b0475d931164736f6c63430007060033", + "devdoc": { + "details": "This is an auxiliary contract meant to be assigned as the admin of a {TransparentUpgradeableProxy}. For an explanation of why you would want to use this see the documentation for {TransparentUpgradeableProxy}.", + "kind": "dev", + "methods": { + "changeProxyAdmin(address,address)": { + "details": "Changes the admin of `proxy` to `newAdmin`. Requirements: - This contract must be the current admin of `proxy`." + }, + "getProxyAdmin(address)": { + "details": "Returns the current admin of `proxy`. Requirements: - This contract must be the admin of `proxy`." + }, + "getProxyImplementation(address)": { + "details": "Returns the current implementation of `proxy`. Requirements: - This contract must be the admin of `proxy`." + }, + "owner()": { + "details": "Returns the address of the current owner." + }, + "renounceOwnership()": { + "details": "Leaves the contract without owner. It will not be possible to call `onlyOwner` functions anymore. Can only be called by the current owner. NOTE: Renouncing ownership will leave the contract without an owner, thereby removing any functionality that is only available to the owner." + }, + "transferOwnership(address)": { + "details": "Transfers ownership of the contract to a new account (`newOwner`). Can only be called by the current owner." + }, + "upgrade(address,address)": { + "details": "Upgrades `proxy` to `implementation`. See {TransparentUpgradeableProxy-upgradeTo}. Requirements: - This contract must be the admin of `proxy`." + }, + "upgradeAndCall(address,address,bytes)": { + "details": "Upgrades `proxy` to `implementation` and calls a function on the new implementation. See {TransparentUpgradeableProxy-upgradeToAndCall}. Requirements: - This contract must be the admin of `proxy`." + } + }, + "version": 1 + }, + "userdoc": { + "kind": "user", + "methods": {}, + "version": 1 + }, + "storageLayout": { + "storage": [ + { + "astId": 30, + "contract": "solc_0.7/openzeppelin/proxy/ProxyAdmin.sol:ProxyAdmin", + "label": "_owner", + "offset": 0, + "slot": "0", + "type": "t_address" + } + ], + "types": { + "t_address": { + "encoding": "inplace", + "label": "address", + "numberOfBytes": "20" + } + } + } +} \ No newline at end of file diff --git a/deployments/dfk/DevMultisig.json b/deployments/dfk/DevMultisig.json new file mode 100644 index 000000000..9c0c238a9 --- /dev/null +++ b/deployments/dfk/DevMultisig.json @@ -0,0 +1,4 @@ +{ + "address": "0x2E62c47f502f512C75bd5Ecd70799EFB0Fe7BAA3", + "abi": [{"type":"function","stateMutability":"view","payable":false,"outputs":[{"type":"address","name":""}],"name":"owners","inputs":[{"type":"uint256","name":""}],"constant":true},{"type":"function","stateMutability":"nonpayable","payable":false,"outputs":[],"name":"removeOwner","inputs":[{"type":"address","name":"owner"}],"constant":false},{"type":"function","stateMutability":"nonpayable","payable":false,"outputs":[],"name":"revokeConfirmation","inputs":[{"type":"uint256","name":"transactionId"}],"constant":false},{"type":"function","stateMutability":"view","payable":false,"outputs":[{"type":"bool","name":""}],"name":"isOwner","inputs":[{"type":"address","name":""}],"constant":true},{"type":"function","stateMutability":"view","payable":false,"outputs":[{"type":"bool","name":""}],"name":"confirmations","inputs":[{"type":"uint256","name":""},{"type":"address","name":""}],"constant":true},{"type":"function","stateMutability":"view","payable":false,"outputs":[{"type":"uint256","name":""}],"name":"calcMaxWithdraw","inputs":[],"constant":true},{"type":"function","stateMutability":"view","payable":false,"outputs":[{"type":"uint256","name":"count"}],"name":"getTransactionCount","inputs":[{"type":"bool","name":"pending"},{"type":"bool","name":"executed"}],"constant":true},{"type":"function","stateMutability":"view","payable":false,"outputs":[{"type":"uint256","name":""}],"name":"dailyLimit","inputs":[],"constant":true},{"type":"function","stateMutability":"view","payable":false,"outputs":[{"type":"uint256","name":""}],"name":"lastDay","inputs":[],"constant":true},{"type":"function","stateMutability":"nonpayable","payable":false,"outputs":[],"name":"addOwner","inputs":[{"type":"address","name":"owner"}],"constant":false},{"type":"function","stateMutability":"view","payable":false,"outputs":[{"type":"bool","name":""}],"name":"isConfirmed","inputs":[{"type":"uint256","name":"transactionId"}],"constant":true},{"type":"function","stateMutability":"view","payable":false,"outputs":[{"type":"uint256","name":"count"}],"name":"getConfirmationCount","inputs":[{"type":"uint256","name":"transactionId"}],"constant":true},{"type":"function","stateMutability":"view","payable":false,"outputs":[{"type":"address","name":"destination"},{"type":"uint256","name":"value"},{"type":"bytes","name":"data"},{"type":"bool","name":"executed"}],"name":"transactions","inputs":[{"type":"uint256","name":""}],"constant":true},{"type":"function","stateMutability":"view","payable":false,"outputs":[{"type":"address[]","name":""}],"name":"getOwners","inputs":[],"constant":true},{"type":"function","stateMutability":"view","payable":false,"outputs":[{"type":"uint256[]","name":"_transactionIds"}],"name":"getTransactionIds","inputs":[{"type":"uint256","name":"from"},{"type":"uint256","name":"to"},{"type":"bool","name":"pending"},{"type":"bool","name":"executed"}],"constant":true},{"type":"function","stateMutability":"view","payable":false,"outputs":[{"type":"address[]","name":"_confirmations"}],"name":"getConfirmations","inputs":[{"type":"uint256","name":"transactionId"}],"constant":true},{"type":"function","stateMutability":"view","payable":false,"outputs":[{"type":"uint256","name":""}],"name":"transactionCount","inputs":[],"constant":true},{"type":"function","stateMutability":"nonpayable","payable":false,"outputs":[],"name":"changeRequirement","inputs":[{"type":"uint256","name":"_required"}],"constant":false},{"type":"function","stateMutability":"nonpayable","payable":false,"outputs":[],"name":"confirmTransaction","inputs":[{"type":"uint256","name":"transactionId"}],"constant":false},{"type":"function","stateMutability":"nonpayable","payable":false,"outputs":[{"type":"uint256","name":"transactionId"}],"name":"submitTransaction","inputs":[{"type":"address","name":"destination"},{"type":"uint256","name":"value"},{"type":"bytes","name":"data"}],"constant":false},{"type":"function","stateMutability":"nonpayable","payable":false,"outputs":[],"name":"changeDailyLimit","inputs":[{"type":"uint256","name":"_dailyLimit"}],"constant":false},{"type":"function","stateMutability":"view","payable":false,"outputs":[{"type":"uint256","name":""}],"name":"MAX_OWNER_COUNT","inputs":[],"constant":true},{"type":"function","stateMutability":"view","payable":false,"outputs":[{"type":"uint256","name":""}],"name":"required","inputs":[],"constant":true},{"type":"function","stateMutability":"nonpayable","payable":false,"outputs":[],"name":"replaceOwner","inputs":[{"type":"address","name":"owner"},{"type":"address","name":"newOwner"}],"constant":false},{"type":"function","stateMutability":"nonpayable","payable":false,"outputs":[],"name":"executeTransaction","inputs":[{"type":"uint256","name":"transactionId"}],"constant":false},{"type":"function","stateMutability":"view","payable":false,"outputs":[{"type":"uint256","name":""}],"name":"spentToday","inputs":[],"constant":true},{"type":"constructor","stateMutability":"nonpayable","payable":false,"inputs":[{"type":"address[]","name":"_owners"},{"type":"uint256","name":"_required"},{"type":"uint256","name":"_dailyLimit"}]},{"type":"fallback","stateMutability":"payable","payable":true},{"type":"event","name":"DailyLimitChange","inputs":[{"type":"uint256","name":"dailyLimit","indexed":false}],"anonymous":false},{"type":"event","name":"Confirmation","inputs":[{"type":"address","name":"sender","indexed":true},{"type":"uint256","name":"transactionId","indexed":true}],"anonymous":false},{"type":"event","name":"Revocation","inputs":[{"type":"address","name":"sender","indexed":true},{"type":"uint256","name":"transactionId","indexed":true}],"anonymous":false},{"type":"event","name":"Submission","inputs":[{"type":"uint256","name":"transactionId","indexed":true}],"anonymous":false},{"type":"event","name":"Execution","inputs":[{"type":"uint256","name":"transactionId","indexed":true}],"anonymous":false},{"type":"event","name":"ExecutionFailure","inputs":[{"type":"uint256","name":"transactionId","indexed":true}],"anonymous":false},{"type":"event","name":"Deposit","inputs":[{"type":"address","name":"sender","indexed":true},{"type":"uint256","name":"value","indexed":false}],"anonymous":false},{"type":"event","name":"OwnerAddition","inputs":[{"type":"address","name":"owner","indexed":true}],"anonymous":false},{"type":"event","name":"OwnerRemoval","inputs":[{"type":"address","name":"owner","indexed":true}],"anonymous":false},{"type":"event","name":"RequirementChange","inputs":[{"type":"uint256","name":"required","indexed":false}],"anonymous":false}] +} \ No newline at end of file diff --git a/deployments/dfk/L1BridgeZap.json b/deployments/dfk/L1BridgeZap.json new file mode 100644 index 000000000..a3b3fdf6d --- /dev/null +++ b/deployments/dfk/L1BridgeZap.json @@ -0,0 +1,754 @@ +{ + "address": "0x75224b0f245Fe51d5bf47A898DbB6720D4150BA7", + "abi": [ + { + "inputs": [ + { + "internalType": "address payable", + "name": "_wethAddress", + "type": "address" + }, + { + "internalType": "contract ISwap", + "name": "_baseSwap", + "type": "address" + }, + { + "internalType": "contract ISynapseBridge", + "name": "_synapseBridge", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [], + "name": "WETH_ADDRESS", + "outputs": [ + { + "internalType": "address payable", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "baseTokens", + "outputs": [ + { + "internalType": "contract IERC20", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "tokenAmount", + "type": "uint256" + }, + { + "internalType": "uint8", + "name": "tokenIndex", + "type": "uint8" + } + ], + "name": "calculateRemoveLiquidityOneToken", + "outputs": [ + { + "internalType": "uint256", + "name": "availableTokenAmount", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256[]", + "name": "amounts", + "type": "uint256[]" + }, + { + "internalType": "bool", + "name": "deposit", + "type": "bool" + } + ], + "name": "calculateTokenAmount", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "chainId", + "type": "uint256" + }, + { + "internalType": "contract IERC20", + "name": "token", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "deposit", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "chainId", + "type": "uint256" + }, + { + "internalType": "contract IERC20", + "name": "token", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "internalType": "uint8", + "name": "tokenIndexFrom", + "type": "uint8" + }, + { + "internalType": "uint8", + "name": "tokenIndexTo", + "type": "uint8" + }, + { + "internalType": "uint256", + "name": "minDy", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" + } + ], + "name": "depositAndSwap", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "chainId", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "depositETH", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "chainId", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "internalType": "uint8", + "name": "tokenIndexFrom", + "type": "uint8" + }, + { + "internalType": "uint8", + "name": "tokenIndexTo", + "type": "uint8" + }, + { + "internalType": "uint256", + "name": "minDy", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" + } + ], + "name": "depositETHAndSwap", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "chainId", + "type": "uint256" + }, + { + "internalType": "contract IERC20", + "name": "token", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "redeem", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "chainId", + "type": "uint256" + }, + { + "internalType": "contract IERC20", + "name": "token", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "internalType": "uint8", + "name": "liqTokenIndex", + "type": "uint8" + }, + { + "internalType": "uint256", + "name": "liqMinAmount", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "liqDeadline", + "type": "uint256" + } + ], + "name": "redeemAndRemove", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "chainId", + "type": "uint256" + }, + { + "internalType": "contract IERC20", + "name": "token", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "internalType": "uint8", + "name": "tokenIndexFrom", + "type": "uint8" + }, + { + "internalType": "uint8", + "name": "tokenIndexTo", + "type": "uint8" + }, + { + "internalType": "uint256", + "name": "minDy", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" + } + ], + "name": "redeemAndSwap", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "to", + "type": "bytes32" + }, + { + "internalType": "uint256", + "name": "chainId", + "type": "uint256" + }, + { + "internalType": "contract IERC20", + "name": "token", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "redeemv2", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "chainId", + "type": "uint256" + }, + { + "internalType": "contract IERC20", + "name": "token", + "type": "address" + }, + { + "internalType": "uint256[]", + "name": "liquidityAmounts", + "type": "uint256[]" + }, + { + "internalType": "uint256", + "name": "minToMint", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" + } + ], + "name": "zapAndDeposit", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "chainId", + "type": "uint256" + }, + { + "internalType": "contract IERC20", + "name": "token", + "type": "address" + }, + { + "internalType": "uint256[]", + "name": "liquidityAmounts", + "type": "uint256[]" + }, + { + "internalType": "uint256", + "name": "minToMint", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "liqDeadline", + "type": "uint256" + }, + { + "internalType": "uint8", + "name": "tokenIndexFrom", + "type": "uint8" + }, + { + "internalType": "uint8", + "name": "tokenIndexTo", + "type": "uint8" + }, + { + "internalType": "uint256", + "name": "minDy", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "swapDeadline", + "type": "uint256" + } + ], + "name": "zapAndDepositAndSwap", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } + ], + "transactionHash": "0xfc19c34e3954dcda1060a1fea1db20e6deebc69d5dd22e66cf47bb7ba79f8373", + "receipt": { + "to": null, + "from": "0x235AF07E770f474d24F5bf73074735892371b40D", + "contractAddress": "0x75224b0f245Fe51d5bf47A898DbB6720D4150BA7", + "transactionIndex": 2, + "gasUsed": "1908172", + "logsBloom": "0x00000000000000000000000000000000000000000000200000000000000200000000000000000000000000000000000801000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000804000000000000000000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000010000000000000000000000000000000000000000000000000000000000000", + "blockHash": "0x4200da1e2ec79de256c9284318606a5ee4368da5e8cdc975e8a9502b43ad561b", + "transactionHash": "0xfc19c34e3954dcda1060a1fea1db20e6deebc69d5dd22e66cf47bb7ba79f8373", + "logs": [ + { + "transactionIndex": 2, + "blockNumber": 47294, + "transactionHash": "0xfc19c34e3954dcda1060a1fea1db20e6deebc69d5dd22e66cf47bb7ba79f8373", + "address": "0xCCb93dABD71c8Dad03Fc4CE5559dC3D89F67a260", + "topics": [ + "0x8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925", + "0x00000000000000000000000075224b0f245fe51d5bf47a898dbb6720d4150ba7", + "0x000000000000000000000000e05c976d3f045d0e6e7a6f61083d98a15603cf6a" + ], + "data": "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + "logIndex": 19, + "blockHash": "0x4200da1e2ec79de256c9284318606a5ee4368da5e8cdc975e8a9502b43ad561b" + } + ], + "blockNumber": 47294, + "cumulativeGasUsed": "2458616", + "status": 1, + "byzantium": true + }, + "args": [ + "0xCCb93dABD71c8Dad03Fc4CE5559dC3D89F67a260", + "0x0000000000000000000000000000000000000000", + "0xE05c976d3f045D0E6E7A6f61083d98A15603cF6A" + ], + "solcInputHash": "f890e19d95a4324c05c431b6e8cd0070", + "metadata": "{\"compiler\":{\"version\":\"0.6.12+commit.27d51765\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address payable\",\"name\":\"_wethAddress\",\"type\":\"address\"},{\"internalType\":\"contract ISwap\",\"name\":\"_baseSwap\",\"type\":\"address\"},{\"internalType\":\"contract ISynapseBridge\",\"name\":\"_synapseBridge\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"WETH_ADDRESS\",\"outputs\":[{\"internalType\":\"address payable\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"baseTokens\",\"outputs\":[{\"internalType\":\"contract IERC20\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"tokenAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint8\",\"name\":\"tokenIndex\",\"type\":\"uint8\"}],\"name\":\"calculateRemoveLiquidityOneToken\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"availableTokenAmount\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256[]\",\"name\":\"amounts\",\"type\":\"uint256[]\"},{\"internalType\":\"bool\",\"name\":\"deposit\",\"type\":\"bool\"}],\"name\":\"calculateTokenAmount\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"chainId\",\"type\":\"uint256\"},{\"internalType\":\"contract IERC20\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"deposit\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"chainId\",\"type\":\"uint256\"},{\"internalType\":\"contract IERC20\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"uint8\",\"name\":\"tokenIndexFrom\",\"type\":\"uint8\"},{\"internalType\":\"uint8\",\"name\":\"tokenIndexTo\",\"type\":\"uint8\"},{\"internalType\":\"uint256\",\"name\":\"minDy\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"deadline\",\"type\":\"uint256\"}],\"name\":\"depositAndSwap\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"chainId\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"depositETH\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"chainId\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"uint8\",\"name\":\"tokenIndexFrom\",\"type\":\"uint8\"},{\"internalType\":\"uint8\",\"name\":\"tokenIndexTo\",\"type\":\"uint8\"},{\"internalType\":\"uint256\",\"name\":\"minDy\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"deadline\",\"type\":\"uint256\"}],\"name\":\"depositETHAndSwap\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"chainId\",\"type\":\"uint256\"},{\"internalType\":\"contract IERC20\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"redeem\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"chainId\",\"type\":\"uint256\"},{\"internalType\":\"contract IERC20\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"uint8\",\"name\":\"liqTokenIndex\",\"type\":\"uint8\"},{\"internalType\":\"uint256\",\"name\":\"liqMinAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"liqDeadline\",\"type\":\"uint256\"}],\"name\":\"redeemAndRemove\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"chainId\",\"type\":\"uint256\"},{\"internalType\":\"contract IERC20\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"uint8\",\"name\":\"tokenIndexFrom\",\"type\":\"uint8\"},{\"internalType\":\"uint8\",\"name\":\"tokenIndexTo\",\"type\":\"uint8\"},{\"internalType\":\"uint256\",\"name\":\"minDy\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"deadline\",\"type\":\"uint256\"}],\"name\":\"redeemAndSwap\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"to\",\"type\":\"bytes32\"},{\"internalType\":\"uint256\",\"name\":\"chainId\",\"type\":\"uint256\"},{\"internalType\":\"contract IERC20\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"redeemv2\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"chainId\",\"type\":\"uint256\"},{\"internalType\":\"contract IERC20\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint256[]\",\"name\":\"liquidityAmounts\",\"type\":\"uint256[]\"},{\"internalType\":\"uint256\",\"name\":\"minToMint\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"deadline\",\"type\":\"uint256\"}],\"name\":\"zapAndDeposit\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"chainId\",\"type\":\"uint256\"},{\"internalType\":\"contract IERC20\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint256[]\",\"name\":\"liquidityAmounts\",\"type\":\"uint256[]\"},{\"internalType\":\"uint256\",\"name\":\"minToMint\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"liqDeadline\",\"type\":\"uint256\"},{\"internalType\":\"uint8\",\"name\":\"tokenIndexFrom\",\"type\":\"uint8\"},{\"internalType\":\"uint8\",\"name\":\"tokenIndexTo\",\"type\":\"uint8\"},{\"internalType\":\"uint256\",\"name\":\"minDy\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"swapDeadline\",\"type\":\"uint256\"}],\"name\":\"zapAndDepositAndSwap\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}],\"devdoc\":{\"details\":\"This contract should be deployed with a base Swap.sol address and a SynapseBridge.sol address, otherwise, it will not function.\",\"kind\":\"dev\",\"methods\":{\"calculateRemoveLiquidityOneToken(uint256,uint8)\":{\"params\":{\"tokenAmount\":\"the amount of LP token to burn\",\"tokenIndex\":\"index of which token will be withdrawn\"},\"returns\":{\"availableTokenAmount\":\"calculated amount of underlying token available to withdraw\"}},\"calculateTokenAmount(uint256[],bool)\":{\"details\":\"This shouldn't be used outside frontends for user estimates.\",\"params\":{\"amounts\":\"an array of token amounts to deposit or withdrawal, corresponding to pooledTokens. The amount should be in each pooled token's native precision.\",\"deposit\":\"whether this is a deposit or a withdrawal\"},\"returns\":{\"_0\":\"token amount the user will receive\"}},\"deposit(address,uint256,address,uint256)\":{\"params\":{\"amount\":\"Amount in native token decimals to transfer cross-chain pre-fees*\",\"chainId\":\"which chain to bridge assets onto\",\"to\":\"address on other chain to bridge assets to\",\"token\":\"ERC20 compatible token to deposit into the bridge\"}},\"depositAndSwap(address,uint256,address,uint256,uint8,uint8,uint256,uint256)\":{\"params\":{\"amount\":\"Amount in native token decimals to transfer cross-chain pre-fees\",\"chainId\":\"which chain to bridge assets onto\",\"deadline\":\"latest timestamp to accept this transaction*\",\"minDy\":\"the min amount the user would like to receive, or revert to only minting the SynERC20 token crosschain.\",\"to\":\"address on other chain to bridge assets to\",\"token\":\"ERC20 compatible token to deposit into the bridge\",\"tokenIndexFrom\":\"the token the user wants to swap from\",\"tokenIndexTo\":\"the token the user wants to swap to\"}},\"depositETH(address,uint256,uint256)\":{\"params\":{\"amount\":\"Amount in native token decimals to transfer cross-chain pre-fees*\",\"chainId\":\"which chain to bridge assets onto\",\"to\":\"address on other chain to bridge assets to\"}},\"depositETHAndSwap(address,uint256,uint256,uint8,uint8,uint256,uint256)\":{\"params\":{\"amount\":\"Amount in native token decimals to transfer cross-chain pre-fees\",\"chainId\":\"which chain to bridge assets onto\",\"deadline\":\"latest timestamp to accept this transaction*\",\"minDy\":\"the min amount the user would like to receive, or revert to only minting the SynERC20 token crosschain.\",\"to\":\"address on other chain to bridge assets to\",\"tokenIndexFrom\":\"the token the user wants to swap from\",\"tokenIndexTo\":\"the token the user wants to swap to\"}},\"redeem(address,uint256,address,uint256)\":{\"params\":{\"amount\":\"Amount in native token decimals to transfer cross-chain pre-fees*\",\"chainId\":\"which chain to bridge assets onto\",\"to\":\"address on other chain to bridge assets to\",\"token\":\"ERC20 compatible token to redeem into the bridge\"}},\"redeemAndRemove(address,uint256,address,uint256,uint8,uint256,uint256)\":{\"params\":{\"amount\":\"Amount of (typically) LP token to pass to the nodes to attempt to removeLiquidity() with to redeem for the underlying assets of the LP token\",\"chainId\":\"which underlying chain to bridge assets onto\",\"liqDeadline\":\"Specificies the deadline that the nodes are allowed to try to redeem/swap the LP token*\",\"liqMinAmount\":\"Specifies the minimum amount of the underlying asset needed for the nodes to execute the redeem/swap\",\"liqTokenIndex\":\"Specifies which of the underlying LP assets the nodes should attempt to redeem for\",\"to\":\"address on other chain to redeem underlying assets to\",\"token\":\"ERC20 compatible token to deposit into the bridge\"}},\"redeemAndSwap(address,uint256,address,uint256,uint8,uint8,uint256,uint256)\":{\"params\":{\"amount\":\"Amount in native token decimals to transfer cross-chain pre-fees\",\"chainId\":\"which underlying chain to bridge assets onto\",\"deadline\":\"latest timestamp to accept this transaction*\",\"minDy\":\"the min amount the user would like to receive, or revert to only minting the SynERC20 token crosschain.\",\"to\":\"address on other chain to redeem underlying assets to\",\"token\":\"ERC20 compatible token to deposit into the bridge\",\"tokenIndexFrom\":\"the token the user wants to swap from\",\"tokenIndexTo\":\"the token the user wants to swap to\"}},\"redeemv2(bytes32,uint256,address,uint256)\":{\"params\":{\"amount\":\"Amount in native token decimals to transfer cross-chain pre-fees*\",\"chainId\":\"which chain to bridge assets onto\",\"to\":\"address on other chain to bridge assets to\",\"token\":\"ERC20 compatible token to redeem into the bridge\"}},\"zapAndDeposit(address,uint256,address,uint256[],uint256,uint256)\":{\"params\":{\"chainId\":\"which chain to bridge assets onto\",\"deadline\":\"latest timestamp to accept this transaction*\",\"liquidityAmounts\":\"the amounts of each token to add, in their native precision\",\"minToMint\":\"the minimum LP tokens adding this amount of liquidity should mint, otherwise revert. Handy for front-running mitigation\",\"to\":\"address on other chain to bridge assets to\",\"token\":\"ERC20 compatible token to deposit into the bridge\"}},\"zapAndDepositAndSwap(address,uint256,address,uint256[],uint256,uint256,uint8,uint8,uint256,uint256)\":{\"params\":{\"chainId\":\"which chain to bridge assets onto\",\"liqDeadline\":\"latest timestamp to accept this transaction\",\"liquidityAmounts\":\"the amounts of each token to add, in their native precision\",\"minDy\":\"the min amount the user would like to receive, or revert to only minting the SynERC20 token crosschain.\",\"minToMint\":\"the minimum LP tokens adding this amount of liquidity should mint, otherwise revert. Handy for front-running mitigation\",\"swapDeadline\":\"latest timestamp to accept this transaction*\",\"to\":\"address on other chain to bridge assets to\",\"token\":\"ERC20 compatible token to deposit into the bridge\",\"tokenIndexFrom\":\"the token the user wants to swap from\",\"tokenIndexTo\":\"the token the user wants to swap to\"}}},\"title\":\"L1BridgeZap\",\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{\"calculateRemoveLiquidityOneToken(uint256,uint8)\":{\"notice\":\"Calculate the amount of underlying token available to withdraw when withdrawing via only single token\"},\"calculateTokenAmount(uint256[],bool)\":{\"notice\":\"A simple method to calculate prices from deposits or withdrawals, excluding fees but including slippage. This is helpful as an input into the various \\\"min\\\" parameters on calls to fight front-running\"},\"constructor\":\"Constructs the contract, approves each token inside of baseSwap to be used by baseSwap (needed for addLiquidity())\",\"deposit(address,uint256,address,uint256)\":{\"notice\":\"Wraps SynapseBridge deposit() function\"},\"depositAndSwap(address,uint256,address,uint256,uint8,uint8,uint256,uint256)\":{\"notice\":\"Wraps SynapseBridge depositAndSwap() function\"},\"depositETH(address,uint256,uint256)\":{\"notice\":\"Wraps SynapseBridge deposit() function to make it compatible w/ ETH -> WETH conversions\"},\"depositETHAndSwap(address,uint256,uint256,uint8,uint8,uint256,uint256)\":{\"notice\":\"Wraps SynapseBridge depositAndSwap() function to make it compatible w/ ETH -> WETH conversions\"},\"redeem(address,uint256,address,uint256)\":{\"notice\":\"Wraps SynapseBridge redeem() function\"},\"redeemAndRemove(address,uint256,address,uint256,uint8,uint256,uint256)\":{\"notice\":\"Wraps redeemAndRemove on SynapseBridge Relays to nodes that (typically) a wrapped synAsset ERC20 token has been burned and the underlying needs to be redeeemed on the native chain. This function indicates to the nodes that they should attempt to redeem the LP token for the underlying assets (E.g \\\"swap\\\" out of the LP token)\"},\"redeemAndSwap(address,uint256,address,uint256,uint8,uint8,uint256,uint256)\":{\"notice\":\"Wraps redeemAndSwap on SynapseBridge.sol Relays to nodes that (typically) a wrapped synAsset ERC20 token has been burned and the underlying needs to be redeeemed on the native chain. This function indicates to the nodes that they should attempt to redeem the LP token for the underlying assets (E.g \\\"swap\\\" out of the LP token)\"},\"redeemv2(bytes32,uint256,address,uint256)\":{\"notice\":\"Wraps SynapseBridge redeemv2() function\"},\"zapAndDeposit(address,uint256,address,uint256[],uint256,uint256)\":{\"notice\":\"Combines adding liquidity to the given Swap, and calls deposit() on the bridge using that LP token\"},\"zapAndDepositAndSwap(address,uint256,address,uint256[],uint256,uint256,uint8,uint8,uint256,uint256)\":{\"notice\":\"Combines adding liquidity to the given Swap, and calls depositAndSwap() on the bridge using that LP token\"}},\"notice\":\"This contract is responsible for handling user Zaps into the SynapseBridge contract, through the Synapse Swap contracts. It does so It does so by combining the action of addLiquidity() to the base swap pool, and then calling either deposit() or depositAndSwap() on the bridge. This is done in hopes of automating portions of the bridge user experience to users, while keeping the SynapseBridge contract logic small.\",\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/bridge/wrappers/L1BridgeZap.sol\":\"L1BridgeZap\"},\"evmVersion\":\"istanbul\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":10000},\"remappings\":[]},\"sources\":{\"@openzeppelin/contracts/math/SafeMath.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity >=0.6.0 <0.8.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\",\"keccak256\":\"0xcc78a17dd88fa5a2edc60c8489e2f405c0913b377216a5b26b35656b2d0dab52\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/ERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity >=0.6.0 <0.8.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_) public {\\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\",\"keccak256\":\"0xca0c2396dbeb3503b51abf4248ebf77a1461edad513c01529df51850a012bee3\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/ERC20Burnable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity >=0.6.0 <0.8.0;\\n\\nimport \\\"../../utils/Context.sol\\\";\\nimport \\\"./ERC20.sol\\\";\\n\\n/**\\n * @dev Extension of {ERC20} that allows token holders to destroy both their own\\n * tokens and those that they have an allowance for, in a way that can be\\n * recognized off-chain (via event analysis).\\n */\\nabstract contract ERC20Burnable is Context, ERC20 {\\n using SafeMath for uint256;\\n\\n /**\\n * @dev Destroys `amount` tokens from the caller.\\n *\\n * See {ERC20-_burn}.\\n */\\n function burn(uint256 amount) public virtual {\\n _burn(_msgSender(), amount);\\n }\\n\\n /**\\n * @dev Destroys `amount` tokens from `account`, deducting from the caller's\\n * allowance.\\n *\\n * See {ERC20-_burn} and {ERC20-allowance}.\\n *\\n * Requirements:\\n *\\n * - the caller must have allowance for ``accounts``'s tokens of at least\\n * `amount`.\\n */\\n function burnFrom(address account, uint256 amount) public virtual {\\n uint256 decreasedAllowance = allowance(account, _msgSender()).sub(amount, \\\"ERC20: burn amount exceeds allowance\\\");\\n\\n _approve(account, _msgSender(), decreasedAllowance);\\n _burn(account, amount);\\n }\\n}\\n\",\"keccak256\":\"0x9c0eb3b0e11d2480d49991dc384f1e5f9c9b9967cc81944d50916a9b9c6c4984\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/IERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity >=0.6.0 <0.8.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\",\"keccak256\":\"0x5f02220344881ce43204ae4a6281145a67bc52c2bb1290a791857df3d19d78f5\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/SafeERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity >=0.6.0 <0.8.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\",\"keccak256\":\"0xf12dfbe97e6276980b83d2830bb0eb75e0cf4f3e626c2471137f82158ae6a0fc\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/Address.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity >=0.6.2 <0.8.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\",\"keccak256\":\"0x28911e614500ae7c607a432a709d35da25f3bc5ddc8bd12b278b66358070c0ea\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/Context.sol\":{\"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\",\"keccak256\":\"0x8d3cb350f04ff49cfb10aef08d87f19dcbaecc8027b0bed12f3275cd12f38cf0\",\"license\":\"MIT\"},\"contracts/bridge/interfaces/ISwap.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity 0.6.12;\\n\\nimport '@openzeppelin/contracts/token/ERC20/ERC20.sol';\\n\\ninterface ISwap {\\n // pool data view functions\\n function getA() external view returns (uint256);\\n\\n function getToken(uint8 index) external view returns (IERC20);\\n\\n function getTokenIndex(address tokenAddress) external view returns (uint8);\\n\\n function getTokenBalance(uint8 index) external view returns (uint256);\\n\\n function getVirtualPrice() external view returns (uint256);\\n\\n // min return calculation functions\\n function calculateSwap(\\n uint8 tokenIndexFrom,\\n uint8 tokenIndexTo,\\n uint256 dx\\n ) external view returns (uint256);\\n\\n function calculateTokenAmount(uint256[] calldata amounts, bool deposit)\\n external\\n view\\n returns (uint256);\\n\\n function calculateRemoveLiquidity(uint256 amount)\\n external\\n view\\n returns (uint256[] memory);\\n\\n function calculateRemoveLiquidityOneToken(\\n uint256 tokenAmount,\\n uint8 tokenIndex\\n ) external view returns (uint256 availableTokenAmount);\\n\\n // state modifying functions\\n function initialize(\\n IERC20[] memory pooledTokens,\\n uint8[] memory decimals,\\n string memory lpTokenName,\\n string memory lpTokenSymbol,\\n uint256 a,\\n uint256 fee,\\n uint256 adminFee,\\n address lpTokenTargetAddress\\n ) external;\\n\\n function swap(\\n uint8 tokenIndexFrom,\\n uint8 tokenIndexTo,\\n uint256 dx,\\n uint256 minDy,\\n uint256 deadline\\n ) external returns (uint256);\\n\\n function addLiquidity(\\n uint256[] calldata amounts,\\n uint256 minToMint,\\n uint256 deadline\\n ) external returns (uint256);\\n\\n function removeLiquidity(\\n uint256 amount,\\n uint256[] calldata minAmounts,\\n uint256 deadline\\n ) external returns (uint256[] memory);\\n\\n function removeLiquidityOneToken(\\n uint256 tokenAmount,\\n uint8 tokenIndex,\\n uint256 minAmount,\\n uint256 deadline\\n ) external returns (uint256);\\n\\n function removeLiquidityImbalance(\\n uint256[] calldata amounts,\\n uint256 maxBurnAmount,\\n uint256 deadline\\n ) external returns (uint256);\\n}\\n\",\"keccak256\":\"0xb51eb389637b2b595a09cd95ea4167a6d945719be1bc127eafae07c06abd8ca8\",\"license\":\"MIT\"},\"contracts/bridge/interfaces/ISynapseBridge.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity 0.6.12;\\n\\nimport '@openzeppelin/contracts/token/ERC20/SafeERC20.sol';\\nimport '@openzeppelin/contracts/token/ERC20/ERC20Burnable.sol';\\n\\ninterface ISynapseBridge {\\n using SafeERC20 for IERC20;\\n\\n function deposit(\\n address to,\\n uint256 chainId,\\n IERC20 token,\\n uint256 amount\\n ) external;\\n\\n function depositAndSwap(\\n address to,\\n uint256 chainId,\\n IERC20 token,\\n uint256 amount,\\n uint8 tokenIndexFrom,\\n uint8 tokenIndexTo,\\n uint256 minDy,\\n uint256 deadline\\n ) external;\\n\\n function redeem(\\n address to,\\n uint256 chainId,\\n IERC20 token,\\n uint256 amount\\n ) external;\\n\\n\\n function redeemv2(\\n bytes32 to,\\n uint256 chainId,\\n IERC20 token,\\n uint256 amount\\n ) external;\\n\\n\\n function redeemAndSwap(\\n address to,\\n uint256 chainId,\\n IERC20 token,\\n uint256 amount,\\n uint8 tokenIndexFrom,\\n uint8 tokenIndexTo,\\n uint256 minDy,\\n uint256 deadline\\n ) external;\\n\\n function redeemAndRemove(\\n address to,\\n uint256 chainId,\\n IERC20 token,\\n uint256 amount,\\n uint8 liqTokenIndex,\\n uint256 liqMinAmount,\\n uint256 liqDeadline\\n ) external;\\n}\\n\",\"keccak256\":\"0x9ae06bbed7d464faceb9c63e929171f422b5eaee1f6d653742ab97862bc6609a\",\"license\":\"MIT\"},\"contracts/bridge/interfaces/IWETH9.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity >=0.4.0;\\n\\ninterface IWETH9 {\\n function name() external view returns (string memory);\\n\\n function symbol() external view returns (string memory);\\n\\n function decimals() external view returns (uint8);\\n\\n function balanceOf(address) external view returns (uint256);\\n\\n function allowance(address, address) external view returns (uint256);\\n\\n receive() external payable;\\n\\n function deposit() external payable;\\n\\n function withdraw(uint256 wad) external;\\n\\n function totalSupply() external view returns (uint256);\\n\\n function approve(address guy, uint256 wad) external returns (bool);\\n\\n function transfer(address dst, uint256 wad) external returns (bool);\\n\\n function transferFrom(\\n address src,\\n address dst,\\n uint256 wad\\n ) external returns (bool);\\n}\",\"keccak256\":\"0x081ebde11dad2210d382564d40336f914d3d621750645f23707ca1a92139dbe2\",\"license\":\"MIT\"},\"contracts/bridge/wrappers/L1BridgeZap.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.6.12;\\n\\nimport '@openzeppelin/contracts/token/ERC20/IERC20.sol';\\nimport '@openzeppelin/contracts/token/ERC20/SafeERC20.sol';\\nimport '../interfaces/ISwap.sol';\\nimport '../interfaces/ISynapseBridge.sol';\\nimport \\\"../interfaces/IWETH9.sol\\\";\\n\\n\\n/**\\n * @title L1BridgeZap\\n * @notice This contract is responsible for handling user Zaps into the SynapseBridge contract, through the Synapse Swap contracts. It does so\\n * It does so by combining the action of addLiquidity() to the base swap pool, and then calling either deposit() or depositAndSwap() on the bridge.\\n * This is done in hopes of automating portions of the bridge user experience to users, while keeping the SynapseBridge contract logic small.\\n *\\n * @dev This contract should be deployed with a base Swap.sol address and a SynapseBridge.sol address, otherwise, it will not function.\\n */\\ncontract L1BridgeZap {\\n using SafeERC20 for IERC20;\\n\\n uint256 constant MAX_UINT256 = 2**256 - 1;\\n \\n ISwap baseSwap;\\n ISynapseBridge synapseBridge;\\n IERC20[] public baseTokens;\\n address payable public immutable WETH_ADDRESS;\\n \\n\\n /**\\n * @notice Constructs the contract, approves each token inside of baseSwap to be used by baseSwap (needed for addLiquidity())\\n */\\n constructor(address payable _wethAddress, ISwap _baseSwap, ISynapseBridge _synapseBridge) public {\\n WETH_ADDRESS = _wethAddress;\\n baseSwap = _baseSwap;\\n synapseBridge = _synapseBridge;\\n IERC20(_wethAddress).safeIncreaseAllowance(address(_synapseBridge), MAX_UINT256);\\n if (address(_baseSwap) != address(0)) {\\n {\\n uint8 i;\\n for (; i < 32; i++) {\\n try _baseSwap.getToken(i) returns (IERC20 token) {\\n baseTokens.push(token);\\n token.safeIncreaseAllowance(address(_baseSwap), MAX_UINT256);\\n } catch {\\n break;\\n }\\n }\\n require(i > 1, 'baseSwap must have at least 2 tokens');\\n }\\n }\\n }\\n \\n /**\\n * @notice Wraps SynapseBridge deposit() function to make it compatible w/ ETH -> WETH conversions\\n * @param to address on other chain to bridge assets to\\n * @param chainId which chain to bridge assets onto\\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\\n **/\\n function depositETH(\\n address to,\\n uint256 chainId,\\n uint256 amount\\n ) external payable {\\n require(msg.value > 0 && msg.value == amount, 'INCORRECT MSG VALUE');\\n IWETH9(WETH_ADDRESS).deposit{value: msg.value}();\\n synapseBridge.deposit(to, chainId, IERC20(WETH_ADDRESS), amount);\\n }\\n\\n /**\\n * @notice Wraps SynapseBridge depositAndSwap() function to make it compatible w/ ETH -> WETH conversions\\n * @param to address on other chain to bridge assets to\\n * @param chainId which chain to bridge assets onto\\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\\n * @param tokenIndexFrom the token the user wants to swap from\\n * @param tokenIndexTo the token the user wants to swap to\\n * @param minDy the min amount the user would like to receive, or revert to only minting the SynERC20 token crosschain.\\n * @param deadline latest timestamp to accept this transaction\\n **/\\n function depositETHAndSwap(\\n address to,\\n uint256 chainId,\\n uint256 amount,\\n uint8 tokenIndexFrom,\\n uint8 tokenIndexTo,\\n uint256 minDy,\\n uint256 deadline\\n ) external payable {\\n require(msg.value > 0 && msg.value == amount, 'INCORRECT MSG VALUE');\\n IWETH9(WETH_ADDRESS).deposit{value: msg.value}();\\n synapseBridge.depositAndSwap(to, chainId, IERC20(WETH_ADDRESS), amount, tokenIndexFrom, tokenIndexTo, minDy, deadline);\\n }\\n\\n\\n /**\\n * @notice A simple method to calculate prices from deposits or\\n * withdrawals, excluding fees but including slippage. This is\\n * helpful as an input into the various \\\"min\\\" parameters on calls\\n * to fight front-running\\n *\\n * @dev This shouldn't be used outside frontends for user estimates.\\n *\\n * @param amounts an array of token amounts to deposit or withdrawal,\\n * corresponding to pooledTokens. The amount should be in each\\n * pooled token's native precision.\\n * @param deposit whether this is a deposit or a withdrawal\\n * @return token amount the user will receive\\n */\\n function calculateTokenAmount(uint256[] calldata amounts, bool deposit)\\n external\\n view\\n virtual\\n returns (uint256)\\n {\\n return baseSwap.calculateTokenAmount(amounts, deposit);\\n }\\n\\n /**\\n * @notice Calculate the amount of underlying token available to withdraw\\n * when withdrawing via only single token\\n * @param tokenAmount the amount of LP token to burn\\n * @param tokenIndex index of which token will be withdrawn\\n * @return availableTokenAmount calculated amount of underlying token\\n * available to withdraw\\n */\\n function calculateRemoveLiquidityOneToken(\\n uint256 tokenAmount,\\n uint8 tokenIndex\\n ) external view virtual returns (uint256 availableTokenAmount) {\\n return baseSwap.calculateRemoveLiquidityOneToken(tokenAmount, tokenIndex);\\n }\\n\\n\\n /**\\n * @notice Combines adding liquidity to the given Swap, and calls deposit() on the bridge using that LP token\\n * @param to address on other chain to bridge assets to\\n * @param chainId which chain to bridge assets onto\\n * @param token ERC20 compatible token to deposit into the bridge\\n * @param liquidityAmounts the amounts of each token to add, in their native precision\\n * @param minToMint the minimum LP tokens adding this amount of liquidity\\n * should mint, otherwise revert. Handy for front-running mitigation\\n * @param deadline latest timestamp to accept this transaction\\n **/\\n function zapAndDeposit(\\n address to,\\n uint256 chainId,\\n IERC20 token,\\n uint256[] calldata liquidityAmounts,\\n uint256 minToMint,\\n uint256 deadline\\n ) external {\\n // add liquidity\\n for (uint256 i = 0; i < baseTokens.length; i++) {\\n if (liquidityAmounts[i] != 0) {\\n baseTokens[i].safeTransferFrom(\\n msg.sender,\\n address(this),\\n liquidityAmounts[i]\\n );\\n }\\n }\\n\\n uint256 liqAdded = baseSwap.addLiquidity(\\n liquidityAmounts,\\n minToMint,\\n deadline\\n );\\n // deposit into bridge, gets nUSD\\n if (token.allowance(address(this), address(synapseBridge)) < liqAdded) {\\n token.safeApprove(address(synapseBridge), MAX_UINT256);\\n }\\n synapseBridge.deposit(to, chainId, token, liqAdded);\\n }\\n\\n /**\\n * @notice Combines adding liquidity to the given Swap, and calls depositAndSwap() on the bridge using that LP token\\n * @param to address on other chain to bridge assets to\\n * @param chainId which chain to bridge assets onto\\n * @param token ERC20 compatible token to deposit into the bridge\\n * @param liquidityAmounts the amounts of each token to add, in their native precision\\n * @param minToMint the minimum LP tokens adding this amount of liquidity\\n * should mint, otherwise revert. Handy for front-running mitigation\\n * @param liqDeadline latest timestamp to accept this transaction\\n * @param tokenIndexFrom the token the user wants to swap from\\n * @param tokenIndexTo the token the user wants to swap to\\n * @param minDy the min amount the user would like to receive, or revert to only minting the SynERC20 token crosschain.\\n * @param swapDeadline latest timestamp to accept this transaction\\n **/\\n function zapAndDepositAndSwap(\\n address to,\\n uint256 chainId,\\n IERC20 token,\\n uint256[] calldata liquidityAmounts,\\n uint256 minToMint,\\n uint256 liqDeadline,\\n uint8 tokenIndexFrom,\\n uint8 tokenIndexTo,\\n uint256 minDy,\\n uint256 swapDeadline\\n ) external {\\n // add liquidity\\n for (uint256 i = 0; i < baseTokens.length; i++) {\\n if (liquidityAmounts[i] != 0) {\\n baseTokens[i].safeTransferFrom(\\n msg.sender,\\n address(this),\\n liquidityAmounts[i]\\n );\\n }\\n }\\n\\n uint256 liqAdded = baseSwap.addLiquidity(\\n liquidityAmounts,\\n minToMint,\\n liqDeadline\\n );\\n // deposit into bridge, bridge attemps to swap into desired asset\\n if (token.allowance(address(this), address(synapseBridge)) < liqAdded) {\\n token.safeApprove(address(synapseBridge), MAX_UINT256);\\n }\\n synapseBridge.depositAndSwap(\\n to,\\n chainId,\\n token,\\n liqAdded,\\n tokenIndexFrom,\\n tokenIndexTo,\\n minDy,\\n swapDeadline\\n );\\n }\\n\\n /**\\n * @notice Wraps SynapseBridge deposit() function\\n * @param to address on other chain to bridge assets to\\n * @param chainId which chain to bridge assets onto\\n * @param token ERC20 compatible token to deposit into the bridge\\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\\n **/\\n function deposit(\\n address to,\\n uint256 chainId,\\n IERC20 token,\\n uint256 amount\\n ) external {\\n token.safeTransferFrom(msg.sender, address(this), amount);\\n\\n if (token.allowance(address(this), address(synapseBridge)) < amount) {\\n token.safeApprove(address(synapseBridge), MAX_UINT256);\\n }\\n synapseBridge.deposit(to, chainId, token, amount);\\n }\\n \\n /**\\n * @notice Wraps SynapseBridge depositAndSwap() function\\n * @param to address on other chain to bridge assets to\\n * @param chainId which chain to bridge assets onto\\n * @param token ERC20 compatible token to deposit into the bridge\\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\\n * @param tokenIndexFrom the token the user wants to swap from\\n * @param tokenIndexTo the token the user wants to swap to\\n * @param minDy the min amount the user would like to receive, or revert to only minting the SynERC20 token crosschain.\\n * @param deadline latest timestamp to accept this transaction\\n **/\\n function depositAndSwap(\\n address to,\\n uint256 chainId,\\n IERC20 token,\\n uint256 amount,\\n uint8 tokenIndexFrom,\\n uint8 tokenIndexTo,\\n uint256 minDy,\\n uint256 deadline\\n ) external {\\n token.safeTransferFrom(msg.sender, address(this), amount);\\n \\n if (token.allowance(address(this), address(synapseBridge)) < amount) {\\n token.safeApprove(address(synapseBridge), MAX_UINT256);\\n }\\n synapseBridge.depositAndSwap(to, chainId, token, amount, tokenIndexFrom, tokenIndexTo, minDy, deadline);\\n }\\n\\n\\n /**\\n * @notice Wraps SynapseBridge redeem() function\\n * @param to address on other chain to bridge assets to\\n * @param chainId which chain to bridge assets onto\\n * @param token ERC20 compatible token to redeem into the bridge\\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\\n **/\\n function redeem(\\n address to,\\n uint256 chainId,\\n IERC20 token,\\n uint256 amount\\n ) external {\\n token.safeTransferFrom(msg.sender, address(this), amount);\\n\\n if (token.allowance(address(this), address(synapseBridge)) < amount) {\\n token.safeApprove(address(synapseBridge), MAX_UINT256);\\n }\\n synapseBridge.redeem(to, chainId, token, amount);\\n }\\n\\n /**\\n * @notice Wraps redeemAndSwap on SynapseBridge.sol\\n * Relays to nodes that (typically) a wrapped synAsset ERC20 token has been burned and the underlying needs to be redeeemed on the native chain. This function indicates to the nodes that they should attempt to redeem the LP token for the underlying assets (E.g \\\"swap\\\" out of the LP token)\\n * @param to address on other chain to redeem underlying assets to\\n * @param chainId which underlying chain to bridge assets onto\\n * @param token ERC20 compatible token to deposit into the bridge\\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\\n * @param tokenIndexFrom the token the user wants to swap from\\n * @param tokenIndexTo the token the user wants to swap to\\n * @param minDy the min amount the user would like to receive, or revert to only minting the SynERC20 token crosschain.\\n * @param deadline latest timestamp to accept this transaction\\n **/\\n function redeemAndSwap(\\n address to,\\n uint256 chainId,\\n IERC20 token,\\n uint256 amount,\\n uint8 tokenIndexFrom,\\n uint8 tokenIndexTo,\\n uint256 minDy,\\n uint256 deadline\\n ) external {\\n token.safeTransferFrom(msg.sender, address(this), amount);\\n if (token.allowance(address(this), address(synapseBridge)) < amount) {\\n token.safeApprove(address(synapseBridge), MAX_UINT256);\\n }\\n synapseBridge.redeemAndSwap(\\n to,\\n chainId,\\n token,\\n amount,\\n tokenIndexFrom,\\n tokenIndexTo,\\n minDy,\\n deadline\\n );\\n }\\n\\n /**\\n * @notice Wraps redeemAndRemove on SynapseBridge\\n * Relays to nodes that (typically) a wrapped synAsset ERC20 token has been burned and the underlying needs to be redeeemed on the native chain. This function indicates to the nodes that they should attempt to redeem the LP token for the underlying assets (E.g \\\"swap\\\" out of the LP token)\\n * @param to address on other chain to redeem underlying assets to\\n * @param chainId which underlying chain to bridge assets onto\\n * @param token ERC20 compatible token to deposit into the bridge\\n * @param amount Amount of (typically) LP token to pass to the nodes to attempt to removeLiquidity() with to redeem for the underlying assets of the LP token\\n * @param liqTokenIndex Specifies which of the underlying LP assets the nodes should attempt to redeem for\\n * @param liqMinAmount Specifies the minimum amount of the underlying asset needed for the nodes to execute the redeem/swap\\n * @param liqDeadline Specificies the deadline that the nodes are allowed to try to redeem/swap the LP token\\n **/\\n function redeemAndRemove(\\n address to,\\n uint256 chainId,\\n IERC20 token,\\n uint256 amount,\\n uint8 liqTokenIndex,\\n uint256 liqMinAmount,\\n uint256 liqDeadline\\n ) external {\\n token.safeTransferFrom(msg.sender, address(this), amount);\\n if (token.allowance(address(this), address(synapseBridge)) < amount) {\\n token.safeApprove(address(synapseBridge), MAX_UINT256);\\n }\\n synapseBridge.redeemAndRemove(\\n to,\\n chainId,\\n token,\\n amount,\\n liqTokenIndex,\\n liqMinAmount,\\n liqDeadline\\n );\\n }\\n\\n\\n /**\\n * @notice Wraps SynapseBridge redeemv2() function\\n * @param to address on other chain to bridge assets to\\n * @param chainId which chain to bridge assets onto\\n * @param token ERC20 compatible token to redeem into the bridge\\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\\n **/\\n function redeemv2(\\n bytes32 to,\\n uint256 chainId,\\n IERC20 token,\\n uint256 amount\\n ) external {\\n token.safeTransferFrom(msg.sender, address(this), amount);\\n\\n if (token.allowance(address(this), address(synapseBridge)) < amount) {\\n token.safeApprove(address(synapseBridge), MAX_UINT256);\\n }\\n synapseBridge.redeemv2(to, chainId, token, amount);\\n }\\n\\n}\\n\",\"keccak256\":\"0x6e058e429d53a995ef2a468be3874950d594eddb0576c1e0fb291975fa5bf302\",\"license\":\"MIT\"}},\"version\":1}", + "bytecode": "0x60a06040523480156200001157600080fd5b506040516200275638038062002756833981810160405260608110156200003757600080fd5b5080516020808301516040909301516001600160601b0319606084901b16608052600080546001600160a01b038087166001600160a01b0319928316179092556001805483851692169190911790559293929091620000a891851690839060001990620018ab62000204821b17901c565b6001600160a01b03821615620001fb5760005b60208160ff161015620001b557826001600160a01b03166382b86600826040518263ffffffff1660e01b8152600401808260ff16815260200191505060206040518083038186803b1580156200011057600080fd5b505afa9250505080156200013757506040513d60208110156200013257600080fd5b505160015b6200014257620001b5565b600280546001810182556000919091527f405787fa12a823e0f2b7631cc41b3ba8828b3321ca811111fa75cd3aa3bb5ace0180546001600160a01b0319166001600160a01b038316908117909155620001ab908560001962000204602090811b620018ab17901c565b50600101620000bb565b60018160ff1611620001f95760405162461bcd60e51b8152600401808060200182810382526024815260200180620027086024913960400191505060405180910390fd5b505b50505062000661565b6000620002ab82856001600160a01b031663dd62ed3e30876040518363ffffffff1660e01b815260040180836001600160a01b03168152602001826001600160a01b031681526020019250505060206040518083038186803b1580156200026a57600080fd5b505afa1580156200027f573d6000803e3d6000fd5b505050506040513d60208110156200029657600080fd5b5051906200030d602090811b620019ca17901c565b604080516001600160a01b038616602482015260448082018490528251808303909101815260649091019091526020810180516001600160e01b0390811663095ea7b360e01b1790915291925062000307918691906200036f16565b50505050565b60008282018381101562000368576040805162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b9392505050565b6060620003cb826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b03166200043060201b62001a3e179092919060201c565b8051909150156200042b57808060200190516020811015620003ec57600080fd5b50516200042b5760405162461bcd60e51b815260040180806020018281038252602a8152602001806200272c602a913960400191505060405180910390fd5b505050565b606062000441848460008562000449565b949350505050565b6060824710156200048c5760405162461bcd60e51b8152600401808060200182810382526026815260200180620026e26026913960400191505060405180910390fd5b6200049785620005b1565b620004e9576040805162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000604482015290519081900360640190fd5b60006060866001600160a01b031685876040518082805190602001908083835b602083106200052a5780518252601f19909201916020918201910162000509565b6001836020036101000a03801982511681845116808217855250505050505090500191505060006040518083038185875af1925050503d80600081146200058e576040519150601f19603f3d011682016040523d82523d6000602084013e62000593565b606091505b509092509050620005a6828286620005b7565b979650505050505050565b3b151590565b60608315620005c857508162000368565b825115620005d95782518084602001fd5b8160405162461bcd60e51b81526004018080602001828103825283818151815260200191508051906020019080838360005b83811015620006255781810151838201526020016200060b565b50505050905090810190601f168015620006535780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b60805160601c61204f62000693600039806105e9528061139c528061144e528061154552806115f7525061204f6000f3fe6080604052600436106100dd5760003560e01c8063839ed90a1161007f578063a9fd8c5711610059578063a9fd8c571461049e578063ce0b63ce146104ef578063e6ab280614610521578063f3f094a1146105a0576100dd565b8063839ed90a1461038957806390d25074146103f0578063a2a2af0b14610437576100dd565b806336e712ed116100bb57806336e712ed14610182578063394023d9146101e057806349b7cf84146102825780638054ae3b146102c7576100dd565b8063040141e5146100e2578063328123a214610113578063342a87a11461013d575b600080fd5b3480156100ee57600080fd5b506100f76105e7565b604080516001600160a01b039092168252519081900360200190f35b34801561011f57600080fd5b506100f76004803603602081101561013657600080fd5b503561060b565b34801561014957600080fd5b506101706004803603604081101561016057600080fd5b508035906020013560ff16610632565b60408051918252519081900360200190f35b34801561018e57600080fd5b506101de600480360360e08110156101a557600080fd5b506001600160a01b0381358116916020810135916040820135169060608101359060ff6080820135169060a08101359060c001356106d4565b005b3480156101ec57600080fd5b506101de600480360360c081101561020357600080fd5b6001600160a01b03823581169260208101359260408201359092169181019060808101606082013564010000000081111561023d57600080fd5b82018360208201111561024f57600080fd5b8035906020019184602083028401116401000000008311171561027157600080fd5b919350915080359060200135610858565b34801561028e57600080fd5b506101de600480360360808110156102a557600080fd5b508035906020810135906001600160a01b036040820135169060600135610afc565b3480156102d357600080fd5b506101de60048036036101408110156102eb57600080fd5b6001600160a01b03823581169260208101359260408201359092169181019060808101606082013564010000000081111561032557600080fd5b82018360208201111561033757600080fd5b8035906020019184602083028401116401000000008311171561035957600080fd5b919350915080359060208101359060ff604082013581169160608101359091169060808101359060a00135610c65565b34801561039557600080fd5b506101de60048036036101008110156103ad57600080fd5b506001600160a01b0381358116916020810135916040820135169060608101359060ff608082013581169160a08101359091169060c08101359060e00135610efc565b3480156103fc57600080fd5b506101de6004803603608081101561041357600080fd5b506001600160a01b0381358116916020810135916040820135169060600135611068565b34801561044357600080fd5b506101de600480360361010081101561045b57600080fd5b506001600160a01b0381358116916020810135916040820135169060608101359060ff608082013581169160a08101359091169060c08101359060e001356111b4565b6101de600480360360e08110156104b457600080fd5b506001600160a01b038135169060208101359060408101359060ff606082013581169160808101359091169060a08101359060c00135611320565b6101de6004803603606081101561050557600080fd5b506001600160a01b0381351690602081013590604001356114c9565b34801561052d57600080fd5b506101706004803603604081101561054457600080fd5b81019060208101813564010000000081111561055f57600080fd5b82018360208201111561057157600080fd5b8035906020019184602083028401116401000000008311171561059357600080fd5b919350915035151561166f565b3480156105ac57600080fd5b506101de600480360360808110156105c357600080fd5b506001600160a01b038135811691602081013591604082013516906060013561175f565b7f000000000000000000000000000000000000000000000000000000000000000081565b6002818154811061061857fe5b6000918252602090912001546001600160a01b0316905081565b60008054604080517f342a87a10000000000000000000000000000000000000000000000000000000081526004810186905260ff8516602482015290516001600160a01b039092169163342a87a191604480820192602092909190829003018186803b1580156106a157600080fd5b505afa1580156106b5573d6000803e3d6000fd5b505050506040513d60208110156106cb57600080fd5b50519392505050565b6106e96001600160a01b038616333087611a55565b600154604080517fdd62ed3e0000000000000000000000000000000000000000000000000000000081523060048201526001600160a01b0392831660248201529051869288169163dd62ed3e916044808301926020929190829003018186803b15801561075557600080fd5b505afa158015610769573d6000803e3d6000fd5b505050506040513d602081101561077f57600080fd5b505110156107a3576001546107a3906001600160a01b038781169116600019611add565b600154604080517f36e712ed0000000000000000000000000000000000000000000000000000000081526001600160a01b038a81166004830152602482018a905288811660448301526064820188905260ff8716608483015260a4820186905260c48201859052915191909216916336e712ed9160e480830192600092919082900301818387803b15801561083757600080fd5b505af115801561084b573d6000803e3d6000fd5b5050505050505050505050565b60005b6002548110156108c95784848281811061087157fe5b905060200201356000146108c1576108c1333087878581811061089057fe5b90506020020135600285815481106108a457fe5b6000918252602090912001546001600160a01b0316929190611a55565b60010161085b565b50600080546040517f4d49e87d0000000000000000000000000000000000000000000000000000000081526024810185905260448101849052606060048201908152606482018790526001600160a01b0390921691634d49e87d9188918891889188918190608401866020870280828437600081840152601f19601f82011690508083019250505095505050505050602060405180830381600087803b15801561097257600080fd5b505af1158015610986573d6000803e3d6000fd5b505050506040513d602081101561099c57600080fd5b5051600154604080517fdd62ed3e0000000000000000000000000000000000000000000000000000000081523060048201526001600160a01b039283166024820152905192935083929189169163dd62ed3e91604480820192602092909190829003018186803b158015610a0f57600080fd5b505afa158015610a23573d6000803e3d6000fd5b505050506040513d6020811015610a3957600080fd5b50511015610a5d57600154610a5d906001600160a01b038881169116600019611add565b600154604080517f90d250740000000000000000000000000000000000000000000000000000000081526001600160a01b038b81166004830152602482018b9052898116604483015260648201859052915191909216916390d2507491608480830192600092919082900301818387803b158015610ada57600080fd5b505af1158015610aee573d6000803e3d6000fd5b505050505050505050505050565b610b116001600160a01b038316333084611a55565b600154604080517fdd62ed3e0000000000000000000000000000000000000000000000000000000081523060048201526001600160a01b0392831660248201529051839285169163dd62ed3e916044808301926020929190829003018186803b158015610b7d57600080fd5b505afa158015610b91573d6000803e3d6000fd5b505050506040513d6020811015610ba757600080fd5b50511015610bcb57600154610bcb906001600160a01b038481169116600019611add565b600154604080517f49b7cf8400000000000000000000000000000000000000000000000000000000815260048101879052602481018690526001600160a01b03858116604483015260648201859052915191909216916349b7cf8491608480830192600092919082900301818387803b158015610c4757600080fd5b505af1158015610c5b573d6000803e3d6000fd5b5050505050505050565b60005b600254811015610ca557888882818110610c7e57fe5b90506020020135600014610c9d57610c9d33308b8b8581811061089057fe5b600101610c68565b50600080546040517f4d49e87d0000000000000000000000000000000000000000000000000000000081526024810189905260448101889052606060048201908152606482018b90526001600160a01b0390921691634d49e87d918c918c918c918c918190608401866020870280828437600081840152601f19601f82011690508083019250505095505050505050602060405180830381600087803b158015610d4e57600080fd5b505af1158015610d62573d6000803e3d6000fd5b505050506040513d6020811015610d7857600080fd5b5051600154604080517fdd62ed3e0000000000000000000000000000000000000000000000000000000081523060048201526001600160a01b03928316602482015290519293508392918d169163dd62ed3e91604480820192602092909190829003018186803b158015610deb57600080fd5b505afa158015610dff573d6000803e3d6000fd5b505050506040513d6020811015610e1557600080fd5b50511015610e3957600154610e39906001600160a01b038c81169116600019611add565b600154604080517fa2a2af0b0000000000000000000000000000000000000000000000000000000081526001600160a01b038f81166004830152602482018f90528d811660448301526064820185905260ff808a166084840152881660a483015260c4820187905260e482018690529151919092169163a2a2af0b9161010480830192600092919082900301818387803b158015610ed657600080fd5b505af1158015610eea573d6000803e3d6000fd5b50505050505050505050505050505050565b610f116001600160a01b038716333088611a55565b600154604080517fdd62ed3e0000000000000000000000000000000000000000000000000000000081523060048201526001600160a01b0392831660248201529051879289169163dd62ed3e916044808301926020929190829003018186803b158015610f7d57600080fd5b505afa158015610f91573d6000803e3d6000fd5b505050506040513d6020811015610fa757600080fd5b50511015610fcb57600154610fcb906001600160a01b038881169116600019611add565b600154604080517f839ed90a0000000000000000000000000000000000000000000000000000000081526001600160a01b038b81166004830152602482018b905289811660448301526064820189905260ff8089166084840152871660a483015260c4820186905260e482018590529151919092169163839ed90a9161010480830192600092919082900301818387803b158015610ada57600080fd5b61107d6001600160a01b038316333084611a55565b600154604080517fdd62ed3e0000000000000000000000000000000000000000000000000000000081523060048201526001600160a01b0392831660248201529051839285169163dd62ed3e916044808301926020929190829003018186803b1580156110e957600080fd5b505afa1580156110fd573d6000803e3d6000fd5b505050506040513d602081101561111357600080fd5b5051101561113757600154611137906001600160a01b038481169116600019611add565b600154604080517f90d250740000000000000000000000000000000000000000000000000000000081526001600160a01b03878116600483015260248201879052858116604483015260648201859052915191909216916390d2507491608480830192600092919082900301818387803b158015610c4757600080fd5b6111c96001600160a01b038716333088611a55565b600154604080517fdd62ed3e0000000000000000000000000000000000000000000000000000000081523060048201526001600160a01b0392831660248201529051879289169163dd62ed3e916044808301926020929190829003018186803b15801561123557600080fd5b505afa158015611249573d6000803e3d6000fd5b505050506040513d602081101561125f57600080fd5b5051101561128357600154611283906001600160a01b038881169116600019611add565b600154604080517fa2a2af0b0000000000000000000000000000000000000000000000000000000081526001600160a01b038b81166004830152602482018b905289811660448301526064820189905260ff8089166084840152871660a483015260c4820186905260e482018590529151919092169163a2a2af0b9161010480830192600092919082900301818387803b158015610ada57600080fd5b60003411801561132f57508434145b61139a57604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f494e434f5252454354204d53472056414c554500000000000000000000000000604482015290519081900360640190fd5b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663d0e30db0346040518263ffffffff1660e01b81526004016000604051808303818588803b1580156113f557600080fd5b505af1158015611409573d6000803e3d6000fd5b5050600154604080517fa2a2af0b0000000000000000000000000000000000000000000000000000000081526001600160a01b038d81166004830152602482018d90527f000000000000000000000000000000000000000000000000000000000000000081166044830152606482018c905260ff808c1660848401528a1660a483015260c4820189905260e48201889052915191909216945063a2a2af0b9350610104808301935060009282900301818387803b15801561083757600080fd5b6000341180156114d857508034145b61154357604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f494e434f5252454354204d53472056414c554500000000000000000000000000604482015290519081900360640190fd5b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663d0e30db0346040518263ffffffff1660e01b81526004016000604051808303818588803b15801561159e57600080fd5b505af11580156115b2573d6000803e3d6000fd5b5050600154604080517f90d250740000000000000000000000000000000000000000000000000000000081526001600160a01b038981166004830152602482018990527f0000000000000000000000000000000000000000000000000000000000000000811660448301526064820188905291519190921694506390d2507493506084808301935060009282900301818387803b15801561165257600080fd5b505af1158015611666573d6000803e3d6000fd5b50505050505050565b60008054604080517fe6ab2806000000000000000000000000000000000000000000000000000000008152841515602482015260048101918252604481018690526001600160a01b039092169163e6ab2806918791879187918190606401856020860280828437600083820152604051601f9091017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016909201965060209550909350505081840390508186803b15801561172957600080fd5b505afa15801561173d573d6000803e3d6000fd5b505050506040513d602081101561175357600080fd5b505190505b9392505050565b6117746001600160a01b038316333084611a55565b600154604080517fdd62ed3e0000000000000000000000000000000000000000000000000000000081523060048201526001600160a01b0392831660248201529051839285169163dd62ed3e916044808301926020929190829003018186803b1580156117e057600080fd5b505afa1580156117f4573d6000803e3d6000fd5b505050506040513d602081101561180a57600080fd5b5051101561182e5760015461182e906001600160a01b038481169116600019611add565b600154604080517ff3f094a10000000000000000000000000000000000000000000000000000000081526001600160a01b038781166004830152602482018790528581166044830152606482018590529151919092169163f3f094a191608480830192600092919082900301818387803b158015610c4757600080fd5b600061194182856001600160a01b031663dd62ed3e30876040518363ffffffff1660e01b815260040180836001600160a01b03168152602001826001600160a01b031681526020019250505060206040518083038186803b15801561190f57600080fd5b505afa158015611923573d6000803e3d6000fd5b505050506040513d602081101561193957600080fd5b5051906119ca565b604080516001600160a01b038616602482015260448082018490528251808303909101815260649091019091526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f095ea7b3000000000000000000000000000000000000000000000000000000001790529091506119c4908590611c56565b50505050565b60008282018381101561175857604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b6060611a4d8484600085611d21565b949350505050565b604080516001600160a01b0380861660248301528416604482015260648082018490528251808303909101815260849091019091526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f23b872dd000000000000000000000000000000000000000000000000000000001790526119c4908590611c56565b801580611b7c5750604080517fdd62ed3e0000000000000000000000000000000000000000000000000000000081523060048201526001600160a01b03848116602483015291519185169163dd62ed3e91604480820192602092909190829003018186803b158015611b4e57600080fd5b505afa158015611b62573d6000803e3d6000fd5b505050506040513d6020811015611b7857600080fd5b5051155b611bd1576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526036815260200180611fe46036913960400191505060405180910390fd5b604080516001600160a01b038416602482015260448082018490528251808303909101815260649091019091526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f095ea7b300000000000000000000000000000000000000000000000000000000179052611c51908490611c56565b505050565b6060611cab826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b0316611a3e9092919063ffffffff16565b805190915015611c5157808060200190516020811015611cca57600080fd5b5051611c51576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602a815260200180611fba602a913960400191505060405180910390fd5b606082471015611d7c576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526026815260200180611f946026913960400191505060405180910390fd5b611d8585611ecf565b611df057604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000604482015290519081900360640190fd5b60006060866001600160a01b031685876040518082805190602001908083835b60208310611e4d57805182527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe09092019160209182019101611e10565b6001836020036101000a03801982511681845116808217855250505050505090500191505060006040518083038185875af1925050503d8060008114611eaf576040519150601f19603f3d011682016040523d82523d6000602084013e611eb4565b606091505b5091509150611ec4828286611ed5565b979650505050505050565b3b151590565b60608315611ee4575081611758565b825115611ef45782518084602001fd5b816040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825283818151815260200191508051906020019080838360005b83811015611f58578181015183820152602001611f40565b50505050905090810190601f168015611f855780820380516001836020036101000a031916815260200191505b509250505060405180910390fdfe416464726573733a20696e73756666696369656e742062616c616e636520666f722063616c6c5361666545524332303a204552433230206f7065726174696f6e20646964206e6f7420737563636565645361666545524332303a20617070726f76652066726f6d206e6f6e2d7a65726f20746f206e6f6e2d7a65726f20616c6c6f77616e6365a2646970667358221220368ae9593dac9c8c71cbdb9d7e6e44b1e9cd5534accc570cb6daa218ba6b2ef864736f6c634300060c0033416464726573733a20696e73756666696369656e742062616c616e636520666f722063616c6c6261736553776170206d7573742068617665206174206c65617374203220746f6b656e735361666545524332303a204552433230206f7065726174696f6e20646964206e6f742073756363656564", + "deployedBytecode": "0x6080604052600436106100dd5760003560e01c8063839ed90a1161007f578063a9fd8c5711610059578063a9fd8c571461049e578063ce0b63ce146104ef578063e6ab280614610521578063f3f094a1146105a0576100dd565b8063839ed90a1461038957806390d25074146103f0578063a2a2af0b14610437576100dd565b806336e712ed116100bb57806336e712ed14610182578063394023d9146101e057806349b7cf84146102825780638054ae3b146102c7576100dd565b8063040141e5146100e2578063328123a214610113578063342a87a11461013d575b600080fd5b3480156100ee57600080fd5b506100f76105e7565b604080516001600160a01b039092168252519081900360200190f35b34801561011f57600080fd5b506100f76004803603602081101561013657600080fd5b503561060b565b34801561014957600080fd5b506101706004803603604081101561016057600080fd5b508035906020013560ff16610632565b60408051918252519081900360200190f35b34801561018e57600080fd5b506101de600480360360e08110156101a557600080fd5b506001600160a01b0381358116916020810135916040820135169060608101359060ff6080820135169060a08101359060c001356106d4565b005b3480156101ec57600080fd5b506101de600480360360c081101561020357600080fd5b6001600160a01b03823581169260208101359260408201359092169181019060808101606082013564010000000081111561023d57600080fd5b82018360208201111561024f57600080fd5b8035906020019184602083028401116401000000008311171561027157600080fd5b919350915080359060200135610858565b34801561028e57600080fd5b506101de600480360360808110156102a557600080fd5b508035906020810135906001600160a01b036040820135169060600135610afc565b3480156102d357600080fd5b506101de60048036036101408110156102eb57600080fd5b6001600160a01b03823581169260208101359260408201359092169181019060808101606082013564010000000081111561032557600080fd5b82018360208201111561033757600080fd5b8035906020019184602083028401116401000000008311171561035957600080fd5b919350915080359060208101359060ff604082013581169160608101359091169060808101359060a00135610c65565b34801561039557600080fd5b506101de60048036036101008110156103ad57600080fd5b506001600160a01b0381358116916020810135916040820135169060608101359060ff608082013581169160a08101359091169060c08101359060e00135610efc565b3480156103fc57600080fd5b506101de6004803603608081101561041357600080fd5b506001600160a01b0381358116916020810135916040820135169060600135611068565b34801561044357600080fd5b506101de600480360361010081101561045b57600080fd5b506001600160a01b0381358116916020810135916040820135169060608101359060ff608082013581169160a08101359091169060c08101359060e001356111b4565b6101de600480360360e08110156104b457600080fd5b506001600160a01b038135169060208101359060408101359060ff606082013581169160808101359091169060a08101359060c00135611320565b6101de6004803603606081101561050557600080fd5b506001600160a01b0381351690602081013590604001356114c9565b34801561052d57600080fd5b506101706004803603604081101561054457600080fd5b81019060208101813564010000000081111561055f57600080fd5b82018360208201111561057157600080fd5b8035906020019184602083028401116401000000008311171561059357600080fd5b919350915035151561166f565b3480156105ac57600080fd5b506101de600480360360808110156105c357600080fd5b506001600160a01b038135811691602081013591604082013516906060013561175f565b7f000000000000000000000000000000000000000000000000000000000000000081565b6002818154811061061857fe5b6000918252602090912001546001600160a01b0316905081565b60008054604080517f342a87a10000000000000000000000000000000000000000000000000000000081526004810186905260ff8516602482015290516001600160a01b039092169163342a87a191604480820192602092909190829003018186803b1580156106a157600080fd5b505afa1580156106b5573d6000803e3d6000fd5b505050506040513d60208110156106cb57600080fd5b50519392505050565b6106e96001600160a01b038616333087611a55565b600154604080517fdd62ed3e0000000000000000000000000000000000000000000000000000000081523060048201526001600160a01b0392831660248201529051869288169163dd62ed3e916044808301926020929190829003018186803b15801561075557600080fd5b505afa158015610769573d6000803e3d6000fd5b505050506040513d602081101561077f57600080fd5b505110156107a3576001546107a3906001600160a01b038781169116600019611add565b600154604080517f36e712ed0000000000000000000000000000000000000000000000000000000081526001600160a01b038a81166004830152602482018a905288811660448301526064820188905260ff8716608483015260a4820186905260c48201859052915191909216916336e712ed9160e480830192600092919082900301818387803b15801561083757600080fd5b505af115801561084b573d6000803e3d6000fd5b5050505050505050505050565b60005b6002548110156108c95784848281811061087157fe5b905060200201356000146108c1576108c1333087878581811061089057fe5b90506020020135600285815481106108a457fe5b6000918252602090912001546001600160a01b0316929190611a55565b60010161085b565b50600080546040517f4d49e87d0000000000000000000000000000000000000000000000000000000081526024810185905260448101849052606060048201908152606482018790526001600160a01b0390921691634d49e87d9188918891889188918190608401866020870280828437600081840152601f19601f82011690508083019250505095505050505050602060405180830381600087803b15801561097257600080fd5b505af1158015610986573d6000803e3d6000fd5b505050506040513d602081101561099c57600080fd5b5051600154604080517fdd62ed3e0000000000000000000000000000000000000000000000000000000081523060048201526001600160a01b039283166024820152905192935083929189169163dd62ed3e91604480820192602092909190829003018186803b158015610a0f57600080fd5b505afa158015610a23573d6000803e3d6000fd5b505050506040513d6020811015610a3957600080fd5b50511015610a5d57600154610a5d906001600160a01b038881169116600019611add565b600154604080517f90d250740000000000000000000000000000000000000000000000000000000081526001600160a01b038b81166004830152602482018b9052898116604483015260648201859052915191909216916390d2507491608480830192600092919082900301818387803b158015610ada57600080fd5b505af1158015610aee573d6000803e3d6000fd5b505050505050505050505050565b610b116001600160a01b038316333084611a55565b600154604080517fdd62ed3e0000000000000000000000000000000000000000000000000000000081523060048201526001600160a01b0392831660248201529051839285169163dd62ed3e916044808301926020929190829003018186803b158015610b7d57600080fd5b505afa158015610b91573d6000803e3d6000fd5b505050506040513d6020811015610ba757600080fd5b50511015610bcb57600154610bcb906001600160a01b038481169116600019611add565b600154604080517f49b7cf8400000000000000000000000000000000000000000000000000000000815260048101879052602481018690526001600160a01b03858116604483015260648201859052915191909216916349b7cf8491608480830192600092919082900301818387803b158015610c4757600080fd5b505af1158015610c5b573d6000803e3d6000fd5b5050505050505050565b60005b600254811015610ca557888882818110610c7e57fe5b90506020020135600014610c9d57610c9d33308b8b8581811061089057fe5b600101610c68565b50600080546040517f4d49e87d0000000000000000000000000000000000000000000000000000000081526024810189905260448101889052606060048201908152606482018b90526001600160a01b0390921691634d49e87d918c918c918c918c918190608401866020870280828437600081840152601f19601f82011690508083019250505095505050505050602060405180830381600087803b158015610d4e57600080fd5b505af1158015610d62573d6000803e3d6000fd5b505050506040513d6020811015610d7857600080fd5b5051600154604080517fdd62ed3e0000000000000000000000000000000000000000000000000000000081523060048201526001600160a01b03928316602482015290519293508392918d169163dd62ed3e91604480820192602092909190829003018186803b158015610deb57600080fd5b505afa158015610dff573d6000803e3d6000fd5b505050506040513d6020811015610e1557600080fd5b50511015610e3957600154610e39906001600160a01b038c81169116600019611add565b600154604080517fa2a2af0b0000000000000000000000000000000000000000000000000000000081526001600160a01b038f81166004830152602482018f90528d811660448301526064820185905260ff808a166084840152881660a483015260c4820187905260e482018690529151919092169163a2a2af0b9161010480830192600092919082900301818387803b158015610ed657600080fd5b505af1158015610eea573d6000803e3d6000fd5b50505050505050505050505050505050565b610f116001600160a01b038716333088611a55565b600154604080517fdd62ed3e0000000000000000000000000000000000000000000000000000000081523060048201526001600160a01b0392831660248201529051879289169163dd62ed3e916044808301926020929190829003018186803b158015610f7d57600080fd5b505afa158015610f91573d6000803e3d6000fd5b505050506040513d6020811015610fa757600080fd5b50511015610fcb57600154610fcb906001600160a01b038881169116600019611add565b600154604080517f839ed90a0000000000000000000000000000000000000000000000000000000081526001600160a01b038b81166004830152602482018b905289811660448301526064820189905260ff8089166084840152871660a483015260c4820186905260e482018590529151919092169163839ed90a9161010480830192600092919082900301818387803b158015610ada57600080fd5b61107d6001600160a01b038316333084611a55565b600154604080517fdd62ed3e0000000000000000000000000000000000000000000000000000000081523060048201526001600160a01b0392831660248201529051839285169163dd62ed3e916044808301926020929190829003018186803b1580156110e957600080fd5b505afa1580156110fd573d6000803e3d6000fd5b505050506040513d602081101561111357600080fd5b5051101561113757600154611137906001600160a01b038481169116600019611add565b600154604080517f90d250740000000000000000000000000000000000000000000000000000000081526001600160a01b03878116600483015260248201879052858116604483015260648201859052915191909216916390d2507491608480830192600092919082900301818387803b158015610c4757600080fd5b6111c96001600160a01b038716333088611a55565b600154604080517fdd62ed3e0000000000000000000000000000000000000000000000000000000081523060048201526001600160a01b0392831660248201529051879289169163dd62ed3e916044808301926020929190829003018186803b15801561123557600080fd5b505afa158015611249573d6000803e3d6000fd5b505050506040513d602081101561125f57600080fd5b5051101561128357600154611283906001600160a01b038881169116600019611add565b600154604080517fa2a2af0b0000000000000000000000000000000000000000000000000000000081526001600160a01b038b81166004830152602482018b905289811660448301526064820189905260ff8089166084840152871660a483015260c4820186905260e482018590529151919092169163a2a2af0b9161010480830192600092919082900301818387803b158015610ada57600080fd5b60003411801561132f57508434145b61139a57604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f494e434f5252454354204d53472056414c554500000000000000000000000000604482015290519081900360640190fd5b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663d0e30db0346040518263ffffffff1660e01b81526004016000604051808303818588803b1580156113f557600080fd5b505af1158015611409573d6000803e3d6000fd5b5050600154604080517fa2a2af0b0000000000000000000000000000000000000000000000000000000081526001600160a01b038d81166004830152602482018d90527f000000000000000000000000000000000000000000000000000000000000000081166044830152606482018c905260ff808c1660848401528a1660a483015260c4820189905260e48201889052915191909216945063a2a2af0b9350610104808301935060009282900301818387803b15801561083757600080fd5b6000341180156114d857508034145b61154357604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f494e434f5252454354204d53472056414c554500000000000000000000000000604482015290519081900360640190fd5b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663d0e30db0346040518263ffffffff1660e01b81526004016000604051808303818588803b15801561159e57600080fd5b505af11580156115b2573d6000803e3d6000fd5b5050600154604080517f90d250740000000000000000000000000000000000000000000000000000000081526001600160a01b038981166004830152602482018990527f0000000000000000000000000000000000000000000000000000000000000000811660448301526064820188905291519190921694506390d2507493506084808301935060009282900301818387803b15801561165257600080fd5b505af1158015611666573d6000803e3d6000fd5b50505050505050565b60008054604080517fe6ab2806000000000000000000000000000000000000000000000000000000008152841515602482015260048101918252604481018690526001600160a01b039092169163e6ab2806918791879187918190606401856020860280828437600083820152604051601f9091017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016909201965060209550909350505081840390508186803b15801561172957600080fd5b505afa15801561173d573d6000803e3d6000fd5b505050506040513d602081101561175357600080fd5b505190505b9392505050565b6117746001600160a01b038316333084611a55565b600154604080517fdd62ed3e0000000000000000000000000000000000000000000000000000000081523060048201526001600160a01b0392831660248201529051839285169163dd62ed3e916044808301926020929190829003018186803b1580156117e057600080fd5b505afa1580156117f4573d6000803e3d6000fd5b505050506040513d602081101561180a57600080fd5b5051101561182e5760015461182e906001600160a01b038481169116600019611add565b600154604080517ff3f094a10000000000000000000000000000000000000000000000000000000081526001600160a01b038781166004830152602482018790528581166044830152606482018590529151919092169163f3f094a191608480830192600092919082900301818387803b158015610c4757600080fd5b600061194182856001600160a01b031663dd62ed3e30876040518363ffffffff1660e01b815260040180836001600160a01b03168152602001826001600160a01b031681526020019250505060206040518083038186803b15801561190f57600080fd5b505afa158015611923573d6000803e3d6000fd5b505050506040513d602081101561193957600080fd5b5051906119ca565b604080516001600160a01b038616602482015260448082018490528251808303909101815260649091019091526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f095ea7b3000000000000000000000000000000000000000000000000000000001790529091506119c4908590611c56565b50505050565b60008282018381101561175857604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b6060611a4d8484600085611d21565b949350505050565b604080516001600160a01b0380861660248301528416604482015260648082018490528251808303909101815260849091019091526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f23b872dd000000000000000000000000000000000000000000000000000000001790526119c4908590611c56565b801580611b7c5750604080517fdd62ed3e0000000000000000000000000000000000000000000000000000000081523060048201526001600160a01b03848116602483015291519185169163dd62ed3e91604480820192602092909190829003018186803b158015611b4e57600080fd5b505afa158015611b62573d6000803e3d6000fd5b505050506040513d6020811015611b7857600080fd5b5051155b611bd1576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526036815260200180611fe46036913960400191505060405180910390fd5b604080516001600160a01b038416602482015260448082018490528251808303909101815260649091019091526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f095ea7b300000000000000000000000000000000000000000000000000000000179052611c51908490611c56565b505050565b6060611cab826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b0316611a3e9092919063ffffffff16565b805190915015611c5157808060200190516020811015611cca57600080fd5b5051611c51576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602a815260200180611fba602a913960400191505060405180910390fd5b606082471015611d7c576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526026815260200180611f946026913960400191505060405180910390fd5b611d8585611ecf565b611df057604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000604482015290519081900360640190fd5b60006060866001600160a01b031685876040518082805190602001908083835b60208310611e4d57805182527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe09092019160209182019101611e10565b6001836020036101000a03801982511681845116808217855250505050505090500191505060006040518083038185875af1925050503d8060008114611eaf576040519150601f19603f3d011682016040523d82523d6000602084013e611eb4565b606091505b5091509150611ec4828286611ed5565b979650505050505050565b3b151590565b60608315611ee4575081611758565b825115611ef45782518084602001fd5b816040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825283818151815260200191508051906020019080838360005b83811015611f58578181015183820152602001611f40565b50505050905090810190601f168015611f855780820380516001836020036101000a031916815260200191505b509250505060405180910390fdfe416464726573733a20696e73756666696369656e742062616c616e636520666f722063616c6c5361666545524332303a204552433230206f7065726174696f6e20646964206e6f7420737563636565645361666545524332303a20617070726f76652066726f6d206e6f6e2d7a65726f20746f206e6f6e2d7a65726f20616c6c6f77616e6365a2646970667358221220368ae9593dac9c8c71cbdb9d7e6e44b1e9cd5534accc570cb6daa218ba6b2ef864736f6c634300060c0033", + "devdoc": { + "details": "This contract should be deployed with a base Swap.sol address and a SynapseBridge.sol address, otherwise, it will not function.", + "kind": "dev", + "methods": { + "calculateRemoveLiquidityOneToken(uint256,uint8)": { + "params": { + "tokenAmount": "the amount of LP token to burn", + "tokenIndex": "index of which token will be withdrawn" + }, + "returns": { + "availableTokenAmount": "calculated amount of underlying token available to withdraw" + } + }, + "calculateTokenAmount(uint256[],bool)": { + "details": "This shouldn't be used outside frontends for user estimates.", + "params": { + "amounts": "an array of token amounts to deposit or withdrawal, corresponding to pooledTokens. The amount should be in each pooled token's native precision.", + "deposit": "whether this is a deposit or a withdrawal" + }, + "returns": { + "_0": "token amount the user will receive" + } + }, + "deposit(address,uint256,address,uint256)": { + "params": { + "amount": "Amount in native token decimals to transfer cross-chain pre-fees*", + "chainId": "which chain to bridge assets onto", + "to": "address on other chain to bridge assets to", + "token": "ERC20 compatible token to deposit into the bridge" + } + }, + "depositAndSwap(address,uint256,address,uint256,uint8,uint8,uint256,uint256)": { + "params": { + "amount": "Amount in native token decimals to transfer cross-chain pre-fees", + "chainId": "which chain to bridge assets onto", + "deadline": "latest timestamp to accept this transaction*", + "minDy": "the min amount the user would like to receive, or revert to only minting the SynERC20 token crosschain.", + "to": "address on other chain to bridge assets to", + "token": "ERC20 compatible token to deposit into the bridge", + "tokenIndexFrom": "the token the user wants to swap from", + "tokenIndexTo": "the token the user wants to swap to" + } + }, + "depositETH(address,uint256,uint256)": { + "params": { + "amount": "Amount in native token decimals to transfer cross-chain pre-fees*", + "chainId": "which chain to bridge assets onto", + "to": "address on other chain to bridge assets to" + } + }, + "depositETHAndSwap(address,uint256,uint256,uint8,uint8,uint256,uint256)": { + "params": { + "amount": "Amount in native token decimals to transfer cross-chain pre-fees", + "chainId": "which chain to bridge assets onto", + "deadline": "latest timestamp to accept this transaction*", + "minDy": "the min amount the user would like to receive, or revert to only minting the SynERC20 token crosschain.", + "to": "address on other chain to bridge assets to", + "tokenIndexFrom": "the token the user wants to swap from", + "tokenIndexTo": "the token the user wants to swap to" + } + }, + "redeem(address,uint256,address,uint256)": { + "params": { + "amount": "Amount in native token decimals to transfer cross-chain pre-fees*", + "chainId": "which chain to bridge assets onto", + "to": "address on other chain to bridge assets to", + "token": "ERC20 compatible token to redeem into the bridge" + } + }, + "redeemAndRemove(address,uint256,address,uint256,uint8,uint256,uint256)": { + "params": { + "amount": "Amount of (typically) LP token to pass to the nodes to attempt to removeLiquidity() with to redeem for the underlying assets of the LP token", + "chainId": "which underlying chain to bridge assets onto", + "liqDeadline": "Specificies the deadline that the nodes are allowed to try to redeem/swap the LP token*", + "liqMinAmount": "Specifies the minimum amount of the underlying asset needed for the nodes to execute the redeem/swap", + "liqTokenIndex": "Specifies which of the underlying LP assets the nodes should attempt to redeem for", + "to": "address on other chain to redeem underlying assets to", + "token": "ERC20 compatible token to deposit into the bridge" + } + }, + "redeemAndSwap(address,uint256,address,uint256,uint8,uint8,uint256,uint256)": { + "params": { + "amount": "Amount in native token decimals to transfer cross-chain pre-fees", + "chainId": "which underlying chain to bridge assets onto", + "deadline": "latest timestamp to accept this transaction*", + "minDy": "the min amount the user would like to receive, or revert to only minting the SynERC20 token crosschain.", + "to": "address on other chain to redeem underlying assets to", + "token": "ERC20 compatible token to deposit into the bridge", + "tokenIndexFrom": "the token the user wants to swap from", + "tokenIndexTo": "the token the user wants to swap to" + } + }, + "redeemv2(bytes32,uint256,address,uint256)": { + "params": { + "amount": "Amount in native token decimals to transfer cross-chain pre-fees*", + "chainId": "which chain to bridge assets onto", + "to": "address on other chain to bridge assets to", + "token": "ERC20 compatible token to redeem into the bridge" + } + }, + "zapAndDeposit(address,uint256,address,uint256[],uint256,uint256)": { + "params": { + "chainId": "which chain to bridge assets onto", + "deadline": "latest timestamp to accept this transaction*", + "liquidityAmounts": "the amounts of each token to add, in their native precision", + "minToMint": "the minimum LP tokens adding this amount of liquidity should mint, otherwise revert. Handy for front-running mitigation", + "to": "address on other chain to bridge assets to", + "token": "ERC20 compatible token to deposit into the bridge" + } + }, + "zapAndDepositAndSwap(address,uint256,address,uint256[],uint256,uint256,uint8,uint8,uint256,uint256)": { + "params": { + "chainId": "which chain to bridge assets onto", + "liqDeadline": "latest timestamp to accept this transaction", + "liquidityAmounts": "the amounts of each token to add, in their native precision", + "minDy": "the min amount the user would like to receive, or revert to only minting the SynERC20 token crosschain.", + "minToMint": "the minimum LP tokens adding this amount of liquidity should mint, otherwise revert. Handy for front-running mitigation", + "swapDeadline": "latest timestamp to accept this transaction*", + "to": "address on other chain to bridge assets to", + "token": "ERC20 compatible token to deposit into the bridge", + "tokenIndexFrom": "the token the user wants to swap from", + "tokenIndexTo": "the token the user wants to swap to" + } + } + }, + "title": "L1BridgeZap", + "version": 1 + }, + "userdoc": { + "kind": "user", + "methods": { + "calculateRemoveLiquidityOneToken(uint256,uint8)": { + "notice": "Calculate the amount of underlying token available to withdraw when withdrawing via only single token" + }, + "calculateTokenAmount(uint256[],bool)": { + "notice": "A simple method to calculate prices from deposits or withdrawals, excluding fees but including slippage. This is helpful as an input into the various \"min\" parameters on calls to fight front-running" + }, + "constructor": "Constructs the contract, approves each token inside of baseSwap to be used by baseSwap (needed for addLiquidity())", + "deposit(address,uint256,address,uint256)": { + "notice": "Wraps SynapseBridge deposit() function" + }, + "depositAndSwap(address,uint256,address,uint256,uint8,uint8,uint256,uint256)": { + "notice": "Wraps SynapseBridge depositAndSwap() function" + }, + "depositETH(address,uint256,uint256)": { + "notice": "Wraps SynapseBridge deposit() function to make it compatible w/ ETH -> WETH conversions" + }, + "depositETHAndSwap(address,uint256,uint256,uint8,uint8,uint256,uint256)": { + "notice": "Wraps SynapseBridge depositAndSwap() function to make it compatible w/ ETH -> WETH conversions" + }, + "redeem(address,uint256,address,uint256)": { + "notice": "Wraps SynapseBridge redeem() function" + }, + "redeemAndRemove(address,uint256,address,uint256,uint8,uint256,uint256)": { + "notice": "Wraps redeemAndRemove on SynapseBridge Relays to nodes that (typically) a wrapped synAsset ERC20 token has been burned and the underlying needs to be redeeemed on the native chain. This function indicates to the nodes that they should attempt to redeem the LP token for the underlying assets (E.g \"swap\" out of the LP token)" + }, + "redeemAndSwap(address,uint256,address,uint256,uint8,uint8,uint256,uint256)": { + "notice": "Wraps redeemAndSwap on SynapseBridge.sol Relays to nodes that (typically) a wrapped synAsset ERC20 token has been burned and the underlying needs to be redeeemed on the native chain. This function indicates to the nodes that they should attempt to redeem the LP token for the underlying assets (E.g \"swap\" out of the LP token)" + }, + "redeemv2(bytes32,uint256,address,uint256)": { + "notice": "Wraps SynapseBridge redeemv2() function" + }, + "zapAndDeposit(address,uint256,address,uint256[],uint256,uint256)": { + "notice": "Combines adding liquidity to the given Swap, and calls deposit() on the bridge using that LP token" + }, + "zapAndDepositAndSwap(address,uint256,address,uint256[],uint256,uint256,uint8,uint8,uint256,uint256)": { + "notice": "Combines adding liquidity to the given Swap, and calls depositAndSwap() on the bridge using that LP token" + } + }, + "notice": "This contract is responsible for handling user Zaps into the SynapseBridge contract, through the Synapse Swap contracts. It does so It does so by combining the action of addLiquidity() to the base swap pool, and then calling either deposit() or depositAndSwap() on the bridge. This is done in hopes of automating portions of the bridge user experience to users, while keeping the SynapseBridge contract logic small.", + "version": 1 + }, + "storageLayout": { + "storage": [ + { + "astId": 23194, + "contract": "contracts/bridge/wrappers/L1BridgeZap.sol:L1BridgeZap", + "label": "baseSwap", + "offset": 0, + "slot": "0", + "type": "t_contract(ISwap)20874" + }, + { + "astId": 23196, + "contract": "contracts/bridge/wrappers/L1BridgeZap.sol:L1BridgeZap", + "label": "synapseBridge", + "offset": 0, + "slot": "1", + "type": "t_contract(ISynapseBridge)20970" + }, + { + "astId": 23199, + "contract": "contracts/bridge/wrappers/L1BridgeZap.sol:L1BridgeZap", + "label": "baseTokens", + "offset": 0, + "slot": "2", + "type": "t_array(t_contract(IERC20)4954)dyn_storage" + } + ], + "types": { + "t_array(t_contract(IERC20)4954)dyn_storage": { + "base": "t_contract(IERC20)4954", + "encoding": "dynamic_array", + "label": "contract IERC20[]", + "numberOfBytes": "32" + }, + "t_contract(IERC20)4954": { + "encoding": "inplace", + "label": "contract IERC20", + "numberOfBytes": "20" + }, + "t_contract(ISwap)20874": { + "encoding": "inplace", + "label": "contract ISwap", + "numberOfBytes": "20" + }, + "t_contract(ISynapseBridge)20970": { + "encoding": "inplace", + "label": "contract ISynapseBridge", + "numberOfBytes": "20" + } + } + } +} \ No newline at end of file diff --git a/deployments/dfk/L2BridgeZap.json b/deployments/dfk/L2BridgeZap.json new file mode 100644 index 000000000..bc4267182 --- /dev/null +++ b/deployments/dfk/L2BridgeZap.json @@ -0,0 +1,814 @@ +{ + "address": "0x33d90B6ce7e0bFC42BCD35d05c443c6915296987", + "abi": [ + { + "inputs": [ + { + "internalType": "address payable", + "name": "_wethAddress", + "type": "address" + }, + { + "internalType": "address", + "name": "_swapOne", + "type": "address" + }, + { + "internalType": "address", + "name": "tokenOne", + "type": "address" + }, + { + "internalType": "address", + "name": "_swapTwo", + "type": "address" + }, + { + "internalType": "address", + "name": "tokenTwo", + "type": "address" + }, + { + "internalType": "contract ISynapseBridge", + "name": "_synapseBridge", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [], + "name": "WETH_ADDRESS", + "outputs": [ + { + "internalType": "address payable", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract IERC20", + "name": "token", + "type": "address" + }, + { + "internalType": "uint8", + "name": "tokenIndexFrom", + "type": "uint8" + }, + { + "internalType": "uint8", + "name": "tokenIndexTo", + "type": "uint8" + }, + { + "internalType": "uint256", + "name": "dx", + "type": "uint256" + } + ], + "name": "calculateSwap", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "chainId", + "type": "uint256" + }, + { + "internalType": "contract IERC20", + "name": "token", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "deposit", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "chainId", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "depositETH", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "chainId", + "type": "uint256" + }, + { + "internalType": "contract IERC20", + "name": "token", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "redeem", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "chainId", + "type": "uint256" + }, + { + "internalType": "contract IERC20", + "name": "token", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "internalType": "uint8", + "name": "liqTokenIndex", + "type": "uint8" + }, + { + "internalType": "uint256", + "name": "liqMinAmount", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "liqDeadline", + "type": "uint256" + } + ], + "name": "redeemAndRemove", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "chainId", + "type": "uint256" + }, + { + "internalType": "contract IERC20", + "name": "token", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "internalType": "uint8", + "name": "tokenIndexFrom", + "type": "uint8" + }, + { + "internalType": "uint8", + "name": "tokenIndexTo", + "type": "uint8" + }, + { + "internalType": "uint256", + "name": "minDy", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" + } + ], + "name": "redeemAndSwap", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "to", + "type": "bytes32" + }, + { + "internalType": "uint256", + "name": "chainId", + "type": "uint256" + }, + { + "internalType": "contract IERC20", + "name": "token", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "redeemv2", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "chainId", + "type": "uint256" + }, + { + "internalType": "contract IERC20", + "name": "token", + "type": "address" + }, + { + "internalType": "uint8", + "name": "tokenIndexFrom", + "type": "uint8" + }, + { + "internalType": "uint8", + "name": "tokenIndexTo", + "type": "uint8" + }, + { + "internalType": "uint256", + "name": "dx", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "minDy", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" + } + ], + "name": "swapAndRedeem", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "chainId", + "type": "uint256" + }, + { + "internalType": "contract IERC20", + "name": "token", + "type": "address" + }, + { + "internalType": "uint8", + "name": "tokenIndexFrom", + "type": "uint8" + }, + { + "internalType": "uint8", + "name": "tokenIndexTo", + "type": "uint8" + }, + { + "internalType": "uint256", + "name": "dx", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "minDy", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" + }, + { + "internalType": "uint8", + "name": "liqTokenIndex", + "type": "uint8" + }, + { + "internalType": "uint256", + "name": "liqMinAmount", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "liqDeadline", + "type": "uint256" + } + ], + "name": "swapAndRedeemAndRemove", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "chainId", + "type": "uint256" + }, + { + "internalType": "contract IERC20", + "name": "token", + "type": "address" + }, + { + "internalType": "uint8", + "name": "tokenIndexFrom", + "type": "uint8" + }, + { + "internalType": "uint8", + "name": "tokenIndexTo", + "type": "uint8" + }, + { + "internalType": "uint256", + "name": "dx", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "minDy", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" + }, + { + "internalType": "uint8", + "name": "swapTokenIndexFrom", + "type": "uint8" + }, + { + "internalType": "uint8", + "name": "swapTokenIndexTo", + "type": "uint8" + }, + { + "internalType": "uint256", + "name": "swapMinDy", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "swapDeadline", + "type": "uint256" + } + ], + "name": "swapAndRedeemAndSwap", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "chainId", + "type": "uint256" + }, + { + "internalType": "contract IERC20", + "name": "token", + "type": "address" + }, + { + "internalType": "uint8", + "name": "tokenIndexFrom", + "type": "uint8" + }, + { + "internalType": "uint8", + "name": "tokenIndexTo", + "type": "uint8" + }, + { + "internalType": "uint256", + "name": "dx", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "minDy", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" + } + ], + "name": "swapETHAndRedeem", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "chainId", + "type": "uint256" + }, + { + "internalType": "contract IERC20", + "name": "token", + "type": "address" + }, + { + "internalType": "uint8", + "name": "tokenIndexFrom", + "type": "uint8" + }, + { + "internalType": "uint8", + "name": "tokenIndexTo", + "type": "uint8" + }, + { + "internalType": "uint256", + "name": "dx", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "minDy", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" + }, + { + "internalType": "uint8", + "name": "swapTokenIndexFrom", + "type": "uint8" + }, + { + "internalType": "uint8", + "name": "swapTokenIndexTo", + "type": "uint8" + }, + { + "internalType": "uint256", + "name": "swapMinDy", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "swapDeadline", + "type": "uint256" + } + ], + "name": "swapETHAndRedeemAndSwap", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "swapMap", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "swapTokensMap", + "outputs": [ + { + "internalType": "contract IERC20", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + } + ], + "transactionHash": "0xcc16136e145c49f3b78dbe5eb37c66a674a16ab45edcaa1984c82e17a9d559ee", + "receipt": { + "to": null, + "from": "0x235AF07E770f474d24F5bf73074735892371b40D", + "contractAddress": "0x33d90B6ce7e0bFC42BCD35d05c443c6915296987", + "transactionIndex": 0, + "gasUsed": "2225407", + "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "blockHash": "0x10433ba650b57c2a3ce42c5a74695373fed4c7a139ef6b8d92c5a46bea888b61", + "transactionHash": "0xcc16136e145c49f3b78dbe5eb37c66a674a16ab45edcaa1984c82e17a9d559ee", + "logs": [], + "blockNumber": 89, + "cumulativeGasUsed": "2225407", + "status": 1, + "byzantium": true + }, + "args": [ + "0x0000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000", + "0xE05c976d3f045D0E6E7A6f61083d98A15603cF6A" + ], + "solcInputHash": "95380060a7ec73498bb886cdc300b807", + "metadata": "{\"compiler\":{\"version\":\"0.6.12+commit.27d51765\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address payable\",\"name\":\"_wethAddress\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_swapOne\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenOne\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_swapTwo\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenTwo\",\"type\":\"address\"},{\"internalType\":\"contract ISynapseBridge\",\"name\":\"_synapseBridge\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"WETH_ADDRESS\",\"outputs\":[{\"internalType\":\"address payable\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contract IERC20\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint8\",\"name\":\"tokenIndexFrom\",\"type\":\"uint8\"},{\"internalType\":\"uint8\",\"name\":\"tokenIndexTo\",\"type\":\"uint8\"},{\"internalType\":\"uint256\",\"name\":\"dx\",\"type\":\"uint256\"}],\"name\":\"calculateSwap\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"chainId\",\"type\":\"uint256\"},{\"internalType\":\"contract IERC20\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"deposit\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"chainId\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"depositETH\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"chainId\",\"type\":\"uint256\"},{\"internalType\":\"contract IERC20\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"redeem\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"chainId\",\"type\":\"uint256\"},{\"internalType\":\"contract IERC20\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"uint8\",\"name\":\"liqTokenIndex\",\"type\":\"uint8\"},{\"internalType\":\"uint256\",\"name\":\"liqMinAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"liqDeadline\",\"type\":\"uint256\"}],\"name\":\"redeemAndRemove\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"chainId\",\"type\":\"uint256\"},{\"internalType\":\"contract IERC20\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"uint8\",\"name\":\"tokenIndexFrom\",\"type\":\"uint8\"},{\"internalType\":\"uint8\",\"name\":\"tokenIndexTo\",\"type\":\"uint8\"},{\"internalType\":\"uint256\",\"name\":\"minDy\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"deadline\",\"type\":\"uint256\"}],\"name\":\"redeemAndSwap\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"to\",\"type\":\"bytes32\"},{\"internalType\":\"uint256\",\"name\":\"chainId\",\"type\":\"uint256\"},{\"internalType\":\"contract IERC20\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"redeemv2\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"chainId\",\"type\":\"uint256\"},{\"internalType\":\"contract IERC20\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint8\",\"name\":\"tokenIndexFrom\",\"type\":\"uint8\"},{\"internalType\":\"uint8\",\"name\":\"tokenIndexTo\",\"type\":\"uint8\"},{\"internalType\":\"uint256\",\"name\":\"dx\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"minDy\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"deadline\",\"type\":\"uint256\"}],\"name\":\"swapAndRedeem\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"chainId\",\"type\":\"uint256\"},{\"internalType\":\"contract IERC20\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint8\",\"name\":\"tokenIndexFrom\",\"type\":\"uint8\"},{\"internalType\":\"uint8\",\"name\":\"tokenIndexTo\",\"type\":\"uint8\"},{\"internalType\":\"uint256\",\"name\":\"dx\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"minDy\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"deadline\",\"type\":\"uint256\"},{\"internalType\":\"uint8\",\"name\":\"liqTokenIndex\",\"type\":\"uint8\"},{\"internalType\":\"uint256\",\"name\":\"liqMinAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"liqDeadline\",\"type\":\"uint256\"}],\"name\":\"swapAndRedeemAndRemove\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"chainId\",\"type\":\"uint256\"},{\"internalType\":\"contract IERC20\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint8\",\"name\":\"tokenIndexFrom\",\"type\":\"uint8\"},{\"internalType\":\"uint8\",\"name\":\"tokenIndexTo\",\"type\":\"uint8\"},{\"internalType\":\"uint256\",\"name\":\"dx\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"minDy\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"deadline\",\"type\":\"uint256\"},{\"internalType\":\"uint8\",\"name\":\"swapTokenIndexFrom\",\"type\":\"uint8\"},{\"internalType\":\"uint8\",\"name\":\"swapTokenIndexTo\",\"type\":\"uint8\"},{\"internalType\":\"uint256\",\"name\":\"swapMinDy\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"swapDeadline\",\"type\":\"uint256\"}],\"name\":\"swapAndRedeemAndSwap\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"chainId\",\"type\":\"uint256\"},{\"internalType\":\"contract IERC20\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint8\",\"name\":\"tokenIndexFrom\",\"type\":\"uint8\"},{\"internalType\":\"uint8\",\"name\":\"tokenIndexTo\",\"type\":\"uint8\"},{\"internalType\":\"uint256\",\"name\":\"dx\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"minDy\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"deadline\",\"type\":\"uint256\"}],\"name\":\"swapETHAndRedeem\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"chainId\",\"type\":\"uint256\"},{\"internalType\":\"contract IERC20\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint8\",\"name\":\"tokenIndexFrom\",\"type\":\"uint8\"},{\"internalType\":\"uint8\",\"name\":\"tokenIndexTo\",\"type\":\"uint8\"},{\"internalType\":\"uint256\",\"name\":\"dx\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"minDy\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"deadline\",\"type\":\"uint256\"},{\"internalType\":\"uint8\",\"name\":\"swapTokenIndexFrom\",\"type\":\"uint8\"},{\"internalType\":\"uint8\",\"name\":\"swapTokenIndexTo\",\"type\":\"uint8\"},{\"internalType\":\"uint256\",\"name\":\"swapMinDy\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"swapDeadline\",\"type\":\"uint256\"}],\"name\":\"swapETHAndRedeemAndSwap\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"swapMap\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"swapTokensMap\",\"outputs\":[{\"internalType\":\"contract IERC20\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{\"calculateSwap(address,uint8,uint8,uint256)\":{\"params\":{\"dx\":\"the amount of tokens the user wants to sell. If the token charges a fee on transfers, use the amount that gets transferred after the fee.\",\"tokenIndexFrom\":\"the token the user wants to sell\",\"tokenIndexTo\":\"the token the user wants to buy\"},\"returns\":{\"_0\":\"amount of tokens the user will receive\"}},\"deposit(address,uint256,address,uint256)\":{\"params\":{\"amount\":\"Amount in native token decimals to transfer cross-chain pre-fees*\",\"chainId\":\"which underlying chain to bridge assets onto\",\"to\":\"address on other chain to redeem underlying assets to\",\"token\":\"ERC20 compatible token to deposit into the bridge\"}},\"depositETH(address,uint256,uint256)\":{\"params\":{\"amount\":\"Amount in native token decimals to transfer cross-chain pre-fees*\",\"chainId\":\"which chain to bridge assets onto\",\"to\":\"address on other chain to bridge assets to\"}},\"redeem(address,uint256,address,uint256)\":{\"params\":{\"amount\":\"Amount in native token decimals to transfer cross-chain pre-fees*\",\"chainId\":\"which underlying chain to bridge assets onto\",\"to\":\"address on other chain to redeem underlying assets to\",\"token\":\"ERC20 compatible token to deposit into the bridge\"}},\"redeemAndRemove(address,uint256,address,uint256,uint8,uint256,uint256)\":{\"params\":{\"amount\":\"Amount of (typically) LP token to pass to the nodes to attempt to removeLiquidity() with to redeem for the underlying assets of the LP token\",\"chainId\":\"which underlying chain to bridge assets onto\",\"liqDeadline\":\"Specificies the deadline that the nodes are allowed to try to redeem/swap the LP token*\",\"liqMinAmount\":\"Specifies the minimum amount of the underlying asset needed for the nodes to execute the redeem/swap\",\"liqTokenIndex\":\"Specifies which of the underlying LP assets the nodes should attempt to redeem for\",\"to\":\"address on other chain to redeem underlying assets to\",\"token\":\"ERC20 compatible token to deposit into the bridge\"}},\"redeemAndSwap(address,uint256,address,uint256,uint8,uint8,uint256,uint256)\":{\"params\":{\"amount\":\"Amount in native token decimals to transfer cross-chain pre-fees\",\"chainId\":\"which underlying chain to bridge assets onto\",\"deadline\":\"latest timestamp to accept this transaction*\",\"minDy\":\"the min amount the user would like to receive, or revert to only minting the SynERC20 token crosschain.\",\"to\":\"address on other chain to redeem underlying assets to\",\"token\":\"ERC20 compatible token to deposit into the bridge\",\"tokenIndexFrom\":\"the token the user wants to swap from\",\"tokenIndexTo\":\"the token the user wants to swap to\"}},\"redeemv2(bytes32,uint256,address,uint256)\":{\"params\":{\"amount\":\"Amount in native token decimals to transfer cross-chain pre-fees*\",\"chainId\":\"which chain to bridge assets onto\",\"to\":\"address on other chain to bridge assets to\",\"token\":\"ERC20 compatible token to redeem into the bridge\"}}},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{\"calculateSwap(address,uint8,uint8,uint256)\":{\"notice\":\"Calculate amount of tokens you receive on swap\"},\"deposit(address,uint256,address,uint256)\":{\"notice\":\"wraps SynapseBridge redeem()\"},\"depositETH(address,uint256,uint256)\":{\"notice\":\"Wraps SynapseBridge deposit() function to make it compatible w/ ETH -> WETH conversions\"},\"redeem(address,uint256,address,uint256)\":{\"notice\":\"wraps SynapseBridge redeem()\"},\"redeemAndRemove(address,uint256,address,uint256,uint8,uint256,uint256)\":{\"notice\":\"Wraps redeemAndRemove on SynapseBridge Relays to nodes that (typically) a wrapped synAsset ERC20 token has been burned and the underlying needs to be redeeemed on the native chain. This function indicates to the nodes that they should attempt to redeem the LP token for the underlying assets (E.g \\\"swap\\\" out of the LP token)\"},\"redeemAndSwap(address,uint256,address,uint256,uint8,uint8,uint256,uint256)\":{\"notice\":\"Wraps redeemAndSwap on SynapseBridge.sol Relays to nodes that (typically) a wrapped synAsset ERC20 token has been burned and the underlying needs to be redeeemed on the native chain. This function indicates to the nodes that they should attempt to redeem the LP token for the underlying assets (E.g \\\"swap\\\" out of the LP token)\"},\"redeemv2(bytes32,uint256,address,uint256)\":{\"notice\":\"Wraps SynapseBridge redeemv2() function\"}},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/bridge/wrappers/L2BridgeZap.sol\":\"L2BridgeZap\"},\"evmVersion\":\"istanbul\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":10000},\"remappings\":[]},\"sources\":{\"@openzeppelin/contracts/math/SafeMath.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity >=0.6.0 <0.8.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\",\"keccak256\":\"0xcc78a17dd88fa5a2edc60c8489e2f405c0913b377216a5b26b35656b2d0dab52\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/ERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity >=0.6.0 <0.8.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_) public {\\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\",\"keccak256\":\"0xca0c2396dbeb3503b51abf4248ebf77a1461edad513c01529df51850a012bee3\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/ERC20Burnable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity >=0.6.0 <0.8.0;\\n\\nimport \\\"../../utils/Context.sol\\\";\\nimport \\\"./ERC20.sol\\\";\\n\\n/**\\n * @dev Extension of {ERC20} that allows token holders to destroy both their own\\n * tokens and those that they have an allowance for, in a way that can be\\n * recognized off-chain (via event analysis).\\n */\\nabstract contract ERC20Burnable is Context, ERC20 {\\n using SafeMath for uint256;\\n\\n /**\\n * @dev Destroys `amount` tokens from the caller.\\n *\\n * See {ERC20-_burn}.\\n */\\n function burn(uint256 amount) public virtual {\\n _burn(_msgSender(), amount);\\n }\\n\\n /**\\n * @dev Destroys `amount` tokens from `account`, deducting from the caller's\\n * allowance.\\n *\\n * See {ERC20-_burn} and {ERC20-allowance}.\\n *\\n * Requirements:\\n *\\n * - the caller must have allowance for ``accounts``'s tokens of at least\\n * `amount`.\\n */\\n function burnFrom(address account, uint256 amount) public virtual {\\n uint256 decreasedAllowance = allowance(account, _msgSender()).sub(amount, \\\"ERC20: burn amount exceeds allowance\\\");\\n\\n _approve(account, _msgSender(), decreasedAllowance);\\n _burn(account, amount);\\n }\\n}\\n\",\"keccak256\":\"0x9c0eb3b0e11d2480d49991dc384f1e5f9c9b9967cc81944d50916a9b9c6c4984\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/IERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity >=0.6.0 <0.8.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\",\"keccak256\":\"0x5f02220344881ce43204ae4a6281145a67bc52c2bb1290a791857df3d19d78f5\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/SafeERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity >=0.6.0 <0.8.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\",\"keccak256\":\"0xf12dfbe97e6276980b83d2830bb0eb75e0cf4f3e626c2471137f82158ae6a0fc\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/Address.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity >=0.6.2 <0.8.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\",\"keccak256\":\"0x28911e614500ae7c607a432a709d35da25f3bc5ddc8bd12b278b66358070c0ea\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/Context.sol\":{\"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\",\"keccak256\":\"0x8d3cb350f04ff49cfb10aef08d87f19dcbaecc8027b0bed12f3275cd12f38cf0\",\"license\":\"MIT\"},\"contracts/bridge/interfaces/ISwap.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity 0.6.12;\\n\\nimport '@openzeppelin/contracts/token/ERC20/ERC20.sol';\\n\\ninterface ISwap {\\n // pool data view functions\\n function getA() external view returns (uint256);\\n\\n function getToken(uint8 index) external view returns (IERC20);\\n\\n function getTokenIndex(address tokenAddress) external view returns (uint8);\\n\\n function getTokenBalance(uint8 index) external view returns (uint256);\\n\\n function getVirtualPrice() external view returns (uint256);\\n\\n // min return calculation functions\\n function calculateSwap(\\n uint8 tokenIndexFrom,\\n uint8 tokenIndexTo,\\n uint256 dx\\n ) external view returns (uint256);\\n\\n function calculateTokenAmount(uint256[] calldata amounts, bool deposit)\\n external\\n view\\n returns (uint256);\\n\\n function calculateRemoveLiquidity(uint256 amount)\\n external\\n view\\n returns (uint256[] memory);\\n\\n function calculateRemoveLiquidityOneToken(\\n uint256 tokenAmount,\\n uint8 tokenIndex\\n ) external view returns (uint256 availableTokenAmount);\\n\\n // state modifying functions\\n function initialize(\\n IERC20[] memory pooledTokens,\\n uint8[] memory decimals,\\n string memory lpTokenName,\\n string memory lpTokenSymbol,\\n uint256 a,\\n uint256 fee,\\n uint256 adminFee,\\n address lpTokenTargetAddress\\n ) external;\\n\\n function swap(\\n uint8 tokenIndexFrom,\\n uint8 tokenIndexTo,\\n uint256 dx,\\n uint256 minDy,\\n uint256 deadline\\n ) external returns (uint256);\\n\\n function addLiquidity(\\n uint256[] calldata amounts,\\n uint256 minToMint,\\n uint256 deadline\\n ) external returns (uint256);\\n\\n function removeLiquidity(\\n uint256 amount,\\n uint256[] calldata minAmounts,\\n uint256 deadline\\n ) external returns (uint256[] memory);\\n\\n function removeLiquidityOneToken(\\n uint256 tokenAmount,\\n uint8 tokenIndex,\\n uint256 minAmount,\\n uint256 deadline\\n ) external returns (uint256);\\n\\n function removeLiquidityImbalance(\\n uint256[] calldata amounts,\\n uint256 maxBurnAmount,\\n uint256 deadline\\n ) external returns (uint256);\\n}\\n\",\"keccak256\":\"0xb51eb389637b2b595a09cd95ea4167a6d945719be1bc127eafae07c06abd8ca8\",\"license\":\"MIT\"},\"contracts/bridge/interfaces/ISynapseBridge.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity 0.6.12;\\n\\nimport '@openzeppelin/contracts/token/ERC20/SafeERC20.sol';\\nimport '@openzeppelin/contracts/token/ERC20/ERC20Burnable.sol';\\n\\ninterface ISynapseBridge {\\n using SafeERC20 for IERC20;\\n\\n function deposit(\\n address to,\\n uint256 chainId,\\n IERC20 token,\\n uint256 amount\\n ) external;\\n\\n function depositAndSwap(\\n address to,\\n uint256 chainId,\\n IERC20 token,\\n uint256 amount,\\n uint8 tokenIndexFrom,\\n uint8 tokenIndexTo,\\n uint256 minDy,\\n uint256 deadline\\n ) external;\\n\\n function redeem(\\n address to,\\n uint256 chainId,\\n IERC20 token,\\n uint256 amount\\n ) external;\\n\\n\\n function redeemv2(\\n bytes32 to,\\n uint256 chainId,\\n IERC20 token,\\n uint256 amount\\n ) external;\\n\\n\\n function redeemAndSwap(\\n address to,\\n uint256 chainId,\\n IERC20 token,\\n uint256 amount,\\n uint8 tokenIndexFrom,\\n uint8 tokenIndexTo,\\n uint256 minDy,\\n uint256 deadline\\n ) external;\\n\\n function redeemAndRemove(\\n address to,\\n uint256 chainId,\\n IERC20 token,\\n uint256 amount,\\n uint8 liqTokenIndex,\\n uint256 liqMinAmount,\\n uint256 liqDeadline\\n ) external;\\n}\\n\",\"keccak256\":\"0x9ae06bbed7d464faceb9c63e929171f422b5eaee1f6d653742ab97862bc6609a\",\"license\":\"MIT\"},\"contracts/bridge/interfaces/IWETH9.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity >=0.4.0;\\n\\ninterface IWETH9 {\\n function name() external view returns (string memory);\\n\\n function symbol() external view returns (string memory);\\n\\n function decimals() external view returns (uint8);\\n\\n function balanceOf(address) external view returns (uint256);\\n\\n function allowance(address, address) external view returns (uint256);\\n\\n receive() external payable;\\n\\n function deposit() external payable;\\n\\n function withdraw(uint256 wad) external;\\n\\n function totalSupply() external view returns (uint256);\\n\\n function approve(address guy, uint256 wad) external returns (bool);\\n\\n function transfer(address dst, uint256 wad) external returns (bool);\\n\\n function transferFrom(\\n address src,\\n address dst,\\n uint256 wad\\n ) external returns (bool);\\n}\",\"keccak256\":\"0x081ebde11dad2210d382564d40336f914d3d621750645f23707ca1a92139dbe2\",\"license\":\"MIT\"},\"contracts/bridge/wrappers/L2BridgeZap.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.6.12;\\n\\nimport \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\nimport \\\"@openzeppelin/contracts/token/ERC20/SafeERC20.sol\\\";\\nimport \\\"../interfaces/ISwap.sol\\\";\\nimport \\\"../interfaces/ISynapseBridge.sol\\\";\\nimport \\\"../interfaces/IWETH9.sol\\\";\\n\\ncontract L2BridgeZap {\\n using SafeERC20 for IERC20;\\n\\n ISynapseBridge synapseBridge;\\n address payable public immutable WETH_ADDRESS;\\n\\n mapping(address => address) public swapMap;\\n mapping(address => IERC20[]) public swapTokensMap;\\n\\n uint256 constant MAX_UINT256 = 2**256 - 1;\\n\\n constructor(\\n address payable _wethAddress,\\n address _swapOne,\\n address tokenOne,\\n address _swapTwo,\\n address tokenTwo,\\n ISynapseBridge _synapseBridge\\n ) public {\\n WETH_ADDRESS = _wethAddress;\\n synapseBridge = _synapseBridge;\\n swapMap[tokenOne] = _swapOne;\\n swapMap[tokenTwo] = _swapTwo;\\n if (_wethAddress != address(0)) {\\n IERC20(_wethAddress).safeIncreaseAllowance(address(_synapseBridge), MAX_UINT256);\\n }\\n if (address(_swapOne) != address(0)) {\\n {\\n uint8 i;\\n for (; i < 32; i++) {\\n try ISwap(_swapOne).getToken(i) returns (\\n IERC20 token\\n ) {\\n swapTokensMap[_swapOne].push(token);\\n token.safeApprove(address(_swapOne), MAX_UINT256);\\n token.safeApprove(address(synapseBridge), MAX_UINT256);\\n } catch {\\n break;\\n }\\n }\\n require(i > 1, \\\"swap must have at least 2 tokens\\\");\\n }\\n }\\n if (address(_swapTwo) != address(0)) {\\n {\\n uint8 i;\\n for (; i < 32; i++) {\\n try ISwap(_swapTwo).getToken(i) returns (\\n IERC20 token\\n ) {\\n swapTokensMap[_swapTwo].push(token);\\n token.safeApprove(address(_swapTwo), MAX_UINT256);\\n token.safeApprove(address(synapseBridge), MAX_UINT256);\\n } catch {\\n break;\\n }\\n }\\n require(i > 1, \\\"swap must have at least 2 tokens\\\");\\n }\\n }\\n }\\n\\n /**\\n * @notice Calculate amount of tokens you receive on swap\\n * @param tokenIndexFrom the token the user wants to sell\\n * @param tokenIndexTo the token the user wants to buy\\n * @param dx the amount of tokens the user wants to sell. If the token charges\\n * a fee on transfers, use the amount that gets transferred after the fee.\\n * @return amount of tokens the user will receive\\n */\\n function calculateSwap(\\n IERC20 token,\\n uint8 tokenIndexFrom,\\n uint8 tokenIndexTo,\\n uint256 dx\\n ) external view virtual returns (uint256) {\\n ISwap swap = ISwap(\\n swapMap[address(token)]\\n );\\n return swap.calculateSwap(tokenIndexFrom, tokenIndexTo, dx);\\n }\\n\\n function swapAndRedeem(\\n address to,\\n uint256 chainId,\\n IERC20 token,\\n uint8 tokenIndexFrom,\\n uint8 tokenIndexTo,\\n uint256 dx,\\n uint256 minDy,\\n uint256 deadline\\n ) external {\\n ISwap swap = ISwap(swapMap[address(token)]);\\n require(address(swap) != address(0), \\\"Swap is 0x00\\\");\\n IERC20[] memory tokens = swapTokensMap[address(swap)];\\n tokens[tokenIndexFrom].safeTransferFrom(\\n msg.sender,\\n address(this),\\n dx\\n );\\n // swap\\n\\n uint256 swappedAmount = swap.swap(\\n tokenIndexFrom,\\n tokenIndexTo,\\n dx,\\n minDy,\\n deadline\\n );\\n // deposit into bridge, gets nUSD\\n if (\\n token.allowance(address(this), address(synapseBridge)) <\\n swappedAmount\\n ) {\\n token.safeApprove(address(synapseBridge), MAX_UINT256);\\n }\\n synapseBridge.redeem(to, chainId, token, swappedAmount);\\n }\\n\\n function swapAndRedeemAndSwap(\\n address to,\\n uint256 chainId,\\n IERC20 token,\\n uint8 tokenIndexFrom,\\n uint8 tokenIndexTo,\\n uint256 dx,\\n uint256 minDy,\\n uint256 deadline,\\n uint8 swapTokenIndexFrom,\\n uint8 swapTokenIndexTo,\\n uint256 swapMinDy,\\n uint256 swapDeadline\\n ) external {\\n require(\\n address(swapMap[address(token)]) != address(0),\\n \\\"Swap is 0x00\\\"\\n );\\n IERC20[] memory tokens = swapTokensMap[\\n swapMap[address(token)]\\n ];\\n tokens[tokenIndexFrom].safeTransferFrom(\\n msg.sender,\\n address(this),\\n dx\\n );\\n // swap\\n\\n uint256 swappedAmount = ISwap(swapMap[address(token)]).swap(tokenIndexFrom, tokenIndexTo, dx, minDy, deadline);\\n // deposit into bridge, gets nUSD\\n if (\\n token.allowance(address(this), address(synapseBridge)) <\\n swappedAmount\\n ) {\\n token.safeApprove(address(synapseBridge), MAX_UINT256);\\n }\\n synapseBridge.redeemAndSwap(\\n to,\\n chainId,\\n token,\\n swappedAmount,\\n swapTokenIndexFrom,\\n swapTokenIndexTo,\\n swapMinDy,\\n swapDeadline\\n );\\n }\\n\\n function swapAndRedeemAndRemove(\\n address to,\\n uint256 chainId,\\n IERC20 token,\\n uint8 tokenIndexFrom,\\n uint8 tokenIndexTo,\\n uint256 dx,\\n uint256 minDy,\\n uint256 deadline,\\n uint8 liqTokenIndex,\\n uint256 liqMinAmount,\\n uint256 liqDeadline\\n ) external {\\n ISwap swap = ISwap(swapMap[address(token)]);\\n require(address(swap) != address(0), \\\"Swap is 0x00\\\");\\n IERC20[] memory tokens = swapTokensMap[address(swap)];\\n tokens[tokenIndexFrom].safeTransferFrom(\\n msg.sender,\\n address(this),\\n dx\\n );\\n // swap\\n\\n uint256 swappedAmount = swap.swap(\\n tokenIndexFrom,\\n tokenIndexTo,\\n dx,\\n minDy,\\n deadline\\n );\\n // deposit into bridge, gets nUSD\\n if (\\n token.allowance(address(this), address(synapseBridge)) <\\n swappedAmount\\n ) {\\n token.safeApprove(address(synapseBridge), MAX_UINT256);\\n }\\n synapseBridge.redeemAndRemove(\\n to,\\n chainId,\\n token,\\n swappedAmount,\\n liqTokenIndex,\\n liqMinAmount,\\n liqDeadline\\n );\\n }\\n\\n /**\\n * @notice wraps SynapseBridge redeem()\\n * @param to address on other chain to redeem underlying assets to\\n * @param chainId which underlying chain to bridge assets onto\\n * @param token ERC20 compatible token to deposit into the bridge\\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\\n **/\\n function redeem(\\n address to,\\n uint256 chainId,\\n IERC20 token,\\n uint256 amount\\n ) external {\\n token.safeTransferFrom(msg.sender, address(this), amount);\\n if (token.allowance(address(this), address(synapseBridge)) < amount) {\\n token.safeApprove(address(synapseBridge), MAX_UINT256);\\n }\\n synapseBridge.redeem(to, chainId, token, amount);\\n }\\n\\n /**\\n * @notice wraps SynapseBridge redeem()\\n * @param to address on other chain to redeem underlying assets to\\n * @param chainId which underlying chain to bridge assets onto\\n * @param token ERC20 compatible token to deposit into the bridge\\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\\n **/\\n function deposit(\\n address to,\\n uint256 chainId,\\n IERC20 token,\\n uint256 amount\\n ) external {\\n token.safeTransferFrom(msg.sender, address(this), amount);\\n if (token.allowance(address(this), address(synapseBridge)) < amount) {\\n token.safeApprove(address(synapseBridge), MAX_UINT256);\\n }\\n synapseBridge.deposit(to, chainId, token, amount);\\n }\\n\\n /**\\n * @notice Wraps SynapseBridge deposit() function to make it compatible w/ ETH -> WETH conversions\\n * @param to address on other chain to bridge assets to\\n * @param chainId which chain to bridge assets onto\\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\\n **/\\n function depositETH(\\n address to,\\n uint256 chainId,\\n uint256 amount\\n ) external payable {\\n require(msg.value > 0 && msg.value == amount, 'INCORRECT MSG VALUE');\\n IWETH9(WETH_ADDRESS).deposit{value: msg.value}();\\n synapseBridge.deposit(to, chainId, IERC20(WETH_ADDRESS), amount);\\n }\\n\\n\\n function swapETHAndRedeem(\\n address to,\\n uint256 chainId,\\n IERC20 token,\\n uint8 tokenIndexFrom,\\n uint8 tokenIndexTo,\\n uint256 dx,\\n uint256 minDy,\\n uint256 deadline\\n ) external payable {\\n require(WETH_ADDRESS != address(0), \\\"WETH 0\\\");\\n require(msg.value > 0 && msg.value == dx, \\\"INCORRECT MSG VALUE\\\");\\n ISwap swap = ISwap(swapMap[address(token)]);\\n require(address(swap) != address(0), \\\"Swap is 0x00\\\");\\n IWETH9(WETH_ADDRESS).deposit{value: msg.value}();\\n\\n // swap\\n uint256 swappedAmount = swap.swap(\\n tokenIndexFrom,\\n tokenIndexTo,\\n dx,\\n minDy,\\n deadline\\n );\\n synapseBridge.redeem(to, chainId, token, swappedAmount);\\n }\\n\\n\\n function swapETHAndRedeemAndSwap(\\n address to,\\n uint256 chainId,\\n IERC20 token,\\n uint8 tokenIndexFrom,\\n uint8 tokenIndexTo,\\n uint256 dx,\\n uint256 minDy,\\n uint256 deadline,\\n uint8 swapTokenIndexFrom,\\n uint8 swapTokenIndexTo,\\n uint256 swapMinDy,\\n uint256 swapDeadline\\n ) external payable {\\n require(WETH_ADDRESS != address(0), \\\"WETH 0\\\");\\n require(msg.value > 0 && msg.value == dx, \\\"INCORRECT MSG VALUE\\\");\\n ISwap swap = ISwap(swapMap[address(token)]);\\n require(address(swap) != address(0), \\\"Swap is 0x00\\\");\\n IWETH9(WETH_ADDRESS).deposit{value: msg.value}();\\n\\n // swap\\n uint256 swappedAmount = swap.swap(\\n tokenIndexFrom,\\n tokenIndexTo,\\n dx,\\n minDy,\\n deadline\\n );\\n synapseBridge.redeemAndSwap(to, chainId, token, swappedAmount,swapTokenIndexFrom,\\n swapTokenIndexTo,\\n swapMinDy,\\n swapDeadline);\\n }\\n\\n\\n /**\\n * @notice Wraps redeemAndSwap on SynapseBridge.sol\\n * Relays to nodes that (typically) a wrapped synAsset ERC20 token has been burned and the underlying needs to be redeeemed on the native chain. This function indicates to the nodes that they should attempt to redeem the LP token for the underlying assets (E.g \\\"swap\\\" out of the LP token)\\n * @param to address on other chain to redeem underlying assets to\\n * @param chainId which underlying chain to bridge assets onto\\n * @param token ERC20 compatible token to deposit into the bridge\\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\\n * @param tokenIndexFrom the token the user wants to swap from\\n * @param tokenIndexTo the token the user wants to swap to\\n * @param minDy the min amount the user would like to receive, or revert to only minting the SynERC20 token crosschain.\\n * @param deadline latest timestamp to accept this transaction\\n **/\\n function redeemAndSwap(\\n address to,\\n uint256 chainId,\\n IERC20 token,\\n uint256 amount,\\n uint8 tokenIndexFrom,\\n uint8 tokenIndexTo,\\n uint256 minDy,\\n uint256 deadline\\n ) external {\\n token.safeTransferFrom(msg.sender, address(this), amount);\\n if (token.allowance(address(this), address(synapseBridge)) < amount) {\\n token.safeApprove(address(synapseBridge), MAX_UINT256);\\n }\\n synapseBridge.redeemAndSwap(\\n to,\\n chainId,\\n token,\\n amount,\\n tokenIndexFrom,\\n tokenIndexTo,\\n minDy,\\n deadline\\n );\\n }\\n\\n /**\\n * @notice Wraps redeemAndRemove on SynapseBridge\\n * Relays to nodes that (typically) a wrapped synAsset ERC20 token has been burned and the underlying needs to be redeeemed on the native chain. This function indicates to the nodes that they should attempt to redeem the LP token for the underlying assets (E.g \\\"swap\\\" out of the LP token)\\n * @param to address on other chain to redeem underlying assets to\\n * @param chainId which underlying chain to bridge assets onto\\n * @param token ERC20 compatible token to deposit into the bridge\\n * @param amount Amount of (typically) LP token to pass to the nodes to attempt to removeLiquidity() with to redeem for the underlying assets of the LP token\\n * @param liqTokenIndex Specifies which of the underlying LP assets the nodes should attempt to redeem for\\n * @param liqMinAmount Specifies the minimum amount of the underlying asset needed for the nodes to execute the redeem/swap\\n * @param liqDeadline Specificies the deadline that the nodes are allowed to try to redeem/swap the LP token\\n **/\\n function redeemAndRemove(\\n address to,\\n uint256 chainId,\\n IERC20 token,\\n uint256 amount,\\n uint8 liqTokenIndex,\\n uint256 liqMinAmount,\\n uint256 liqDeadline\\n ) external {\\n token.safeTransferFrom(msg.sender, address(this), amount);\\n if (token.allowance(address(this), address(synapseBridge)) < amount) {\\n token.safeApprove(address(synapseBridge), MAX_UINT256);\\n }\\n synapseBridge.redeemAndRemove(\\n to,\\n chainId,\\n token,\\n amount,\\n liqTokenIndex,\\n liqMinAmount,\\n liqDeadline\\n );\\n }\\n\\n /**\\n * @notice Wraps SynapseBridge redeemv2() function\\n * @param to address on other chain to bridge assets to\\n * @param chainId which chain to bridge assets onto\\n * @param token ERC20 compatible token to redeem into the bridge\\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\\n **/\\n function redeemv2(\\n bytes32 to,\\n uint256 chainId,\\n IERC20 token,\\n uint256 amount\\n ) external {\\n token.safeTransferFrom(msg.sender, address(this), amount);\\n\\n if (token.allowance(address(this), address(synapseBridge)) < amount) {\\n token.safeApprove(address(synapseBridge), MAX_UINT256);\\n }\\n synapseBridge.redeemv2(to, chainId, token, amount);\\n }\\n}\\n\",\"keccak256\":\"0x9aacd1e2f6bea60913adcb50b1bedee75481d9e2afab333058f1c3cd0996e7dc\",\"license\":\"MIT\"}},\"version\":1}", + "bytecode": "0x60a06040523480156200001157600080fd5b506040516200309438038062003094833981810160405260c08110156200003757600080fd5b50805160208083015160408085015160608087015160808089015160a0909901519288901b6001600160601b0319169052600080546001600160a01b03199081166001600160a01b038086169190911783558086168352600190985285822080548216898916179055878a168252949020805490941686821617909355949592949093919291861615620000ec57620000ec81600019886001600160a01b0316620003e060201b62001f4b179092919060201c565b6001600160a01b03851615620002605760005b60208160ff1610156200021657856001600160a01b03166382b86600826040518263ffffffff1660e01b8152600401808260ff16815260200191505060206040518083038186803b1580156200015457600080fd5b505afa9250505080156200017b57506040513d60208110156200017657600080fd5b505160015b620001865762000216565b6001600160a01b038781166000908152600260209081526040822080546001810182559083529181902090910180546001600160a01b0319169284169283179055620001e29190899060001990620004e9811b6200206a17901c565b6000546200020c906001600160a01b038381169116600019620004e9602090811b6200206a17901c565b50600101620000ff565b60018160ff16116200025e576040805162461bcd60e51b8152602060048201819052602482015260008051602062003014833981519152604482015290519081900360640190fd5b505b6001600160a01b03831615620003d45760005b60208160ff1610156200038a57836001600160a01b03166382b86600826040518263ffffffff1660e01b8152600401808260ff16815260200191505060206040518083038186803b158015620002c857600080fd5b505afa925050508015620002ef57506040513d6020811015620002ea57600080fd5b505160015b620002fa576200038a565b6001600160a01b038581166000908152600260209081526040822080546001810182559083529181902090910180546001600160a01b0319169284169283179055620003569190879060001990620004e9811b6200206a17901c565b60005462000380906001600160a01b038381169116600019620004e9602090811b6200206a17901c565b5060010162000273565b60018160ff1611620003d2576040805162461bcd60e51b8152602060048201819052602482015260008051602062003014833981519152604482015290519081900360640190fd5b505b5050505050506200095c565b60006200048782856001600160a01b031663dd62ed3e30876040518363ffffffff1660e01b815260040180836001600160a01b03168152602001826001600160a01b031681526020019250505060206040518083038186803b1580156200044657600080fd5b505afa1580156200045b573d6000803e3d6000fd5b505050506040513d60208110156200047257600080fd5b5051906200060d602090811b620021c917901c565b604080516001600160a01b038616602482015260448082018490528251808303909101815260649091019091526020810180516001600160e01b0390811663095ea7b360e01b17909152919250620004e3918691906200066f16565b50505050565b80158062000573575060408051636eb1769f60e11b81523060048201526001600160a01b03848116602483015291519185169163dd62ed3e91604480820192602092909190829003018186803b1580156200054357600080fd5b505afa15801562000558573d6000803e3d6000fd5b505050506040513d60208110156200056f57600080fd5b5051155b620005b05760405162461bcd60e51b81526004018080602001828103825260368152602001806200305e6036913960400191505060405180910390fd5b604080516001600160a01b038416602482015260448082018490528251808303909101815260649091019091526020810180516001600160e01b0390811663095ea7b360e01b17909152620006089185916200066f16565b505050565b60008282018381101562000668576040805162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b9392505050565b6060620006cb826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b03166200072b60201b6200222a179092919060201c565b8051909150156200060857808060200190516020811015620006ec57600080fd5b5051620006085760405162461bcd60e51b815260040180806020018281038252602a81526020018062003034602a913960400191505060405180910390fd5b60606200073c848460008562000744565b949350505050565b606082471015620007875760405162461bcd60e51b815260040180806020018281038252602681526020018062002fee6026913960400191505060405180910390fd5b6200079285620008ac565b620007e4576040805162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000604482015290519081900360640190fd5b60006060866001600160a01b031685876040518082805190602001908083835b60208310620008255780518252601f19909201916020918201910162000804565b6001836020036101000a03801982511681845116808217855250505050505090500191505060006040518083038185875af1925050503d806000811462000889576040519150601f19603f3d011682016040523d82523d6000602084013e6200088e565b606091505b509092509050620008a1828286620008b2565b979650505050505050565b3b151590565b60608315620008c357508162000668565b825115620008d45782518084602001fd5b8160405162461bcd60e51b81526004018080602001828103825283818151815260200191508051906020019080838360005b838110156200092057818101518382015260200162000906565b50505050905090810190601f1680156200094e5780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b60805160601c61265662000998600039806105f05280610b135280610c5b528061128a52806113d25280611cd85280611d8b52506126566000f3fe6080604052600436106100e85760003560e01c806365749c9d1161008a57806390d250741161005957806390d25074146104a95780639f330727146104f0578063ce0b63ce14610575578063f3f094a1146105a7576100e8565b806365749c9d14610357578063798af720146103b1578063839ed90a1461040f57806385528f0b14610476576100e8565b8063393494b8116100c6578063393494b8146101fa5780633d5da1641461023357806349b7cf84146102ab5780634a517a55146102f0576100e8565b8063040141e5146100ed578063174dc9521461011e57806336e712ed1461019e575b600080fd5b3480156100f957600080fd5b506101026105ee565b604080516001600160a01b039092168252519081900360200190f35b34801561012a57600080fd5b5061019c600480360361016081101561014257600080fd5b506001600160a01b0381358116916020810135916040820135169060ff6060820135811691608081013582169160a08201359160c08101359160e08201359161010081013590911690610120810135906101400135610612565b005b3480156101aa57600080fd5b5061019c600480360360e08110156101c157600080fd5b506001600160a01b0381358116916020810135916040820135169060608101359060ff6080820135169060a08101359060c0013561095b565b34801561020657600080fd5b506101026004803603604081101561021d57600080fd5b506001600160a01b038135169060200135610adc565b61019c600480360361018081101561024a57600080fd5b506001600160a01b0381358116916020810135916040820135169060ff6060820135811691608081013582169160a08201359160c08101359160e0820135916101008101358216916101208201351690610140810135906101600135610b11565b3480156102b757600080fd5b5061019c600480360360808110156102ce57600080fd5b508035906020810135906001600160a01b036040820135169060600135610e21565b3480156102fc57600080fd5b5061019c600480360361010081101561031457600080fd5b506001600160a01b0381358116916020810135916040820135169060ff606082013581169160808101359091169060a08101359060c08101359060e00135610f87565b61019c600480360361010081101561036e57600080fd5b506001600160a01b0381358116916020810135916040820135169060ff606082013581169160808101359091169060a08101359060c08101359060e00135611288565b3480156103bd57600080fd5b506103fd600480360360808110156103d457600080fd5b506001600160a01b038135169060ff602082013581169160408101359091169060600135611594565b60408051918252519081900360200190f35b34801561041b57600080fd5b5061019c600480360361010081101561043357600080fd5b506001600160a01b0381358116916020810135916040820135169060608101359060ff608082013581169160a08101359091169060c08101359060e0013561164d565b34801561048257600080fd5b506101026004803603602081101561049957600080fd5b50356001600160a01b03166117d8565b3480156104b557600080fd5b5061019c600480360360808110156104cc57600080fd5b506001600160a01b03813581169160208101359160408201351690606001356117f3565b3480156104fc57600080fd5b5061019c600480360361018081101561051457600080fd5b506001600160a01b0381358116916020810135916040820135169060ff6060820135811691608081013582169160a08201359160c08101359160e082013591610100810135821691610120820135169061014081013590610160013561193c565b61019c6004803603606081101561058b57600080fd5b506001600160a01b038135169060208101359060400135611c76565b3480156105b357600080fd5b5061019c600480360360808110156105ca57600080fd5b506001600160a01b0381358116916020810135916040820135169060600135611e02565b7f000000000000000000000000000000000000000000000000000000000000000081565b6001600160a01b03808a16600090815260016020526040902054168061067f576040805162461bcd60e51b815260206004820152600c60248201527f5377617020697320307830300000000000000000000000000000000000000000604482015290519081900360640190fd5b6001600160a01b0381166000908152600260209081526040918290208054835181840281018401909452808452606093928301828280156106e957602002820191906000526020600020905b81546001600160a01b031681526001909101906020018083116106cb575b5050505050905061072633308a848e60ff168151811061070557fe5b60200260200101516001600160a01b0316612241909392919063ffffffff16565b604080517f9169558600000000000000000000000000000000000000000000000000000000815260ff808d1660048301528b166024820152604481018a9052606481018990526084810188905290516000916001600160a01b0385169163916955869160a48082019260209290919082900301818787803b1580156107aa57600080fd5b505af11580156107be573d6000803e3d6000fd5b505050506040513d60208110156107d457600080fd5b5051600054604080517fdd62ed3e0000000000000000000000000000000000000000000000000000000081523060048201526001600160a01b03928316602482015290519293508392918f169163dd62ed3e91604480820192602092909190829003018186803b15801561084757600080fd5b505afa15801561085b573d6000803e3d6000fd5b505050506040513d602081101561087157600080fd5b5051101561089557600054610895906001600160a01b038e8116911660001961206a565b60008054906101000a90046001600160a01b03166001600160a01b03166336e712ed8f8f8f858b8b8b6040518863ffffffff1660e01b815260040180886001600160a01b03168152602001878152602001866001600160a01b031681526020018581526020018460ff168152602001838152602001828152602001975050505050505050600060405180830381600087803b15801561093357600080fd5b505af1158015610947573d6000803e3d6000fd5b505050505050505050505050505050505050565b6109706001600160a01b038616333087612241565b600054604080517fdd62ed3e0000000000000000000000000000000000000000000000000000000081523060048201526001600160a01b0392831660248201529051869288169163dd62ed3e916044808301926020929190829003018186803b1580156109dc57600080fd5b505afa1580156109f0573d6000803e3d6000fd5b505050506040513d6020811015610a0657600080fd5b50511015610a2a57600054610a2a906001600160a01b03878116911660001961206a565b60008054604080517f36e712ed0000000000000000000000000000000000000000000000000000000081526001600160a01b038b81166004830152602482018b905289811660448301526064820189905260ff8816608483015260a4820187905260c48201869052915191909216926336e712ed9260e4808201939182900301818387803b158015610abb57600080fd5b505af1158015610acf573d6000803e3d6000fd5b5050505050505050505050565b60026020528160005260406000208181548110610af557fe5b6000918252602090912001546001600160a01b03169150829050565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316610b8c576040805162461bcd60e51b815260206004820152600660248201527f5745544820300000000000000000000000000000000000000000000000000000604482015290519081900360640190fd5b600034118015610b9b57508634145b610bec576040805162461bcd60e51b815260206004820152601360248201527f494e434f5252454354204d53472056414c554500000000000000000000000000604482015290519081900360640190fd5b6001600160a01b03808b166000908152600160205260409020541680610c59576040805162461bcd60e51b815260206004820152600c60248201527f5377617020697320307830300000000000000000000000000000000000000000604482015290519081900360640190fd5b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663d0e30db0346040518263ffffffff1660e01b81526004016000604051808303818588803b158015610cb457600080fd5b505af1158015610cc8573d6000803e3d6000fd5b50505050506000816001600160a01b031663916955868c8c8c8c8c6040518663ffffffff1660e01b8152600401808660ff1681526020018560ff16815260200184815260200183815260200182815260200195505050505050602060405180830381600087803b158015610d3b57600080fd5b505af1158015610d4f573d6000803e3d6000fd5b505050506040513d6020811015610d6557600080fd5b8101908080519060200190929190505050905060008054906101000a90046001600160a01b03166001600160a01b031663839ed90a8f8f8f858b8b8b8b6040518963ffffffff1660e01b815260040180896001600160a01b03168152602001888152602001876001600160a01b031681526020018681526020018560ff1681526020018460ff16815260200183815260200182815260200198505050505050505050600060405180830381600087803b15801561093357600080fd5b610e366001600160a01b038316333084612241565b600054604080517fdd62ed3e0000000000000000000000000000000000000000000000000000000081523060048201526001600160a01b0392831660248201529051839285169163dd62ed3e916044808301926020929190829003018186803b158015610ea257600080fd5b505afa158015610eb6573d6000803e3d6000fd5b505050506040513d6020811015610ecc57600080fd5b50511015610ef057600054610ef0906001600160a01b03848116911660001961206a565b60008054604080517f49b7cf8400000000000000000000000000000000000000000000000000000000815260048101889052602481018790526001600160a01b03868116604483015260648201869052915191909216926349b7cf84926084808201939182900301818387803b158015610f6957600080fd5b505af1158015610f7d573d6000803e3d6000fd5b5050505050505050565b6001600160a01b038087166000908152600160205260409020541680610ff4576040805162461bcd60e51b815260206004820152600c60248201527f5377617020697320307830300000000000000000000000000000000000000000604482015290519081900360640190fd5b6001600160a01b03811660009081526002602090815260409182902080548351818402810184019094528084526060939283018282801561105e57602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311611040575b5050505050905061107a333087848b60ff168151811061070557fe5b604080517f9169558600000000000000000000000000000000000000000000000000000000815260ff808a1660048301528816602482015260448101879052606481018690526084810185905290516000916001600160a01b0385169163916955869160a48082019260209290919082900301818787803b1580156110fe57600080fd5b505af1158015611112573d6000803e3d6000fd5b505050506040513d602081101561112857600080fd5b5051600054604080517fdd62ed3e0000000000000000000000000000000000000000000000000000000081523060048201526001600160a01b03928316602482015290519293508392918c169163dd62ed3e91604480820192602092909190829003018186803b15801561119b57600080fd5b505afa1580156111af573d6000803e3d6000fd5b505050506040513d60208110156111c557600080fd5b505110156111e9576000546111e9906001600160a01b038b8116911660001961206a565b60008054604080517ff3f094a10000000000000000000000000000000000000000000000000000000081526001600160a01b038f81166004830152602482018f90528d81166044830152606482018690529151919092169263f3f094a1926084808201939182900301818387803b15801561126357600080fd5b505af1158015611277573d6000803e3d6000fd5b505050505050505050505050505050565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316611303576040805162461bcd60e51b815260206004820152600660248201527f5745544820300000000000000000000000000000000000000000000000000000604482015290519081900360640190fd5b60003411801561131257508234145b611363576040805162461bcd60e51b815260206004820152601360248201527f494e434f5252454354204d53472056414c554500000000000000000000000000604482015290519081900360640190fd5b6001600160a01b0380871660009081526001602052604090205416806113d0576040805162461bcd60e51b815260206004820152600c60248201527f5377617020697320307830300000000000000000000000000000000000000000604482015290519081900360640190fd5b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663d0e30db0346040518263ffffffff1660e01b81526004016000604051808303818588803b15801561142b57600080fd5b505af115801561143f573d6000803e3d6000fd5b5050604080517f9169558600000000000000000000000000000000000000000000000000000000815260ff808c1660048301528a1660248201526044810189905260648101889052608481018790529051600094506001600160a01b03861693506391695586925060a480830192602092919082900301818787803b1580156114c757600080fd5b505af11580156114db573d6000803e3d6000fd5b505050506040513d60208110156114f157600080fd5b505160008054604080517ff3f094a10000000000000000000000000000000000000000000000000000000081526001600160a01b038f81166004830152602482018f90528d8116604483015260648201869052915194955091169263f3f094a19260848084019391929182900301818387803b15801561157057600080fd5b505af1158015611584573d6000803e3d6000fd5b5050505050505050505050505050565b6001600160a01b0380851660009081526001602090815260408083205481517fa95b089f00000000000000000000000000000000000000000000000000000000815260ff808a1660048301528816602482015260448101879052915193941692839263a95b089f9260648082019391829003018186803b15801561161757600080fd5b505afa15801561162b573d6000803e3d6000fd5b505050506040513d602081101561164157600080fd5b50519695505050505050565b6116626001600160a01b038716333088612241565b600054604080517fdd62ed3e0000000000000000000000000000000000000000000000000000000081523060048201526001600160a01b0392831660248201529051879289169163dd62ed3e916044808301926020929190829003018186803b1580156116ce57600080fd5b505afa1580156116e2573d6000803e3d6000fd5b505050506040513d60208110156116f857600080fd5b5051101561171c5760005461171c906001600160a01b03888116911660001961206a565b60008054604080517f839ed90a0000000000000000000000000000000000000000000000000000000081526001600160a01b038c81166004830152602482018c90528a81166044830152606482018a905260ff808a166084840152881660a483015260c4820187905260e482018690529151919092169263839ed90a92610104808201939182900301818387803b1580156117b657600080fd5b505af11580156117ca573d6000803e3d6000fd5b505050505050505050505050565b6001602052600090815260409020546001600160a01b031681565b6118086001600160a01b038316333084612241565b600054604080517fdd62ed3e0000000000000000000000000000000000000000000000000000000081523060048201526001600160a01b0392831660248201529051839285169163dd62ed3e916044808301926020929190829003018186803b15801561187457600080fd5b505afa158015611888573d6000803e3d6000fd5b505050506040513d602081101561189e57600080fd5b505110156118c2576000546118c2906001600160a01b03848116911660001961206a565b60008054604080517f90d250740000000000000000000000000000000000000000000000000000000081526001600160a01b03888116600483015260248201889052868116604483015260648201869052915191909216926390d25074926084808201939182900301818387803b158015610f6957600080fd5b6001600160a01b038a8116600090815260016020526040902054166119a8576040805162461bcd60e51b815260206004820152600c60248201527f5377617020697320307830300000000000000000000000000000000000000000604482015290519081900360640190fd5b6001600160a01b03808b1660009081526001602090815260408083205490931682526002815290829020805483518184028101840190945280845260609392830182828015611a2057602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311611a02575b50505050509050611a3c33308a848e60ff168151811061070557fe5b6000600160008d6001600160a01b03166001600160a01b0316815260200190815260200160002060009054906101000a90046001600160a01b03166001600160a01b031663916955868c8c8c8c8c6040518663ffffffff1660e01b8152600401808660ff1681526020018560ff16815260200184815260200183815260200182815260200195505050505050602060405180830381600087803b158015611ae257600080fd5b505af1158015611af6573d6000803e3d6000fd5b505050506040513d6020811015611b0c57600080fd5b5051600054604080517fdd62ed3e0000000000000000000000000000000000000000000000000000000081523060048201526001600160a01b03928316602482015290519293508392918f169163dd62ed3e91604480820192602092909190829003018186803b158015611b7f57600080fd5b505afa158015611b93573d6000803e3d6000fd5b505050506040513d6020811015611ba957600080fd5b50511015611bcd57600054611bcd906001600160a01b038e8116911660001961206a565b60008054906101000a90046001600160a01b03166001600160a01b031663839ed90a8f8f8f858b8b8b8b6040518963ffffffff1660e01b815260040180896001600160a01b03168152602001888152602001876001600160a01b031681526020018681526020018560ff1681526020018460ff16815260200183815260200182815260200198505050505050505050600060405180830381600087803b15801561093357600080fd5b600034118015611c8557508034145b611cd6576040805162461bcd60e51b815260206004820152601360248201527f494e434f5252454354204d53472056414c554500000000000000000000000000604482015290519081900360640190fd5b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663d0e30db0346040518263ffffffff1660e01b81526004016000604051808303818588803b158015611d3157600080fd5b505af1158015611d45573d6000803e3d6000fd5b505060008054604080517f90d250740000000000000000000000000000000000000000000000000000000081526001600160a01b038a81166004830152602482018a90527f0000000000000000000000000000000000000000000000000000000000000000811660448301526064820189905291519190921695506390d25074945060848083019450909182900301818387803b158015611de557600080fd5b505af1158015611df9573d6000803e3d6000fd5b50505050505050565b611e176001600160a01b038316333084612241565b600054604080517fdd62ed3e0000000000000000000000000000000000000000000000000000000081523060048201526001600160a01b0392831660248201529051839285169163dd62ed3e916044808301926020929190829003018186803b158015611e8357600080fd5b505afa158015611e97573d6000803e3d6000fd5b505050506040513d6020811015611ead57600080fd5b50511015611ed157600054611ed1906001600160a01b03848116911660001961206a565b60008054604080517ff3f094a10000000000000000000000000000000000000000000000000000000081526001600160a01b038881166004830152602482018890528681166044830152606482018690529151919092169263f3f094a1926084808201939182900301818387803b158015610f6957600080fd5b6000611fe182856001600160a01b031663dd62ed3e30876040518363ffffffff1660e01b815260040180836001600160a01b03168152602001826001600160a01b031681526020019250505060206040518083038186803b158015611faf57600080fd5b505afa158015611fc3573d6000803e3d6000fd5b505050506040513d6020811015611fd957600080fd5b5051906121c9565b604080516001600160a01b038616602482015260448082018490528251808303909101815260649091019091526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f095ea7b3000000000000000000000000000000000000000000000000000000001790529091506120649085906122c5565b50505050565b8015806121095750604080517fdd62ed3e0000000000000000000000000000000000000000000000000000000081523060048201526001600160a01b03848116602483015291519185169163dd62ed3e91604480820192602092909190829003018186803b1580156120db57600080fd5b505afa1580156120ef573d6000803e3d6000fd5b505050506040513d602081101561210557600080fd5b5051155b6121445760405162461bcd60e51b81526004018080602001828103825260368152602001806125eb6036913960400191505060405180910390fd5b604080516001600160a01b038416602482015260448082018490528251808303909101815260649091019091526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f095ea7b3000000000000000000000000000000000000000000000000000000001790526121c49084906122c5565b505050565b600082820183811015612223576040805162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b9392505050565b60606122398484600085612376565b949350505050565b604080516001600160a01b0380861660248301528416604482015260648082018490528251808303909101815260849091019091526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f23b872dd000000000000000000000000000000000000000000000000000000001790526120649085905b606061231a826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b031661222a9092919063ffffffff16565b8051909150156121c45780806020019051602081101561233957600080fd5b50516121c45760405162461bcd60e51b815260040180806020018281038252602a8152602001806125c1602a913960400191505060405180910390fd5b6060824710156123b75760405162461bcd60e51b815260040180806020018281038252602681526020018061259b6026913960400191505060405180910390fd5b6123c0856124f0565b612411576040805162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000604482015290519081900360640190fd5b60006060866001600160a01b031685876040518082805190602001908083835b6020831061246e57805182527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe09092019160209182019101612431565b6001836020036101000a03801982511681845116808217855250505050505090500191505060006040518083038185875af1925050503d80600081146124d0576040519150601f19603f3d011682016040523d82523d6000602084013e6124d5565b606091505b50915091506124e58282866124f6565b979650505050505050565b3b151590565b60608315612505575081612223565b8251156125155782518084602001fd5b8160405162461bcd60e51b81526004018080602001828103825283818151815260200191508051906020019080838360005b8381101561255f578181015183820152602001612547565b50505050905090810190601f16801561258c5780820380516001836020036101000a031916815260200191505b509250505060405180910390fdfe416464726573733a20696e73756666696369656e742062616c616e636520666f722063616c6c5361666545524332303a204552433230206f7065726174696f6e20646964206e6f7420737563636565645361666545524332303a20617070726f76652066726f6d206e6f6e2d7a65726f20746f206e6f6e2d7a65726f20616c6c6f77616e6365a264697066735822122086f0b6eef8d1c8fa1defa89c8ce1494b6429d2d219bf49226585f9129da06b1e64736f6c634300060c0033416464726573733a20696e73756666696369656e742062616c616e636520666f722063616c6c73776170206d7573742068617665206174206c65617374203220746f6b656e735361666545524332303a204552433230206f7065726174696f6e20646964206e6f7420737563636565645361666545524332303a20617070726f76652066726f6d206e6f6e2d7a65726f20746f206e6f6e2d7a65726f20616c6c6f77616e6365", + "deployedBytecode": "0x6080604052600436106100e85760003560e01c806365749c9d1161008a57806390d250741161005957806390d25074146104a95780639f330727146104f0578063ce0b63ce14610575578063f3f094a1146105a7576100e8565b806365749c9d14610357578063798af720146103b1578063839ed90a1461040f57806385528f0b14610476576100e8565b8063393494b8116100c6578063393494b8146101fa5780633d5da1641461023357806349b7cf84146102ab5780634a517a55146102f0576100e8565b8063040141e5146100ed578063174dc9521461011e57806336e712ed1461019e575b600080fd5b3480156100f957600080fd5b506101026105ee565b604080516001600160a01b039092168252519081900360200190f35b34801561012a57600080fd5b5061019c600480360361016081101561014257600080fd5b506001600160a01b0381358116916020810135916040820135169060ff6060820135811691608081013582169160a08201359160c08101359160e08201359161010081013590911690610120810135906101400135610612565b005b3480156101aa57600080fd5b5061019c600480360360e08110156101c157600080fd5b506001600160a01b0381358116916020810135916040820135169060608101359060ff6080820135169060a08101359060c0013561095b565b34801561020657600080fd5b506101026004803603604081101561021d57600080fd5b506001600160a01b038135169060200135610adc565b61019c600480360361018081101561024a57600080fd5b506001600160a01b0381358116916020810135916040820135169060ff6060820135811691608081013582169160a08201359160c08101359160e0820135916101008101358216916101208201351690610140810135906101600135610b11565b3480156102b757600080fd5b5061019c600480360360808110156102ce57600080fd5b508035906020810135906001600160a01b036040820135169060600135610e21565b3480156102fc57600080fd5b5061019c600480360361010081101561031457600080fd5b506001600160a01b0381358116916020810135916040820135169060ff606082013581169160808101359091169060a08101359060c08101359060e00135610f87565b61019c600480360361010081101561036e57600080fd5b506001600160a01b0381358116916020810135916040820135169060ff606082013581169160808101359091169060a08101359060c08101359060e00135611288565b3480156103bd57600080fd5b506103fd600480360360808110156103d457600080fd5b506001600160a01b038135169060ff602082013581169160408101359091169060600135611594565b60408051918252519081900360200190f35b34801561041b57600080fd5b5061019c600480360361010081101561043357600080fd5b506001600160a01b0381358116916020810135916040820135169060608101359060ff608082013581169160a08101359091169060c08101359060e0013561164d565b34801561048257600080fd5b506101026004803603602081101561049957600080fd5b50356001600160a01b03166117d8565b3480156104b557600080fd5b5061019c600480360360808110156104cc57600080fd5b506001600160a01b03813581169160208101359160408201351690606001356117f3565b3480156104fc57600080fd5b5061019c600480360361018081101561051457600080fd5b506001600160a01b0381358116916020810135916040820135169060ff6060820135811691608081013582169160a08201359160c08101359160e082013591610100810135821691610120820135169061014081013590610160013561193c565b61019c6004803603606081101561058b57600080fd5b506001600160a01b038135169060208101359060400135611c76565b3480156105b357600080fd5b5061019c600480360360808110156105ca57600080fd5b506001600160a01b0381358116916020810135916040820135169060600135611e02565b7f000000000000000000000000000000000000000000000000000000000000000081565b6001600160a01b03808a16600090815260016020526040902054168061067f576040805162461bcd60e51b815260206004820152600c60248201527f5377617020697320307830300000000000000000000000000000000000000000604482015290519081900360640190fd5b6001600160a01b0381166000908152600260209081526040918290208054835181840281018401909452808452606093928301828280156106e957602002820191906000526020600020905b81546001600160a01b031681526001909101906020018083116106cb575b5050505050905061072633308a848e60ff168151811061070557fe5b60200260200101516001600160a01b0316612241909392919063ffffffff16565b604080517f9169558600000000000000000000000000000000000000000000000000000000815260ff808d1660048301528b166024820152604481018a9052606481018990526084810188905290516000916001600160a01b0385169163916955869160a48082019260209290919082900301818787803b1580156107aa57600080fd5b505af11580156107be573d6000803e3d6000fd5b505050506040513d60208110156107d457600080fd5b5051600054604080517fdd62ed3e0000000000000000000000000000000000000000000000000000000081523060048201526001600160a01b03928316602482015290519293508392918f169163dd62ed3e91604480820192602092909190829003018186803b15801561084757600080fd5b505afa15801561085b573d6000803e3d6000fd5b505050506040513d602081101561087157600080fd5b5051101561089557600054610895906001600160a01b038e8116911660001961206a565b60008054906101000a90046001600160a01b03166001600160a01b03166336e712ed8f8f8f858b8b8b6040518863ffffffff1660e01b815260040180886001600160a01b03168152602001878152602001866001600160a01b031681526020018581526020018460ff168152602001838152602001828152602001975050505050505050600060405180830381600087803b15801561093357600080fd5b505af1158015610947573d6000803e3d6000fd5b505050505050505050505050505050505050565b6109706001600160a01b038616333087612241565b600054604080517fdd62ed3e0000000000000000000000000000000000000000000000000000000081523060048201526001600160a01b0392831660248201529051869288169163dd62ed3e916044808301926020929190829003018186803b1580156109dc57600080fd5b505afa1580156109f0573d6000803e3d6000fd5b505050506040513d6020811015610a0657600080fd5b50511015610a2a57600054610a2a906001600160a01b03878116911660001961206a565b60008054604080517f36e712ed0000000000000000000000000000000000000000000000000000000081526001600160a01b038b81166004830152602482018b905289811660448301526064820189905260ff8816608483015260a4820187905260c48201869052915191909216926336e712ed9260e4808201939182900301818387803b158015610abb57600080fd5b505af1158015610acf573d6000803e3d6000fd5b5050505050505050505050565b60026020528160005260406000208181548110610af557fe5b6000918252602090912001546001600160a01b03169150829050565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316610b8c576040805162461bcd60e51b815260206004820152600660248201527f5745544820300000000000000000000000000000000000000000000000000000604482015290519081900360640190fd5b600034118015610b9b57508634145b610bec576040805162461bcd60e51b815260206004820152601360248201527f494e434f5252454354204d53472056414c554500000000000000000000000000604482015290519081900360640190fd5b6001600160a01b03808b166000908152600160205260409020541680610c59576040805162461bcd60e51b815260206004820152600c60248201527f5377617020697320307830300000000000000000000000000000000000000000604482015290519081900360640190fd5b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663d0e30db0346040518263ffffffff1660e01b81526004016000604051808303818588803b158015610cb457600080fd5b505af1158015610cc8573d6000803e3d6000fd5b50505050506000816001600160a01b031663916955868c8c8c8c8c6040518663ffffffff1660e01b8152600401808660ff1681526020018560ff16815260200184815260200183815260200182815260200195505050505050602060405180830381600087803b158015610d3b57600080fd5b505af1158015610d4f573d6000803e3d6000fd5b505050506040513d6020811015610d6557600080fd5b8101908080519060200190929190505050905060008054906101000a90046001600160a01b03166001600160a01b031663839ed90a8f8f8f858b8b8b8b6040518963ffffffff1660e01b815260040180896001600160a01b03168152602001888152602001876001600160a01b031681526020018681526020018560ff1681526020018460ff16815260200183815260200182815260200198505050505050505050600060405180830381600087803b15801561093357600080fd5b610e366001600160a01b038316333084612241565b600054604080517fdd62ed3e0000000000000000000000000000000000000000000000000000000081523060048201526001600160a01b0392831660248201529051839285169163dd62ed3e916044808301926020929190829003018186803b158015610ea257600080fd5b505afa158015610eb6573d6000803e3d6000fd5b505050506040513d6020811015610ecc57600080fd5b50511015610ef057600054610ef0906001600160a01b03848116911660001961206a565b60008054604080517f49b7cf8400000000000000000000000000000000000000000000000000000000815260048101889052602481018790526001600160a01b03868116604483015260648201869052915191909216926349b7cf84926084808201939182900301818387803b158015610f6957600080fd5b505af1158015610f7d573d6000803e3d6000fd5b5050505050505050565b6001600160a01b038087166000908152600160205260409020541680610ff4576040805162461bcd60e51b815260206004820152600c60248201527f5377617020697320307830300000000000000000000000000000000000000000604482015290519081900360640190fd5b6001600160a01b03811660009081526002602090815260409182902080548351818402810184019094528084526060939283018282801561105e57602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311611040575b5050505050905061107a333087848b60ff168151811061070557fe5b604080517f9169558600000000000000000000000000000000000000000000000000000000815260ff808a1660048301528816602482015260448101879052606481018690526084810185905290516000916001600160a01b0385169163916955869160a48082019260209290919082900301818787803b1580156110fe57600080fd5b505af1158015611112573d6000803e3d6000fd5b505050506040513d602081101561112857600080fd5b5051600054604080517fdd62ed3e0000000000000000000000000000000000000000000000000000000081523060048201526001600160a01b03928316602482015290519293508392918c169163dd62ed3e91604480820192602092909190829003018186803b15801561119b57600080fd5b505afa1580156111af573d6000803e3d6000fd5b505050506040513d60208110156111c557600080fd5b505110156111e9576000546111e9906001600160a01b038b8116911660001961206a565b60008054604080517ff3f094a10000000000000000000000000000000000000000000000000000000081526001600160a01b038f81166004830152602482018f90528d81166044830152606482018690529151919092169263f3f094a1926084808201939182900301818387803b15801561126357600080fd5b505af1158015611277573d6000803e3d6000fd5b505050505050505050505050505050565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316611303576040805162461bcd60e51b815260206004820152600660248201527f5745544820300000000000000000000000000000000000000000000000000000604482015290519081900360640190fd5b60003411801561131257508234145b611363576040805162461bcd60e51b815260206004820152601360248201527f494e434f5252454354204d53472056414c554500000000000000000000000000604482015290519081900360640190fd5b6001600160a01b0380871660009081526001602052604090205416806113d0576040805162461bcd60e51b815260206004820152600c60248201527f5377617020697320307830300000000000000000000000000000000000000000604482015290519081900360640190fd5b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663d0e30db0346040518263ffffffff1660e01b81526004016000604051808303818588803b15801561142b57600080fd5b505af115801561143f573d6000803e3d6000fd5b5050604080517f9169558600000000000000000000000000000000000000000000000000000000815260ff808c1660048301528a1660248201526044810189905260648101889052608481018790529051600094506001600160a01b03861693506391695586925060a480830192602092919082900301818787803b1580156114c757600080fd5b505af11580156114db573d6000803e3d6000fd5b505050506040513d60208110156114f157600080fd5b505160008054604080517ff3f094a10000000000000000000000000000000000000000000000000000000081526001600160a01b038f81166004830152602482018f90528d8116604483015260648201869052915194955091169263f3f094a19260848084019391929182900301818387803b15801561157057600080fd5b505af1158015611584573d6000803e3d6000fd5b5050505050505050505050505050565b6001600160a01b0380851660009081526001602090815260408083205481517fa95b089f00000000000000000000000000000000000000000000000000000000815260ff808a1660048301528816602482015260448101879052915193941692839263a95b089f9260648082019391829003018186803b15801561161757600080fd5b505afa15801561162b573d6000803e3d6000fd5b505050506040513d602081101561164157600080fd5b50519695505050505050565b6116626001600160a01b038716333088612241565b600054604080517fdd62ed3e0000000000000000000000000000000000000000000000000000000081523060048201526001600160a01b0392831660248201529051879289169163dd62ed3e916044808301926020929190829003018186803b1580156116ce57600080fd5b505afa1580156116e2573d6000803e3d6000fd5b505050506040513d60208110156116f857600080fd5b5051101561171c5760005461171c906001600160a01b03888116911660001961206a565b60008054604080517f839ed90a0000000000000000000000000000000000000000000000000000000081526001600160a01b038c81166004830152602482018c90528a81166044830152606482018a905260ff808a166084840152881660a483015260c4820187905260e482018690529151919092169263839ed90a92610104808201939182900301818387803b1580156117b657600080fd5b505af11580156117ca573d6000803e3d6000fd5b505050505050505050505050565b6001602052600090815260409020546001600160a01b031681565b6118086001600160a01b038316333084612241565b600054604080517fdd62ed3e0000000000000000000000000000000000000000000000000000000081523060048201526001600160a01b0392831660248201529051839285169163dd62ed3e916044808301926020929190829003018186803b15801561187457600080fd5b505afa158015611888573d6000803e3d6000fd5b505050506040513d602081101561189e57600080fd5b505110156118c2576000546118c2906001600160a01b03848116911660001961206a565b60008054604080517f90d250740000000000000000000000000000000000000000000000000000000081526001600160a01b03888116600483015260248201889052868116604483015260648201869052915191909216926390d25074926084808201939182900301818387803b158015610f6957600080fd5b6001600160a01b038a8116600090815260016020526040902054166119a8576040805162461bcd60e51b815260206004820152600c60248201527f5377617020697320307830300000000000000000000000000000000000000000604482015290519081900360640190fd5b6001600160a01b03808b1660009081526001602090815260408083205490931682526002815290829020805483518184028101840190945280845260609392830182828015611a2057602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311611a02575b50505050509050611a3c33308a848e60ff168151811061070557fe5b6000600160008d6001600160a01b03166001600160a01b0316815260200190815260200160002060009054906101000a90046001600160a01b03166001600160a01b031663916955868c8c8c8c8c6040518663ffffffff1660e01b8152600401808660ff1681526020018560ff16815260200184815260200183815260200182815260200195505050505050602060405180830381600087803b158015611ae257600080fd5b505af1158015611af6573d6000803e3d6000fd5b505050506040513d6020811015611b0c57600080fd5b5051600054604080517fdd62ed3e0000000000000000000000000000000000000000000000000000000081523060048201526001600160a01b03928316602482015290519293508392918f169163dd62ed3e91604480820192602092909190829003018186803b158015611b7f57600080fd5b505afa158015611b93573d6000803e3d6000fd5b505050506040513d6020811015611ba957600080fd5b50511015611bcd57600054611bcd906001600160a01b038e8116911660001961206a565b60008054906101000a90046001600160a01b03166001600160a01b031663839ed90a8f8f8f858b8b8b8b6040518963ffffffff1660e01b815260040180896001600160a01b03168152602001888152602001876001600160a01b031681526020018681526020018560ff1681526020018460ff16815260200183815260200182815260200198505050505050505050600060405180830381600087803b15801561093357600080fd5b600034118015611c8557508034145b611cd6576040805162461bcd60e51b815260206004820152601360248201527f494e434f5252454354204d53472056414c554500000000000000000000000000604482015290519081900360640190fd5b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663d0e30db0346040518263ffffffff1660e01b81526004016000604051808303818588803b158015611d3157600080fd5b505af1158015611d45573d6000803e3d6000fd5b505060008054604080517f90d250740000000000000000000000000000000000000000000000000000000081526001600160a01b038a81166004830152602482018a90527f0000000000000000000000000000000000000000000000000000000000000000811660448301526064820189905291519190921695506390d25074945060848083019450909182900301818387803b158015611de557600080fd5b505af1158015611df9573d6000803e3d6000fd5b50505050505050565b611e176001600160a01b038316333084612241565b600054604080517fdd62ed3e0000000000000000000000000000000000000000000000000000000081523060048201526001600160a01b0392831660248201529051839285169163dd62ed3e916044808301926020929190829003018186803b158015611e8357600080fd5b505afa158015611e97573d6000803e3d6000fd5b505050506040513d6020811015611ead57600080fd5b50511015611ed157600054611ed1906001600160a01b03848116911660001961206a565b60008054604080517ff3f094a10000000000000000000000000000000000000000000000000000000081526001600160a01b038881166004830152602482018890528681166044830152606482018690529151919092169263f3f094a1926084808201939182900301818387803b158015610f6957600080fd5b6000611fe182856001600160a01b031663dd62ed3e30876040518363ffffffff1660e01b815260040180836001600160a01b03168152602001826001600160a01b031681526020019250505060206040518083038186803b158015611faf57600080fd5b505afa158015611fc3573d6000803e3d6000fd5b505050506040513d6020811015611fd957600080fd5b5051906121c9565b604080516001600160a01b038616602482015260448082018490528251808303909101815260649091019091526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f095ea7b3000000000000000000000000000000000000000000000000000000001790529091506120649085906122c5565b50505050565b8015806121095750604080517fdd62ed3e0000000000000000000000000000000000000000000000000000000081523060048201526001600160a01b03848116602483015291519185169163dd62ed3e91604480820192602092909190829003018186803b1580156120db57600080fd5b505afa1580156120ef573d6000803e3d6000fd5b505050506040513d602081101561210557600080fd5b5051155b6121445760405162461bcd60e51b81526004018080602001828103825260368152602001806125eb6036913960400191505060405180910390fd5b604080516001600160a01b038416602482015260448082018490528251808303909101815260649091019091526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f095ea7b3000000000000000000000000000000000000000000000000000000001790526121c49084906122c5565b505050565b600082820183811015612223576040805162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b9392505050565b60606122398484600085612376565b949350505050565b604080516001600160a01b0380861660248301528416604482015260648082018490528251808303909101815260849091019091526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f23b872dd000000000000000000000000000000000000000000000000000000001790526120649085905b606061231a826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b031661222a9092919063ffffffff16565b8051909150156121c45780806020019051602081101561233957600080fd5b50516121c45760405162461bcd60e51b815260040180806020018281038252602a8152602001806125c1602a913960400191505060405180910390fd5b6060824710156123b75760405162461bcd60e51b815260040180806020018281038252602681526020018061259b6026913960400191505060405180910390fd5b6123c0856124f0565b612411576040805162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000604482015290519081900360640190fd5b60006060866001600160a01b031685876040518082805190602001908083835b6020831061246e57805182527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe09092019160209182019101612431565b6001836020036101000a03801982511681845116808217855250505050505090500191505060006040518083038185875af1925050503d80600081146124d0576040519150601f19603f3d011682016040523d82523d6000602084013e6124d5565b606091505b50915091506124e58282866124f6565b979650505050505050565b3b151590565b60608315612505575081612223565b8251156125155782518084602001fd5b8160405162461bcd60e51b81526004018080602001828103825283818151815260200191508051906020019080838360005b8381101561255f578181015183820152602001612547565b50505050905090810190601f16801561258c5780820380516001836020036101000a031916815260200191505b509250505060405180910390fdfe416464726573733a20696e73756666696369656e742062616c616e636520666f722063616c6c5361666545524332303a204552433230206f7065726174696f6e20646964206e6f7420737563636565645361666545524332303a20617070726f76652066726f6d206e6f6e2d7a65726f20746f206e6f6e2d7a65726f20616c6c6f77616e6365a264697066735822122086f0b6eef8d1c8fa1defa89c8ce1494b6429d2d219bf49226585f9129da06b1e64736f6c634300060c0033", + "devdoc": { + "kind": "dev", + "methods": { + "calculateSwap(address,uint8,uint8,uint256)": { + "params": { + "dx": "the amount of tokens the user wants to sell. If the token charges a fee on transfers, use the amount that gets transferred after the fee.", + "tokenIndexFrom": "the token the user wants to sell", + "tokenIndexTo": "the token the user wants to buy" + }, + "returns": { + "_0": "amount of tokens the user will receive" + } + }, + "deposit(address,uint256,address,uint256)": { + "params": { + "amount": "Amount in native token decimals to transfer cross-chain pre-fees*", + "chainId": "which underlying chain to bridge assets onto", + "to": "address on other chain to redeem underlying assets to", + "token": "ERC20 compatible token to deposit into the bridge" + } + }, + "depositETH(address,uint256,uint256)": { + "params": { + "amount": "Amount in native token decimals to transfer cross-chain pre-fees*", + "chainId": "which chain to bridge assets onto", + "to": "address on other chain to bridge assets to" + } + }, + "redeem(address,uint256,address,uint256)": { + "params": { + "amount": "Amount in native token decimals to transfer cross-chain pre-fees*", + "chainId": "which underlying chain to bridge assets onto", + "to": "address on other chain to redeem underlying assets to", + "token": "ERC20 compatible token to deposit into the bridge" + } + }, + "redeemAndRemove(address,uint256,address,uint256,uint8,uint256,uint256)": { + "params": { + "amount": "Amount of (typically) LP token to pass to the nodes to attempt to removeLiquidity() with to redeem for the underlying assets of the LP token", + "chainId": "which underlying chain to bridge assets onto", + "liqDeadline": "Specificies the deadline that the nodes are allowed to try to redeem/swap the LP token*", + "liqMinAmount": "Specifies the minimum amount of the underlying asset needed for the nodes to execute the redeem/swap", + "liqTokenIndex": "Specifies which of the underlying LP assets the nodes should attempt to redeem for", + "to": "address on other chain to redeem underlying assets to", + "token": "ERC20 compatible token to deposit into the bridge" + } + }, + "redeemAndSwap(address,uint256,address,uint256,uint8,uint8,uint256,uint256)": { + "params": { + "amount": "Amount in native token decimals to transfer cross-chain pre-fees", + "chainId": "which underlying chain to bridge assets onto", + "deadline": "latest timestamp to accept this transaction*", + "minDy": "the min amount the user would like to receive, or revert to only minting the SynERC20 token crosschain.", + "to": "address on other chain to redeem underlying assets to", + "token": "ERC20 compatible token to deposit into the bridge", + "tokenIndexFrom": "the token the user wants to swap from", + "tokenIndexTo": "the token the user wants to swap to" + } + }, + "redeemv2(bytes32,uint256,address,uint256)": { + "params": { + "amount": "Amount in native token decimals to transfer cross-chain pre-fees*", + "chainId": "which chain to bridge assets onto", + "to": "address on other chain to bridge assets to", + "token": "ERC20 compatible token to redeem into the bridge" + } + } + }, + "version": 1 + }, + "userdoc": { + "kind": "user", + "methods": { + "calculateSwap(address,uint8,uint8,uint256)": { + "notice": "Calculate amount of tokens you receive on swap" + }, + "deposit(address,uint256,address,uint256)": { + "notice": "wraps SynapseBridge redeem()" + }, + "depositETH(address,uint256,uint256)": { + "notice": "Wraps SynapseBridge deposit() function to make it compatible w/ ETH -> WETH conversions" + }, + "redeem(address,uint256,address,uint256)": { + "notice": "wraps SynapseBridge redeem()" + }, + "redeemAndRemove(address,uint256,address,uint256,uint8,uint256,uint256)": { + "notice": "Wraps redeemAndRemove on SynapseBridge Relays to nodes that (typically) a wrapped synAsset ERC20 token has been burned and the underlying needs to be redeeemed on the native chain. This function indicates to the nodes that they should attempt to redeem the LP token for the underlying assets (E.g \"swap\" out of the LP token)" + }, + "redeemAndSwap(address,uint256,address,uint256,uint8,uint8,uint256,uint256)": { + "notice": "Wraps redeemAndSwap on SynapseBridge.sol Relays to nodes that (typically) a wrapped synAsset ERC20 token has been burned and the underlying needs to be redeeemed on the native chain. This function indicates to the nodes that they should attempt to redeem the LP token for the underlying assets (E.g \"swap\" out of the LP token)" + }, + "redeemv2(bytes32,uint256,address,uint256)": { + "notice": "Wraps SynapseBridge redeemv2() function" + } + }, + "version": 1 + }, + "storageLayout": { + "storage": [ + { + "astId": 25403, + "contract": "contracts/bridge/wrappers/L2BridgeZap.sol:L2BridgeZap", + "label": "synapseBridge", + "offset": 0, + "slot": "0", + "type": "t_contract(ISynapseBridge)20970" + }, + { + "astId": 25409, + "contract": "contracts/bridge/wrappers/L2BridgeZap.sol:L2BridgeZap", + "label": "swapMap", + "offset": 0, + "slot": "1", + "type": "t_mapping(t_address,t_address)" + }, + { + "astId": 25414, + "contract": "contracts/bridge/wrappers/L2BridgeZap.sol:L2BridgeZap", + "label": "swapTokensMap", + "offset": 0, + "slot": "2", + "type": "t_mapping(t_address,t_array(t_contract(IERC20)4954)dyn_storage)" + } + ], + "types": { + "t_address": { + "encoding": "inplace", + "label": "address", + "numberOfBytes": "20" + }, + "t_array(t_contract(IERC20)4954)dyn_storage": { + "base": "t_contract(IERC20)4954", + "encoding": "dynamic_array", + "label": "contract IERC20[]", + "numberOfBytes": "32" + }, + "t_contract(IERC20)4954": { + "encoding": "inplace", + "label": "contract IERC20", + "numberOfBytes": "20" + }, + "t_contract(ISynapseBridge)20970": { + "encoding": "inplace", + "label": "contract ISynapseBridge", + "numberOfBytes": "20" + }, + "t_mapping(t_address,t_address)": { + "encoding": "mapping", + "key": "t_address", + "label": "mapping(address => address)", + "numberOfBytes": "32", + "value": "t_address" + }, + "t_mapping(t_address,t_array(t_contract(IERC20)4954)dyn_storage)": { + "encoding": "mapping", + "key": "t_address", + "label": "mapping(address => contract IERC20[])", + "numberOfBytes": "32", + "value": "t_array(t_contract(IERC20)4954)dyn_storage" + } + } + } +} \ No newline at end of file diff --git a/deployments/dfk/MiniChefV2.json b/deployments/dfk/MiniChefV2.json new file mode 100644 index 000000000..203d504c7 --- /dev/null +++ b/deployments/dfk/MiniChefV2.json @@ -0,0 +1,1160 @@ +{ + "address": "0x164c02a681282faaddf4bb10cfab599a8999ed20", + "abi": [ + { + "inputs": [ + { + "internalType": "contract IERC20", + "name": "_synapse", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "user", + "type": "address" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "pid", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "Deposit", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "user", + "type": "address" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "pid", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "EmergencyWithdraw", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "user", + "type": "address" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "pid", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "Harvest", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "pid", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "allocPoint", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "contract IERC20", + "name": "lpToken", + "type": "address" + }, + { + "indexed": true, + "internalType": "contract IRewarder", + "name": "rewarder", + "type": "address" + } + ], + "name": "LogPoolAddition", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "pid", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "allocPoint", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "contract IRewarder", + "name": "rewarder", + "type": "address" + }, + { + "indexed": false, + "internalType": "bool", + "name": "overwrite", + "type": "bool" + } + ], + "name": "LogSetPool", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "synapsePerSecond", + "type": "uint256" + } + ], + "name": "LogSynapsePerSecond", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "pid", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint64", + "name": "lastRewardTime", + "type": "uint64" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "lpSupply", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "accSynapsePerShare", + "type": "uint256" + } + ], + "name": "LogUpdatePool", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "previousOwner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "OwnershipTransferred", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "user", + "type": "address" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "pid", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "Withdraw", + "type": "event" + }, + { + "inputs": [], + "name": "SYNAPSE", + "outputs": [ + { + "internalType": "contract IERC20", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "allocPoint", + "type": "uint256" + }, + { + "internalType": "contract IERC20", + "name": "_lpToken", + "type": "address" + }, + { + "internalType": "contract IRewarder", + "name": "_rewarder", + "type": "address" + } + ], + "name": "add", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes[]", + "name": "calls", + "type": "bytes[]" + }, + { + "internalType": "bool", + "name": "revertOnFail", + "type": "bool" + } + ], + "name": "batch", + "outputs": [ + { + "internalType": "bool[]", + "name": "successes", + "type": "bool[]" + }, + { + "internalType": "bytes[]", + "name": "results", + "type": "bytes[]" + } + ], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [], + "name": "claimOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "pid", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "deposit", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "pid", + "type": "uint256" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "emergencyWithdraw", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "pid", + "type": "uint256" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "harvest", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "lpToken", + "outputs": [ + { + "internalType": "contract IERC20", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256[]", + "name": "pids", + "type": "uint256[]" + } + ], + "name": "massUpdatePools", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "pendingOwner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_pid", + "type": "uint256" + }, + { + "internalType": "address", + "name": "_user", + "type": "address" + } + ], + "name": "pendingSynapse", + "outputs": [ + { + "internalType": "uint256", + "name": "pending", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract IERC20", + "name": "token", + "type": "address" + }, + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" + }, + { + "internalType": "uint8", + "name": "v", + "type": "uint8" + }, + { + "internalType": "bytes32", + "name": "r", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "s", + "type": "bytes32" + } + ], + "name": "permitToken", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "poolInfo", + "outputs": [ + { + "internalType": "uint128", + "name": "accSynapsePerShare", + "type": "uint128" + }, + { + "internalType": "uint64", + "name": "lastRewardTime", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "allocPoint", + "type": "uint64" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "poolLength", + "outputs": [ + { + "internalType": "uint256", + "name": "pools", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "rewarder", + "outputs": [ + { + "internalType": "contract IRewarder", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_pid", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_allocPoint", + "type": "uint256" + }, + { + "internalType": "contract IRewarder", + "name": "_rewarder", + "type": "address" + }, + { + "internalType": "bool", + "name": "overwrite", + "type": "bool" + } + ], + "name": "set", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_synapsePerSecond", + "type": "uint256" + } + ], + "name": "setSynapsePerSecond", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "synapsePerSecond", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "totalAllocPoint", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newOwner", + "type": "address" + }, + { + "internalType": "bool", + "name": "direct", + "type": "bool" + }, + { + "internalType": "bool", + "name": "renounce", + "type": "bool" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "pid", + "type": "uint256" + } + ], + "name": "updatePool", + "outputs": [ + { + "components": [ + { + "internalType": "uint128", + "name": "accSynapsePerShare", + "type": "uint128" + }, + { + "internalType": "uint64", + "name": "lastRewardTime", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "allocPoint", + "type": "uint64" + } + ], + "internalType": "struct MiniChefV2.PoolInfo", + "name": "pool", + "type": "tuple" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "userInfo", + "outputs": [ + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "internalType": "int256", + "name": "rewardDebt", + "type": "int256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "pid", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "withdraw", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "pid", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "withdrawAndHarvest", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } + ], + "transactionHash": "0x5d81b6dc923b8a50908e6db5d7e973a5463499c9410b5369a4df6f594da3edb2", + "receipt": { + "to": null, + "from": "0x235af07e770f474d24f5bf73074735892371b40d", + "contractAddress": "0x164c02a681282faaddf4bb10cfab599a8999ed20", + "transactionIndex": "0x0", + "gasUsed": "0x2564b7", + "logsBloom": "0x00000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000001000080000000000000000000000800000000020000000000000000000800000000000000000000000000000000400000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000020000000000000000000000000000000000800000000000000000000000000000000", + "blockHash": "0xf74d80d20c7478ab308b8155c21d7b9e721a8c4d5db9af6b546bdfcbb2df68a4", + "transactionHash": "0x5d81b6dc923b8a50908e6db5d7e973a5463499c9410b5369a4df6f594da3edb2", + "logs": [ + { + "address": "0x164c02a681282faaddf4bb10cfab599a8999ed20", + "topics": [ + "0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x000000000000000000000000235af07e770f474d24f5bf73074735892371b40d" + ], + "data": "0x", + "blockNumber": "0x43", + "transactionHash": "0x5d81b6dc923b8a50908e6db5d7e973a5463499c9410b5369a4df6f594da3edb2", + "transactionIndex": "0x0", + "blockHash": "0xf74d80d20c7478ab308b8155c21d7b9e721a8c4d5db9af6b546bdfcbb2df68a4", + "logIndex": "0x0", + "removed": false + } + ], + "blockNumber": "0x43", + "cumulativeGasUsed": "0x2564b7", + "status": "0x1" + }, + "args": [ + "0xB6b5C854a8f71939556d4f3a2e5829F7FcC1bf2A" + ], + "solcInputHash": "76b4e8a3d6fd1a3364758c7f6c169cd0", + "metadata": "{\"compiler\":{\"version\":\"0.6.12+commit.27d51765\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"contract IERC20\",\"name\":\"_synapse\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"user\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"pid\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"Deposit\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"user\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"pid\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"EmergencyWithdraw\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"user\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"pid\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"Harvest\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"pid\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"allocPoint\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"contract IERC20\",\"name\":\"lpToken\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"contract IRewarder\",\"name\":\"rewarder\",\"type\":\"address\"}],\"name\":\"LogPoolAddition\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"pid\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"allocPoint\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"contract IRewarder\",\"name\":\"rewarder\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"bool\",\"name\":\"overwrite\",\"type\":\"bool\"}],\"name\":\"LogSetPool\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"synapsePerSecond\",\"type\":\"uint256\"}],\"name\":\"LogSynapsePerSecond\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"pid\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"lastRewardTime\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"lpSupply\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"accSynapsePerShare\",\"type\":\"uint256\"}],\"name\":\"LogUpdatePool\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"previousOwner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"user\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"pid\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"Withdraw\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"SYNAPSE\",\"outputs\":[{\"internalType\":\"contract IERC20\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"allocPoint\",\"type\":\"uint256\"},{\"internalType\":\"contract IERC20\",\"name\":\"_lpToken\",\"type\":\"address\"},{\"internalType\":\"contract IRewarder\",\"name\":\"_rewarder\",\"type\":\"address\"}],\"name\":\"add\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes[]\",\"name\":\"calls\",\"type\":\"bytes[]\"},{\"internalType\":\"bool\",\"name\":\"revertOnFail\",\"type\":\"bool\"}],\"name\":\"batch\",\"outputs\":[{\"internalType\":\"bool[]\",\"name\":\"successes\",\"type\":\"bool[]\"},{\"internalType\":\"bytes[]\",\"name\":\"results\",\"type\":\"bytes[]\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"claimOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"pid\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"deposit\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"pid\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"emergencyWithdraw\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"pid\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"harvest\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"lpToken\",\"outputs\":[{\"internalType\":\"contract IERC20\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256[]\",\"name\":\"pids\",\"type\":\"uint256[]\"}],\"name\":\"massUpdatePools\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"pendingOwner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_pid\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"_user\",\"type\":\"address\"}],\"name\":\"pendingSynapse\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"pending\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contract IERC20\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"deadline\",\"type\":\"uint256\"},{\"internalType\":\"uint8\",\"name\":\"v\",\"type\":\"uint8\"},{\"internalType\":\"bytes32\",\"name\":\"r\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"s\",\"type\":\"bytes32\"}],\"name\":\"permitToken\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"poolInfo\",\"outputs\":[{\"internalType\":\"uint128\",\"name\":\"accSynapsePerShare\",\"type\":\"uint128\"},{\"internalType\":\"uint64\",\"name\":\"lastRewardTime\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"allocPoint\",\"type\":\"uint64\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"poolLength\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"pools\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"rewarder\",\"outputs\":[{\"internalType\":\"contract IRewarder\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_pid\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_allocPoint\",\"type\":\"uint256\"},{\"internalType\":\"contract IRewarder\",\"name\":\"_rewarder\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"overwrite\",\"type\":\"bool\"}],\"name\":\"set\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_synapsePerSecond\",\"type\":\"uint256\"}],\"name\":\"setSynapsePerSecond\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"synapsePerSecond\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"totalAllocPoint\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"direct\",\"type\":\"bool\"},{\"internalType\":\"bool\",\"name\":\"renounce\",\"type\":\"bool\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"pid\",\"type\":\"uint256\"}],\"name\":\"updatePool\",\"outputs\":[{\"components\":[{\"internalType\":\"uint128\",\"name\":\"accSynapsePerShare\",\"type\":\"uint128\"},{\"internalType\":\"uint64\",\"name\":\"lastRewardTime\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"allocPoint\",\"type\":\"uint64\"}],\"internalType\":\"struct MiniChefV2.PoolInfo\",\"name\":\"pool\",\"type\":\"tuple\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"userInfo\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"int256\",\"name\":\"rewardDebt\",\"type\":\"int256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"pid\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"withdraw\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"pid\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"withdrawAndHarvest\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{\"add(uint256,address,address)\":{\"params\":{\"_lpToken\":\"Address of the LP ERC-20 token.\",\"_rewarder\":\"Address of the rewarder delegate.\",\"allocPoint\":\"AP of the new pool.\"}},\"constructor\":{\"params\":{\"_synapse\":\"The SYNAPSE token contract address.\"}},\"deposit(uint256,uint256,address)\":{\"params\":{\"amount\":\"LP token amount to deposit.\",\"pid\":\"The index of the pool. See `poolInfo`.\",\"to\":\"The receiver of `amount` deposit benefit.\"}},\"emergencyWithdraw(uint256,address)\":{\"params\":{\"pid\":\"The index of the pool. See `poolInfo`.\",\"to\":\"Receiver of the LP tokens.\"}},\"harvest(uint256,address)\":{\"params\":{\"pid\":\"The index of the pool. See `poolInfo`.\",\"to\":\"Receiver of SYNAPSE rewards.\"}},\"massUpdatePools(uint256[])\":{\"params\":{\"pids\":\"Pool IDs of all to be updated. Make sure to update all active pools.\"}},\"pendingSynapse(uint256,address)\":{\"params\":{\"_pid\":\"The index of the pool. See `poolInfo`.\",\"_user\":\"Address of user.\"},\"returns\":{\"pending\":\"SYNAPSE reward for a given user.\"}},\"set(uint256,uint256,address,bool)\":{\"params\":{\"_allocPoint\":\"New AP of the pool.\",\"_pid\":\"The index of the pool. See `poolInfo`.\",\"_rewarder\":\"Address of the rewarder delegate.\",\"overwrite\":\"True if _rewarder should be `set`. Otherwise `_rewarder` is ignored.\"}},\"setSynapsePerSecond(uint256)\":{\"params\":{\"_synapsePerSecond\":\"The amount of Synapse to be distributed per second.\"}},\"updatePool(uint256)\":{\"params\":{\"pid\":\"The index of the pool. See `poolInfo`.\"},\"returns\":{\"pool\":\"Returns the pool that was updated.\"}},\"withdraw(uint256,uint256,address)\":{\"params\":{\"amount\":\"LP token amount to withdraw.\",\"pid\":\"The index of the pool. See `poolInfo`.\",\"to\":\"Receiver of the LP tokens.\"}},\"withdrawAndHarvest(uint256,uint256,address)\":{\"params\":{\"amount\":\"LP token amount to withdraw.\",\"pid\":\"The index of the pool. See `poolInfo`.\",\"to\":\"Receiver of the LP tokens and SYNAPSE rewards.\"}}},\"stateVariables\":{\"totalAllocPoint\":{\"details\":\"Total allocation points. Must be the sum of all allocation points in all pools.\"}},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{\"SYNAPSE()\":{\"notice\":\"Address of SYNAPSE contract.\"},\"add(uint256,address,address)\":{\"notice\":\"Add a new LP to the pool. Can only be called by the owner. DO NOT add the same LP token more than once. Rewards will be messed up if you do.\"},\"deposit(uint256,uint256,address)\":{\"notice\":\"Deposit LP tokens to MCV2 for SYNAPSE allocation.\"},\"emergencyWithdraw(uint256,address)\":{\"notice\":\"Withdraw without caring about rewards. EMERGENCY ONLY.\"},\"harvest(uint256,address)\":{\"notice\":\"Harvest proceeds for transaction sender to `to`.\"},\"lpToken(uint256)\":{\"notice\":\"Address of the LP token for each MCV2 pool.\"},\"massUpdatePools(uint256[])\":{\"notice\":\"Update reward variables for all pools. Be careful of gas spending!\"},\"pendingSynapse(uint256,address)\":{\"notice\":\"View function to see pending SYNAPSE on frontend.\"},\"poolInfo(uint256)\":{\"notice\":\"Info of each MCV2 pool.\"},\"poolLength()\":{\"notice\":\"Returns the number of MCV2 pools.\"},\"rewarder(uint256)\":{\"notice\":\"Address of each `IRewarder` contract in MCV2.\"},\"set(uint256,uint256,address,bool)\":{\"notice\":\"Update the given pool's SYNAPSE allocation point and `IRewarder` contract. Can only be called by the owner.\"},\"setSynapsePerSecond(uint256)\":{\"notice\":\"Sets the synapse per second to be distributed. Can only be called by the owner.\"},\"updatePool(uint256)\":{\"notice\":\"Update reward variables of the given pool.\"},\"userInfo(uint256,address)\":{\"notice\":\"Info of each user that stakes LP tokens.\"},\"withdraw(uint256,uint256,address)\":{\"notice\":\"Withdraw LP tokens from MCV2.\"},\"withdrawAndHarvest(uint256,uint256,address)\":{\"notice\":\"Withdraw LP tokens from MCV2 and harvest proceeds for transaction sender to `to`.\"}},\"notice\":\"The (older) MasterChef contract gives out a constant number of SYNAPSE tokens per block. It is the only address with minting rights for SYNAPSE. The idea for this MasterChef V2 (MCV2) contract is therefore to be the owner of a dummy token that is deposited into the MasterChef V1 (MCV1) contract. The allocation point for this pool on MCV1 is the total allocation point for all pools that receive double incentives.\",\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/bridge/MiniChefV2.sol\":\"MiniChefV2\"},\"evmVersion\":\"istanbul\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":10000},\"remappings\":[]},\"sources\":{\"@boringcrypto/boring-solidity/contracts/BoringBatchable.sol\":{\"content\":\"// SPDX-License-Identifier: UNLICENSED\\r\\n// Audit on 5-Jan-2021 by Keno and BoringCrypto\\r\\n\\r\\n// P1 - P3: OK\\r\\npragma solidity 0.6.12;\\r\\npragma experimental ABIEncoderV2;\\r\\n// solhint-disable avoid-low-level-calls\\r\\n\\r\\nimport \\\"./libraries/BoringERC20.sol\\\";\\r\\n\\r\\n// T1 - T4: OK\\r\\ncontract BaseBoringBatchable {\\r\\n function _getRevertMsg(bytes memory _returnData) internal pure returns (string memory) {\\r\\n // If the _res length is less than 68, then the transaction failed silently (without a revert message)\\r\\n if (_returnData.length < 68) return \\\"Transaction reverted silently\\\";\\r\\n\\r\\n assembly {\\r\\n // Slice the sighash.\\r\\n _returnData := add(_returnData, 0x04)\\r\\n }\\r\\n return abi.decode(_returnData, (string)); // All that remains is the revert string\\r\\n } \\r\\n \\r\\n // F3 - F9: OK\\r\\n // F1: External is ok here because this is the batch function, adding it to a batch makes no sense\\r\\n // F2: Calls in the batch may be payable, delegatecall operates in the same context, so each call in the batch has access to msg.value\\r\\n // C1 - C21: OK\\r\\n // C3: The length of the loop is fully under user control, so can't be exploited\\r\\n // C7: Delegatecall is only used on the same contract, so it's safe\\r\\n function batch(bytes[] calldata calls, bool revertOnFail) external payable returns(bool[] memory successes, bytes[] memory results) {\\r\\n // Interactions\\r\\n successes = new bool[](calls.length);\\r\\n results = new bytes[](calls.length);\\r\\n for (uint256 i = 0; i < calls.length; i++) {\\r\\n (bool success, bytes memory result) = address(this).delegatecall(calls[i]);\\r\\n require(success || !revertOnFail, _getRevertMsg(result));\\r\\n successes[i] = success;\\r\\n results[i] = result;\\r\\n }\\r\\n }\\r\\n}\\r\\n\\r\\n// T1 - T4: OK\\r\\ncontract BoringBatchable is BaseBoringBatchable {\\r\\n // F1 - F9: OK\\r\\n // F6: Parameters can be used front-run the permit and the user's permit will fail (due to nonce or other revert)\\r\\n // if part of a batch this could be used to grief once as the second call would not need the permit\\r\\n // C1 - C21: OK\\r\\n function permitToken(IERC20 token, address from, address to, uint256 amount, uint256 deadline, uint8 v, bytes32 r, bytes32 s) public {\\r\\n // Interactions\\r\\n // X1 - X5\\r\\n token.permit(from, to, amount, deadline, v, r, s);\\r\\n }\\r\\n}\",\"keccak256\":\"0xe0b0316b015447ee28c6b7d96c4347b410a66e5d26e922ef3bcccc22f3b4d590\",\"license\":\"UNLICENSED\"},\"@boringcrypto/boring-solidity/contracts/BoringOwnable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\r\\n// Audit on 5-Jan-2021 by Keno and BoringCrypto\\r\\n\\r\\n// P1 - P3: OK\\r\\npragma solidity 0.6.12;\\r\\n\\r\\n// Source: https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/access/Ownable.sol + Claimable.sol\\r\\n// Edited by BoringCrypto\\r\\n\\r\\n// T1 - T4: OK\\r\\ncontract BoringOwnableData {\\r\\n // V1 - V5: OK\\r\\n address public owner;\\r\\n // V1 - V5: OK\\r\\n address public pendingOwner;\\r\\n}\\r\\n\\r\\n// T1 - T4: OK\\r\\ncontract BoringOwnable is BoringOwnableData {\\r\\n // E1: OK\\r\\n event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\\r\\n\\r\\n constructor () public {\\r\\n owner = msg.sender;\\r\\n emit OwnershipTransferred(address(0), msg.sender);\\r\\n }\\r\\n\\r\\n // F1 - F9: OK\\r\\n // C1 - C21: OK\\r\\n function transferOwnership(address newOwner, bool direct, bool renounce) public onlyOwner {\\r\\n if (direct) {\\r\\n // Checks\\r\\n require(newOwner != address(0) || renounce, \\\"Ownable: zero address\\\");\\r\\n\\r\\n // Effects\\r\\n emit OwnershipTransferred(owner, newOwner);\\r\\n owner = newOwner;\\r\\n pendingOwner = address(0);\\r\\n } else {\\r\\n // Effects\\r\\n pendingOwner = newOwner;\\r\\n }\\r\\n }\\r\\n\\r\\n // F1 - F9: OK\\r\\n // C1 - C21: OK\\r\\n function claimOwnership() public {\\r\\n address _pendingOwner = pendingOwner;\\r\\n \\r\\n // Checks\\r\\n require(msg.sender == _pendingOwner, \\\"Ownable: caller != pending owner\\\");\\r\\n\\r\\n // Effects\\r\\n emit OwnershipTransferred(owner, _pendingOwner);\\r\\n owner = _pendingOwner;\\r\\n pendingOwner = address(0);\\r\\n }\\r\\n\\r\\n // M1 - M5: OK\\r\\n // C1 - C21: OK\\r\\n modifier onlyOwner() {\\r\\n require(msg.sender == owner, \\\"Ownable: caller is not the owner\\\");\\r\\n _;\\r\\n }\\r\\n}\",\"keccak256\":\"0xfafb586b248c1c697227f5745397562cfe5be2f04e19fb80fc79fc94e3afaba1\",\"license\":\"MIT\"},\"@boringcrypto/boring-solidity/contracts/interfaces/IERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\r\\npragma solidity 0.6.12;\\r\\n\\r\\ninterface IERC20 {\\r\\n function totalSupply() external view returns (uint256);\\r\\n function balanceOf(address account) external view returns (uint256);\\r\\n function allowance(address owner, address spender) external view returns (uint256);\\r\\n function approve(address spender, uint256 amount) external returns (bool);\\r\\n event Transfer(address indexed from, address indexed to, uint256 value);\\r\\n event Approval(address indexed owner, address indexed spender, uint256 value);\\r\\n\\r\\n // EIP 2612\\r\\n function permit(address owner, address spender, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s) external;\\r\\n}\",\"keccak256\":\"0x8004f86e4536cca55b8eeb2621fe18e1ee57d779396ddef50bce5bf70fb59867\",\"license\":\"MIT\"},\"@boringcrypto/boring-solidity/contracts/libraries/BoringERC20.sol\":{\"content\":\"// SPDX-License-Identifier: UNLICENSED\\r\\npragma solidity 0.6.12;\\r\\n\\r\\nimport \\\"../interfaces/IERC20.sol\\\";\\r\\n\\r\\nlibrary BoringERC20 {\\r\\n function safeSymbol(IERC20 token) internal view returns(string memory) {\\r\\n (bool success, bytes memory data) = address(token).staticcall(abi.encodeWithSelector(0x95d89b41));\\r\\n return success && data.length > 0 ? abi.decode(data, (string)) : \\\"???\\\";\\r\\n }\\r\\n\\r\\n function safeName(IERC20 token) internal view returns(string memory) {\\r\\n (bool success, bytes memory data) = address(token).staticcall(abi.encodeWithSelector(0x06fdde03));\\r\\n return success && data.length > 0 ? abi.decode(data, (string)) : \\\"???\\\";\\r\\n }\\r\\n\\r\\n function safeDecimals(IERC20 token) internal view returns (uint8) {\\r\\n (bool success, bytes memory data) = address(token).staticcall(abi.encodeWithSelector(0x313ce567));\\r\\n return success && data.length == 32 ? abi.decode(data, (uint8)) : 18;\\r\\n }\\r\\n\\r\\n function safeTransfer(IERC20 token, address to, uint256 amount) internal {\\r\\n (bool success, bytes memory data) = address(token).call(abi.encodeWithSelector(0xa9059cbb, to, amount));\\r\\n require(success && (data.length == 0 || abi.decode(data, (bool))), \\\"BoringERC20: Transfer failed\\\");\\r\\n }\\r\\n\\r\\n function safeTransferFrom(IERC20 token, address from, address to, uint256 amount) internal {\\r\\n (bool success, bytes memory data) = address(token).call(abi.encodeWithSelector(0x23b872dd, from, to, amount));\\r\\n require(success && (data.length == 0 || abi.decode(data, (bool))), \\\"BoringERC20: TransferFrom failed\\\");\\r\\n }\\r\\n}\",\"keccak256\":\"0x69f1ccf716991e5d6d64dc0e3bc3828fd1990bc18400d680b1aa1960675daaaa\",\"license\":\"UNLICENSED\"},\"@boringcrypto/boring-solidity/contracts/libraries/BoringMath.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\r\\npragma solidity 0.6.12;\\r\\n// a library for performing overflow-safe math, updated with awesomeness from of DappHub (https://github.com/dapphub/ds-math)\\r\\nlibrary BoringMath {\\r\\n function add(uint256 a, uint256 b) internal pure returns (uint256 c) {require((c = a + b) >= b, \\\"BoringMath: Add Overflow\\\");}\\r\\n function sub(uint256 a, uint256 b) internal pure returns (uint256 c) {require((c = a - b) <= a, \\\"BoringMath: Underflow\\\");}\\r\\n function mul(uint256 a, uint256 b) internal pure returns (uint256 c) {require(b == 0 || (c = a * b)/b == a, \\\"BoringMath: Mul Overflow\\\");}\\r\\n function to128(uint256 a) internal pure returns (uint128 c) {\\r\\n require(a <= uint128(-1), \\\"BoringMath: uint128 Overflow\\\");\\r\\n c = uint128(a);\\r\\n }\\r\\n function to64(uint256 a) internal pure returns (uint64 c) {\\r\\n require(a <= uint64(-1), \\\"BoringMath: uint64 Overflow\\\");\\r\\n c = uint64(a);\\r\\n }\\r\\n function to32(uint256 a) internal pure returns (uint32 c) {\\r\\n require(a <= uint32(-1), \\\"BoringMath: uint32 Overflow\\\");\\r\\n c = uint32(a);\\r\\n }\\r\\n}\\r\\n\\r\\nlibrary BoringMath128 {\\r\\n function add(uint128 a, uint128 b) internal pure returns (uint128 c) {require((c = a + b) >= b, \\\"BoringMath: Add Overflow\\\");}\\r\\n function sub(uint128 a, uint128 b) internal pure returns (uint128 c) {require((c = a - b) <= a, \\\"BoringMath: Underflow\\\");}\\r\\n}\\r\\n\\r\\nlibrary BoringMath64 {\\r\\n function add(uint64 a, uint64 b) internal pure returns (uint64 c) {require((c = a + b) >= b, \\\"BoringMath: Add Overflow\\\");}\\r\\n function sub(uint64 a, uint64 b) internal pure returns (uint64 c) {require((c = a - b) <= a, \\\"BoringMath: Underflow\\\");}\\r\\n}\\r\\n\\r\\nlibrary BoringMath32 {\\r\\n function add(uint32 a, uint32 b) internal pure returns (uint32 c) {require((c = a + b) >= b, \\\"BoringMath: Add Overflow\\\");}\\r\\n function sub(uint32 a, uint32 b) internal pure returns (uint32 c) {require((c = a - b) <= a, \\\"BoringMath: Underflow\\\");}\\r\\n}\",\"keccak256\":\"0x2d0e99483c5618251d4b52e8551918253bf044c63e0d09a2f1f652671f9ff762\",\"license\":\"MIT\"},\"contracts/bridge/MiniChefV2.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity 0.6.12;\\npragma experimental ABIEncoderV2;\\n\\nimport \\\"@boringcrypto/boring-solidity/contracts/libraries/BoringMath.sol\\\";\\nimport \\\"@boringcrypto/boring-solidity/contracts/BoringBatchable.sol\\\";\\nimport \\\"@boringcrypto/boring-solidity/contracts/BoringOwnable.sol\\\";\\nimport \\\"./libraries/SignedSafeMath.sol\\\";\\nimport \\\"./interfaces/IRewarder.sol\\\";\\nimport \\\"./interfaces/IMasterChef.sol\\\";\\n\\n/// @notice The (older) MasterChef contract gives out a constant number of SYNAPSE tokens per block.\\n/// It is the only address with minting rights for SYNAPSE.\\n/// The idea for this MasterChef V2 (MCV2) contract is therefore to be the owner of a dummy token\\n/// that is deposited into the MasterChef V1 (MCV1) contract.\\n/// The allocation point for this pool on MCV1 is the total allocation point for all pools that receive double incentives.\\ncontract MiniChefV2 is BoringOwnable, BoringBatchable {\\n using BoringMath for uint256;\\n using BoringMath128 for uint128;\\n using BoringERC20 for IERC20;\\n using SignedSafeMath for int256;\\n\\n /// @notice Info of each MCV2 user.\\n /// `amount` LP token amount the user has provided.\\n /// `rewardDebt` The amount of SYNAPSE entitled to the user.\\n struct UserInfo {\\n uint256 amount;\\n int256 rewardDebt;\\n }\\n\\n /// @notice Info of each MCV2 pool.\\n /// `allocPoint` The amount of allocation points assigned to the pool.\\n /// Also known as the amount of SYNAPSE to distribute per block.\\n struct PoolInfo {\\n uint128 accSynapsePerShare;\\n uint64 lastRewardTime;\\n uint64 allocPoint;\\n }\\n\\n /// @notice Address of SYNAPSE contract.\\n IERC20 public immutable SYNAPSE;\\n\\n /// @notice Info of each MCV2 pool.\\n PoolInfo[] public poolInfo;\\n /// @notice Address of the LP token for each MCV2 pool.\\n IERC20[] public lpToken;\\n /// @notice Address of each `IRewarder` contract in MCV2.\\n IRewarder[] public rewarder;\\n\\n /// @notice Info of each user that stakes LP tokens.\\n mapping(uint256 => mapping(address => UserInfo)) public userInfo;\\n /// @dev Total allocation points. Must be the sum of all allocation points in all pools.\\n uint256 public totalAllocPoint;\\n\\n uint256 public synapsePerSecond;\\n uint256 private constant ACC_SYNAPSE_PRECISION = 1e12;\\n\\n event Deposit(\\n address indexed user,\\n uint256 indexed pid,\\n uint256 amount,\\n address indexed to\\n );\\n event Withdraw(\\n address indexed user,\\n uint256 indexed pid,\\n uint256 amount,\\n address indexed to\\n );\\n event EmergencyWithdraw(\\n address indexed user,\\n uint256 indexed pid,\\n uint256 amount,\\n address indexed to\\n );\\n event Harvest(address indexed user, uint256 indexed pid, uint256 amount);\\n event LogPoolAddition(\\n uint256 indexed pid,\\n uint256 allocPoint,\\n IERC20 indexed lpToken,\\n IRewarder indexed rewarder\\n );\\n event LogSetPool(\\n uint256 indexed pid,\\n uint256 allocPoint,\\n IRewarder indexed rewarder,\\n bool overwrite\\n );\\n event LogUpdatePool(\\n uint256 indexed pid,\\n uint64 lastRewardTime,\\n uint256 lpSupply,\\n uint256 accSynapsePerShare\\n );\\n event LogSynapsePerSecond(uint256 synapsePerSecond);\\n\\n /// @param _synapse The SYNAPSE token contract address.\\n constructor(IERC20 _synapse) public {\\n SYNAPSE = _synapse;\\n }\\n\\n /// @notice Returns the number of MCV2 pools.\\n function poolLength() public view returns (uint256 pools) {\\n pools = poolInfo.length;\\n }\\n\\n /// @notice Add a new LP to the pool. Can only be called by the owner.\\n /// DO NOT add the same LP token more than once. Rewards will be messed up if you do.\\n /// @param allocPoint AP of the new pool.\\n /// @param _lpToken Address of the LP ERC-20 token.\\n /// @param _rewarder Address of the rewarder delegate.\\n function add(\\n uint256 allocPoint,\\n IERC20 _lpToken,\\n IRewarder _rewarder\\n ) public onlyOwner {\\n totalAllocPoint = totalAllocPoint.add(allocPoint);\\n lpToken.push(_lpToken);\\n rewarder.push(_rewarder);\\n\\n poolInfo.push(\\n PoolInfo({\\n allocPoint: allocPoint.to64(),\\n lastRewardTime: block.timestamp.to64(),\\n accSynapsePerShare: 0\\n })\\n );\\n emit LogPoolAddition(\\n lpToken.length.sub(1),\\n allocPoint,\\n _lpToken,\\n _rewarder\\n );\\n }\\n\\n /// @notice Update the given pool's SYNAPSE allocation point and `IRewarder` contract. Can only be called by the owner.\\n /// @param _pid The index of the pool. See `poolInfo`.\\n /// @param _allocPoint New AP of the pool.\\n /// @param _rewarder Address of the rewarder delegate.\\n /// @param overwrite True if _rewarder should be `set`. Otherwise `_rewarder` is ignored.\\n function set(\\n uint256 _pid,\\n uint256 _allocPoint,\\n IRewarder _rewarder,\\n bool overwrite\\n ) public onlyOwner {\\n totalAllocPoint = totalAllocPoint.sub(poolInfo[_pid].allocPoint).add(\\n _allocPoint\\n );\\n poolInfo[_pid].allocPoint = _allocPoint.to64();\\n if (overwrite) {\\n rewarder[_pid] = _rewarder;\\n }\\n emit LogSetPool(\\n _pid,\\n _allocPoint,\\n overwrite ? _rewarder : rewarder[_pid],\\n overwrite\\n );\\n }\\n\\n /// @notice Sets the synapse per second to be distributed. Can only be called by the owner.\\n /// @param _synapsePerSecond The amount of Synapse to be distributed per second.\\n function setSynapsePerSecond(uint256 _synapsePerSecond) public onlyOwner {\\n synapsePerSecond = _synapsePerSecond;\\n emit LogSynapsePerSecond(_synapsePerSecond);\\n }\\n\\n /// @notice View function to see pending SYNAPSE on frontend.\\n /// @param _pid The index of the pool. See `poolInfo`.\\n /// @param _user Address of user.\\n /// @return pending SYNAPSE reward for a given user.\\n function pendingSynapse(uint256 _pid, address _user)\\n external\\n view\\n returns (uint256 pending)\\n {\\n PoolInfo memory pool = poolInfo[_pid];\\n UserInfo storage user = userInfo[_pid][_user];\\n uint256 accSynapsePerShare = pool.accSynapsePerShare;\\n uint256 lpSupply = lpToken[_pid].balanceOf(address(this));\\n if (block.timestamp > pool.lastRewardTime && lpSupply != 0) {\\n uint256 time = block.timestamp.sub(pool.lastRewardTime);\\n uint256 synapseReward = time.mul(synapsePerSecond).mul(\\n pool.allocPoint\\n ) / totalAllocPoint;\\n accSynapsePerShare = accSynapsePerShare.add(\\n synapseReward.mul(ACC_SYNAPSE_PRECISION) / lpSupply\\n );\\n }\\n pending = int256(\\n user.amount.mul(accSynapsePerShare) / ACC_SYNAPSE_PRECISION\\n ).sub(user.rewardDebt)\\n .toUInt256();\\n }\\n\\n /// @notice Update reward variables for all pools. Be careful of gas spending!\\n /// @param pids Pool IDs of all to be updated. Make sure to update all active pools.\\n function massUpdatePools(uint256[] calldata pids) external {\\n uint256 len = pids.length;\\n for (uint256 i = 0; i < len; ++i) {\\n updatePool(pids[i]);\\n }\\n }\\n\\n /// @notice Update reward variables of the given pool.\\n /// @param pid The index of the pool. See `poolInfo`.\\n /// @return pool Returns the pool that was updated.\\n function updatePool(uint256 pid) public returns (PoolInfo memory pool) {\\n pool = poolInfo[pid];\\n if (block.timestamp > pool.lastRewardTime) {\\n uint256 lpSupply = lpToken[pid].balanceOf(address(this));\\n if (lpSupply > 0) {\\n uint256 time = block.timestamp.sub(pool.lastRewardTime);\\n uint256 synapseReward = time.mul(synapsePerSecond).mul(\\n pool.allocPoint\\n ) / totalAllocPoint;\\n pool.accSynapsePerShare = pool.accSynapsePerShare.add(\\n (synapseReward.mul(ACC_SYNAPSE_PRECISION) / lpSupply)\\n .to128()\\n );\\n }\\n pool.lastRewardTime = block.timestamp.to64();\\n poolInfo[pid] = pool;\\n emit LogUpdatePool(\\n pid,\\n pool.lastRewardTime,\\n lpSupply,\\n pool.accSynapsePerShare\\n );\\n }\\n }\\n\\n /// @notice Deposit LP tokens to MCV2 for SYNAPSE allocation.\\n /// @param pid The index of the pool. See `poolInfo`.\\n /// @param amount LP token amount to deposit.\\n /// @param to The receiver of `amount` deposit benefit.\\n function deposit(\\n uint256 pid,\\n uint256 amount,\\n address to\\n ) public {\\n PoolInfo memory pool = updatePool(pid);\\n UserInfo storage user = userInfo[pid][to];\\n\\n // Effects\\n user.amount = user.amount.add(amount);\\n user.rewardDebt = user.rewardDebt.add(\\n int256(amount.mul(pool.accSynapsePerShare) / ACC_SYNAPSE_PRECISION)\\n );\\n\\n // Interactions\\n IRewarder _rewarder = rewarder[pid];\\n if (address(_rewarder) != address(0)) {\\n _rewarder.onSynapseReward(pid, to, to, 0, user.amount);\\n }\\n\\n lpToken[pid].safeTransferFrom(msg.sender, address(this), amount);\\n\\n emit Deposit(msg.sender, pid, amount, to);\\n }\\n\\n /// @notice Withdraw LP tokens from MCV2.\\n /// @param pid The index of the pool. See `poolInfo`.\\n /// @param amount LP token amount to withdraw.\\n /// @param to Receiver of the LP tokens.\\n function withdraw(\\n uint256 pid,\\n uint256 amount,\\n address to\\n ) public {\\n PoolInfo memory pool = updatePool(pid);\\n UserInfo storage user = userInfo[pid][msg.sender];\\n\\n // Effects\\n user.rewardDebt = user.rewardDebt.sub(\\n int256(amount.mul(pool.accSynapsePerShare) / ACC_SYNAPSE_PRECISION)\\n );\\n user.amount = user.amount.sub(amount);\\n\\n // Interactions\\n IRewarder _rewarder = rewarder[pid];\\n if (address(_rewarder) != address(0)) {\\n _rewarder.onSynapseReward(pid, msg.sender, to, 0, user.amount);\\n }\\n\\n lpToken[pid].safeTransfer(to, amount);\\n\\n emit Withdraw(msg.sender, pid, amount, to);\\n }\\n\\n /// @notice Harvest proceeds for transaction sender to `to`.\\n /// @param pid The index of the pool. See `poolInfo`.\\n /// @param to Receiver of SYNAPSE rewards.\\n function harvest(uint256 pid, address to) public {\\n PoolInfo memory pool = updatePool(pid);\\n UserInfo storage user = userInfo[pid][msg.sender];\\n int256 accumulatedSynapse = int256(\\n user.amount.mul(pool.accSynapsePerShare) / ACC_SYNAPSE_PRECISION\\n );\\n uint256 _pendingSynapse = accumulatedSynapse\\n .sub(user.rewardDebt)\\n .toUInt256();\\n\\n // Effects\\n user.rewardDebt = accumulatedSynapse;\\n\\n // Interactions\\n if (_pendingSynapse != 0) {\\n SYNAPSE.safeTransfer(to, _pendingSynapse);\\n }\\n\\n IRewarder _rewarder = rewarder[pid];\\n if (address(_rewarder) != address(0)) {\\n _rewarder.onSynapseReward(\\n pid,\\n msg.sender,\\n to,\\n _pendingSynapse,\\n user.amount\\n );\\n }\\n\\n emit Harvest(msg.sender, pid, _pendingSynapse);\\n }\\n\\n /// @notice Withdraw LP tokens from MCV2 and harvest proceeds for transaction sender to `to`.\\n /// @param pid The index of the pool. See `poolInfo`.\\n /// @param amount LP token amount to withdraw.\\n /// @param to Receiver of the LP tokens and SYNAPSE rewards.\\n function withdrawAndHarvest(\\n uint256 pid,\\n uint256 amount,\\n address to\\n ) public {\\n PoolInfo memory pool = updatePool(pid);\\n UserInfo storage user = userInfo[pid][msg.sender];\\n int256 accumulatedSynapse = int256(\\n user.amount.mul(pool.accSynapsePerShare) / ACC_SYNAPSE_PRECISION\\n );\\n uint256 _pendingSynapse = accumulatedSynapse\\n .sub(user.rewardDebt)\\n .toUInt256();\\n\\n // Effects\\n user.rewardDebt = accumulatedSynapse.sub(\\n int256(amount.mul(pool.accSynapsePerShare) / ACC_SYNAPSE_PRECISION)\\n );\\n user.amount = user.amount.sub(amount);\\n\\n // Interactions\\n SYNAPSE.safeTransfer(to, _pendingSynapse);\\n\\n IRewarder _rewarder = rewarder[pid];\\n if (address(_rewarder) != address(0)) {\\n _rewarder.onSynapseReward(\\n pid,\\n msg.sender,\\n to,\\n _pendingSynapse,\\n user.amount\\n );\\n }\\n\\n lpToken[pid].safeTransfer(to, amount);\\n\\n emit Withdraw(msg.sender, pid, amount, to);\\n emit Harvest(msg.sender, pid, _pendingSynapse);\\n }\\n\\n /// @notice Withdraw without caring about rewards. EMERGENCY ONLY.\\n /// @param pid The index of the pool. See `poolInfo`.\\n /// @param to Receiver of the LP tokens.\\n function emergencyWithdraw(uint256 pid, address to) public {\\n UserInfo storage user = userInfo[pid][msg.sender];\\n uint256 amount = user.amount;\\n user.amount = 0;\\n user.rewardDebt = 0;\\n\\n IRewarder _rewarder = rewarder[pid];\\n if (address(_rewarder) != address(0)) {\\n _rewarder.onSynapseReward(pid, msg.sender, to, 0, 0);\\n }\\n\\n // Note: transfer can fail or succeed if `amount` is zero.\\n lpToken[pid].safeTransfer(to, amount);\\n emit EmergencyWithdraw(msg.sender, pid, amount, to);\\n }\\n}\\n\",\"keccak256\":\"0xd7be8607fc4e6024dc190d830b12ce393dc55a111ccb83f182d2a064396eb927\",\"license\":\"MIT\"},\"contracts/bridge/interfaces/IMasterChef.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.6.12;\\npragma experimental ABIEncoderV2;\\nimport \\\"@boringcrypto/boring-solidity/contracts/libraries/BoringERC20.sol\\\";\\n\\ninterface IMasterChef {\\n using BoringERC20 for IERC20;\\n struct UserInfo {\\n uint256 amount; // How many LP tokens the user has provided.\\n uint256 rewardDebt; // Reward debt. See explanation below.\\n }\\n\\n struct PoolInfo {\\n IERC20 lpToken; // Address of LP token contract.\\n uint256 allocPoint; // How many allocation points assigned to this pool. SYNAPSE to distribute per block.\\n uint256 lastRewardBlock; // Last block number that SYNAPSE distribution occurs.\\n uint256 accSynapsePerShare; // Accumulated SYNAPSE per share, times 1e12. See below.\\n }\\n\\n function poolInfo(uint256 pid) external view returns (IMasterChef.PoolInfo memory);\\n function totalAllocPoint() external view returns (uint256);\\n function deposit(uint256 _pid, uint256 _amount) external;\\n}\",\"keccak256\":\"0x0e682a9ae81910361d93eeea39afad0edfeff2b7a665a7d629ff3ce8e388bf44\",\"license\":\"MIT\"},\"contracts/bridge/interfaces/IRewarder.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity 0.6.12;\\nimport \\\"@boringcrypto/boring-solidity/contracts/libraries/BoringERC20.sol\\\";\\ninterface IRewarder {\\n using BoringERC20 for IERC20;\\n function onSynapseReward(uint256 pid, address user, address recipient, uint256 synapseAmount, uint256 newLpAmount) external;\\n function pendingTokens(uint256 pid, address user, uint256 synapseAmount) external view returns (IERC20[] memory, uint256[] memory);\\n}\",\"keccak256\":\"0xd9f95057ed49946660984509b877e7239b0a0f1ee8ee1ec24c153cd22b0830e5\",\"license\":\"MIT\"},\"contracts/bridge/libraries/SignedSafeMath.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity 0.6.12;\\n\\nlibrary SignedSafeMath {\\n int256 constant private _INT256_MIN = -2**255;\\n\\n /**\\n * @dev Returns the multiplication of two signed integers, reverting on\\n * overflow.\\n *\\n * Counterpart to Solidity's `*` operator.\\n *\\n * Requirements:\\n *\\n * - Multiplication cannot overflow.\\n */\\n function mul(int256 a, int256 b) internal pure returns (int256) {\\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) {\\n return 0;\\n }\\n\\n require(!(a == -1 && b == _INT256_MIN), \\\"SignedSafeMath: multiplication overflow\\\");\\n\\n int256 c = a * b;\\n require(c / a == b, \\\"SignedSafeMath: multiplication overflow\\\");\\n\\n return c;\\n }\\n\\n /**\\n * @dev Returns the integer division of two signed integers. Reverts 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(int256 a, int256 b) internal pure returns (int256) {\\n require(b != 0, \\\"SignedSafeMath: division by zero\\\");\\n require(!(b == -1 && a == _INT256_MIN), \\\"SignedSafeMath: division overflow\\\");\\n\\n int256 c = a / b;\\n\\n return c;\\n }\\n\\n /**\\n * @dev Returns the subtraction of two signed integers, reverting on\\n * overflow.\\n *\\n * Counterpart to Solidity's `-` operator.\\n *\\n * Requirements:\\n *\\n * - Subtraction cannot overflow.\\n */\\n function sub(int256 a, int256 b) internal pure returns (int256) {\\n int256 c = a - b;\\n require((b >= 0 && c <= a) || (b < 0 && c > a), \\\"SignedSafeMath: subtraction overflow\\\");\\n\\n return c;\\n }\\n\\n /**\\n * @dev Returns the addition of two signed integers, reverting on\\n * overflow.\\n *\\n * Counterpart to Solidity's `+` operator.\\n *\\n * Requirements:\\n *\\n * - Addition cannot overflow.\\n */\\n function add(int256 a, int256 b) internal pure returns (int256) {\\n int256 c = a + b;\\n require((b >= 0 && c >= a) || (b < 0 && c < a), \\\"SignedSafeMath: addition overflow\\\");\\n\\n return c;\\n }\\n\\n function toUInt256(int256 a) internal pure returns (uint256) {\\n require(a >= 0, \\\"Integer < 0\\\");\\n return uint256(a);\\n }\\n}\",\"keccak256\":\"0x4991beb21b224dfcdc3d251e0a60fdc304d4f6b699b2c35d08f3974e5b84c86a\",\"license\":\"MIT\"}},\"version\":1}", + "bytecode": "0x60a06040523480156200001157600080fd5b5060405162002bea38038062002bea833981016040819052620000349162000089565b600080546001600160a01b0319163390811782556040519091907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908290a360601b6001600160601b031916608052620000b9565b6000602082840312156200009b578081fd5b81516001600160a01b0381168114620000b2578182fd5b9392505050565b60805160601c612b09620000e160003980610aee528061113b52806118f15250612b096000f3fe6080604052600436106101965760003560e01c806357a5b58c116100e157806393f1a40b1161008a578063d1abb90711610064578063d1abb90714610448578063d2423b5114610468578063e30c397814610489578063f7edf2031461049e57610196565b806393f1a40b146103da578063ab7de09814610408578063c346253d1461042857610196565b806388bba42f116100bb57806388bba42f146103855780638da5cb5b146103a55780638dbdbe6d146103ba57610196565b806357a5b58c1461032557806378ed5d1f146103455780637c516e941461036557610196565b806318fccc76116101435780634e71e0c81161011d5780634e71e0c8146102c157806351eb05a6146102d65780635766e7171461030357610196565b806318fccc761461026c5780632f940c701461028c5780634db4addf146102ac57610196565b80631491f6fe116101745780631491f6fe146102085780631526fe271461022857806317caf6f11461025757610196565b8063078dfbe71461019b578063081e3eda146101bd5780630ad58d2f146101e8575b600080fd5b3480156101a757600080fd5b506101bb6101b636600461211c565b6104be565b005b3480156101c957600080fd5b506101d26105dd565b6040516101df9190612994565b60405180910390f35b3480156101f457600080fd5b506101bb6102033660046123e1565b6105e3565b34801561021457600080fd5b506101d261022336600461237c565b610795565b34801561023457600080fd5b5061024861024336600461234c565b6109e2565b6040516101df93929190612960565b34801561026357600080fd5b506101d2610a50565b34801561027857600080fd5b506101bb61028736600461237c565b610a56565b34801561029857600080fd5b506101bb6102a736600461237c565b610c0d565b3480156102b857600080fd5b506101d2610d47565b3480156102cd57600080fd5b506101bb610d4d565b3480156102e257600080fd5b506102f66102f136600461234c565b610df2565b6040516101df919061291d565b34801561030f57600080fd5b50610318611139565b6040516101df91906124cd565b34801561033157600080fd5b506101bb6103403660046121b0565b61115d565b34801561035157600080fd5b5061031861036036600461234c565b611193565b34801561037157600080fd5b506101bb61038036600461220c565b6111ba565b34801561039157600080fd5b506101bb6103a036600461240e565b611247565b3480156103b157600080fd5b506103186113cc565b3480156103c657600080fd5b506101bb6103d53660046123e1565b6113db565b3480156103e657600080fd5b506103fa6103f536600461237c565b611588565b6040516101df9291906129dc565b34801561041457600080fd5b506101bb6104233660046123ab565b6115ac565b34801561043457600080fd5b5061031861044336600461234c565b611804565b34801561045457600080fd5b506101bb6104633660046123e1565b611811565b61047b610476366004612166565b611a6f565b6040516101df92919061255f565b34801561049557600080fd5b50610318611c01565b3480156104aa57600080fd5b506101bb6104b936600461234c565b611c10565b6000546001600160a01b031633146104f15760405162461bcd60e51b81526004016104e8906127b3565b60405180910390fd5b81156105a4576001600160a01b03831615158061050b5750805b6105275760405162461bcd60e51b81526004016104e89061270e565b600080546040516001600160a01b03808716939216917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a3600080546001600160a01b0385167fffffffffffffffffffffffff0000000000000000000000000000000000000000918216179091556001805490911690556105d8565b600180547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0385161790555b505050565b60025490565b6105eb6120b3565b6105f484610df2565b6000858152600560209081526040808320338452909152902081519192509061064f9064e8d4a510009061063b9087906fffffffffffffffffffffffffffffffff16611c7a565b8161064257fe5b6001840154919004611cb7565b600182015580546106609085611d04565b815560048054600091908790811061067457fe5b6000918252602090912001546001600160a01b0316905080156107135781546040517f0eb9eaf10000000000000000000000000000000000000000000000000000000081526001600160a01b03831691630eb9eaf1916106e0918a9133918a916000919060040161299d565b600060405180830381600087803b1580156106fa57600080fd5b505af115801561070e573d6000803e3d6000fd5b505050505b61074184866003898154811061072557fe5b6000918252602090912001546001600160a01b03169190611d27565b836001600160a01b031686336001600160a01b03167f8166bf25f8a2b7ed3c85049207da4358d16edbed977d23fa2ee6f0dde3ec2132886040516107859190612994565b60405180910390a4505050505050565b600061079f6120b3565b600284815481106107ac57fe5b600091825260208083206040805160608101825291909301546fffffffffffffffffffffffffffffffff808216835267ffffffffffffffff7001000000000000000000000000000000008304811684860152780100000000000000000000000000000000000000000000000090920490911682850152888552600583528385206001600160a01b038916865290925291832082516003805494965091949216928890811061085657fe5b6000918252602090912001546040517f70a082310000000000000000000000000000000000000000000000000000000081526001600160a01b03909116906370a08231906108a89030906004016124cd565b60206040518083038186803b1580156108c057600080fd5b505afa1580156108d4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108f89190612364565b9050836020015167ffffffffffffffff164211801561091657508015155b156109a457600061093e856020015167ffffffffffffffff1642611d0490919063ffffffff16565b90506000600654610972876040015167ffffffffffffffff1661096c60075486611c7a90919063ffffffff16565b90611c7a565b8161097957fe5b04905061099f8361098f8364e8d4a51000611c7a565b8161099657fe5b86919004611e2a565b935050505b600183015483546109d7916109d29164e8d4a51000906109c49087611c7a565b816109cb57fe5b0490611cb7565b611e4d565b979650505050505050565b600281815481106109ef57fe5b6000918252602090912001546fffffffffffffffffffffffffffffffff8116915067ffffffffffffffff7001000000000000000000000000000000008204811691780100000000000000000000000000000000000000000000000090041683565b60065481565b610a5e6120b3565b610a6783610df2565b6000848152600560209081526040808320338452909152812082518154939450909264e8d4a5100091610aac91906fffffffffffffffffffffffffffffffff16611c7a565b81610ab357fe5b0490506000610ad26109d2846001015484611cb790919063ffffffff16565b6001840183905590508015610b1557610b156001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000168683611d27565b600060048781548110610b2457fe5b6000918252602090912001546001600160a01b031690508015610bc25783546040517f0eb9eaf10000000000000000000000000000000000000000000000000000000081526001600160a01b03831691630eb9eaf191610b8f918b9133918c9189919060040161299d565b600060405180830381600087803b158015610ba957600080fd5b505af1158015610bbd573d6000803e3d6000fd5b505050505b86336001600160a01b03167f71bab65ced2e5750775a0613be067df48ef06cf92a496ebf7663ae066092495484604051610bfc9190612994565b60405180910390a350505050505050565b60008281526005602090815260408083203384529091528120805482825560018201839055600480549293919286908110610c4457fe5b6000918252602090912001546001600160a01b031690508015610ce2576040517f0eb9eaf10000000000000000000000000000000000000000000000000000000081526001600160a01b03821690630eb9eaf190610caf90889033908990600090819060040161299d565b600060405180830381600087803b158015610cc957600080fd5b505af1158015610cdd573d6000803e3d6000fd5b505050505b610cf484836003888154811061072557fe5b836001600160a01b031685336001600160a01b03167f2cac5e20e1541d836381527a43f651851e302817b71dc8e810284e69210c1c6b85604051610d389190612994565b60405180910390a45050505050565b60075481565b6001546001600160a01b0316338114610d785760405162461bcd60e51b81526004016104e8906127e8565b600080546040516001600160a01b03808516939216917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a3600080546001600160a01b039092167fffffffffffffffffffffffff0000000000000000000000000000000000000000928316179055600180549091169055565b610dfa6120b3565b60028281548110610e0757fe5b60009182526020918290206040805160608101825292909101546fffffffffffffffffffffffffffffffff8116835267ffffffffffffffff7001000000000000000000000000000000008204811694840185905278010000000000000000000000000000000000000000000000009091041690820152915042111561113457600060038381548110610e9557fe5b6000918252602090912001546040517f70a082310000000000000000000000000000000000000000000000000000000081526001600160a01b03909116906370a0823190610ee79030906004016124cd565b60206040518083038186803b158015610eff57600080fd5b505afa158015610f13573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f379190612364565b90508015610fee576000610f62836020015167ffffffffffffffff1642611d0490919063ffffffff16565b90506000600654610f90856040015167ffffffffffffffff1661096c60075486611c7a90919063ffffffff16565b81610f9757fe5b049050610fd7610fbd84610fb08464e8d4a51000611c7a565b81610fb757fe5b04611e73565b85516fffffffffffffffffffffffffffffffff1690611ea5565b6fffffffffffffffffffffffffffffffff16845250505b610ff742611edd565b67ffffffffffffffff166020830152600280548391908590811061101757fe5b6000918252602091829020835191018054848401516040958601517fffffffffffffffffffffffffffffffff000000000000000000000000000000009092166fffffffffffffffffffffffffffffffff909416939093177fffffffffffffffff0000000000000000ffffffffffffffffffffffffffffffff1670010000000000000000000000000000000067ffffffffffffffff948516021777ffffffffffffffffffffffffffffffffffffffffffffffff16780100000000000000000000000000000000000000000000000093909116929092029190911790558301518351915185927f0fc9545022a542541ad085d091fb09a2ab36fee366a4576ab63714ea907ad3539261112a92909186916129ea565b60405180910390a2505b919050565b7f000000000000000000000000000000000000000000000000000000000000000081565b8060005b8181101561118d5761118484848381811061117857fe5b90506020020135610df2565b50600101611161565b50505050565b600381815481106111a057fe5b6000918252602090912001546001600160a01b0316905081565b6040517fd505accf0000000000000000000000000000000000000000000000000000000081526001600160a01b0389169063d505accf9061120b908a908a908a908a908a908a908a90600401612505565b600060405180830381600087803b15801561122557600080fd5b505af1158015611239573d6000803e3d6000fd5b505050505050505050505050565b6000546001600160a01b031633146112715760405162461bcd60e51b81526004016104e8906127b3565b6112c6836112c06002878154811061128557fe5b600091825260209091200154600654907801000000000000000000000000000000000000000000000000900467ffffffffffffffff16611d04565b90611e2a565b6006556112d283611edd565b600285815481106112df57fe5b9060005260206000200160000160186101000a81548167ffffffffffffffff021916908367ffffffffffffffff160217905550801561135557816004858154811061132657fe5b9060005260206000200160006101000a8154816001600160a01b0302191690836001600160a01b031602179055505b80611381576004848154811061136757fe5b6000918252602090912001546001600160a01b0316611383565b815b6001600160a01b0316847f95895a6ab1df54420d241b55243258a33e61b2194db66c1179ec521aae8e186585846040516113be9291906129cc565b60405180910390a350505050565b6000546001600160a01b031681565b6113e36120b3565b6113ec84610df2565b60008581526005602090815260408083206001600160a01b0387168452909152902080549192509061141e9085611e2a565b8155815161145e9064e8d4a510009061144a9087906fffffffffffffffffffffffffffffffff16611c7a565b8161145157fe5b6001840154919004611f07565b816001018190555060006004868154811061147557fe5b6000918252602090912001546001600160a01b0316905080156115145781546040517f0eb9eaf10000000000000000000000000000000000000000000000000000000081526001600160a01b03831691630eb9eaf1916114e1918a91899182916000919060040161299d565b600060405180830381600087803b1580156114fb57600080fd5b505af115801561150f573d6000803e3d6000fd5b505050505b61154433308760038a8154811061152757fe5b6000918252602090912001546001600160a01b0316929190611f4d565b836001600160a01b031686336001600160a01b03167f02d7e648dd130fc184d383e55bb126ac4c9c60e8f94bf05acdf557ba2d540b47886040516107859190612994565b60056020908152600092835260408084209091529082529020805460019091015482565b6000546001600160a01b031633146115d65760405162461bcd60e51b81526004016104e8906127b3565b6006546115e39084611e2a565b6006556003805460018181019092557fc2575a0e9e593c00f959f8c92f12db2869c3395a3b0502d05e2516446f71f85b0180546001600160a01b038086167fffffffffffffffffffffffff00000000000000000000000000000000000000009283161790925560048054938401815560009081527f8a35acfbc15ff81a39ae7d344fd709f28e8600b4aa8c65c6b64bfe7fe36bd19b9093018054928516929091169190911790556040805160608101909152908152600290602081016116a842611edd565b67ffffffffffffffff1681526020016116c086611edd565b67ffffffffffffffff908116909152825460018181018555600094855260209485902084519201805495850151604090950151841678010000000000000000000000000000000000000000000000000277ffffffffffffffffffffffffffffffffffffffffffffffff95909416700100000000000000000000000000000000027fffffffffffffffff0000000000000000ffffffffffffffffffffffffffffffff6fffffffffffffffffffffffffffffffff9094167fffffffffffffffffffffffffffffffff00000000000000000000000000000000909716969096179290921694909417929092161790556003546001600160a01b0380841692908516916117c891611d04565b7f81ee0f8c5c46e2cb41984886f77a84181724abb86c32a5f6de539b07509d45e5866040516117f79190612994565b60405180910390a4505050565b600481815481106111a057fe5b6118196120b3565b61182284610df2565b6000858152600560209081526040808320338452909152812082518154939450909264e8d4a510009161186791906fffffffffffffffffffffffffffffffff16611c7a565b8161186e57fe5b049050600061188d6109d2846001015484611cb790919063ffffffff16565b90506118d164e8d4a510006118c186600001516fffffffffffffffffffffffffffffffff1689611c7a90919063ffffffff16565b816118c857fe5b84919004611cb7565b600184015582546118e29087611d04565b83556119186001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000168683611d27565b60006004888154811061192757fe5b6000918252602090912001546001600160a01b0316905080156119c55783546040517f0eb9eaf10000000000000000000000000000000000000000000000000000000081526001600160a01b03831691630eb9eaf191611992918c9133918c9189919060040161299d565b600060405180830381600087803b1580156119ac57600080fd5b505af11580156119c0573d6000803e3d6000fd5b505050505b6119d7868860038b8154811061072557fe5b856001600160a01b031688336001600160a01b03167f8166bf25f8a2b7ed3c85049207da4358d16edbed977d23fa2ee6f0dde3ec21328a604051611a1b9190612994565b60405180910390a487336001600160a01b03167f71bab65ced2e5750775a0613be067df48ef06cf92a496ebf7663ae066092495484604051611a5d9190612994565b60405180910390a35050505050505050565b6060808367ffffffffffffffff81118015611a8957600080fd5b50604051908082528060200260200182016040528015611ab3578160200160208202803683370190505b5091508367ffffffffffffffff81118015611acd57600080fd5b50604051908082528060200260200182016040528015611b0157816020015b6060815260200190600190039081611aec5790505b50905060005b84811015611bf8576000606030888885818110611b2057fe5b9050602002810190611b329190612a1e565b604051611b409291906124a1565b600060405180830381855af49150503d8060008114611b7b576040519150601f19603f3d011682016040523d82523d6000602084013e611b80565b606091505b50915091508180611b8f575085155b611b9882612053565b90611bb65760405162461bcd60e51b81526004016104e891906125f9565b5081858481518110611bc457fe5b60200260200101901515908115158152505080848481518110611be357fe5b60209081029190910101525050600101611b07565b50935093915050565b6001546001600160a01b031681565b6000546001600160a01b03163314611c3a5760405162461bcd60e51b81526004016104e8906127b3565b60078190556040517f3476d39c7306c672c1b7bb49f494ba500a8d0993c322e79472d2b4b88439dc9a90611c6f908390612994565b60405180910390a150565b6000811580611c9557505080820282828281611c9257fe5b04145b611cb15760405162461bcd60e51b81526004016104e8906128e6565b92915050565b6000818303818312801590611ccc5750838113155b80611ce15750600083128015611ce157508381135b611cfd5760405162461bcd60e51b81526004016104e890612854565b9392505050565b80820382811115611cb15760405162461bcd60e51b81526004016104e89061260c565b60006060846001600160a01b031663a9059cbb8585604051602401611d4d929190612546565b6040516020818303038152906040529060e01b6020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8381831617835250505050604051611d9b91906124b1565b6000604051808303816000865af19150503d8060008114611dd8576040519150601f19603f3d011682016040523d82523d6000602084013e611ddd565b606091505b5091509150818015611e07575080511580611e07575080806020019051810190611e0791906121f0565b611e235760405162461bcd60e51b81526004016104e89061267a565b5050505050565b81810181811015611cb15760405162461bcd60e51b81526004016104e89061277c565b600080821215611e6f5760405162461bcd60e51b81526004016104e890612643565b5090565b60006fffffffffffffffffffffffffffffffff821115611e6f5760405162461bcd60e51b81526004016104e890612745565b8181016fffffffffffffffffffffffffffffffff8083169082161015611cb15760405162461bcd60e51b81526004016104e89061277c565b600067ffffffffffffffff821115611e6f5760405162461bcd60e51b81526004016104e89061281d565b6000828201818312801590611f1c5750838112155b80611f315750600083128015611f3157508381125b611cfd5760405162461bcd60e51b81526004016104e8906126b1565b60006060856001600160a01b03166323b872dd868686604051602401611f75939291906124e1565b6040516020818303038152906040529060e01b6020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8381831617835250505050604051611fc391906124b1565b6000604051808303816000865af19150503d8060008114612000576040519150601f19603f3d011682016040523d82523d6000602084013e612005565b606091505b509150915081801561202f57508051158061202f57508080602001905181019061202f91906121f0565b61204b5760405162461bcd60e51b81526004016104e8906128b1565b505050505050565b6060604482511015612099575060408051808201909152601d81527f5472616e73616374696f6e2072657665727465642073696c656e746c790000006020820152611134565b60048201915081806020019051810190611cb19190612293565b604080516060810182526000808252602082018190529181019190915290565b60008083601f8401126120e4578182fd5b50813567ffffffffffffffff8111156120fb578182fd5b602083019150836020808302850101111561211557600080fd5b9250929050565b600080600060608486031215612130578283fd5b833561213b81612aad565b9250602084013561214b81612ac5565b9150604084013561215b81612ac5565b809150509250925092565b60008060006040848603121561217a578283fd5b833567ffffffffffffffff811115612190578384fd5b61219c868287016120d3565b909450925050602084013561215b81612ac5565b600080602083850312156121c2578182fd5b823567ffffffffffffffff8111156121d8578283fd5b6121e4858286016120d3565b90969095509350505050565b600060208284031215612201578081fd5b8151611cfd81612ac5565b600080600080600080600080610100898b031215612228578384fd5b883561223381612aad565b9750602089013561224381612aad565b9650604089013561225381612aad565b9550606089013594506080890135935060a089013560ff81168114612276578384fd5b979a969950949793969295929450505060c08201359160e0013590565b6000602082840312156122a4578081fd5b815167ffffffffffffffff808211156122bb578283fd5b818401915084601f8301126122ce578283fd5b8151818111156122dc578384fd5b60405160207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116820101818110848211171561231a578586fd5b604052818152838201602001871015612331578485fd5b612342826020830160208701612a81565b9695505050505050565b60006020828403121561235d578081fd5b5035919050565b600060208284031215612375578081fd5b5051919050565b6000806040838503121561238e578182fd5b8235915060208301356123a081612aad565b809150509250929050565b6000806000606084860312156123bf578283fd5b8335925060208401356123d181612aad565b9150604084013561215b81612aad565b6000806000606084860312156123f5578283fd5b8335925060208401359150604084013561215b81612aad565b60008060008060808587031215612423578182fd5b8435935060208501359250604085013561243c81612aad565b9150606085013561244c81612ac5565b939692955090935050565b6000815180845261246f816020860160208601612a81565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b6000828483379101908152919050565b600082516124c3818460208701612a81565b9190910192915050565b6001600160a01b0391909116815260200190565b6001600160a01b039384168152919092166020820152604081019190915260600190565b6001600160a01b0397881681529590961660208601526040850193909352606084019190915260ff16608083015260a082015260c081019190915260e00190565b6001600160a01b03929092168252602082015260400190565b604080825283519082018190526000906020906060840190828701845b8281101561259a57815115158452928401929084019060010161257c565b505050838103828501528085516125b18184612994565b91508192508381028201848801865b838110156125ea5785830385526125d8838351612457565b948701949250908601906001016125c0565b50909998505050505050505050565b600060208252611cfd6020830184612457565b60208082526015908201527f426f72696e674d6174683a20556e646572666c6f770000000000000000000000604082015260600190565b6020808252600b908201527f496e7465676572203c2030000000000000000000000000000000000000000000604082015260600190565b6020808252601c908201527f426f72696e6745524332303a205472616e73666572206661696c656400000000604082015260600190565b60208082526021908201527f5369676e6564536166654d6174683a206164646974696f6e206f766572666c6f60408201527f7700000000000000000000000000000000000000000000000000000000000000606082015260800190565b60208082526015908201527f4f776e61626c653a207a65726f20616464726573730000000000000000000000604082015260600190565b6020808252601c908201527f426f72696e674d6174683a2075696e74313238204f766572666c6f7700000000604082015260600190565b60208082526018908201527f426f72696e674d6174683a20416464204f766572666c6f770000000000000000604082015260600190565b6020808252818101527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604082015260600190565b6020808252818101527f4f776e61626c653a2063616c6c657220213d2070656e64696e67206f776e6572604082015260600190565b6020808252601b908201527f426f72696e674d6174683a2075696e743634204f766572666c6f770000000000604082015260600190565b60208082526024908201527f5369676e6564536166654d6174683a207375627472616374696f6e206f76657260408201527f666c6f7700000000000000000000000000000000000000000000000000000000606082015260800190565b6020808252818101527f426f72696e6745524332303a205472616e7366657246726f6d206661696c6564604082015260600190565b60208082526018908201527f426f72696e674d6174683a204d756c204f766572666c6f770000000000000000604082015260600190565b81516fffffffffffffffffffffffffffffffff16815260208083015167ffffffffffffffff90811691830191909152604092830151169181019190915260600190565b6fffffffffffffffffffffffffffffffff93909316835267ffffffffffffffff918216602084015216604082015260600190565b90815260200190565b9485526001600160a01b0393841660208601529190921660408401526060830191909152608082015260a00190565b9182521515602082015260400190565b918252602082015260400190565b67ffffffffffffffff93909316835260208301919091526fffffffffffffffffffffffffffffffff16604082015260600190565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe1843603018112612a52578283fd5b83018035915067ffffffffffffffff821115612a6c578283fd5b60200191503681900382131561211557600080fd5b60005b83811015612a9c578181015183820152602001612a84565b8381111561118d5750506000910152565b6001600160a01b0381168114612ac257600080fd5b50565b8015158114612ac257600080fdfea26469706673582212209b227994a2bd20fbb712f7f537079ba3b5587a3b84270821893d08eab495368064736f6c634300060c0033", + "deployedBytecode": "0x6080604052600436106101965760003560e01c806357a5b58c116100e157806393f1a40b1161008a578063d1abb90711610064578063d1abb90714610448578063d2423b5114610468578063e30c397814610489578063f7edf2031461049e57610196565b806393f1a40b146103da578063ab7de09814610408578063c346253d1461042857610196565b806388bba42f116100bb57806388bba42f146103855780638da5cb5b146103a55780638dbdbe6d146103ba57610196565b806357a5b58c1461032557806378ed5d1f146103455780637c516e941461036557610196565b806318fccc76116101435780634e71e0c81161011d5780634e71e0c8146102c157806351eb05a6146102d65780635766e7171461030357610196565b806318fccc761461026c5780632f940c701461028c5780634db4addf146102ac57610196565b80631491f6fe116101745780631491f6fe146102085780631526fe271461022857806317caf6f11461025757610196565b8063078dfbe71461019b578063081e3eda146101bd5780630ad58d2f146101e8575b600080fd5b3480156101a757600080fd5b506101bb6101b636600461211c565b6104be565b005b3480156101c957600080fd5b506101d26105dd565b6040516101df9190612994565b60405180910390f35b3480156101f457600080fd5b506101bb6102033660046123e1565b6105e3565b34801561021457600080fd5b506101d261022336600461237c565b610795565b34801561023457600080fd5b5061024861024336600461234c565b6109e2565b6040516101df93929190612960565b34801561026357600080fd5b506101d2610a50565b34801561027857600080fd5b506101bb61028736600461237c565b610a56565b34801561029857600080fd5b506101bb6102a736600461237c565b610c0d565b3480156102b857600080fd5b506101d2610d47565b3480156102cd57600080fd5b506101bb610d4d565b3480156102e257600080fd5b506102f66102f136600461234c565b610df2565b6040516101df919061291d565b34801561030f57600080fd5b50610318611139565b6040516101df91906124cd565b34801561033157600080fd5b506101bb6103403660046121b0565b61115d565b34801561035157600080fd5b5061031861036036600461234c565b611193565b34801561037157600080fd5b506101bb61038036600461220c565b6111ba565b34801561039157600080fd5b506101bb6103a036600461240e565b611247565b3480156103b157600080fd5b506103186113cc565b3480156103c657600080fd5b506101bb6103d53660046123e1565b6113db565b3480156103e657600080fd5b506103fa6103f536600461237c565b611588565b6040516101df9291906129dc565b34801561041457600080fd5b506101bb6104233660046123ab565b6115ac565b34801561043457600080fd5b5061031861044336600461234c565b611804565b34801561045457600080fd5b506101bb6104633660046123e1565b611811565b61047b610476366004612166565b611a6f565b6040516101df92919061255f565b34801561049557600080fd5b50610318611c01565b3480156104aa57600080fd5b506101bb6104b936600461234c565b611c10565b6000546001600160a01b031633146104f15760405162461bcd60e51b81526004016104e8906127b3565b60405180910390fd5b81156105a4576001600160a01b03831615158061050b5750805b6105275760405162461bcd60e51b81526004016104e89061270e565b600080546040516001600160a01b03808716939216917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a3600080546001600160a01b0385167fffffffffffffffffffffffff0000000000000000000000000000000000000000918216179091556001805490911690556105d8565b600180547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0385161790555b505050565b60025490565b6105eb6120b3565b6105f484610df2565b6000858152600560209081526040808320338452909152902081519192509061064f9064e8d4a510009061063b9087906fffffffffffffffffffffffffffffffff16611c7a565b8161064257fe5b6001840154919004611cb7565b600182015580546106609085611d04565b815560048054600091908790811061067457fe5b6000918252602090912001546001600160a01b0316905080156107135781546040517f0eb9eaf10000000000000000000000000000000000000000000000000000000081526001600160a01b03831691630eb9eaf1916106e0918a9133918a916000919060040161299d565b600060405180830381600087803b1580156106fa57600080fd5b505af115801561070e573d6000803e3d6000fd5b505050505b61074184866003898154811061072557fe5b6000918252602090912001546001600160a01b03169190611d27565b836001600160a01b031686336001600160a01b03167f8166bf25f8a2b7ed3c85049207da4358d16edbed977d23fa2ee6f0dde3ec2132886040516107859190612994565b60405180910390a4505050505050565b600061079f6120b3565b600284815481106107ac57fe5b600091825260208083206040805160608101825291909301546fffffffffffffffffffffffffffffffff808216835267ffffffffffffffff7001000000000000000000000000000000008304811684860152780100000000000000000000000000000000000000000000000090920490911682850152888552600583528385206001600160a01b038916865290925291832082516003805494965091949216928890811061085657fe5b6000918252602090912001546040517f70a082310000000000000000000000000000000000000000000000000000000081526001600160a01b03909116906370a08231906108a89030906004016124cd565b60206040518083038186803b1580156108c057600080fd5b505afa1580156108d4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108f89190612364565b9050836020015167ffffffffffffffff164211801561091657508015155b156109a457600061093e856020015167ffffffffffffffff1642611d0490919063ffffffff16565b90506000600654610972876040015167ffffffffffffffff1661096c60075486611c7a90919063ffffffff16565b90611c7a565b8161097957fe5b04905061099f8361098f8364e8d4a51000611c7a565b8161099657fe5b86919004611e2a565b935050505b600183015483546109d7916109d29164e8d4a51000906109c49087611c7a565b816109cb57fe5b0490611cb7565b611e4d565b979650505050505050565b600281815481106109ef57fe5b6000918252602090912001546fffffffffffffffffffffffffffffffff8116915067ffffffffffffffff7001000000000000000000000000000000008204811691780100000000000000000000000000000000000000000000000090041683565b60065481565b610a5e6120b3565b610a6783610df2565b6000848152600560209081526040808320338452909152812082518154939450909264e8d4a5100091610aac91906fffffffffffffffffffffffffffffffff16611c7a565b81610ab357fe5b0490506000610ad26109d2846001015484611cb790919063ffffffff16565b6001840183905590508015610b1557610b156001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000168683611d27565b600060048781548110610b2457fe5b6000918252602090912001546001600160a01b031690508015610bc25783546040517f0eb9eaf10000000000000000000000000000000000000000000000000000000081526001600160a01b03831691630eb9eaf191610b8f918b9133918c9189919060040161299d565b600060405180830381600087803b158015610ba957600080fd5b505af1158015610bbd573d6000803e3d6000fd5b505050505b86336001600160a01b03167f71bab65ced2e5750775a0613be067df48ef06cf92a496ebf7663ae066092495484604051610bfc9190612994565b60405180910390a350505050505050565b60008281526005602090815260408083203384529091528120805482825560018201839055600480549293919286908110610c4457fe5b6000918252602090912001546001600160a01b031690508015610ce2576040517f0eb9eaf10000000000000000000000000000000000000000000000000000000081526001600160a01b03821690630eb9eaf190610caf90889033908990600090819060040161299d565b600060405180830381600087803b158015610cc957600080fd5b505af1158015610cdd573d6000803e3d6000fd5b505050505b610cf484836003888154811061072557fe5b836001600160a01b031685336001600160a01b03167f2cac5e20e1541d836381527a43f651851e302817b71dc8e810284e69210c1c6b85604051610d389190612994565b60405180910390a45050505050565b60075481565b6001546001600160a01b0316338114610d785760405162461bcd60e51b81526004016104e8906127e8565b600080546040516001600160a01b03808516939216917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a3600080546001600160a01b039092167fffffffffffffffffffffffff0000000000000000000000000000000000000000928316179055600180549091169055565b610dfa6120b3565b60028281548110610e0757fe5b60009182526020918290206040805160608101825292909101546fffffffffffffffffffffffffffffffff8116835267ffffffffffffffff7001000000000000000000000000000000008204811694840185905278010000000000000000000000000000000000000000000000009091041690820152915042111561113457600060038381548110610e9557fe5b6000918252602090912001546040517f70a082310000000000000000000000000000000000000000000000000000000081526001600160a01b03909116906370a0823190610ee79030906004016124cd565b60206040518083038186803b158015610eff57600080fd5b505afa158015610f13573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f379190612364565b90508015610fee576000610f62836020015167ffffffffffffffff1642611d0490919063ffffffff16565b90506000600654610f90856040015167ffffffffffffffff1661096c60075486611c7a90919063ffffffff16565b81610f9757fe5b049050610fd7610fbd84610fb08464e8d4a51000611c7a565b81610fb757fe5b04611e73565b85516fffffffffffffffffffffffffffffffff1690611ea5565b6fffffffffffffffffffffffffffffffff16845250505b610ff742611edd565b67ffffffffffffffff166020830152600280548391908590811061101757fe5b6000918252602091829020835191018054848401516040958601517fffffffffffffffffffffffffffffffff000000000000000000000000000000009092166fffffffffffffffffffffffffffffffff909416939093177fffffffffffffffff0000000000000000ffffffffffffffffffffffffffffffff1670010000000000000000000000000000000067ffffffffffffffff948516021777ffffffffffffffffffffffffffffffffffffffffffffffff16780100000000000000000000000000000000000000000000000093909116929092029190911790558301518351915185927f0fc9545022a542541ad085d091fb09a2ab36fee366a4576ab63714ea907ad3539261112a92909186916129ea565b60405180910390a2505b919050565b7f000000000000000000000000000000000000000000000000000000000000000081565b8060005b8181101561118d5761118484848381811061117857fe5b90506020020135610df2565b50600101611161565b50505050565b600381815481106111a057fe5b6000918252602090912001546001600160a01b0316905081565b6040517fd505accf0000000000000000000000000000000000000000000000000000000081526001600160a01b0389169063d505accf9061120b908a908a908a908a908a908a908a90600401612505565b600060405180830381600087803b15801561122557600080fd5b505af1158015611239573d6000803e3d6000fd5b505050505050505050505050565b6000546001600160a01b031633146112715760405162461bcd60e51b81526004016104e8906127b3565b6112c6836112c06002878154811061128557fe5b600091825260209091200154600654907801000000000000000000000000000000000000000000000000900467ffffffffffffffff16611d04565b90611e2a565b6006556112d283611edd565b600285815481106112df57fe5b9060005260206000200160000160186101000a81548167ffffffffffffffff021916908367ffffffffffffffff160217905550801561135557816004858154811061132657fe5b9060005260206000200160006101000a8154816001600160a01b0302191690836001600160a01b031602179055505b80611381576004848154811061136757fe5b6000918252602090912001546001600160a01b0316611383565b815b6001600160a01b0316847f95895a6ab1df54420d241b55243258a33e61b2194db66c1179ec521aae8e186585846040516113be9291906129cc565b60405180910390a350505050565b6000546001600160a01b031681565b6113e36120b3565b6113ec84610df2565b60008581526005602090815260408083206001600160a01b0387168452909152902080549192509061141e9085611e2a565b8155815161145e9064e8d4a510009061144a9087906fffffffffffffffffffffffffffffffff16611c7a565b8161145157fe5b6001840154919004611f07565b816001018190555060006004868154811061147557fe5b6000918252602090912001546001600160a01b0316905080156115145781546040517f0eb9eaf10000000000000000000000000000000000000000000000000000000081526001600160a01b03831691630eb9eaf1916114e1918a91899182916000919060040161299d565b600060405180830381600087803b1580156114fb57600080fd5b505af115801561150f573d6000803e3d6000fd5b505050505b61154433308760038a8154811061152757fe5b6000918252602090912001546001600160a01b0316929190611f4d565b836001600160a01b031686336001600160a01b03167f02d7e648dd130fc184d383e55bb126ac4c9c60e8f94bf05acdf557ba2d540b47886040516107859190612994565b60056020908152600092835260408084209091529082529020805460019091015482565b6000546001600160a01b031633146115d65760405162461bcd60e51b81526004016104e8906127b3565b6006546115e39084611e2a565b6006556003805460018181019092557fc2575a0e9e593c00f959f8c92f12db2869c3395a3b0502d05e2516446f71f85b0180546001600160a01b038086167fffffffffffffffffffffffff00000000000000000000000000000000000000009283161790925560048054938401815560009081527f8a35acfbc15ff81a39ae7d344fd709f28e8600b4aa8c65c6b64bfe7fe36bd19b9093018054928516929091169190911790556040805160608101909152908152600290602081016116a842611edd565b67ffffffffffffffff1681526020016116c086611edd565b67ffffffffffffffff908116909152825460018181018555600094855260209485902084519201805495850151604090950151841678010000000000000000000000000000000000000000000000000277ffffffffffffffffffffffffffffffffffffffffffffffff95909416700100000000000000000000000000000000027fffffffffffffffff0000000000000000ffffffffffffffffffffffffffffffff6fffffffffffffffffffffffffffffffff9094167fffffffffffffffffffffffffffffffff00000000000000000000000000000000909716969096179290921694909417929092161790556003546001600160a01b0380841692908516916117c891611d04565b7f81ee0f8c5c46e2cb41984886f77a84181724abb86c32a5f6de539b07509d45e5866040516117f79190612994565b60405180910390a4505050565b600481815481106111a057fe5b6118196120b3565b61182284610df2565b6000858152600560209081526040808320338452909152812082518154939450909264e8d4a510009161186791906fffffffffffffffffffffffffffffffff16611c7a565b8161186e57fe5b049050600061188d6109d2846001015484611cb790919063ffffffff16565b90506118d164e8d4a510006118c186600001516fffffffffffffffffffffffffffffffff1689611c7a90919063ffffffff16565b816118c857fe5b84919004611cb7565b600184015582546118e29087611d04565b83556119186001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000168683611d27565b60006004888154811061192757fe5b6000918252602090912001546001600160a01b0316905080156119c55783546040517f0eb9eaf10000000000000000000000000000000000000000000000000000000081526001600160a01b03831691630eb9eaf191611992918c9133918c9189919060040161299d565b600060405180830381600087803b1580156119ac57600080fd5b505af11580156119c0573d6000803e3d6000fd5b505050505b6119d7868860038b8154811061072557fe5b856001600160a01b031688336001600160a01b03167f8166bf25f8a2b7ed3c85049207da4358d16edbed977d23fa2ee6f0dde3ec21328a604051611a1b9190612994565b60405180910390a487336001600160a01b03167f71bab65ced2e5750775a0613be067df48ef06cf92a496ebf7663ae066092495484604051611a5d9190612994565b60405180910390a35050505050505050565b6060808367ffffffffffffffff81118015611a8957600080fd5b50604051908082528060200260200182016040528015611ab3578160200160208202803683370190505b5091508367ffffffffffffffff81118015611acd57600080fd5b50604051908082528060200260200182016040528015611b0157816020015b6060815260200190600190039081611aec5790505b50905060005b84811015611bf8576000606030888885818110611b2057fe5b9050602002810190611b329190612a1e565b604051611b409291906124a1565b600060405180830381855af49150503d8060008114611b7b576040519150601f19603f3d011682016040523d82523d6000602084013e611b80565b606091505b50915091508180611b8f575085155b611b9882612053565b90611bb65760405162461bcd60e51b81526004016104e891906125f9565b5081858481518110611bc457fe5b60200260200101901515908115158152505080848481518110611be357fe5b60209081029190910101525050600101611b07565b50935093915050565b6001546001600160a01b031681565b6000546001600160a01b03163314611c3a5760405162461bcd60e51b81526004016104e8906127b3565b60078190556040517f3476d39c7306c672c1b7bb49f494ba500a8d0993c322e79472d2b4b88439dc9a90611c6f908390612994565b60405180910390a150565b6000811580611c9557505080820282828281611c9257fe5b04145b611cb15760405162461bcd60e51b81526004016104e8906128e6565b92915050565b6000818303818312801590611ccc5750838113155b80611ce15750600083128015611ce157508381135b611cfd5760405162461bcd60e51b81526004016104e890612854565b9392505050565b80820382811115611cb15760405162461bcd60e51b81526004016104e89061260c565b60006060846001600160a01b031663a9059cbb8585604051602401611d4d929190612546565b6040516020818303038152906040529060e01b6020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8381831617835250505050604051611d9b91906124b1565b6000604051808303816000865af19150503d8060008114611dd8576040519150601f19603f3d011682016040523d82523d6000602084013e611ddd565b606091505b5091509150818015611e07575080511580611e07575080806020019051810190611e0791906121f0565b611e235760405162461bcd60e51b81526004016104e89061267a565b5050505050565b81810181811015611cb15760405162461bcd60e51b81526004016104e89061277c565b600080821215611e6f5760405162461bcd60e51b81526004016104e890612643565b5090565b60006fffffffffffffffffffffffffffffffff821115611e6f5760405162461bcd60e51b81526004016104e890612745565b8181016fffffffffffffffffffffffffffffffff8083169082161015611cb15760405162461bcd60e51b81526004016104e89061277c565b600067ffffffffffffffff821115611e6f5760405162461bcd60e51b81526004016104e89061281d565b6000828201818312801590611f1c5750838112155b80611f315750600083128015611f3157508381125b611cfd5760405162461bcd60e51b81526004016104e8906126b1565b60006060856001600160a01b03166323b872dd868686604051602401611f75939291906124e1565b6040516020818303038152906040529060e01b6020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8381831617835250505050604051611fc391906124b1565b6000604051808303816000865af19150503d8060008114612000576040519150601f19603f3d011682016040523d82523d6000602084013e612005565b606091505b509150915081801561202f57508051158061202f57508080602001905181019061202f91906121f0565b61204b5760405162461bcd60e51b81526004016104e8906128b1565b505050505050565b6060604482511015612099575060408051808201909152601d81527f5472616e73616374696f6e2072657665727465642073696c656e746c790000006020820152611134565b60048201915081806020019051810190611cb19190612293565b604080516060810182526000808252602082018190529181019190915290565b60008083601f8401126120e4578182fd5b50813567ffffffffffffffff8111156120fb578182fd5b602083019150836020808302850101111561211557600080fd5b9250929050565b600080600060608486031215612130578283fd5b833561213b81612aad565b9250602084013561214b81612ac5565b9150604084013561215b81612ac5565b809150509250925092565b60008060006040848603121561217a578283fd5b833567ffffffffffffffff811115612190578384fd5b61219c868287016120d3565b909450925050602084013561215b81612ac5565b600080602083850312156121c2578182fd5b823567ffffffffffffffff8111156121d8578283fd5b6121e4858286016120d3565b90969095509350505050565b600060208284031215612201578081fd5b8151611cfd81612ac5565b600080600080600080600080610100898b031215612228578384fd5b883561223381612aad565b9750602089013561224381612aad565b9650604089013561225381612aad565b9550606089013594506080890135935060a089013560ff81168114612276578384fd5b979a969950949793969295929450505060c08201359160e0013590565b6000602082840312156122a4578081fd5b815167ffffffffffffffff808211156122bb578283fd5b818401915084601f8301126122ce578283fd5b8151818111156122dc578384fd5b60405160207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116820101818110848211171561231a578586fd5b604052818152838201602001871015612331578485fd5b612342826020830160208701612a81565b9695505050505050565b60006020828403121561235d578081fd5b5035919050565b600060208284031215612375578081fd5b5051919050565b6000806040838503121561238e578182fd5b8235915060208301356123a081612aad565b809150509250929050565b6000806000606084860312156123bf578283fd5b8335925060208401356123d181612aad565b9150604084013561215b81612aad565b6000806000606084860312156123f5578283fd5b8335925060208401359150604084013561215b81612aad565b60008060008060808587031215612423578182fd5b8435935060208501359250604085013561243c81612aad565b9150606085013561244c81612ac5565b939692955090935050565b6000815180845261246f816020860160208601612a81565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b6000828483379101908152919050565b600082516124c3818460208701612a81565b9190910192915050565b6001600160a01b0391909116815260200190565b6001600160a01b039384168152919092166020820152604081019190915260600190565b6001600160a01b0397881681529590961660208601526040850193909352606084019190915260ff16608083015260a082015260c081019190915260e00190565b6001600160a01b03929092168252602082015260400190565b604080825283519082018190526000906020906060840190828701845b8281101561259a57815115158452928401929084019060010161257c565b505050838103828501528085516125b18184612994565b91508192508381028201848801865b838110156125ea5785830385526125d8838351612457565b948701949250908601906001016125c0565b50909998505050505050505050565b600060208252611cfd6020830184612457565b60208082526015908201527f426f72696e674d6174683a20556e646572666c6f770000000000000000000000604082015260600190565b6020808252600b908201527f496e7465676572203c2030000000000000000000000000000000000000000000604082015260600190565b6020808252601c908201527f426f72696e6745524332303a205472616e73666572206661696c656400000000604082015260600190565b60208082526021908201527f5369676e6564536166654d6174683a206164646974696f6e206f766572666c6f60408201527f7700000000000000000000000000000000000000000000000000000000000000606082015260800190565b60208082526015908201527f4f776e61626c653a207a65726f20616464726573730000000000000000000000604082015260600190565b6020808252601c908201527f426f72696e674d6174683a2075696e74313238204f766572666c6f7700000000604082015260600190565b60208082526018908201527f426f72696e674d6174683a20416464204f766572666c6f770000000000000000604082015260600190565b6020808252818101527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604082015260600190565b6020808252818101527f4f776e61626c653a2063616c6c657220213d2070656e64696e67206f776e6572604082015260600190565b6020808252601b908201527f426f72696e674d6174683a2075696e743634204f766572666c6f770000000000604082015260600190565b60208082526024908201527f5369676e6564536166654d6174683a207375627472616374696f6e206f76657260408201527f666c6f7700000000000000000000000000000000000000000000000000000000606082015260800190565b6020808252818101527f426f72696e6745524332303a205472616e7366657246726f6d206661696c6564604082015260600190565b60208082526018908201527f426f72696e674d6174683a204d756c204f766572666c6f770000000000000000604082015260600190565b81516fffffffffffffffffffffffffffffffff16815260208083015167ffffffffffffffff90811691830191909152604092830151169181019190915260600190565b6fffffffffffffffffffffffffffffffff93909316835267ffffffffffffffff918216602084015216604082015260600190565b90815260200190565b9485526001600160a01b0393841660208601529190921660408401526060830191909152608082015260a00190565b9182521515602082015260400190565b918252602082015260400190565b67ffffffffffffffff93909316835260208301919091526fffffffffffffffffffffffffffffffff16604082015260600190565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe1843603018112612a52578283fd5b83018035915067ffffffffffffffff821115612a6c578283fd5b60200191503681900382131561211557600080fd5b60005b83811015612a9c578181015183820152602001612a84565b8381111561118d5750506000910152565b6001600160a01b0381168114612ac257600080fd5b50565b8015158114612ac257600080fdfea26469706673582212209b227994a2bd20fbb712f7f537079ba3b5587a3b84270821893d08eab495368064736f6c634300060c0033", + "devdoc": { + "kind": "dev", + "methods": { + "add(uint256,address,address)": { + "params": { + "_lpToken": "Address of the LP ERC-20 token.", + "_rewarder": "Address of the rewarder delegate.", + "allocPoint": "AP of the new pool." + } + }, + "constructor": { + "params": { + "_synapse": "The SYNAPSE token contract address." + } + }, + "deposit(uint256,uint256,address)": { + "params": { + "amount": "LP token amount to deposit.", + "pid": "The index of the pool. See `poolInfo`.", + "to": "The receiver of `amount` deposit benefit." + } + }, + "emergencyWithdraw(uint256,address)": { + "params": { + "pid": "The index of the pool. See `poolInfo`.", + "to": "Receiver of the LP tokens." + } + }, + "harvest(uint256,address)": { + "params": { + "pid": "The index of the pool. See `poolInfo`.", + "to": "Receiver of SYNAPSE rewards." + } + }, + "massUpdatePools(uint256[])": { + "params": { + "pids": "Pool IDs of all to be updated. Make sure to update all active pools." + } + }, + "pendingSynapse(uint256,address)": { + "params": { + "_pid": "The index of the pool. See `poolInfo`.", + "_user": "Address of user." + }, + "returns": { + "pending": "SYNAPSE reward for a given user." + } + }, + "set(uint256,uint256,address,bool)": { + "params": { + "_allocPoint": "New AP of the pool.", + "_pid": "The index of the pool. See `poolInfo`.", + "_rewarder": "Address of the rewarder delegate.", + "overwrite": "True if _rewarder should be `set`. Otherwise `_rewarder` is ignored." + } + }, + "setSynapsePerSecond(uint256)": { + "params": { + "_synapsePerSecond": "The amount of Synapse to be distributed per second." + } + }, + "updatePool(uint256)": { + "params": { + "pid": "The index of the pool. See `poolInfo`." + }, + "returns": { + "pool": "Returns the pool that was updated." + } + }, + "withdraw(uint256,uint256,address)": { + "params": { + "amount": "LP token amount to withdraw.", + "pid": "The index of the pool. See `poolInfo`.", + "to": "Receiver of the LP tokens." + } + }, + "withdrawAndHarvest(uint256,uint256,address)": { + "params": { + "amount": "LP token amount to withdraw.", + "pid": "The index of the pool. See `poolInfo`.", + "to": "Receiver of the LP tokens and SYNAPSE rewards." + } + } + }, + "stateVariables": { + "totalAllocPoint": { + "details": "Total allocation points. Must be the sum of all allocation points in all pools." + } + }, + "version": 1 + }, + "userdoc": { + "kind": "user", + "methods": { + "SYNAPSE()": { + "notice": "Address of SYNAPSE contract." + }, + "add(uint256,address,address)": { + "notice": "Add a new LP to the pool. Can only be called by the owner. DO NOT add the same LP token more than once. Rewards will be messed up if you do." + }, + "deposit(uint256,uint256,address)": { + "notice": "Deposit LP tokens to MCV2 for SYNAPSE allocation." + }, + "emergencyWithdraw(uint256,address)": { + "notice": "Withdraw without caring about rewards. EMERGENCY ONLY." + }, + "harvest(uint256,address)": { + "notice": "Harvest proceeds for transaction sender to `to`." + }, + "lpToken(uint256)": { + "notice": "Address of the LP token for each MCV2 pool." + }, + "massUpdatePools(uint256[])": { + "notice": "Update reward variables for all pools. Be careful of gas spending!" + }, + "pendingSynapse(uint256,address)": { + "notice": "View function to see pending SYNAPSE on frontend." + }, + "poolInfo(uint256)": { + "notice": "Info of each MCV2 pool." + }, + "poolLength()": { + "notice": "Returns the number of MCV2 pools." + }, + "rewarder(uint256)": { + "notice": "Address of each `IRewarder` contract in MCV2." + }, + "set(uint256,uint256,address,bool)": { + "notice": "Update the given pool's SYNAPSE allocation point and `IRewarder` contract. Can only be called by the owner." + }, + "setSynapsePerSecond(uint256)": { + "notice": "Sets the synapse per second to be distributed. Can only be called by the owner." + }, + "updatePool(uint256)": { + "notice": "Update reward variables of the given pool." + }, + "userInfo(uint256,address)": { + "notice": "Info of each user that stakes LP tokens." + }, + "withdraw(uint256,uint256,address)": { + "notice": "Withdraw LP tokens from MCV2." + }, + "withdrawAndHarvest(uint256,uint256,address)": { + "notice": "Withdraw LP tokens from MCV2 and harvest proceeds for transaction sender to `to`." + } + }, + "notice": "The (older) MasterChef contract gives out a constant number of SYNAPSE tokens per block. It is the only address with minting rights for SYNAPSE. The idea for this MasterChef V2 (MCV2) contract is therefore to be the owner of a dummy token that is deposited into the MasterChef V1 (MCV1) contract. The allocation point for this pool on MCV1 is the total allocation point for all pools that receive double incentives.", + "version": 1 + }, + "storageLayout": { + "storage": [ + { + "astId": 149, + "contract": "contracts/bridge/MiniChefV2.sol:MiniChefV2", + "label": "owner", + "offset": 0, + "slot": "0", + "type": "t_address" + }, + { + "astId": 151, + "contract": "contracts/bridge/MiniChefV2.sol:MiniChefV2", + "label": "pendingOwner", + "offset": 0, + "slot": "1", + "type": "t_address" + }, + { + "astId": 886, + "contract": "contracts/bridge/MiniChefV2.sol:MiniChefV2", + "label": "poolInfo", + "offset": 0, + "slot": "2", + "type": "t_array(t_struct(PoolInfo)879_storage)dyn_storage" + }, + { + "astId": 890, + "contract": "contracts/bridge/MiniChefV2.sol:MiniChefV2", + "label": "lpToken", + "offset": 0, + "slot": "3", + "type": "t_array(t_contract(IERC20)337)dyn_storage" + }, + { + "astId": 894, + "contract": "contracts/bridge/MiniChefV2.sol:MiniChefV2", + "label": "rewarder", + "offset": 0, + "slot": "4", + "type": "t_array(t_contract(IRewarder)1975)dyn_storage" + }, + { + "astId": 901, + "contract": "contracts/bridge/MiniChefV2.sol:MiniChefV2", + "label": "userInfo", + "offset": 0, + "slot": "5", + "type": "t_mapping(t_uint256,t_mapping(t_address,t_struct(UserInfo)872_storage))" + }, + { + "astId": 904, + "contract": "contracts/bridge/MiniChefV2.sol:MiniChefV2", + "label": "totalAllocPoint", + "offset": 0, + "slot": "6", + "type": "t_uint256" + }, + { + "astId": 906, + "contract": "contracts/bridge/MiniChefV2.sol:MiniChefV2", + "label": "synapsePerSecond", + "offset": 0, + "slot": "7", + "type": "t_uint256" + } + ], + "types": { + "t_address": { + "encoding": "inplace", + "label": "address", + "numberOfBytes": "20" + }, + "t_array(t_contract(IERC20)337)dyn_storage": { + "base": "t_contract(IERC20)337", + "encoding": "dynamic_array", + "label": "contract IERC20[]", + "numberOfBytes": "32" + }, + "t_array(t_contract(IRewarder)1975)dyn_storage": { + "base": "t_contract(IRewarder)1975", + "encoding": "dynamic_array", + "label": "contract IRewarder[]", + "numberOfBytes": "32" + }, + "t_array(t_struct(PoolInfo)879_storage)dyn_storage": { + "base": "t_struct(PoolInfo)879_storage", + "encoding": "dynamic_array", + "label": "struct MiniChefV2.PoolInfo[]", + "numberOfBytes": "32" + }, + "t_contract(IERC20)337": { + "encoding": "inplace", + "label": "contract IERC20", + "numberOfBytes": "20" + }, + "t_contract(IRewarder)1975": { + "encoding": "inplace", + "label": "contract IRewarder", + "numberOfBytes": "20" + }, + "t_int256": { + "encoding": "inplace", + "label": "int256", + "numberOfBytes": "32" + }, + "t_mapping(t_address,t_struct(UserInfo)872_storage)": { + "encoding": "mapping", + "key": "t_address", + "label": "mapping(address => struct MiniChefV2.UserInfo)", + "numberOfBytes": "32", + "value": "t_struct(UserInfo)872_storage" + }, + "t_mapping(t_uint256,t_mapping(t_address,t_struct(UserInfo)872_storage))": { + "encoding": "mapping", + "key": "t_uint256", + "label": "mapping(uint256 => mapping(address => struct MiniChefV2.UserInfo))", + "numberOfBytes": "32", + "value": "t_mapping(t_address,t_struct(UserInfo)872_storage)" + }, + "t_struct(PoolInfo)879_storage": { + "encoding": "inplace", + "label": "struct MiniChefV2.PoolInfo", + "members": [ + { + "astId": 874, + "contract": "contracts/bridge/MiniChefV2.sol:MiniChefV2", + "label": "accSynapsePerShare", + "offset": 0, + "slot": "0", + "type": "t_uint128" + }, + { + "astId": 876, + "contract": "contracts/bridge/MiniChefV2.sol:MiniChefV2", + "label": "lastRewardTime", + "offset": 16, + "slot": "0", + "type": "t_uint64" + }, + { + "astId": 878, + "contract": "contracts/bridge/MiniChefV2.sol:MiniChefV2", + "label": "allocPoint", + "offset": 24, + "slot": "0", + "type": "t_uint64" + } + ], + "numberOfBytes": "32" + }, + "t_struct(UserInfo)872_storage": { + "encoding": "inplace", + "label": "struct MiniChefV2.UserInfo", + "members": [ + { + "astId": 869, + "contract": "contracts/bridge/MiniChefV2.sol:MiniChefV2", + "label": "amount", + "offset": 0, + "slot": "0", + "type": "t_uint256" + }, + { + "astId": 871, + "contract": "contracts/bridge/MiniChefV2.sol:MiniChefV2", + "label": "rewardDebt", + "offset": 0, + "slot": "1", + "type": "t_int256" + } + ], + "numberOfBytes": "64" + }, + "t_uint128": { + "encoding": "inplace", + "label": "uint128", + "numberOfBytes": "16" + }, + "t_uint256": { + "encoding": "inplace", + "label": "uint256", + "numberOfBytes": "32" + }, + "t_uint64": { + "encoding": "inplace", + "label": "uint64", + "numberOfBytes": "8" + } + } + } +} \ No newline at end of file diff --git a/deployments/dfk/MultiSigWalletFactory.json b/deployments/dfk/MultiSigWalletFactory.json new file mode 100644 index 000000000..b3030d2f5 --- /dev/null +++ b/deployments/dfk/MultiSigWalletFactory.json @@ -0,0 +1,151 @@ +{ + "address": "0xE2F6d34fd09D21F4121d648E191e842Ac95Ac0Dc", + "abi": [ + { + "constant": true, + "inputs": [ + { + "name": "", + "type": "address" + } + ], + "name": "isInstantiation", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "name": "", + "type": "address" + }, + { + "name": "", + "type": "uint256" + } + ], + "name": "instantiations", + "outputs": [ + { + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "name": "creator", + "type": "address" + } + ], + "name": "getInstantiationCount", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "name": "_owners", + "type": "address[]" + }, + { + "name": "_required", + "type": "uint256" + } + ], + "name": "create", + "outputs": [ + { + "name": "wallet", + "type": "address" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "sender", + "type": "address" + }, + { + "indexed": false, + "name": "instantiation", + "type": "address" + } + ], + "name": "ContractInstantiation", + "type": "event" + } + ], + "transactionHash": "0x8fb1ec6b85561fd4355699e1ff328a24e2181f13e785cf3b1adf882e5f1fb6a6", + "receipt": { + "to": null, + "from": "0x235AF07E770f474d24F5bf73074735892371b40D", + "contractAddress": "0xE2F6d34fd09D21F4121d648E191e842Ac95Ac0Dc", + "transactionIndex": 0, + "gasUsed": "2383418", + "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "blockHash": "0x2066d0bc3b349fb44b87af651a89836f6e0a2d2ca4a3847403f70d411b0a92e0", + "transactionHash": "0x8fb1ec6b85561fd4355699e1ff328a24e2181f13e785cf3b1adf882e5f1fb6a6", + "logs": [], + "blockNumber": 19, + "cumulativeGasUsed": "2383418", + "status": 1, + "byzantium": true + }, + "args": [], + "solcInputHash": "f2fd7140f46faca58f086e028b2ac3b2", + "metadata": "{\"compiler\":{\"version\":\"0.4.24+commit.e67f0147\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"constant\":true,\"inputs\":[{\"name\":\"\",\"type\":\"address\"}],\"name\":\"isInstantiation\",\"outputs\":[{\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"\",\"type\":\"address\"},{\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"instantiations\",\"outputs\":[{\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"creator\",\"type\":\"address\"}],\"name\":\"getInstantiationCount\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"_owners\",\"type\":\"address[]\"},{\"name\":\"_required\",\"type\":\"uint256\"}],\"name\":\"create\",\"outputs\":[{\"name\":\"wallet\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":false,\"name\":\"instantiation\",\"type\":\"address\"}],\"name\":\"ContractInstantiation\",\"type\":\"event\"}],\"devdoc\":{\"author\":\"Stefan George - \",\"methods\":{\"create(address[],uint256)\":{\"details\":\"Allows verified creation of multisignature wallet.\",\"params\":{\"_owners\":\"List of initial owners.\",\"_required\":\"Number of required confirmations.\"},\"return\":\"Returns wallet address.\"},\"getInstantiationCount(address)\":{\"details\":\"Returns number of instantiations by creator.\",\"params\":{\"creator\":\"Contract creator.\"},\"return\":\"Returns number of instantiations by creator.\"}},\"title\":\"Multisignature wallet factory - Allows creation of multisig wallet.\"},\"userdoc\":{\"methods\":{}}},\"settings\":{\"compilationTarget\":{\"contracts/MultisigWallet/contracts/MultiSigWalletFactory.sol\":\"MultiSigWalletFactory\"},\"evmVersion\":\"byzantium\",\"libraries\":{},\"optimizer\":{\"enabled\":false,\"runs\":200},\"remappings\":[]},\"sources\":{\"contracts/MultisigWallet/contracts/Factory.sol\":{\"content\":\"// SPDX-License-Identifier: ISC\\n\\npragma solidity ^0.4.15;\\n\\ncontract Factory {\\n\\n /*\\n * Events\\n */\\n event ContractInstantiation(address sender, address instantiation);\\n\\n /*\\n * Storage\\n */\\n mapping(address => bool) public isInstantiation;\\n mapping(address => address[]) public instantiations;\\n\\n /*\\n * Public functions\\n */\\n /// @dev Returns number of instantiations by creator.\\n /// @param creator Contract creator.\\n /// @return Returns number of instantiations by creator.\\n function getInstantiationCount(address creator)\\n public\\n constant\\n returns (uint)\\n {\\n return instantiations[creator].length;\\n }\\n\\n /*\\n * Internal functions\\n */\\n /// @dev Registers contract in factory registry.\\n /// @param instantiation Address of contract instantiation.\\n function register(address instantiation)\\n internal\\n {\\n isInstantiation[instantiation] = true;\\n instantiations[msg.sender].push(instantiation);\\n ContractInstantiation(msg.sender, instantiation);\\n }\\n}\\n\",\"keccak256\":\"0x968d8ad58a9246c6338359772c76dbe4fbc02830588dc0b8a59e986ed92522e8\"},\"contracts/MultisigWallet/contracts/MultiSigWallet.sol\":{\"content\":\"// SPDX-License-Identifier: ISC\\n\\npragma solidity ^0.4.15;\\n\\n\\n/// @title Multisignature wallet - Allows multiple parties to agree on transactions before execution.\\n/// @author Stefan George - \\ncontract MultiSigWallet {\\n\\n /*\\n * Events\\n */\\n event Confirmation(address indexed sender, uint indexed transactionId);\\n event Revocation(address indexed sender, uint indexed transactionId);\\n event Submission(uint indexed transactionId);\\n event Execution(uint indexed transactionId);\\n event ExecutionFailure(uint indexed transactionId);\\n event Deposit(address indexed sender, uint value);\\n event OwnerAddition(address indexed owner);\\n event OwnerRemoval(address indexed owner);\\n event RequirementChange(uint required);\\n\\n /*\\n * Constants\\n */\\n uint constant public MAX_OWNER_COUNT = 50;\\n\\n /*\\n * Storage\\n */\\n mapping (uint => Transaction) public transactions;\\n mapping (uint => mapping (address => bool)) public confirmations;\\n mapping (address => bool) public isOwner;\\n address[] public owners;\\n uint public required;\\n uint public transactionCount;\\n\\n struct Transaction {\\n address destination;\\n uint value;\\n bytes data;\\n bool executed;\\n }\\n\\n /*\\n * Modifiers\\n */\\n modifier onlyWallet() {\\n require(msg.sender == address(this));\\n _;\\n }\\n\\n modifier ownerDoesNotExist(address owner) {\\n require(!isOwner[owner]);\\n _;\\n }\\n\\n modifier ownerExists(address owner) {\\n require(isOwner[owner]);\\n _;\\n }\\n\\n modifier transactionExists(uint transactionId) {\\n require(transactions[transactionId].destination != 0);\\n _;\\n }\\n\\n modifier confirmed(uint transactionId, address owner) {\\n require(confirmations[transactionId][owner]);\\n _;\\n }\\n\\n modifier notConfirmed(uint transactionId, address owner) {\\n require(!confirmations[transactionId][owner]);\\n _;\\n }\\n\\n modifier notExecuted(uint transactionId) {\\n require(!transactions[transactionId].executed);\\n _;\\n }\\n\\n modifier notNull(address _address) {\\n require(_address != 0);\\n _;\\n }\\n\\n modifier validRequirement(uint ownerCount, uint _required) {\\n require(ownerCount <= MAX_OWNER_COUNT\\n && _required <= ownerCount\\n && _required != 0\\n && ownerCount != 0);\\n _;\\n }\\n\\n /// @dev Fallback function allows to deposit ether.\\n function()\\n payable\\n {\\n if (msg.value > 0)\\n Deposit(msg.sender, msg.value);\\n }\\n\\n /*\\n * Public functions\\n */\\n /// @dev Contract constructor sets initial owners and required number of confirmations.\\n /// @param _owners List of initial owners.\\n /// @param _required Number of required confirmations.\\n function MultiSigWallet(address[] _owners, uint _required)\\n public\\n validRequirement(_owners.length, _required)\\n {\\n for (uint i=0; i<_owners.length; i++) {\\n require(!isOwner[_owners[i]] && _owners[i] != 0);\\n isOwner[_owners[i]] = true;\\n }\\n owners = _owners;\\n required = _required;\\n }\\n\\n /// @dev Allows to add a new owner. Transaction has to be sent by wallet.\\n /// @param owner Address of new owner.\\n function addOwner(address owner)\\n public\\n onlyWallet\\n ownerDoesNotExist(owner)\\n notNull(owner)\\n validRequirement(owners.length + 1, required)\\n {\\n isOwner[owner] = true;\\n owners.push(owner);\\n OwnerAddition(owner);\\n }\\n\\n /// @dev Allows to remove an owner. Transaction has to be sent by wallet.\\n /// @param owner Address of owner.\\n function removeOwner(address owner)\\n public\\n onlyWallet\\n ownerExists(owner)\\n {\\n isOwner[owner] = false;\\n for (uint i=0; i owners.length)\\n changeRequirement(owners.length);\\n OwnerRemoval(owner);\\n }\\n\\n /// @dev Allows to replace an owner with a new owner. Transaction has to be sent by wallet.\\n /// @param owner Address of owner to be replaced.\\n /// @param newOwner Address of new owner.\\n function replaceOwner(address owner, address newOwner)\\n public\\n onlyWallet\\n ownerExists(owner)\\n ownerDoesNotExist(newOwner)\\n {\\n for (uint i=0; i\\ncontract MultiSigWalletFactory is Factory {\\n\\n /*\\n * Public functions\\n */\\n /// @dev Allows verified creation of multisignature wallet.\\n /// @param _owners List of initial owners.\\n /// @param _required Number of required confirmations.\\n /// @return Returns wallet address.\\n function create(address[] _owners, uint _required)\\n public\\n returns (address wallet)\\n {\\n wallet = new MultiSigWallet(_owners, _required);\\n register(wallet);\\n }\\n}\\n\",\"keccak256\":\"0x7caddc8ccbca401786af99fde5415fa7daec057ad79083c4c2f1ab80657991da\"}},\"version\":1}", + "bytecode": "0x608060405234801561001057600080fd5b50612a33806100206000396000f300608060405260043610610062576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff1680632f4f33161461006757806357183c82146100c25780638f8384781461014f578063f8f73808146101a6575b600080fd5b34801561007357600080fd5b506100a8600480360381019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050610256565b604051808215151515815260200191505060405180910390f35b3480156100ce57600080fd5b5061010d600480360381019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190929190505050610276565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b34801561015b57600080fd5b50610190600480360381019080803573ffffffffffffffffffffffffffffffffffffffff1690602001909291905050506102c3565b6040518082815260200191505060405180910390f35b3480156101b257600080fd5b50610214600480360381019080803590602001908201803590602001908080602002602001604051908101604052809392919081815260200183836020028082843782019150505050505091929192908035906020019092919050505061030f565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b60006020528060005260406000206000915054906101000a900460ff1681565b60016020528160005260406000208181548110151561029157fe5b906000526020600020016000915091509054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b6000600160008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020805490509050919050565b6000828261031b61052f565b8080602001838152602001828103825284818151815260200191508051906020019060200280838360005b83811015610361578082015181840152602081019050610346565b505050509050019350505050604051809103906000f080158015610389573d6000803e3d6000fd5b5090506103958161039b565b92915050565b60016000808373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff021916908315150217905550600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208190806001815401808255809150509060018203906000526020600020016000909192909190916101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550507f4fb057ad4a26ed17a57957fa69c306f11987596069b89521c511fc9a894e61613382604051808373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019250505060405180910390a150565b6040516124c88061054083390190560060806040523480156200001157600080fd5b50604051620024c8380380620024c883398101806040528101908080518201929190602001805190602001909291905050506000825182603282111580156200005a5750818111155b801562000068575060008114155b801562000076575060008214155b15156200008257600080fd5b600092505b8451831015620001bd57600260008685815181101515620000a457fe5b9060200190602002015173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff16158015620001335750600085848151811015156200011057fe5b9060200190602002015173ffffffffffffffffffffffffffffffffffffffff1614155b15156200013f57600080fd5b60016002600087868151811015156200015457fe5b9060200190602002015173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff021916908315150217905550828060010193505062000087565b8460039080519060200190620001d5929190620001e8565b50836004819055505050505050620002bd565b82805482825590600052602060002090810192821562000264579160200282015b82811115620002635782518260006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055509160200191906001019062000209565b5b50905062000273919062000277565b5090565b620002ba91905b80821115620002b657600081816101000a81549073ffffffffffffffffffffffffffffffffffffffff0219169055506001016200027e565b5090565b90565b6121fb80620002cd6000396000f30060806040526004361061011d576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff168063025e7c2714610177578063173825d9146101e457806320ea8d86146102275780632f54bf6e146102545780633411c81c146102af57806354741525146103145780637065cb4814610363578063784547a7146103a65780638b51d13f146103eb5780639ace38c21461042c578063a0e67e2b14610517578063a8abe69a14610583578063b5dc40c314610627578063b77bf600146106a9578063ba51a6df146106d4578063c01a8c8414610701578063c64274741461072e578063d74f8edd146107d5578063dc8452cd14610800578063e20056e61461082b578063ee22610b1461088e575b6000341115610175573373ffffffffffffffffffffffffffffffffffffffff167fe1fffcc4923d04b559f4d29a8bfc6cda04eb5b0d3c460751c2402c5c5cc9109c346040518082815260200191505060405180910390a25b005b34801561018357600080fd5b506101a2600480360381019080803590602001909291905050506108bb565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b3480156101f057600080fd5b50610225600480360381019080803573ffffffffffffffffffffffffffffffffffffffff1690602001909291905050506108f9565b005b34801561023357600080fd5b5061025260048036038101908080359060200190929190505050610b92565b005b34801561026057600080fd5b50610295600480360381019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050610d3a565b604051808215151515815260200191505060405180910390f35b3480156102bb57600080fd5b506102fa60048036038101908080359060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050610d5a565b604051808215151515815260200191505060405180910390f35b34801561032057600080fd5b5061034d600480360381019080803515159060200190929190803515159060200190929190505050610d89565b6040518082815260200191505060405180910390f35b34801561036f57600080fd5b506103a4600480360381019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050610e1b565b005b3480156103b257600080fd5b506103d160048036038101908080359060200190929190505050611020565b604051808215151515815260200191505060405180910390f35b3480156103f757600080fd5b5061041660048036038101908080359060200190929190505050611105565b6040518082815260200191505060405180910390f35b34801561043857600080fd5b50610457600480360381019080803590602001909291905050506111d0565b604051808573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018481526020018060200183151515158152602001828103825284818151815260200191508051906020019080838360005b838110156104d95780820151818401526020810190506104be565b50505050905090810190601f1680156105065780820380516001836020036101000a031916815260200191505b509550505050505060405180910390f35b34801561052357600080fd5b5061052c6112c5565b6040518080602001828103825283818151815260200191508051906020019060200280838360005b8381101561056f578082015181840152602081019050610554565b505050509050019250505060405180910390f35b34801561058f57600080fd5b506105d06004803603810190808035906020019092919080359060200190929190803515159060200190929190803515159060200190929190505050611353565b6040518080602001828103825283818151815260200191508051906020019060200280838360005b838110156106135780820151818401526020810190506105f8565b505050509050019250505060405180910390f35b34801561063357600080fd5b50610652600480360381019080803590602001909291905050506114c4565b6040518080602001828103825283818151815260200191508051906020019060200280838360005b8381101561069557808201518184015260208101905061067a565b505050509050019250505060405180910390f35b3480156106b557600080fd5b506106be611701565b6040518082815260200191505060405180910390f35b3480156106e057600080fd5b506106ff60048036038101908080359060200190929190505050611707565b005b34801561070d57600080fd5b5061072c600480360381019080803590602001909291905050506117c1565b005b34801561073a57600080fd5b506107bf600480360381019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190929190803590602001908201803590602001908080601f016020809104026020016040519081016040528093929190818152602001838380828437820191505050505050919291929050505061199e565b6040518082815260200191505060405180910390f35b3480156107e157600080fd5b506107ea6119bd565b6040518082815260200191505060405180910390f35b34801561080c57600080fd5b506108156119c2565b6040518082815260200191505060405180910390f35b34801561083757600080fd5b5061088c600480360381019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff1690602001909291905050506119c8565b005b34801561089a57600080fd5b506108b960048036038101908080359060200190929190505050611cdd565b005b6003818154811015156108ca57fe5b906000526020600020016000915054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b60003073ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614151561093557600080fd5b81600260008273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff16151561098e57600080fd5b6000600260008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff021916908315150217905550600091505b600160038054905003821015610b13578273ffffffffffffffffffffffffffffffffffffffff16600383815481101515610a2157fe5b9060005260206000200160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff161415610b06576003600160038054905003815481101515610a7f57fe5b9060005260206000200160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16600383815481101515610ab957fe5b9060005260206000200160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550610b13565b81806001019250506109eb565b6001600381818054905003915081610b2b91906120fe565b506003805490506004541115610b4a57610b49600380549050611707565b5b8273ffffffffffffffffffffffffffffffffffffffff167f8001553a916ef2f495d26a907cc54d96ed840d7bda71e73194bf5a9df7a76b9060405160405180910390a2505050565b33600260008273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff161515610beb57600080fd5b81336001600083815260200190815260200160002060008273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff161515610c5657600080fd5b8360008082815260200190815260200160002060030160009054906101000a900460ff16151515610c8657600080fd5b60006001600087815260200190815260200160002060003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff021916908315150217905550843373ffffffffffffffffffffffffffffffffffffffff167ff6a317157440607f36269043eb55f1287a5a19ba2216afeab88cd46cbcfb88e960405160405180910390a35050505050565b60026020528060005260406000206000915054906101000a900460ff1681565b60016020528160005260406000206020528060005260406000206000915091509054906101000a900460ff1681565b600080600090505b600554811015610e1457838015610dc8575060008082815260200190815260200160002060030160009054906101000a900460ff16155b80610dfb5750828015610dfa575060008082815260200190815260200160002060030160009054906101000a900460ff165b5b15610e07576001820191505b8080600101915050610d91565b5092915050565b3073ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16141515610e5557600080fd5b80600260008273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff16151515610eaf57600080fd5b8160008173ffffffffffffffffffffffffffffffffffffffff1614151515610ed657600080fd5b60016003805490500160045460328211158015610ef35750818111155b8015610f00575060008114155b8015610f0d575060008214155b1515610f1857600080fd5b6001600260008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff02191690831515021790555060038590806001815401808255809150509060018203906000526020600020016000909192909190916101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550508473ffffffffffffffffffffffffffffffffffffffff167ff39e6e1eb0edcf53c221607b54b00cd28f3196fed0a24994dc308b8f611b682d60405160405180910390a25050505050565b6000806000809150600090505b6003805490508110156110fd5760016000858152602001908152602001600020600060038381548110151561105e57fe5b9060005260206000200160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff16156110dd576001820191505b6004548214156110f057600192506110fe565b808060010191505061102d565b5b5050919050565b600080600090505b6003805490508110156111ca5760016000848152602001908152602001600020600060038381548110151561113e57fe5b9060005260206000200160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff16156111bd576001820191505b808060010191505061110d565b50919050565b60006020528060005260406000206000915090508060000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1690806001015490806002018054600181600116156101000203166002900480601f0160208091040260200160405190810160405280929190818152602001828054600181600116156101000203166002900480156112a85780601f1061127d576101008083540402835291602001916112a8565b820191906000526020600020905b81548152906001019060200180831161128b57829003601f168201915b5050505050908060030160009054906101000a900460ff16905084565b6060600380548060200260200160405190810160405280929190818152602001828054801561134957602002820191906000526020600020905b8160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190600101908083116112ff575b5050505050905090565b60608060008060055460405190808252806020026020018201604052801561138a5781602001602082028038833980820191505090505b50925060009150600090505b600554811015611436578580156113cd575060008082815260200190815260200160002060030160009054906101000a900460ff16155b8061140057508480156113ff575060008082815260200190815260200160002060030160009054906101000a900460ff165b5b156114295780838381518110151561141457fe5b90602001906020020181815250506001820191505b8080600101915050611396565b8787036040519080825280602002602001820160405280156114675781602001602082028038833980820191505090505b5093508790505b868110156114b957828181518110151561148457fe5b906020019060200201518489830381518110151561149e57fe5b9060200190602002018181525050808060010191505061146e565b505050949350505050565b6060806000806003805490506040519080825280602002602001820160405280156114fe5781602001602082028038833980820191505090505b50925060009150600090505b60038054905081101561164b5760016000868152602001908152602001600020600060038381548110151561153b57fe5b9060005260206000200160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff161561163e576003818154811015156115c257fe5b9060005260206000200160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1683838151811015156115fb57fe5b9060200190602002019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250506001820191505b808060010191505061150a565b8160405190808252806020026020018201604052801561167a5781602001602082028038833980820191505090505b509350600090505b818110156116f957828181518110151561169857fe5b9060200190602002015184828151811015156116b057fe5b9060200190602002019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250508080600101915050611682565b505050919050565b60055481565b3073ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614151561174157600080fd5b60038054905081603282111580156117595750818111155b8015611766575060008114155b8015611773575060008214155b151561177e57600080fd5b826004819055507fa3f1ee9126a074d9326c682f561767f710e927faa811f7a99829d49dc421797a836040518082815260200191505060405180910390a1505050565b33600260008273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff16151561181a57600080fd5b81600080600083815260200190815260200160002060000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff161415151561187657600080fd5b82336001600083815260200190815260200160002060008273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff161515156118e257600080fd5b600180600087815260200190815260200160002060003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff021916908315150217905550843373ffffffffffffffffffffffffffffffffffffffff167f4a504a94899432a9846e1aa406dceb1bcfd538bb839071d49d1e5e23f5be30ef60405160405180910390a361199785611cdd565b5050505050565b60006119ab848484611f85565b90506119b6816117c1565b9392505050565b603281565b60045481565b60003073ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16141515611a0457600080fd5b82600260008273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff161515611a5d57600080fd5b82600260008273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff16151515611ab757600080fd5b600092505b600380549050831015611ba0578473ffffffffffffffffffffffffffffffffffffffff16600384815481101515611aef57fe5b9060005260206000200160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff161415611b935783600384815481101515611b4657fe5b9060005260206000200160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550611ba0565b8280600101935050611abc565b6000600260008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff0219169083151502179055506001600260008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff0219169083151502179055508473ffffffffffffffffffffffffffffffffffffffff167f8001553a916ef2f495d26a907cc54d96ed840d7bda71e73194bf5a9df7a76b9060405160405180910390a28373ffffffffffffffffffffffffffffffffffffffff167ff39e6e1eb0edcf53c221607b54b00cd28f3196fed0a24994dc308b8f611b682d60405160405180910390a25050505050565b600033600260008273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff161515611d3857600080fd5b82336001600083815260200190815260200160002060008273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff161515611da357600080fd5b8460008082815260200190815260200160002060030160009054906101000a900460ff16151515611dd357600080fd5b611ddc86611020565b15611f7d57600080878152602001908152602001600020945060018560030160006101000a81548160ff021916908315150217905550611efa8560000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16866001015487600201805460018160011615610100020316600290049050886002018054600181600116156101000203166002900480601f016020809104026020016040519081016040528092919081815260200182805460018160011615610100020316600290048015611ef05780601f10611ec557610100808354040283529160200191611ef0565b820191906000526020600020905b815481529060010190602001808311611ed357829003601f168201915b50505050506120d7565b15611f3157857f33e13ecb54c3076d8e8bb8c2881800a4d972b792045ffae98fdf46df365fed7560405160405180910390a2611f7c565b857f526441bb6c1aba3c9a4a6ca1d6545da9c2333c8c48343ef398eb858d72b7923660405160405180910390a260008560030160006101000a81548160ff0219169083151502179055505b5b505050505050565b60008360008173ffffffffffffffffffffffffffffffffffffffff1614151515611fae57600080fd5b60055491506080604051908101604052808673ffffffffffffffffffffffffffffffffffffffff1681526020018581526020018481526020016000151581525060008084815260200190815260200160002060008201518160000160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555060208201518160010155604082015181600201908051906020019061206d92919061212a565b5060608201518160030160006101000a81548160ff0219169083151502179055509050506001600560008282540192505081905550817fc0ba8fe4b176c1714197d43b9cc6bcf797a4a7461c5fe8d0ef6e184ae7601e5160405160405180910390a2509392505050565b6000806040516020840160008287838a8c6187965a03f19250505080915050949350505050565b8154818355818111156121255781836000526020600020918201910161212491906121aa565b5b505050565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f1061216b57805160ff1916838001178555612199565b82800160010185558215612199579182015b8281111561219857825182559160200191906001019061217d565b5b5090506121a691906121aa565b5090565b6121cc91905b808211156121c85760008160009055506001016121b0565b5090565b905600a165627a7a72305820177ee94963ac07e99a2f84a1f9e9ee6e87b6d82f5125a93fdefeb951772ebb930029a165627a7a723058205586bae58da8c4a20ff094484cac661d1e74dbd3d1f38de4a6dcaafcee42ce170029", + "deployedBytecode": "0x608060405260043610610062576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff1680632f4f33161461006757806357183c82146100c25780638f8384781461014f578063f8f73808146101a6575b600080fd5b34801561007357600080fd5b506100a8600480360381019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050610256565b604051808215151515815260200191505060405180910390f35b3480156100ce57600080fd5b5061010d600480360381019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190929190505050610276565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b34801561015b57600080fd5b50610190600480360381019080803573ffffffffffffffffffffffffffffffffffffffff1690602001909291905050506102c3565b6040518082815260200191505060405180910390f35b3480156101b257600080fd5b50610214600480360381019080803590602001908201803590602001908080602002602001604051908101604052809392919081815260200183836020028082843782019150505050505091929192908035906020019092919050505061030f565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b60006020528060005260406000206000915054906101000a900460ff1681565b60016020528160005260406000208181548110151561029157fe5b906000526020600020016000915091509054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b6000600160008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020805490509050919050565b6000828261031b61052f565b8080602001838152602001828103825284818151815260200191508051906020019060200280838360005b83811015610361578082015181840152602081019050610346565b505050509050019350505050604051809103906000f080158015610389573d6000803e3d6000fd5b5090506103958161039b565b92915050565b60016000808373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff021916908315150217905550600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208190806001815401808255809150509060018203906000526020600020016000909192909190916101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550507f4fb057ad4a26ed17a57957fa69c306f11987596069b89521c511fc9a894e61613382604051808373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019250505060405180910390a150565b6040516124c88061054083390190560060806040523480156200001157600080fd5b50604051620024c8380380620024c883398101806040528101908080518201929190602001805190602001909291905050506000825182603282111580156200005a5750818111155b801562000068575060008114155b801562000076575060008214155b15156200008257600080fd5b600092505b8451831015620001bd57600260008685815181101515620000a457fe5b9060200190602002015173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff16158015620001335750600085848151811015156200011057fe5b9060200190602002015173ffffffffffffffffffffffffffffffffffffffff1614155b15156200013f57600080fd5b60016002600087868151811015156200015457fe5b9060200190602002015173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff021916908315150217905550828060010193505062000087565b8460039080519060200190620001d5929190620001e8565b50836004819055505050505050620002bd565b82805482825590600052602060002090810192821562000264579160200282015b82811115620002635782518260006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055509160200191906001019062000209565b5b50905062000273919062000277565b5090565b620002ba91905b80821115620002b657600081816101000a81549073ffffffffffffffffffffffffffffffffffffffff0219169055506001016200027e565b5090565b90565b6121fb80620002cd6000396000f30060806040526004361061011d576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff168063025e7c2714610177578063173825d9146101e457806320ea8d86146102275780632f54bf6e146102545780633411c81c146102af57806354741525146103145780637065cb4814610363578063784547a7146103a65780638b51d13f146103eb5780639ace38c21461042c578063a0e67e2b14610517578063a8abe69a14610583578063b5dc40c314610627578063b77bf600146106a9578063ba51a6df146106d4578063c01a8c8414610701578063c64274741461072e578063d74f8edd146107d5578063dc8452cd14610800578063e20056e61461082b578063ee22610b1461088e575b6000341115610175573373ffffffffffffffffffffffffffffffffffffffff167fe1fffcc4923d04b559f4d29a8bfc6cda04eb5b0d3c460751c2402c5c5cc9109c346040518082815260200191505060405180910390a25b005b34801561018357600080fd5b506101a2600480360381019080803590602001909291905050506108bb565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b3480156101f057600080fd5b50610225600480360381019080803573ffffffffffffffffffffffffffffffffffffffff1690602001909291905050506108f9565b005b34801561023357600080fd5b5061025260048036038101908080359060200190929190505050610b92565b005b34801561026057600080fd5b50610295600480360381019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050610d3a565b604051808215151515815260200191505060405180910390f35b3480156102bb57600080fd5b506102fa60048036038101908080359060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050610d5a565b604051808215151515815260200191505060405180910390f35b34801561032057600080fd5b5061034d600480360381019080803515159060200190929190803515159060200190929190505050610d89565b6040518082815260200191505060405180910390f35b34801561036f57600080fd5b506103a4600480360381019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050610e1b565b005b3480156103b257600080fd5b506103d160048036038101908080359060200190929190505050611020565b604051808215151515815260200191505060405180910390f35b3480156103f757600080fd5b5061041660048036038101908080359060200190929190505050611105565b6040518082815260200191505060405180910390f35b34801561043857600080fd5b50610457600480360381019080803590602001909291905050506111d0565b604051808573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018481526020018060200183151515158152602001828103825284818151815260200191508051906020019080838360005b838110156104d95780820151818401526020810190506104be565b50505050905090810190601f1680156105065780820380516001836020036101000a031916815260200191505b509550505050505060405180910390f35b34801561052357600080fd5b5061052c6112c5565b6040518080602001828103825283818151815260200191508051906020019060200280838360005b8381101561056f578082015181840152602081019050610554565b505050509050019250505060405180910390f35b34801561058f57600080fd5b506105d06004803603810190808035906020019092919080359060200190929190803515159060200190929190803515159060200190929190505050611353565b6040518080602001828103825283818151815260200191508051906020019060200280838360005b838110156106135780820151818401526020810190506105f8565b505050509050019250505060405180910390f35b34801561063357600080fd5b50610652600480360381019080803590602001909291905050506114c4565b6040518080602001828103825283818151815260200191508051906020019060200280838360005b8381101561069557808201518184015260208101905061067a565b505050509050019250505060405180910390f35b3480156106b557600080fd5b506106be611701565b6040518082815260200191505060405180910390f35b3480156106e057600080fd5b506106ff60048036038101908080359060200190929190505050611707565b005b34801561070d57600080fd5b5061072c600480360381019080803590602001909291905050506117c1565b005b34801561073a57600080fd5b506107bf600480360381019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190929190803590602001908201803590602001908080601f016020809104026020016040519081016040528093929190818152602001838380828437820191505050505050919291929050505061199e565b6040518082815260200191505060405180910390f35b3480156107e157600080fd5b506107ea6119bd565b6040518082815260200191505060405180910390f35b34801561080c57600080fd5b506108156119c2565b6040518082815260200191505060405180910390f35b34801561083757600080fd5b5061088c600480360381019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff1690602001909291905050506119c8565b005b34801561089a57600080fd5b506108b960048036038101908080359060200190929190505050611cdd565b005b6003818154811015156108ca57fe5b906000526020600020016000915054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b60003073ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614151561093557600080fd5b81600260008273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff16151561098e57600080fd5b6000600260008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff021916908315150217905550600091505b600160038054905003821015610b13578273ffffffffffffffffffffffffffffffffffffffff16600383815481101515610a2157fe5b9060005260206000200160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff161415610b06576003600160038054905003815481101515610a7f57fe5b9060005260206000200160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16600383815481101515610ab957fe5b9060005260206000200160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550610b13565b81806001019250506109eb565b6001600381818054905003915081610b2b91906120fe565b506003805490506004541115610b4a57610b49600380549050611707565b5b8273ffffffffffffffffffffffffffffffffffffffff167f8001553a916ef2f495d26a907cc54d96ed840d7bda71e73194bf5a9df7a76b9060405160405180910390a2505050565b33600260008273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff161515610beb57600080fd5b81336001600083815260200190815260200160002060008273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff161515610c5657600080fd5b8360008082815260200190815260200160002060030160009054906101000a900460ff16151515610c8657600080fd5b60006001600087815260200190815260200160002060003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff021916908315150217905550843373ffffffffffffffffffffffffffffffffffffffff167ff6a317157440607f36269043eb55f1287a5a19ba2216afeab88cd46cbcfb88e960405160405180910390a35050505050565b60026020528060005260406000206000915054906101000a900460ff1681565b60016020528160005260406000206020528060005260406000206000915091509054906101000a900460ff1681565b600080600090505b600554811015610e1457838015610dc8575060008082815260200190815260200160002060030160009054906101000a900460ff16155b80610dfb5750828015610dfa575060008082815260200190815260200160002060030160009054906101000a900460ff165b5b15610e07576001820191505b8080600101915050610d91565b5092915050565b3073ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16141515610e5557600080fd5b80600260008273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff16151515610eaf57600080fd5b8160008173ffffffffffffffffffffffffffffffffffffffff1614151515610ed657600080fd5b60016003805490500160045460328211158015610ef35750818111155b8015610f00575060008114155b8015610f0d575060008214155b1515610f1857600080fd5b6001600260008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff02191690831515021790555060038590806001815401808255809150509060018203906000526020600020016000909192909190916101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550508473ffffffffffffffffffffffffffffffffffffffff167ff39e6e1eb0edcf53c221607b54b00cd28f3196fed0a24994dc308b8f611b682d60405160405180910390a25050505050565b6000806000809150600090505b6003805490508110156110fd5760016000858152602001908152602001600020600060038381548110151561105e57fe5b9060005260206000200160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff16156110dd576001820191505b6004548214156110f057600192506110fe565b808060010191505061102d565b5b5050919050565b600080600090505b6003805490508110156111ca5760016000848152602001908152602001600020600060038381548110151561113e57fe5b9060005260206000200160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff16156111bd576001820191505b808060010191505061110d565b50919050565b60006020528060005260406000206000915090508060000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1690806001015490806002018054600181600116156101000203166002900480601f0160208091040260200160405190810160405280929190818152602001828054600181600116156101000203166002900480156112a85780601f1061127d576101008083540402835291602001916112a8565b820191906000526020600020905b81548152906001019060200180831161128b57829003601f168201915b5050505050908060030160009054906101000a900460ff16905084565b6060600380548060200260200160405190810160405280929190818152602001828054801561134957602002820191906000526020600020905b8160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190600101908083116112ff575b5050505050905090565b60608060008060055460405190808252806020026020018201604052801561138a5781602001602082028038833980820191505090505b50925060009150600090505b600554811015611436578580156113cd575060008082815260200190815260200160002060030160009054906101000a900460ff16155b8061140057508480156113ff575060008082815260200190815260200160002060030160009054906101000a900460ff165b5b156114295780838381518110151561141457fe5b90602001906020020181815250506001820191505b8080600101915050611396565b8787036040519080825280602002602001820160405280156114675781602001602082028038833980820191505090505b5093508790505b868110156114b957828181518110151561148457fe5b906020019060200201518489830381518110151561149e57fe5b9060200190602002018181525050808060010191505061146e565b505050949350505050565b6060806000806003805490506040519080825280602002602001820160405280156114fe5781602001602082028038833980820191505090505b50925060009150600090505b60038054905081101561164b5760016000868152602001908152602001600020600060038381548110151561153b57fe5b9060005260206000200160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff161561163e576003818154811015156115c257fe5b9060005260206000200160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1683838151811015156115fb57fe5b9060200190602002019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250506001820191505b808060010191505061150a565b8160405190808252806020026020018201604052801561167a5781602001602082028038833980820191505090505b509350600090505b818110156116f957828181518110151561169857fe5b9060200190602002015184828151811015156116b057fe5b9060200190602002019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250508080600101915050611682565b505050919050565b60055481565b3073ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614151561174157600080fd5b60038054905081603282111580156117595750818111155b8015611766575060008114155b8015611773575060008214155b151561177e57600080fd5b826004819055507fa3f1ee9126a074d9326c682f561767f710e927faa811f7a99829d49dc421797a836040518082815260200191505060405180910390a1505050565b33600260008273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff16151561181a57600080fd5b81600080600083815260200190815260200160002060000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff161415151561187657600080fd5b82336001600083815260200190815260200160002060008273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff161515156118e257600080fd5b600180600087815260200190815260200160002060003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff021916908315150217905550843373ffffffffffffffffffffffffffffffffffffffff167f4a504a94899432a9846e1aa406dceb1bcfd538bb839071d49d1e5e23f5be30ef60405160405180910390a361199785611cdd565b5050505050565b60006119ab848484611f85565b90506119b6816117c1565b9392505050565b603281565b60045481565b60003073ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16141515611a0457600080fd5b82600260008273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff161515611a5d57600080fd5b82600260008273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff16151515611ab757600080fd5b600092505b600380549050831015611ba0578473ffffffffffffffffffffffffffffffffffffffff16600384815481101515611aef57fe5b9060005260206000200160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff161415611b935783600384815481101515611b4657fe5b9060005260206000200160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550611ba0565b8280600101935050611abc565b6000600260008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff0219169083151502179055506001600260008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff0219169083151502179055508473ffffffffffffffffffffffffffffffffffffffff167f8001553a916ef2f495d26a907cc54d96ed840d7bda71e73194bf5a9df7a76b9060405160405180910390a28373ffffffffffffffffffffffffffffffffffffffff167ff39e6e1eb0edcf53c221607b54b00cd28f3196fed0a24994dc308b8f611b682d60405160405180910390a25050505050565b600033600260008273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff161515611d3857600080fd5b82336001600083815260200190815260200160002060008273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff161515611da357600080fd5b8460008082815260200190815260200160002060030160009054906101000a900460ff16151515611dd357600080fd5b611ddc86611020565b15611f7d57600080878152602001908152602001600020945060018560030160006101000a81548160ff021916908315150217905550611efa8560000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16866001015487600201805460018160011615610100020316600290049050886002018054600181600116156101000203166002900480601f016020809104026020016040519081016040528092919081815260200182805460018160011615610100020316600290048015611ef05780601f10611ec557610100808354040283529160200191611ef0565b820191906000526020600020905b815481529060010190602001808311611ed357829003601f168201915b50505050506120d7565b15611f3157857f33e13ecb54c3076d8e8bb8c2881800a4d972b792045ffae98fdf46df365fed7560405160405180910390a2611f7c565b857f526441bb6c1aba3c9a4a6ca1d6545da9c2333c8c48343ef398eb858d72b7923660405160405180910390a260008560030160006101000a81548160ff0219169083151502179055505b5b505050505050565b60008360008173ffffffffffffffffffffffffffffffffffffffff1614151515611fae57600080fd5b60055491506080604051908101604052808673ffffffffffffffffffffffffffffffffffffffff1681526020018581526020018481526020016000151581525060008084815260200190815260200160002060008201518160000160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555060208201518160010155604082015181600201908051906020019061206d92919061212a565b5060608201518160030160006101000a81548160ff0219169083151502179055509050506001600560008282540192505081905550817fc0ba8fe4b176c1714197d43b9cc6bcf797a4a7461c5fe8d0ef6e184ae7601e5160405160405180910390a2509392505050565b6000806040516020840160008287838a8c6187965a03f19250505080915050949350505050565b8154818355818111156121255781836000526020600020918201910161212491906121aa565b5b505050565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f1061216b57805160ff1916838001178555612199565b82800160010185558215612199579182015b8281111561219857825182559160200191906001019061217d565b5b5090506121a691906121aa565b5090565b6121cc91905b808211156121c85760008160009055506001016121b0565b5090565b905600a165627a7a72305820177ee94963ac07e99a2f84a1f9e9ee6e87b6d82f5125a93fdefeb951772ebb930029a165627a7a723058205586bae58da8c4a20ff094484cac661d1e74dbd3d1f38de4a6dcaafcee42ce170029", + "devdoc": { + "author": "Stefan George - ", + "methods": { + "create(address[],uint256)": { + "details": "Allows verified creation of multisignature wallet.", + "params": { + "_owners": "List of initial owners.", + "_required": "Number of required confirmations." + }, + "return": "Returns wallet address." + }, + "getInstantiationCount(address)": { + "details": "Returns number of instantiations by creator.", + "params": { + "creator": "Contract creator." + }, + "return": "Returns number of instantiations by creator." + } + }, + "title": "Multisignature wallet factory - Allows creation of multisig wallet." + }, + "userdoc": { + "methods": {} + } +} \ No newline at end of file diff --git a/deployments/dfk/Multicall2.json b/deployments/dfk/Multicall2.json new file mode 100644 index 000000000..bb3fbe98a --- /dev/null +++ b/deployments/dfk/Multicall2.json @@ -0,0 +1,353 @@ +{ + "address": "0x7F1Baeb399997e1ecA9A090a4Df6DecBD4f125e2", + "abi": [ + { + "inputs": [ + { + "components": [ + { + "internalType": "address", + "name": "target", + "type": "address" + }, + { + "internalType": "bytes", + "name": "callData", + "type": "bytes" + } + ], + "internalType": "struct Multicall2.Call[]", + "name": "calls", + "type": "tuple[]" + } + ], + "name": "aggregate", + "outputs": [ + { + "internalType": "uint256", + "name": "blockNumber", + "type": "uint256" + }, + { + "internalType": "bytes[]", + "name": "returnData", + "type": "bytes[]" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { + "internalType": "address", + "name": "target", + "type": "address" + }, + { + "internalType": "bytes", + "name": "callData", + "type": "bytes" + } + ], + "internalType": "struct Multicall2.Call[]", + "name": "calls", + "type": "tuple[]" + } + ], + "name": "blockAndAggregate", + "outputs": [ + { + "internalType": "uint256", + "name": "blockNumber", + "type": "uint256" + }, + { + "internalType": "bytes32", + "name": "blockHash", + "type": "bytes32" + }, + { + "components": [ + { + "internalType": "bool", + "name": "success", + "type": "bool" + }, + { + "internalType": "bytes", + "name": "returnData", + "type": "bytes" + } + ], + "internalType": "struct Multicall2.Result[]", + "name": "returnData", + "type": "tuple[]" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "blockNumber", + "type": "uint256" + } + ], + "name": "getBlockHash", + "outputs": [ + { + "internalType": "bytes32", + "name": "blockHash", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getBlockNumber", + "outputs": [ + { + "internalType": "uint256", + "name": "blockNumber", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getCurrentBlockCoinbase", + "outputs": [ + { + "internalType": "address", + "name": "coinbase", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getCurrentBlockDifficulty", + "outputs": [ + { + "internalType": "uint256", + "name": "difficulty", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getCurrentBlockGasLimit", + "outputs": [ + { + "internalType": "uint256", + "name": "gaslimit", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getCurrentBlockTimestamp", + "outputs": [ + { + "internalType": "uint256", + "name": "timestamp", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "addr", + "type": "address" + } + ], + "name": "getEthBalance", + "outputs": [ + { + "internalType": "uint256", + "name": "balance", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getLastBlockHash", + "outputs": [ + { + "internalType": "bytes32", + "name": "blockHash", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bool", + "name": "requireSuccess", + "type": "bool" + }, + { + "components": [ + { + "internalType": "address", + "name": "target", + "type": "address" + }, + { + "internalType": "bytes", + "name": "callData", + "type": "bytes" + } + ], + "internalType": "struct Multicall2.Call[]", + "name": "calls", + "type": "tuple[]" + } + ], + "name": "tryAggregate", + "outputs": [ + { + "components": [ + { + "internalType": "bool", + "name": "success", + "type": "bool" + }, + { + "internalType": "bytes", + "name": "returnData", + "type": "bytes" + } + ], + "internalType": "struct Multicall2.Result[]", + "name": "returnData", + "type": "tuple[]" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bool", + "name": "requireSuccess", + "type": "bool" + }, + { + "components": [ + { + "internalType": "address", + "name": "target", + "type": "address" + }, + { + "internalType": "bytes", + "name": "callData", + "type": "bytes" + } + ], + "internalType": "struct Multicall2.Call[]", + "name": "calls", + "type": "tuple[]" + } + ], + "name": "tryBlockAndAggregate", + "outputs": [ + { + "internalType": "uint256", + "name": "blockNumber", + "type": "uint256" + }, + { + "internalType": "bytes32", + "name": "blockHash", + "type": "bytes32" + }, + { + "components": [ + { + "internalType": "bool", + "name": "success", + "type": "bool" + }, + { + "internalType": "bytes", + "name": "returnData", + "type": "bytes" + } + ], + "internalType": "struct Multicall2.Result[]", + "name": "returnData", + "type": "tuple[]" + } + ], + "stateMutability": "nonpayable", + "type": "function" + } + ], + "transactionHash": "0x182c38d309355a7ab78700c3261fc43a64954e4820917eede4df3dbdef680f3b", + "receipt": { + "to": null, + "from": "0x235AF07E770f474d24F5bf73074735892371b40D", + "contractAddress": "0x7F1Baeb399997e1ecA9A090a4Df6DecBD4f125e2", + "transactionIndex": 0, + "gasUsed": "677633", + "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "blockHash": "0x4f5136630655d53237d200cd2208b0321d3658fd3da048c614a06888ed92afdb", + "transactionHash": "0x182c38d309355a7ab78700c3261fc43a64954e4820917eede4df3dbdef680f3b", + "logs": [], + "blockNumber": 18, + "cumulativeGasUsed": "677633", + "status": 1, + "byzantium": true + }, + "args": [], + "solcInputHash": "67709d0e6d2903fa456800932c6c2db8", + "metadata": "{\"compiler\":{\"version\":\"0.8.11+commit.d7f03943\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"target\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"callData\",\"type\":\"bytes\"}],\"internalType\":\"struct Multicall2.Call[]\",\"name\":\"calls\",\"type\":\"tuple[]\"}],\"name\":\"aggregate\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"blockNumber\",\"type\":\"uint256\"},{\"internalType\":\"bytes[]\",\"name\":\"returnData\",\"type\":\"bytes[]\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"target\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"callData\",\"type\":\"bytes\"}],\"internalType\":\"struct Multicall2.Call[]\",\"name\":\"calls\",\"type\":\"tuple[]\"}],\"name\":\"blockAndAggregate\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"blockNumber\",\"type\":\"uint256\"},{\"internalType\":\"bytes32\",\"name\":\"blockHash\",\"type\":\"bytes32\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"success\",\"type\":\"bool\"},{\"internalType\":\"bytes\",\"name\":\"returnData\",\"type\":\"bytes\"}],\"internalType\":\"struct Multicall2.Result[]\",\"name\":\"returnData\",\"type\":\"tuple[]\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"blockNumber\",\"type\":\"uint256\"}],\"name\":\"getBlockHash\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"blockHash\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getBlockNumber\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"blockNumber\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getCurrentBlockCoinbase\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"coinbase\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getCurrentBlockDifficulty\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"difficulty\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getCurrentBlockGasLimit\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"gaslimit\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getCurrentBlockTimestamp\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"timestamp\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"addr\",\"type\":\"address\"}],\"name\":\"getEthBalance\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"balance\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getLastBlockHash\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"blockHash\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bool\",\"name\":\"requireSuccess\",\"type\":\"bool\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"target\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"callData\",\"type\":\"bytes\"}],\"internalType\":\"struct Multicall2.Call[]\",\"name\":\"calls\",\"type\":\"tuple[]\"}],\"name\":\"tryAggregate\",\"outputs\":[{\"components\":[{\"internalType\":\"bool\",\"name\":\"success\",\"type\":\"bool\"},{\"internalType\":\"bytes\",\"name\":\"returnData\",\"type\":\"bytes\"}],\"internalType\":\"struct Multicall2.Result[]\",\"name\":\"returnData\",\"type\":\"tuple[]\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bool\",\"name\":\"requireSuccess\",\"type\":\"bool\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"target\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"callData\",\"type\":\"bytes\"}],\"internalType\":\"struct Multicall2.Call[]\",\"name\":\"calls\",\"type\":\"tuple[]\"}],\"name\":\"tryBlockAndAggregate\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"blockNumber\",\"type\":\"uint256\"},{\"internalType\":\"bytes32\",\"name\":\"blockHash\",\"type\":\"bytes32\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"success\",\"type\":\"bool\"},{\"internalType\":\"bytes\",\"name\":\"returnData\",\"type\":\"bytes\"}],\"internalType\":\"struct Multicall2.Result[]\",\"name\":\"returnData\",\"type\":\"tuple[]\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}],\"devdoc\":{\"author\":\"Michael Elliot Joshua Levine Nick Johnson \",\"kind\":\"dev\",\"methods\":{},\"title\":\"Multicall2 - Aggregate results from multiple read-only function calls\",\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/amm/helper/Multicall2.sol\":\"Multicall2\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":5000000},\"remappings\":[]},\"sources\":{\"contracts/amm/helper/Multicall2.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity >=0.5.0;\\npragma experimental ABIEncoderV2;\\n\\n/// @title Multicall2 - Aggregate results from multiple read-only function calls\\n/// @author Michael Elliot \\n/// @author Joshua Levine \\n/// @author Nick Johnson \\n\\ncontract Multicall2 {\\n struct Call {\\n address target;\\n bytes callData;\\n }\\n struct Result {\\n bool success;\\n bytes returnData;\\n }\\n\\n function aggregate(Call[] memory calls)\\n public\\n returns (uint256 blockNumber, bytes[] memory returnData)\\n {\\n blockNumber = block.number;\\n returnData = new bytes[](calls.length);\\n for (uint256 i = 0; i < calls.length; i++) {\\n (bool success, bytes memory ret) =\\n calls[i].target.call(calls[i].callData);\\n require(success, \\\"Multicall aggregate: call failed\\\");\\n returnData[i] = ret;\\n }\\n }\\n\\n function blockAndAggregate(Call[] memory calls)\\n public\\n returns (\\n uint256 blockNumber,\\n bytes32 blockHash,\\n Result[] memory returnData\\n )\\n {\\n (blockNumber, blockHash, returnData) = tryBlockAndAggregate(\\n true,\\n calls\\n );\\n }\\n\\n function getBlockHash(uint256 blockNumber)\\n public\\n view\\n returns (bytes32 blockHash)\\n {\\n blockHash = blockhash(blockNumber);\\n }\\n\\n function getBlockNumber() public view returns (uint256 blockNumber) {\\n blockNumber = block.number;\\n }\\n\\n function getCurrentBlockCoinbase() public view returns (address coinbase) {\\n coinbase = block.coinbase;\\n }\\n\\n function getCurrentBlockDifficulty()\\n public\\n view\\n returns (uint256 difficulty)\\n {\\n difficulty = block.difficulty;\\n }\\n\\n function getCurrentBlockGasLimit() public view returns (uint256 gaslimit) {\\n gaslimit = block.gaslimit;\\n }\\n\\n function getCurrentBlockTimestamp()\\n public\\n view\\n returns (uint256 timestamp)\\n {\\n timestamp = block.timestamp;\\n }\\n\\n function getEthBalance(address addr) public view returns (uint256 balance) {\\n balance = addr.balance;\\n }\\n\\n function getLastBlockHash() public view returns (bytes32 blockHash) {\\n blockHash = blockhash(block.number - 1);\\n }\\n\\n function tryAggregate(bool requireSuccess, Call[] memory calls)\\n public\\n returns (Result[] memory returnData)\\n {\\n returnData = new Result[](calls.length);\\n for (uint256 i = 0; i < calls.length; i++) {\\n (bool success, bytes memory ret) =\\n calls[i].target.call(calls[i].callData);\\n\\n if (requireSuccess) {\\n require(success, \\\"Multicall2 aggregate: call failed\\\");\\n }\\n\\n returnData[i] = Result(success, ret);\\n }\\n }\\n\\n function tryBlockAndAggregate(bool requireSuccess, Call[] memory calls)\\n public\\n returns (\\n uint256 blockNumber,\\n bytes32 blockHash,\\n Result[] memory returnData\\n )\\n {\\n blockNumber = block.number;\\n blockHash = blockhash(block.number);\\n returnData = tryAggregate(requireSuccess, calls);\\n }\\n}\\n\",\"keccak256\":\"0x30a19f416b7a77ba82c01b2978e10cf7c28baaf96d34d7c340a21ddc9c327971\",\"license\":\"MIT\"}},\"version\":1}", + "bytecode": "0x608060405234801561001057600080fd5b50610b55806100206000396000f3fe608060405234801561001057600080fd5b50600436106100d45760003560e01c806372425d9d11610081578063bce38bd71161005b578063bce38bd714610181578063c3077fa9146101a1578063ee82ac5e146101b457600080fd5b806372425d9d1461016757806386d516e81461016d578063a8b0574e1461017357600080fd5b8063399542e9116100b2578063399542e91461011757806342cbb15c146101395780634d2301cc1461013f57600080fd5b80630f28c97d146100d9578063252dba42146100ee57806327e86d6e1461010f575b600080fd5b425b6040519081526020015b60405180910390f35b6101016100fc3660046107e3565b6101c6565b6040516100e592919061089a565b6100db610375565b61012a610125366004610922565b610388565b6040516100e5939291906109df565b436100db565b6100db61014d366004610a07565b73ffffffffffffffffffffffffffffffffffffffff163190565b446100db565b456100db565b6040514181526020016100e5565b61019461018f366004610922565b6103a0565b6040516100e59190610a29565b61012a6101af3660046107e3565b61059d565b6100db6101c2366004610a3c565b4090565b8051439060609067ffffffffffffffff8111156101e5576101e56105ba565b60405190808252806020026020018201604052801561021857816020015b60608152602001906001900390816102035790505b50905060005b835181101561036f5760008085838151811061023c5761023c610a55565b60200260200101516000015173ffffffffffffffffffffffffffffffffffffffff1686848151811061027057610270610a55565b6020026020010151602001516040516102899190610a84565b6000604051808303816000865af19150503d80600081146102c6576040519150601f19603f3d011682016040523d82523d6000602084013e6102cb565b606091505b50915091508161033c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4d756c746963616c6c206167677265676174653a2063616c6c206661696c656460448201526064015b60405180910390fd5b8084848151811061034f5761034f610a55565b60200260200101819052505050808061036790610acf565b91505061021e565b50915091565b6000610382600143610b08565b40905090565b438040606061039785856103a0565b90509250925092565b6060815167ffffffffffffffff8111156103bc576103bc6105ba565b60405190808252806020026020018201604052801561040257816020015b6040805180820190915260008152606060208201528152602001906001900390816103da5790505b50905060005b82518110156105965760008084838151811061042657610426610a55565b60200260200101516000015173ffffffffffffffffffffffffffffffffffffffff1685848151811061045a5761045a610a55565b6020026020010151602001516040516104739190610a84565b6000604051808303816000865af19150503d80600081146104b0576040519150601f19603f3d011682016040523d82523d6000602084013e6104b5565b606091505b5091509150851561054d578161054d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602160248201527f4d756c746963616c6c32206167677265676174653a2063616c6c206661696c6560448201527f64000000000000000000000000000000000000000000000000000000000000006064820152608401610333565b604051806040016040528083151581526020018281525084848151811061057657610576610a55565b60200260200101819052505050808061058e90610acf565b915050610408565b5092915050565b60008060606105ad600185610388565b9196909550909350915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6040805190810167ffffffffffffffff8111828210171561060c5761060c6105ba565b60405290565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff81118282101715610659576106596105ba565b604052919050565b803573ffffffffffffffffffffffffffffffffffffffff8116811461068557600080fd5b919050565b6000601f838184011261069c57600080fd5b8235602067ffffffffffffffff808311156106b9576106b96105ba565b8260051b6106c8838201610612565b93845286810183019383810190898611156106e257600080fd5b84890192505b858310156107d6578235848111156107005760008081fd5b890160407fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0828d0381018213156107375760008081fd5b61073f6105e9565b61074a898501610661565b8152828401358881111561075e5760008081fd5b8085019450508d603f8501126107745760008081fd5b8884013588811115610788576107886105ba565b6107978a848e84011601610612565b92508083528e848287010111156107ae5760008081fd5b808486018b85013760009083018a0152808901919091528452505091840191908401906106e8565b9998505050505050505050565b6000602082840312156107f557600080fd5b813567ffffffffffffffff81111561080c57600080fd5b6108188482850161068a565b949350505050565b60005b8381101561083b578181015183820152602001610823565b8381111561084a576000848401525b50505050565b60008151808452610868816020860160208601610820565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b600060408201848352602060408185015281855180845260608601915060608160051b870101935082870160005b82811015610914577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa0888703018452610902868351610850565b955092840192908401906001016108c8565b509398975050505050505050565b6000806040838503121561093557600080fd5b8235801515811461094557600080fd5b9150602083013567ffffffffffffffff81111561096157600080fd5b61096d8582860161068a565b9150509250929050565b6000815180845260208085019450848260051b860182860160005b858110156109d2578383038952815180511515845285015160408685018190526109be81860183610850565b9a87019a9450505090840190600101610992565b5090979650505050505050565b8381528260208201526060604082015260006109fe6060830184610977565b95945050505050565b600060208284031215610a1957600080fd5b610a2282610661565b9392505050565b602081526000610a226020830184610977565b600060208284031215610a4e57600080fd5b5035919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60008251610a96818460208701610820565b9190910192915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff821415610b0157610b01610aa0565b5060010190565b600082821015610b1a57610b1a610aa0565b50039056fea264697066735822122060fd9c48d0bb96ed1264e555a4028436310b9ecab175977b1a9aad0fcc5102ed64736f6c634300080b0033", + "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106100d45760003560e01c806372425d9d11610081578063bce38bd71161005b578063bce38bd714610181578063c3077fa9146101a1578063ee82ac5e146101b457600080fd5b806372425d9d1461016757806386d516e81461016d578063a8b0574e1461017357600080fd5b8063399542e9116100b2578063399542e91461011757806342cbb15c146101395780634d2301cc1461013f57600080fd5b80630f28c97d146100d9578063252dba42146100ee57806327e86d6e1461010f575b600080fd5b425b6040519081526020015b60405180910390f35b6101016100fc3660046107e3565b6101c6565b6040516100e592919061089a565b6100db610375565b61012a610125366004610922565b610388565b6040516100e5939291906109df565b436100db565b6100db61014d366004610a07565b73ffffffffffffffffffffffffffffffffffffffff163190565b446100db565b456100db565b6040514181526020016100e5565b61019461018f366004610922565b6103a0565b6040516100e59190610a29565b61012a6101af3660046107e3565b61059d565b6100db6101c2366004610a3c565b4090565b8051439060609067ffffffffffffffff8111156101e5576101e56105ba565b60405190808252806020026020018201604052801561021857816020015b60608152602001906001900390816102035790505b50905060005b835181101561036f5760008085838151811061023c5761023c610a55565b60200260200101516000015173ffffffffffffffffffffffffffffffffffffffff1686848151811061027057610270610a55565b6020026020010151602001516040516102899190610a84565b6000604051808303816000865af19150503d80600081146102c6576040519150601f19603f3d011682016040523d82523d6000602084013e6102cb565b606091505b50915091508161033c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4d756c746963616c6c206167677265676174653a2063616c6c206661696c656460448201526064015b60405180910390fd5b8084848151811061034f5761034f610a55565b60200260200101819052505050808061036790610acf565b91505061021e565b50915091565b6000610382600143610b08565b40905090565b438040606061039785856103a0565b90509250925092565b6060815167ffffffffffffffff8111156103bc576103bc6105ba565b60405190808252806020026020018201604052801561040257816020015b6040805180820190915260008152606060208201528152602001906001900390816103da5790505b50905060005b82518110156105965760008084838151811061042657610426610a55565b60200260200101516000015173ffffffffffffffffffffffffffffffffffffffff1685848151811061045a5761045a610a55565b6020026020010151602001516040516104739190610a84565b6000604051808303816000865af19150503d80600081146104b0576040519150601f19603f3d011682016040523d82523d6000602084013e6104b5565b606091505b5091509150851561054d578161054d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602160248201527f4d756c746963616c6c32206167677265676174653a2063616c6c206661696c6560448201527f64000000000000000000000000000000000000000000000000000000000000006064820152608401610333565b604051806040016040528083151581526020018281525084848151811061057657610576610a55565b60200260200101819052505050808061058e90610acf565b915050610408565b5092915050565b60008060606105ad600185610388565b9196909550909350915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6040805190810167ffffffffffffffff8111828210171561060c5761060c6105ba565b60405290565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff81118282101715610659576106596105ba565b604052919050565b803573ffffffffffffffffffffffffffffffffffffffff8116811461068557600080fd5b919050565b6000601f838184011261069c57600080fd5b8235602067ffffffffffffffff808311156106b9576106b96105ba565b8260051b6106c8838201610612565b93845286810183019383810190898611156106e257600080fd5b84890192505b858310156107d6578235848111156107005760008081fd5b890160407fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0828d0381018213156107375760008081fd5b61073f6105e9565b61074a898501610661565b8152828401358881111561075e5760008081fd5b8085019450508d603f8501126107745760008081fd5b8884013588811115610788576107886105ba565b6107978a848e84011601610612565b92508083528e848287010111156107ae5760008081fd5b808486018b85013760009083018a0152808901919091528452505091840191908401906106e8565b9998505050505050505050565b6000602082840312156107f557600080fd5b813567ffffffffffffffff81111561080c57600080fd5b6108188482850161068a565b949350505050565b60005b8381101561083b578181015183820152602001610823565b8381111561084a576000848401525b50505050565b60008151808452610868816020860160208601610820565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b600060408201848352602060408185015281855180845260608601915060608160051b870101935082870160005b82811015610914577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa0888703018452610902868351610850565b955092840192908401906001016108c8565b509398975050505050505050565b6000806040838503121561093557600080fd5b8235801515811461094557600080fd5b9150602083013567ffffffffffffffff81111561096157600080fd5b61096d8582860161068a565b9150509250929050565b6000815180845260208085019450848260051b860182860160005b858110156109d2578383038952815180511515845285015160408685018190526109be81860183610850565b9a87019a9450505090840190600101610992565b5090979650505050505050565b8381528260208201526060604082015260006109fe6060830184610977565b95945050505050565b600060208284031215610a1957600080fd5b610a2282610661565b9392505050565b602081526000610a226020830184610977565b600060208284031215610a4e57600080fd5b5035919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60008251610a96818460208701610820565b9190910192915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff821415610b0157610b01610aa0565b5060010190565b600082821015610b1a57610b1a610aa0565b50039056fea264697066735822122060fd9c48d0bb96ed1264e555a4028436310b9ecab175977b1a9aad0fcc5102ed64736f6c634300080b0033", + "devdoc": { + "author": "Michael Elliot Joshua Levine Nick Johnson ", + "kind": "dev", + "methods": {}, + "title": "Multicall2 - Aggregate results from multiple read-only function calls", + "version": 1 + }, + "userdoc": { + "kind": "user", + "methods": {}, + "version": 1 + }, + "storageLayout": { + "storage": [], + "types": null + } +} \ No newline at end of file diff --git a/deployments/dfk/SynapseBridge.json b/deployments/dfk/SynapseBridge.json new file mode 100644 index 000000000..ddad045c2 --- /dev/null +++ b/deployments/dfk/SynapseBridge.json @@ -0,0 +1,1521 @@ +{ + "address": "0xE05c976d3f045D0E6E7A6f61083d98A15603cF6A", + "abi": [ + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "previousAdmin", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "newAdmin", + "type": "address" + } + ], + "name": "AdminChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "implementation", + "type": "address" + } + ], + "name": "Upgraded", + "type": "event" + }, + { + "stateMutability": "payable", + "type": "fallback" + }, + { + "inputs": [], + "name": "admin", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newAdmin", + "type": "address" + } + ], + "name": "changeAdmin", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "implementation", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newImplementation", + "type": "address" + } + ], + "name": "upgradeTo", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newImplementation", + "type": "address" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "upgradeToAndCall", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "stateMutability": "payable", + "type": "receive" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "Paused", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "bytes32", + "name": "previousAdminRole", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "bytes32", + "name": "newAdminRole", + "type": "bytes32" + } + ], + "name": "RoleAdminChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "sender", + "type": "address" + } + ], + "name": "RoleGranted", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "sender", + "type": "address" + } + ], + "name": "RoleRevoked", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "chainId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "contract IERC20", + "name": "token", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "TokenDeposit", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "chainId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "contract IERC20", + "name": "token", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint8", + "name": "tokenIndexFrom", + "type": "uint8" + }, + { + "indexed": false, + "internalType": "uint8", + "name": "tokenIndexTo", + "type": "uint8" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "minDy", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "deadline", + "type": "uint256" + } + ], + "name": "TokenDepositAndSwap", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "contract IERC20Mintable", + "name": "token", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "fee", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "bytes32", + "name": "kappa", + "type": "bytes32" + } + ], + "name": "TokenMint", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "contract IERC20Mintable", + "name": "token", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "fee", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint8", + "name": "tokenIndexFrom", + "type": "uint8" + }, + { + "indexed": false, + "internalType": "uint8", + "name": "tokenIndexTo", + "type": "uint8" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "minDy", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "deadline", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "bool", + "name": "swapSuccess", + "type": "bool" + }, + { + "indexed": true, + "internalType": "bytes32", + "name": "kappa", + "type": "bytes32" + } + ], + "name": "TokenMintAndSwap", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "chainId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "contract IERC20", + "name": "token", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "TokenRedeem", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "chainId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "contract IERC20", + "name": "token", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint8", + "name": "swapTokenIndex", + "type": "uint8" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "swapMinAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "swapDeadline", + "type": "uint256" + } + ], + "name": "TokenRedeemAndRemove", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "chainId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "contract IERC20", + "name": "token", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint8", + "name": "tokenIndexFrom", + "type": "uint8" + }, + { + "indexed": false, + "internalType": "uint8", + "name": "tokenIndexTo", + "type": "uint8" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "minDy", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "deadline", + "type": "uint256" + } + ], + "name": "TokenRedeemAndSwap", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "to", + "type": "bytes32" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "chainId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "contract IERC20", + "name": "token", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "TokenRedeemV2", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "contract IERC20", + "name": "token", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "fee", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "bytes32", + "name": "kappa", + "type": "bytes32" + } + ], + "name": "TokenWithdraw", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "contract IERC20", + "name": "token", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "fee", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint8", + "name": "swapTokenIndex", + "type": "uint8" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "swapMinAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "swapDeadline", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "bool", + "name": "swapSuccess", + "type": "bool" + }, + { + "indexed": true, + "internalType": "bytes32", + "name": "kappa", + "type": "bytes32" + } + ], + "name": "TokenWithdrawAndRemove", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "Unpaused", + "type": "event" + }, + { + "inputs": [], + "name": "DEFAULT_ADMIN_ROLE", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "GOVERNANCE_ROLE", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "NODEGROUP_ROLE", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "WETH_ADDRESS", + "outputs": [ + { + "internalType": "address payable", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32[]", + "name": "kappas", + "type": "bytes32[]" + } + ], + "name": "addKappas", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "bridgeVersion", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "chainGasAmount", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "chainId", + "type": "uint256" + }, + { + "internalType": "contract IERC20", + "name": "token", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "deposit", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "chainId", + "type": "uint256" + }, + { + "internalType": "contract IERC20", + "name": "token", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "internalType": "uint8", + "name": "tokenIndexFrom", + "type": "uint8" + }, + { + "internalType": "uint8", + "name": "tokenIndexTo", + "type": "uint8" + }, + { + "internalType": "uint256", + "name": "minDy", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" + } + ], + "name": "depositAndSwap", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "tokenAddress", + "type": "address" + } + ], + "name": "getFeeBalance", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + } + ], + "name": "getRoleAdmin", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "internalType": "uint256", + "name": "index", + "type": "uint256" + } + ], + "name": "getRoleMember", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + } + ], + "name": "getRoleMemberCount", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "grantRole", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "hasRole", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "initialize", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "kappa", + "type": "bytes32" + } + ], + "name": "kappaExists", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address payable", + "name": "to", + "type": "address" + }, + { + "internalType": "contract IERC20Mintable", + "name": "token", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "fee", + "type": "uint256" + }, + { + "internalType": "bytes32", + "name": "kappa", + "type": "bytes32" + } + ], + "name": "mint", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address payable", + "name": "to", + "type": "address" + }, + { + "internalType": "contract IERC20Mintable", + "name": "token", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "fee", + "type": "uint256" + }, + { + "internalType": "contract ISwap", + "name": "pool", + "type": "address" + }, + { + "internalType": "uint8", + "name": "tokenIndexFrom", + "type": "uint8" + }, + { + "internalType": "uint8", + "name": "tokenIndexTo", + "type": "uint8" + }, + { + "internalType": "uint256", + "name": "minDy", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" + }, + { + "internalType": "bytes32", + "name": "kappa", + "type": "bytes32" + } + ], + "name": "mintAndSwap", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "pause", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "paused", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "chainId", + "type": "uint256" + }, + { + "internalType": "contract ERC20Burnable", + "name": "token", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "redeem", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "chainId", + "type": "uint256" + }, + { + "internalType": "contract ERC20Burnable", + "name": "token", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "internalType": "uint8", + "name": "swapTokenIndex", + "type": "uint8" + }, + { + "internalType": "uint256", + "name": "swapMinAmount", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "swapDeadline", + "type": "uint256" + } + ], + "name": "redeemAndRemove", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "chainId", + "type": "uint256" + }, + { + "internalType": "contract ERC20Burnable", + "name": "token", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "internalType": "uint8", + "name": "tokenIndexFrom", + "type": "uint8" + }, + { + "internalType": "uint8", + "name": "tokenIndexTo", + "type": "uint8" + }, + { + "internalType": "uint256", + "name": "minDy", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" + } + ], + "name": "redeemAndSwap", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "to", + "type": "bytes32" + }, + { + "internalType": "uint256", + "name": "chainId", + "type": "uint256" + }, + { + "internalType": "contract ERC20Burnable", + "name": "token", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "redeemV2", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "renounceRole", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "revokeRole", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "setChainGasAmount", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address payable", + "name": "_wethAddress", + "type": "address" + } + ], + "name": "setWethAddress", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "startBlockNumber", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "unpause", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "contract IERC20", + "name": "token", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "fee", + "type": "uint256" + }, + { + "internalType": "bytes32", + "name": "kappa", + "type": "bytes32" + } + ], + "name": "withdraw", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "contract IERC20", + "name": "token", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "fee", + "type": "uint256" + }, + { + "internalType": "contract ISwap", + "name": "pool", + "type": "address" + }, + { + "internalType": "uint8", + "name": "swapTokenIndex", + "type": "uint8" + }, + { + "internalType": "uint256", + "name": "swapMinAmount", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "swapDeadline", + "type": "uint256" + }, + { + "internalType": "bytes32", + "name": "kappa", + "type": "bytes32" + } + ], + "name": "withdrawAndRemove", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract IERC20", + "name": "token", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "withdrawFees", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "initialLogic", + "type": "address" + }, + { + "internalType": "address", + "name": "initialAdmin", + "type": "address" + }, + { + "internalType": "bytes", + "name": "_data", + "type": "bytes" + } + ], + "stateMutability": "payable", + "type": "constructor" + } + ], + "transactionHash": "0x1e4968b76cc2ed65f244bc976b248049b6078c9b37822eb2ee304070faee818e", + "receipt": { + "to": null, + "from": "0x235AF07E770f474d24F5bf73074735892371b40D", + "contractAddress": "0xE05c976d3f045D0E6E7A6f61083d98A15603cF6A", + "transactionIndex": 0, + "gasUsed": "544341", + "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "blockHash": "0x87e00cb166ddf14c9303439a632dbb7803111f5a2ffb35cf28f64f8499723024", + "transactionHash": "0x1e4968b76cc2ed65f244bc976b248049b6078c9b37822eb2ee304070faee818e", + "logs": [], + "blockNumber": 66, + "cumulativeGasUsed": "544341", + "status": 1, + "byzantium": true + }, + "args": [ + "0x159F2A9D7304Da210bE99F3d704B9823486DE24E", + "0x587AEf47a56224B5775Ff289Fb259d59F35ADdF9", + "0x" + ], + "solcInputHash": "1635d55d57a0a2552952c0d22586ed23", + "metadata": "{\"compiler\":{\"version\":\"0.7.6+commit.7338295f\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"initialLogic\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"initialAdmin\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"_data\",\"type\":\"bytes\"}],\"stateMutability\":\"payable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"previousAdmin\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"newAdmin\",\"type\":\"address\"}],\"name\":\"AdminChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"implementation\",\"type\":\"address\"}],\"name\":\"Upgraded\",\"type\":\"event\"},{\"stateMutability\":\"payable\",\"type\":\"fallback\"},{\"inputs\":[],\"name\":\"admin\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newAdmin\",\"type\":\"address\"}],\"name\":\"changeAdmin\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"implementation\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newImplementation\",\"type\":\"address\"}],\"name\":\"upgradeTo\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newImplementation\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"upgradeToAndCall\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"stateMutability\":\"payable\",\"type\":\"receive\"}],\"devdoc\":{\"details\":\"This contract implements a proxy that is upgradeable by an admin. To avoid https://medium.com/nomic-labs-blog/malicious-backdoors-in-ethereum-proxies-62629adf3357[proxy selector clashing], which can potentially be used in an attack, this contract uses the https://blog.openzeppelin.com/the-transparent-proxy-pattern/[transparent proxy pattern]. This pattern implies two things that go hand in hand: 1. If any account other than the admin calls the proxy, the call will be forwarded to the implementation, even if that call matches one of the admin functions exposed by the proxy itself. 2. If the admin calls the proxy, it can access the admin functions, but its calls will never be forwarded to the implementation. If the admin tries to call a function on the implementation it will fail with an error that says \\\"admin cannot fallback to proxy target\\\". These properties mean that the admin account can only be used for admin actions like upgrading the proxy or changing the admin, so it's best if it's a dedicated account that is not used for anything else. This will avoid headaches due to sudden errors when trying to call a function from the proxy implementation. Our recommendation is for the dedicated account to be an instance of the {ProxyAdmin} contract. If set up this way, you should think of the `ProxyAdmin` instance as the real administrative inerface of your proxy.\",\"events\":{\"AdminChanged(address,address)\":{\"details\":\"Emitted when the admin account has changed.\"}},\"kind\":\"dev\",\"methods\":{\"admin()\":{\"details\":\"Returns the current admin. NOTE: Only the admin can call this function. See {ProxyAdmin-getProxyAdmin}. TIP: To get this value clients can read directly from the storage slot shown below (specified by EIP1967) using the https://eth.wiki/json-rpc/API#eth_getstorageat[`eth_getStorageAt`] RPC call. `0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103`\"},\"changeAdmin(address)\":{\"details\":\"Changes the admin of the proxy. Emits an {AdminChanged} event. NOTE: Only the admin can call this function. See {ProxyAdmin-changeProxyAdmin}.\"},\"constructor\":{\"details\":\"Initializes an upgradeable proxy managed by `_admin`, backed by the implementation at `_logic`, and optionally initialized with `_data` as explained in {UpgradeableProxy-constructor}.\"},\"implementation()\":{\"details\":\"Returns the current implementation. NOTE: Only the admin can call this function. See {ProxyAdmin-getProxyImplementation}. TIP: To get this value clients can read directly from the storage slot shown below (specified by EIP1967) using the https://eth.wiki/json-rpc/API#eth_getstorageat[`eth_getStorageAt`] RPC call. `0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc`\"},\"upgradeTo(address)\":{\"details\":\"Upgrade the implementation of the proxy. NOTE: Only the admin can call this function. See {ProxyAdmin-upgrade}.\"},\"upgradeToAndCall(address,bytes)\":{\"details\":\"Upgrade the implementation of the proxy, and then call a function from the new implementation as specified by `data`, which should be an encoded function call. This is useful to initialize new storage variables in the proxied contract. NOTE: Only the admin can call this function. See {ProxyAdmin-upgradeAndCall}.\"}},\"stateVariables\":{\"_ADMIN_SLOT\":{\"details\":\"Storage slot with the admin of the contract. This is the keccak-256 hash of \\\"eip1967.proxy.admin\\\" subtracted by 1, and is validated in the constructor.\"}},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"solc_0.7/openzeppelin/proxy/TransparentUpgradeableProxy.sol\":\"TransparentUpgradeableProxy\"},\"evmVersion\":\"istanbul\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":999999},\"remappings\":[]},\"sources\":{\"solc_0.7/openzeppelin/proxy/Proxy.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\n/**\\n * @dev This abstract contract provides a fallback function that delegates all calls to another contract using the EVM\\n * instruction `delegatecall`. We refer to the second contract as the _implementation_ behind the proxy, and it has to\\n * be specified by overriding the virtual {_implementation} function.\\n * \\n * Additionally, delegation to the implementation can be triggered manually through the {_fallback} function, or to a\\n * different contract through the {_delegate} function.\\n * \\n * The success and return data of the delegated call will be returned back to the caller of the proxy.\\n */\\nabstract contract Proxy {\\n /**\\n * @dev Delegates the current call to `implementation`.\\n * \\n * This function does not return to its internall call site, it will return directly to the external caller.\\n */\\n function _delegate(address implementation) internal {\\n // solhint-disable-next-line no-inline-assembly\\n assembly {\\n // Copy msg.data. We take full control of memory in this inline assembly\\n // block because it will not return to Solidity code. We overwrite the\\n // Solidity scratch pad at memory position 0.\\n calldatacopy(0, 0, calldatasize())\\n\\n // Call the implementation.\\n // out and outsize are 0 because we don't know the size yet.\\n let result := delegatecall(gas(), implementation, 0, calldatasize(), 0, 0)\\n\\n // Copy the returned data.\\n returndatacopy(0, 0, returndatasize())\\n\\n switch result\\n // delegatecall returns 0 on error.\\n case 0 { revert(0, returndatasize()) }\\n default { return(0, returndatasize()) }\\n }\\n }\\n\\n /**\\n * @dev This is a virtual function that should be overriden so it returns the address to which the fallback function\\n * and {_fallback} should delegate.\\n */\\n function _implementation() internal virtual view returns (address);\\n\\n /**\\n * @dev Delegates the current call to the address returned by `_implementation()`.\\n * \\n * This function does not return to its internall call site, it will return directly to the external caller.\\n */\\n function _fallback() internal {\\n _beforeFallback();\\n _delegate(_implementation());\\n }\\n\\n /**\\n * @dev Fallback function that delegates calls to the address returned by `_implementation()`. Will run if no other\\n * function in the contract matches the call data.\\n */\\n fallback () payable external {\\n _fallback();\\n }\\n\\n /**\\n * @dev Fallback function that delegates calls to the address returned by `_implementation()`. Will run if call data\\n * is empty.\\n */\\n receive () payable external {\\n _fallback();\\n }\\n\\n /**\\n * @dev Hook that is called before falling back to the implementation. Can happen as part of a manual `_fallback`\\n * call, or as part of the Solidity `fallback` or `receive` functions.\\n * \\n * If overriden should call `super._beforeFallback()`.\\n */\\n function _beforeFallback() internal virtual {\\n }\\n}\\n\",\"keccak256\":\"0xc33f9858a67e34c77831163d5611d21fc627dfd2c303806a98a6c9db5a01b034\",\"license\":\"MIT\"},\"solc_0.7/openzeppelin/proxy/TransparentUpgradeableProxy.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\nimport \\\"./UpgradeableProxy.sol\\\";\\n\\n/**\\n * @dev This contract implements a proxy that is upgradeable by an admin.\\n * \\n * To avoid https://medium.com/nomic-labs-blog/malicious-backdoors-in-ethereum-proxies-62629adf3357[proxy selector\\n * clashing], which can potentially be used in an attack, this contract uses the\\n * https://blog.openzeppelin.com/the-transparent-proxy-pattern/[transparent proxy pattern]. This pattern implies two\\n * things that go hand in hand:\\n * \\n * 1. If any account other than the admin calls the proxy, the call will be forwarded to the implementation, even if\\n * that call matches one of the admin functions exposed by the proxy itself.\\n * 2. If the admin calls the proxy, it can access the admin functions, but its calls will never be forwarded to the\\n * implementation. If the admin tries to call a function on the implementation it will fail with an error that says\\n * \\\"admin cannot fallback to proxy target\\\".\\n * \\n * These properties mean that the admin account can only be used for admin actions like upgrading the proxy or changing\\n * the admin, so it's best if it's a dedicated account that is not used for anything else. This will avoid headaches due\\n * to sudden errors when trying to call a function from the proxy implementation.\\n * \\n * Our recommendation is for the dedicated account to be an instance of the {ProxyAdmin} contract. If set up this way,\\n * you should think of the `ProxyAdmin` instance as the real administrative inerface of your proxy.\\n */\\ncontract TransparentUpgradeableProxy is UpgradeableProxy {\\n /**\\n * @dev Initializes an upgradeable proxy managed by `_admin`, backed by the implementation at `_logic`, and\\n * optionally initialized with `_data` as explained in {UpgradeableProxy-constructor}.\\n */\\n constructor(address initialLogic, address initialAdmin, bytes memory _data) payable UpgradeableProxy(initialLogic, _data) {\\n assert(_ADMIN_SLOT == bytes32(uint256(keccak256(\\\"eip1967.proxy.admin\\\")) - 1));\\n _setAdmin(initialAdmin);\\n }\\n\\n /**\\n * @dev Emitted when the admin account has changed.\\n */\\n event AdminChanged(address previousAdmin, address newAdmin);\\n\\n /**\\n * @dev Storage slot with the admin of the contract.\\n * This is the keccak-256 hash of \\\"eip1967.proxy.admin\\\" subtracted by 1, and is\\n * validated in the constructor.\\n */\\n bytes32 private constant _ADMIN_SLOT = 0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103;\\n\\n /**\\n * @dev Modifier used internally that will delegate the call to the implementation unless the sender is the admin.\\n */\\n modifier ifAdmin() {\\n if (msg.sender == _admin()) {\\n _;\\n } else {\\n _fallback();\\n }\\n }\\n\\n /**\\n * @dev Returns the current admin.\\n * \\n * NOTE: Only the admin can call this function. See {ProxyAdmin-getProxyAdmin}.\\n * \\n * TIP: To get this value clients can read directly from the storage slot shown below (specified by EIP1967) using the\\n * https://eth.wiki/json-rpc/API#eth_getstorageat[`eth_getStorageAt`] RPC call.\\n * `0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103`\\n */\\n function admin() external ifAdmin returns (address) {\\n return _admin();\\n }\\n\\n /**\\n * @dev Returns the current implementation.\\n * \\n * NOTE: Only the admin can call this function. See {ProxyAdmin-getProxyImplementation}.\\n * \\n * TIP: To get this value clients can read directly from the storage slot shown below (specified by EIP1967) using the\\n * https://eth.wiki/json-rpc/API#eth_getstorageat[`eth_getStorageAt`] RPC call.\\n * `0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc`\\n */\\n function implementation() external ifAdmin returns (address) {\\n return _implementation();\\n }\\n\\n /**\\n * @dev Changes the admin of the proxy.\\n * \\n * Emits an {AdminChanged} event.\\n * \\n * NOTE: Only the admin can call this function. See {ProxyAdmin-changeProxyAdmin}.\\n */\\n function changeAdmin(address newAdmin) external ifAdmin {\\n require(newAdmin != address(0), \\\"TransparentUpgradeableProxy: new admin is the zero address\\\");\\n emit AdminChanged(_admin(), newAdmin);\\n _setAdmin(newAdmin);\\n }\\n\\n /**\\n * @dev Upgrade the implementation of the proxy.\\n * \\n * NOTE: Only the admin can call this function. See {ProxyAdmin-upgrade}.\\n */\\n function upgradeTo(address newImplementation) external ifAdmin {\\n _upgradeTo(newImplementation);\\n }\\n\\n /**\\n * @dev Upgrade the implementation of the proxy, and then call a function from the new implementation as specified\\n * by `data`, which should be an encoded function call. This is useful to initialize new storage variables in the\\n * proxied contract.\\n * \\n * NOTE: Only the admin can call this function. See {ProxyAdmin-upgradeAndCall}.\\n */\\n function upgradeToAndCall(address newImplementation, bytes calldata data) external payable ifAdmin {\\n _upgradeTo(newImplementation);\\n // solhint-disable-next-line avoid-low-level-calls\\n (bool success,) = newImplementation.delegatecall(data);\\n require(success);\\n }\\n\\n /**\\n * @dev Returns the current admin.\\n */\\n function _admin() internal view returns (address adm) {\\n bytes32 slot = _ADMIN_SLOT;\\n // solhint-disable-next-line no-inline-assembly\\n assembly {\\n adm := sload(slot)\\n }\\n }\\n\\n /**\\n * @dev Stores a new address in the EIP1967 admin slot.\\n */\\n function _setAdmin(address newAdmin) private {\\n bytes32 slot = _ADMIN_SLOT;\\n\\n // solhint-disable-next-line no-inline-assembly\\n assembly {\\n sstore(slot, newAdmin)\\n }\\n }\\n\\n /**\\n * @dev Makes sure the admin cannot access the fallback function. See {Proxy-_beforeFallback}.\\n */\\n function _beforeFallback() internal override virtual {\\n require(msg.sender != _admin(), \\\"TransparentUpgradeableProxy: admin cannot fallback to proxy target\\\");\\n super._beforeFallback();\\n }\\n}\\n\",\"keccak256\":\"0xd6cecbe00dc78355aff1a16d83487bb73c54701004d61a2e48cdb81e2bcacc26\",\"license\":\"MIT\"},\"solc_0.7/openzeppelin/proxy/UpgradeableProxy.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\nimport \\\"./Proxy.sol\\\";\\nimport \\\"../utils/Address.sol\\\";\\n\\n/**\\n * @dev This contract implements an upgradeable proxy. It is upgradeable because calls are delegated to an\\n * implementation address that can be changed. This address is stored in storage in the location specified by\\n * https://eips.ethereum.org/EIPS/eip-1967[EIP1967], so that it doesn't conflict with the storage layout of the\\n * implementation behind the proxy.\\n * \\n * Upgradeability is only provided internally through {_upgradeTo}. For an externally upgradeable proxy see\\n * {TransparentUpgradeableProxy}.\\n */\\ncontract UpgradeableProxy is Proxy {\\n /**\\n * @dev Initializes the upgradeable proxy with an initial implementation specified by `_logic`.\\n * \\n * If `_data` is nonempty, it's used as data in a delegate call to `_logic`. This will typically be an encoded\\n * function call, and allows initializating the storage of the proxy like a Solidity constructor.\\n */\\n constructor(address _logic, bytes memory _data) payable {\\n assert(_IMPLEMENTATION_SLOT == bytes32(uint256(keccak256(\\\"eip1967.proxy.implementation\\\")) - 1));\\n _setImplementation(_logic);\\n if(_data.length > 0) {\\n // solhint-disable-next-line avoid-low-level-calls\\n (bool success,) = _logic.delegatecall(_data);\\n require(success);\\n }\\n }\\n\\n /**\\n * @dev Emitted when the implementation is upgraded.\\n */\\n event Upgraded(address indexed implementation);\\n\\n /**\\n * @dev Storage slot with the address of the current implementation.\\n * This is the keccak-256 hash of \\\"eip1967.proxy.implementation\\\" subtracted by 1, and is\\n * validated in the constructor.\\n */\\n bytes32 private constant _IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc;\\n\\n /**\\n * @dev Returns the current implementation address.\\n */\\n function _implementation() internal override view returns (address impl) {\\n bytes32 slot = _IMPLEMENTATION_SLOT;\\n // solhint-disable-next-line no-inline-assembly\\n assembly {\\n impl := sload(slot)\\n }\\n }\\n\\n /**\\n * @dev Upgrades the proxy to a new implementation.\\n * \\n * Emits an {Upgraded} event.\\n */\\n function _upgradeTo(address newImplementation) internal {\\n _setImplementation(newImplementation);\\n emit Upgraded(newImplementation);\\n }\\n\\n /**\\n * @dev Stores a new address in the EIP1967 implementation slot.\\n */\\n function _setImplementation(address newImplementation) private {\\n require(Address.isContract(newImplementation), \\\"UpgradeableProxy: new implementation is not a contract\\\");\\n\\n bytes32 slot = _IMPLEMENTATION_SLOT;\\n\\n // solhint-disable-next-line no-inline-assembly\\n assembly {\\n sstore(slot, newImplementation)\\n }\\n }\\n}\\n\",\"keccak256\":\"0xd68f4c11941712db79a61b9dca81a5db663cfacec3d7bb19f8d2c23bb1ab8afe\",\"license\":\"MIT\"},\"solc_0.7/openzeppelin/utils/Address.sol\":{\"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 // According to EIP-1052, 0x0 is the value returned for not-yet created accounts\\n // and 0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470 is returned\\n // for accounts without code, i.e. `keccak256('')`\\n bytes32 codehash;\\n bytes32 accountHash = 0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470;\\n // solhint-disable-next-line no-inline-assembly\\n assembly { codehash := extcodehash(account) }\\n return (codehash != accountHash && codehash != 0x0);\\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 return _functionCallWithValue(target, data, value, errorMessage);\\n }\\n\\n function _functionCallWithValue(address target, bytes memory data, uint256 weiValue, string memory errorMessage) private returns (bytes memory) {\\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: weiValue }(data);\\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\",\"keccak256\":\"0x698f929f1097637d051976b322a2d532c27df022b09010e8d091e2888a5ebdf8\",\"license\":\"MIT\"}},\"version\":1}", + "bytecode": "0x6080604052604051610aaa380380610aaa8339818101604052606081101561002657600080fd5b8151602083015160408085018051915193959294830192918464010000000082111561005157600080fd5b90830190602082018581111561006657600080fd5b825164010000000081118282018810171561008057600080fd5b82525081516020918201929091019080838360005b838110156100ad578181015183820152602001610095565b50505050905090810190601f1680156100da5780820380516001836020036101000a031916815260200191505b50604052508491508290506100ee826101bf565b8051156101a6576000826001600160a01b0316826040518082805190602001908083835b602083106101315780518252601f199092019160209182019101610112565b6001836020036101000a038019825116818451168082178552505050505050905001915050600060405180830381855af49150503d8060008114610191576040519150601f19603f3d011682016040523d82523d6000602084013e610196565b606091505b50509050806101a457600080fd5b505b506101ae9050565b6101b782610231565b505050610291565b6101d28161025560201b6104bb1760201c565b61020d5760405162461bcd60e51b8152600401808060200182810382526036815260200180610a746036913960400191505060405180910390fd5b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc55565b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d610355565b6000813f7fc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a47081811480159061028957508115155b949350505050565b6107d4806102a06000396000f3fe60806040526004361061005e5760003560e01c80635c60da1b116100435780635c60da1b146101425780638f28397014610180578063f851a440146101c05761006d565b80633659cfe6146100755780634f1ef286146100b55761006d565b3661006d5761006b6101d5565b005b61006b6101d5565b34801561008157600080fd5b5061006b6004803603602081101561009857600080fd5b503573ffffffffffffffffffffffffffffffffffffffff166101ef565b61006b600480360360408110156100cb57600080fd5b73ffffffffffffffffffffffffffffffffffffffff823516919081019060408101602082013564010000000081111561010357600080fd5b82018360208201111561011557600080fd5b8035906020019184600183028401116401000000008311171561013757600080fd5b509092509050610243565b34801561014e57600080fd5b50610157610317565b6040805173ffffffffffffffffffffffffffffffffffffffff9092168252519081900360200190f35b34801561018c57600080fd5b5061006b600480360360208110156101a357600080fd5b503573ffffffffffffffffffffffffffffffffffffffff1661036e565b3480156101cc57600080fd5b50610157610476565b6101dd6104f7565b6101ed6101e861058b565b6105b0565b565b6101f76105d4565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16141561023857610233816105f9565b610240565b6102406101d5565b50565b61024b6105d4565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16141561030a57610287836105f9565b60008373ffffffffffffffffffffffffffffffffffffffff1683836040518083838082843760405192019450600093509091505080830381855af49150503d80600081146102f1576040519150601f19603f3d011682016040523d82523d6000602084013e6102f6565b606091505b505090508061030457600080fd5b50610312565b6103126101d5565b505050565b60006103216105d4565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614156103635761035c61058b565b905061036b565b61036b6101d5565b90565b6103766105d4565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614156102385773ffffffffffffffffffffffffffffffffffffffff8116610415576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252603a8152602001806106ed603a913960400191505060405180910390fd5b7f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f61043e6105d4565b6040805173ffffffffffffffffffffffffffffffffffffffff928316815291841660208301528051918290030190a161023381610646565b60006104806105d4565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614156103635761035c6105d4565b6000813f7fc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a4708181148015906104ef57508115155b949350505050565b6104ff6105d4565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161415610583576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252604281526020018061075d6042913960600191505060405180910390fd5b6101ed6101ed565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b3660008037600080366000845af43d6000803e8080156105cf573d6000f35b3d6000fd5b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b6106028161066a565b60405173ffffffffffffffffffffffffffffffffffffffff8216907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a250565b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d610355565b610673816104bb565b6106c8576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260368152602001806107276036913960400191505060405180910390fd5b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5556fe5472616e73706172656e745570677261646561626c6550726f78793a206e65772061646d696e20697320746865207a65726f20616464726573735570677261646561626c6550726f78793a206e657720696d706c656d656e746174696f6e206973206e6f74206120636f6e74726163745472616e73706172656e745570677261646561626c6550726f78793a2061646d696e2063616e6e6f742066616c6c6261636b20746f2070726f787920746172676574a2646970667358221220b141ef72de179b8b56cef31601d40ff2875391088197e73cac39eba1ddcd0fdd64736f6c634300070600335570677261646561626c6550726f78793a206e657720696d706c656d656e746174696f6e206973206e6f74206120636f6e7472616374", + "deployedBytecode": "0x60806040526004361061005e5760003560e01c80635c60da1b116100435780635c60da1b146101425780638f28397014610180578063f851a440146101c05761006d565b80633659cfe6146100755780634f1ef286146100b55761006d565b3661006d5761006b6101d5565b005b61006b6101d5565b34801561008157600080fd5b5061006b6004803603602081101561009857600080fd5b503573ffffffffffffffffffffffffffffffffffffffff166101ef565b61006b600480360360408110156100cb57600080fd5b73ffffffffffffffffffffffffffffffffffffffff823516919081019060408101602082013564010000000081111561010357600080fd5b82018360208201111561011557600080fd5b8035906020019184600183028401116401000000008311171561013757600080fd5b509092509050610243565b34801561014e57600080fd5b50610157610317565b6040805173ffffffffffffffffffffffffffffffffffffffff9092168252519081900360200190f35b34801561018c57600080fd5b5061006b600480360360208110156101a357600080fd5b503573ffffffffffffffffffffffffffffffffffffffff1661036e565b3480156101cc57600080fd5b50610157610476565b6101dd6104f7565b6101ed6101e861058b565b6105b0565b565b6101f76105d4565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16141561023857610233816105f9565b610240565b6102406101d5565b50565b61024b6105d4565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16141561030a57610287836105f9565b60008373ffffffffffffffffffffffffffffffffffffffff1683836040518083838082843760405192019450600093509091505080830381855af49150503d80600081146102f1576040519150601f19603f3d011682016040523d82523d6000602084013e6102f6565b606091505b505090508061030457600080fd5b50610312565b6103126101d5565b505050565b60006103216105d4565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614156103635761035c61058b565b905061036b565b61036b6101d5565b90565b6103766105d4565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614156102385773ffffffffffffffffffffffffffffffffffffffff8116610415576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252603a8152602001806106ed603a913960400191505060405180910390fd5b7f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f61043e6105d4565b6040805173ffffffffffffffffffffffffffffffffffffffff928316815291841660208301528051918290030190a161023381610646565b60006104806105d4565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614156103635761035c6105d4565b6000813f7fc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a4708181148015906104ef57508115155b949350505050565b6104ff6105d4565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161415610583576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252604281526020018061075d6042913960600191505060405180910390fd5b6101ed6101ed565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b3660008037600080366000845af43d6000803e8080156105cf573d6000f35b3d6000fd5b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b6106028161066a565b60405173ffffffffffffffffffffffffffffffffffffffff8216907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a250565b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d610355565b610673816104bb565b6106c8576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260368152602001806107276036913960400191505060405180910390fd5b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5556fe5472616e73706172656e745570677261646561626c6550726f78793a206e65772061646d696e20697320746865207a65726f20616464726573735570677261646561626c6550726f78793a206e657720696d706c656d656e746174696f6e206973206e6f74206120636f6e74726163745472616e73706172656e745570677261646561626c6550726f78793a2061646d696e2063616e6e6f742066616c6c6261636b20746f2070726f787920746172676574a2646970667358221220b141ef72de179b8b56cef31601d40ff2875391088197e73cac39eba1ddcd0fdd64736f6c63430007060033", + "implementation": "0x159F2A9D7304Da210bE99F3d704B9823486DE24E", + "devdoc": { + "details": "This contract implements a proxy that is upgradeable by an admin. To avoid https://medium.com/nomic-labs-blog/malicious-backdoors-in-ethereum-proxies-62629adf3357[proxy selector clashing], which can potentially be used in an attack, this contract uses the https://blog.openzeppelin.com/the-transparent-proxy-pattern/[transparent proxy pattern]. This pattern implies two things that go hand in hand: 1. If any account other than the admin calls the proxy, the call will be forwarded to the implementation, even if that call matches one of the admin functions exposed by the proxy itself. 2. If the admin calls the proxy, it can access the admin functions, but its calls will never be forwarded to the implementation. If the admin tries to call a function on the implementation it will fail with an error that says \"admin cannot fallback to proxy target\". These properties mean that the admin account can only be used for admin actions like upgrading the proxy or changing the admin, so it's best if it's a dedicated account that is not used for anything else. This will avoid headaches due to sudden errors when trying to call a function from the proxy implementation. Our recommendation is for the dedicated account to be an instance of the {ProxyAdmin} contract. If set up this way, you should think of the `ProxyAdmin` instance as the real administrative inerface of your proxy.", + "events": { + "AdminChanged(address,address)": { + "details": "Emitted when the admin account has changed." + } + }, + "kind": "dev", + "methods": { + "admin()": { + "details": "Returns the current admin. NOTE: Only the admin can call this function. See {ProxyAdmin-getProxyAdmin}. TIP: To get this value clients can read directly from the storage slot shown below (specified by EIP1967) using the https://eth.wiki/json-rpc/API#eth_getstorageat[`eth_getStorageAt`] RPC call. `0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103`" + }, + "changeAdmin(address)": { + "details": "Changes the admin of the proxy. Emits an {AdminChanged} event. NOTE: Only the admin can call this function. See {ProxyAdmin-changeProxyAdmin}." + }, + "constructor": { + "details": "Initializes an upgradeable proxy managed by `_admin`, backed by the implementation at `_logic`, and optionally initialized with `_data` as explained in {UpgradeableProxy-constructor}." + }, + "implementation()": { + "details": "Returns the current implementation. NOTE: Only the admin can call this function. See {ProxyAdmin-getProxyImplementation}. TIP: To get this value clients can read directly from the storage slot shown below (specified by EIP1967) using the https://eth.wiki/json-rpc/API#eth_getstorageat[`eth_getStorageAt`] RPC call. `0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc`" + }, + "upgradeTo(address)": { + "details": "Upgrade the implementation of the proxy. NOTE: Only the admin can call this function. See {ProxyAdmin-upgrade}." + }, + "upgradeToAndCall(address,bytes)": { + "details": "Upgrade the implementation of the proxy, and then call a function from the new implementation as specified by `data`, which should be an encoded function call. This is useful to initialize new storage variables in the proxied contract. NOTE: Only the admin can call this function. See {ProxyAdmin-upgradeAndCall}." + } + }, + "stateVariables": { + "_ADMIN_SLOT": { + "details": "Storage slot with the admin of the contract. This is the keccak-256 hash of \"eip1967.proxy.admin\" subtracted by 1, and is validated in the constructor." + } + }, + "version": 1 + }, + "userdoc": { + "kind": "user", + "methods": {}, + "version": 1 + }, + "storageLayout": { + "storage": [], + "types": null + } +} \ No newline at end of file diff --git a/deployments/dfk/SynapseBridge_Implementation.json b/deployments/dfk/SynapseBridge_Implementation.json new file mode 100644 index 000000000..4081ad3c8 --- /dev/null +++ b/deployments/dfk/SynapseBridge_Implementation.json @@ -0,0 +1,1776 @@ +{ + "address": "0x159F2A9D7304Da210bE99F3d704B9823486DE24E", + "abi": [ + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "Paused", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "bytes32", + "name": "previousAdminRole", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "bytes32", + "name": "newAdminRole", + "type": "bytes32" + } + ], + "name": "RoleAdminChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "sender", + "type": "address" + } + ], + "name": "RoleGranted", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "sender", + "type": "address" + } + ], + "name": "RoleRevoked", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "chainId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "contract IERC20", + "name": "token", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "TokenDeposit", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "chainId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "contract IERC20", + "name": "token", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint8", + "name": "tokenIndexFrom", + "type": "uint8" + }, + { + "indexed": false, + "internalType": "uint8", + "name": "tokenIndexTo", + "type": "uint8" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "minDy", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "deadline", + "type": "uint256" + } + ], + "name": "TokenDepositAndSwap", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "contract IERC20Mintable", + "name": "token", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "fee", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "bytes32", + "name": "kappa", + "type": "bytes32" + } + ], + "name": "TokenMint", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "contract IERC20Mintable", + "name": "token", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "fee", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint8", + "name": "tokenIndexFrom", + "type": "uint8" + }, + { + "indexed": false, + "internalType": "uint8", + "name": "tokenIndexTo", + "type": "uint8" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "minDy", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "deadline", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "bool", + "name": "swapSuccess", + "type": "bool" + }, + { + "indexed": true, + "internalType": "bytes32", + "name": "kappa", + "type": "bytes32" + } + ], + "name": "TokenMintAndSwap", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "chainId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "contract IERC20", + "name": "token", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "TokenRedeem", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "chainId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "contract IERC20", + "name": "token", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint8", + "name": "swapTokenIndex", + "type": "uint8" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "swapMinAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "swapDeadline", + "type": "uint256" + } + ], + "name": "TokenRedeemAndRemove", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "chainId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "contract IERC20", + "name": "token", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint8", + "name": "tokenIndexFrom", + "type": "uint8" + }, + { + "indexed": false, + "internalType": "uint8", + "name": "tokenIndexTo", + "type": "uint8" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "minDy", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "deadline", + "type": "uint256" + } + ], + "name": "TokenRedeemAndSwap", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "to", + "type": "bytes32" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "chainId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "contract IERC20", + "name": "token", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "TokenRedeemV2", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "contract IERC20", + "name": "token", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "fee", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "bytes32", + "name": "kappa", + "type": "bytes32" + } + ], + "name": "TokenWithdraw", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "contract IERC20", + "name": "token", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "fee", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint8", + "name": "swapTokenIndex", + "type": "uint8" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "swapMinAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "swapDeadline", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "bool", + "name": "swapSuccess", + "type": "bool" + }, + { + "indexed": true, + "internalType": "bytes32", + "name": "kappa", + "type": "bytes32" + } + ], + "name": "TokenWithdrawAndRemove", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "Unpaused", + "type": "event" + }, + { + "inputs": [], + "name": "DEFAULT_ADMIN_ROLE", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "GOVERNANCE_ROLE", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "NODEGROUP_ROLE", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "WETH_ADDRESS", + "outputs": [ + { + "internalType": "address payable", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32[]", + "name": "kappas", + "type": "bytes32[]" + } + ], + "name": "addKappas", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "bridgeVersion", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "chainGasAmount", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "chainId", + "type": "uint256" + }, + { + "internalType": "contract IERC20", + "name": "token", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "deposit", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "chainId", + "type": "uint256" + }, + { + "internalType": "contract IERC20", + "name": "token", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "internalType": "uint8", + "name": "tokenIndexFrom", + "type": "uint8" + }, + { + "internalType": "uint8", + "name": "tokenIndexTo", + "type": "uint8" + }, + { + "internalType": "uint256", + "name": "minDy", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" + } + ], + "name": "depositAndSwap", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "tokenAddress", + "type": "address" + } + ], + "name": "getFeeBalance", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + } + ], + "name": "getRoleAdmin", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "internalType": "uint256", + "name": "index", + "type": "uint256" + } + ], + "name": "getRoleMember", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + } + ], + "name": "getRoleMemberCount", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "grantRole", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "hasRole", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "initialize", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "kappa", + "type": "bytes32" + } + ], + "name": "kappaExists", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address payable", + "name": "to", + "type": "address" + }, + { + "internalType": "contract IERC20Mintable", + "name": "token", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "fee", + "type": "uint256" + }, + { + "internalType": "bytes32", + "name": "kappa", + "type": "bytes32" + } + ], + "name": "mint", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address payable", + "name": "to", + "type": "address" + }, + { + "internalType": "contract IERC20Mintable", + "name": "token", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "fee", + "type": "uint256" + }, + { + "internalType": "contract ISwap", + "name": "pool", + "type": "address" + }, + { + "internalType": "uint8", + "name": "tokenIndexFrom", + "type": "uint8" + }, + { + "internalType": "uint8", + "name": "tokenIndexTo", + "type": "uint8" + }, + { + "internalType": "uint256", + "name": "minDy", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" + }, + { + "internalType": "bytes32", + "name": "kappa", + "type": "bytes32" + } + ], + "name": "mintAndSwap", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "pause", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "paused", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "chainId", + "type": "uint256" + }, + { + "internalType": "contract ERC20Burnable", + "name": "token", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "redeem", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "chainId", + "type": "uint256" + }, + { + "internalType": "contract ERC20Burnable", + "name": "token", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "internalType": "uint8", + "name": "swapTokenIndex", + "type": "uint8" + }, + { + "internalType": "uint256", + "name": "swapMinAmount", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "swapDeadline", + "type": "uint256" + } + ], + "name": "redeemAndRemove", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "chainId", + "type": "uint256" + }, + { + "internalType": "contract ERC20Burnable", + "name": "token", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "internalType": "uint8", + "name": "tokenIndexFrom", + "type": "uint8" + }, + { + "internalType": "uint8", + "name": "tokenIndexTo", + "type": "uint8" + }, + { + "internalType": "uint256", + "name": "minDy", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" + } + ], + "name": "redeemAndSwap", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "to", + "type": "bytes32" + }, + { + "internalType": "uint256", + "name": "chainId", + "type": "uint256" + }, + { + "internalType": "contract ERC20Burnable", + "name": "token", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "redeemV2", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "renounceRole", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "revokeRole", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "setChainGasAmount", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address payable", + "name": "_wethAddress", + "type": "address" + } + ], + "name": "setWethAddress", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "startBlockNumber", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "unpause", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "contract IERC20", + "name": "token", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "fee", + "type": "uint256" + }, + { + "internalType": "bytes32", + "name": "kappa", + "type": "bytes32" + } + ], + "name": "withdraw", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "contract IERC20", + "name": "token", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "fee", + "type": "uint256" + }, + { + "internalType": "contract ISwap", + "name": "pool", + "type": "address" + }, + { + "internalType": "uint8", + "name": "swapTokenIndex", + "type": "uint8" + }, + { + "internalType": "uint256", + "name": "swapMinAmount", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "swapDeadline", + "type": "uint256" + }, + { + "internalType": "bytes32", + "name": "kappa", + "type": "bytes32" + } + ], + "name": "withdrawAndRemove", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract IERC20", + "name": "token", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "withdrawFees", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "stateMutability": "payable", + "type": "receive" + } + ], + "transactionHash": "0x9ca7311961429552e72a8041f2f262a19b6a1493bae1b5e2e03e4bcb0e3481ac", + "receipt": { + "to": null, + "from": "0x235AF07E770f474d24F5bf73074735892371b40D", + "contractAddress": "0x159F2A9D7304Da210bE99F3d704B9823486DE24E", + "transactionIndex": 0, + "gasUsed": "3461819", + "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "blockHash": "0x095a2e311576010830490b46be1774b4bf8b18743503d1479e7a8f25786b7cb2", + "transactionHash": "0x9ca7311961429552e72a8041f2f262a19b6a1493bae1b5e2e03e4bcb0e3481ac", + "logs": [], + "blockNumber": 65, + "cumulativeGasUsed": "3461819", + "status": 1, + "byzantium": true + }, + "args": [], + "solcInputHash": "cefd51132bfcd0aab10340ca057c092d", + "metadata": "{\"compiler\":{\"version\":\"0.6.12+commit.27d51765\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"Paused\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"previousAdminRole\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"newAdminRole\",\"type\":\"bytes32\"}],\"name\":\"RoleAdminChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"RoleGranted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"RoleRevoked\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"chainId\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"contract IERC20\",\"name\":\"token\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"TokenDeposit\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"chainId\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"contract IERC20\",\"name\":\"token\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint8\",\"name\":\"tokenIndexFrom\",\"type\":\"uint8\"},{\"indexed\":false,\"internalType\":\"uint8\",\"name\":\"tokenIndexTo\",\"type\":\"uint8\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"minDy\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"deadline\",\"type\":\"uint256\"}],\"name\":\"TokenDepositAndSwap\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"contract IERC20Mintable\",\"name\":\"token\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"fee\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"kappa\",\"type\":\"bytes32\"}],\"name\":\"TokenMint\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"contract IERC20Mintable\",\"name\":\"token\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"fee\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint8\",\"name\":\"tokenIndexFrom\",\"type\":\"uint8\"},{\"indexed\":false,\"internalType\":\"uint8\",\"name\":\"tokenIndexTo\",\"type\":\"uint8\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"minDy\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"deadline\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"bool\",\"name\":\"swapSuccess\",\"type\":\"bool\"},{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"kappa\",\"type\":\"bytes32\"}],\"name\":\"TokenMintAndSwap\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"chainId\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"contract IERC20\",\"name\":\"token\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"TokenRedeem\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"chainId\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"contract IERC20\",\"name\":\"token\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint8\",\"name\":\"swapTokenIndex\",\"type\":\"uint8\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"swapMinAmount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"swapDeadline\",\"type\":\"uint256\"}],\"name\":\"TokenRedeemAndRemove\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"chainId\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"contract IERC20\",\"name\":\"token\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint8\",\"name\":\"tokenIndexFrom\",\"type\":\"uint8\"},{\"indexed\":false,\"internalType\":\"uint8\",\"name\":\"tokenIndexTo\",\"type\":\"uint8\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"minDy\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"deadline\",\"type\":\"uint256\"}],\"name\":\"TokenRedeemAndSwap\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"to\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"chainId\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"contract IERC20\",\"name\":\"token\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"TokenRedeemV2\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"contract IERC20\",\"name\":\"token\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"fee\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"kappa\",\"type\":\"bytes32\"}],\"name\":\"TokenWithdraw\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"contract IERC20\",\"name\":\"token\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"fee\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint8\",\"name\":\"swapTokenIndex\",\"type\":\"uint8\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"swapMinAmount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"swapDeadline\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"bool\",\"name\":\"swapSuccess\",\"type\":\"bool\"},{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"kappa\",\"type\":\"bytes32\"}],\"name\":\"TokenWithdrawAndRemove\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"Unpaused\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"DEFAULT_ADMIN_ROLE\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"GOVERNANCE_ROLE\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"NODEGROUP_ROLE\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"WETH_ADDRESS\",\"outputs\":[{\"internalType\":\"address payable\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32[]\",\"name\":\"kappas\",\"type\":\"bytes32[]\"}],\"name\":\"addKappas\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"bridgeVersion\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"chainGasAmount\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"chainId\",\"type\":\"uint256\"},{\"internalType\":\"contract IERC20\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"deposit\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"chainId\",\"type\":\"uint256\"},{\"internalType\":\"contract IERC20\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"uint8\",\"name\":\"tokenIndexFrom\",\"type\":\"uint8\"},{\"internalType\":\"uint8\",\"name\":\"tokenIndexTo\",\"type\":\"uint8\"},{\"internalType\":\"uint256\",\"name\":\"minDy\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"deadline\",\"type\":\"uint256\"}],\"name\":\"depositAndSwap\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"tokenAddress\",\"type\":\"address\"}],\"name\":\"getFeeBalance\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"}],\"name\":\"getRoleAdmin\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"internalType\":\"uint256\",\"name\":\"index\",\"type\":\"uint256\"}],\"name\":\"getRoleMember\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"}],\"name\":\"getRoleMemberCount\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"grantRole\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"hasRole\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"initialize\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"kappa\",\"type\":\"bytes32\"}],\"name\":\"kappaExists\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address payable\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"contract IERC20Mintable\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"fee\",\"type\":\"uint256\"},{\"internalType\":\"bytes32\",\"name\":\"kappa\",\"type\":\"bytes32\"}],\"name\":\"mint\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address payable\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"contract IERC20Mintable\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"fee\",\"type\":\"uint256\"},{\"internalType\":\"contract ISwap\",\"name\":\"pool\",\"type\":\"address\"},{\"internalType\":\"uint8\",\"name\":\"tokenIndexFrom\",\"type\":\"uint8\"},{\"internalType\":\"uint8\",\"name\":\"tokenIndexTo\",\"type\":\"uint8\"},{\"internalType\":\"uint256\",\"name\":\"minDy\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"deadline\",\"type\":\"uint256\"},{\"internalType\":\"bytes32\",\"name\":\"kappa\",\"type\":\"bytes32\"}],\"name\":\"mintAndSwap\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"pause\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"paused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"chainId\",\"type\":\"uint256\"},{\"internalType\":\"contract ERC20Burnable\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"redeem\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"chainId\",\"type\":\"uint256\"},{\"internalType\":\"contract ERC20Burnable\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"uint8\",\"name\":\"swapTokenIndex\",\"type\":\"uint8\"},{\"internalType\":\"uint256\",\"name\":\"swapMinAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"swapDeadline\",\"type\":\"uint256\"}],\"name\":\"redeemAndRemove\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"chainId\",\"type\":\"uint256\"},{\"internalType\":\"contract ERC20Burnable\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"uint8\",\"name\":\"tokenIndexFrom\",\"type\":\"uint8\"},{\"internalType\":\"uint8\",\"name\":\"tokenIndexTo\",\"type\":\"uint8\"},{\"internalType\":\"uint256\",\"name\":\"minDy\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"deadline\",\"type\":\"uint256\"}],\"name\":\"redeemAndSwap\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"to\",\"type\":\"bytes32\"},{\"internalType\":\"uint256\",\"name\":\"chainId\",\"type\":\"uint256\"},{\"internalType\":\"contract ERC20Burnable\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"redeemV2\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"renounceRole\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"revokeRole\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"setChainGasAmount\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address payable\",\"name\":\"_wethAddress\",\"type\":\"address\"}],\"name\":\"setWethAddress\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"startBlockNumber\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"unpause\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"contract IERC20\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"fee\",\"type\":\"uint256\"},{\"internalType\":\"bytes32\",\"name\":\"kappa\",\"type\":\"bytes32\"}],\"name\":\"withdraw\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"contract IERC20\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"fee\",\"type\":\"uint256\"},{\"internalType\":\"contract ISwap\",\"name\":\"pool\",\"type\":\"address\"},{\"internalType\":\"uint8\",\"name\":\"swapTokenIndex\",\"type\":\"uint8\"},{\"internalType\":\"uint256\",\"name\":\"swapMinAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"swapDeadline\",\"type\":\"uint256\"},{\"internalType\":\"bytes32\",\"name\":\"kappa\",\"type\":\"bytes32\"}],\"name\":\"withdrawAndRemove\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contract IERC20\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"withdrawFees\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"stateMutability\":\"payable\",\"type\":\"receive\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{\"deposit(address,uint256,address,uint256)\":{\"params\":{\"amount\":\"Amount in native token decimals to transfer cross-chain pre-fees*\",\"chainId\":\"which chain to bridge assets onto\",\"to\":\"address on other chain to bridge assets to\",\"token\":\"ERC20 compatible token to deposit into the bridge\"}},\"depositAndSwap(address,uint256,address,uint256,uint8,uint8,uint256,uint256)\":{\"params\":{\"amount\":\"Amount in native token decimals to transfer cross-chain pre-fees\",\"chainId\":\"which chain to bridge assets onto\",\"deadline\":\"latest timestamp to accept this transaction*\",\"minDy\":\"the min amount the user would like to receive, or revert to only minting the SynERC20 token crosschain.\",\"to\":\"address on other chain to bridge assets to\",\"token\":\"ERC20 compatible token to deposit into the bridge\",\"tokenIndexFrom\":\"the token the user wants to swap from\",\"tokenIndexTo\":\"the token the user wants to swap to\"}},\"getRoleAdmin(bytes32)\":{\"details\":\"Returns the admin role that controls `role`. See {grantRole} and {revokeRole}. To change a role's admin, use {_setRoleAdmin}.\"},\"getRoleMember(bytes32,uint256)\":{\"details\":\"Returns one of the accounts that have `role`. `index` must be a value between 0 and {getRoleMemberCount}, non-inclusive. Role bearers are not sorted in any particular way, and their ordering may change at any point. WARNING: When using {getRoleMember} and {getRoleMemberCount}, make sure you perform all queries on the same block. See the following https://forum.openzeppelin.com/t/iterating-over-elements-on-enumerableset-in-openzeppelin-contracts/2296[forum post] for more information.\"},\"getRoleMemberCount(bytes32)\":{\"details\":\"Returns the number of accounts that have `role`. Can be used together with {getRoleMember} to enumerate all bearers of a role.\"},\"grantRole(bytes32,address)\":{\"details\":\"Grants `role` to `account`. If `account` had not been already granted `role`, emits a {RoleGranted} event. Requirements: - the caller must have ``role``'s admin role.\"},\"hasRole(bytes32,address)\":{\"details\":\"Returns `true` if `account` has been granted `role`.\"},\"mint(address,address,uint256,uint256,bytes32)\":{\"details\":\"This means the SynapseBridge.sol contract must have minter access to the token attempting to be minted\",\"params\":{\"amount\":\"Amount in native token decimals to transfer cross-chain post-fees\",\"fee\":\"Amount in native token decimals to save to the contract as fees\",\"kappa\":\"kappa*\",\"to\":\"address on other chain to redeem underlying assets to\",\"token\":\"ERC20 compatible token to deposit into the bridge\"}},\"mintAndSwap(address,address,uint256,uint256,address,uint8,uint8,uint256,uint256,bytes32)\":{\"details\":\"This means the BridgeDeposit.sol contract must have minter access to the token attempting to be minted\",\"params\":{\"amount\":\"Amount in native token decimals to transfer cross-chain post-fees\",\"deadline\":\"Epoch time of the deadline that the swap is allowed to be executed.\",\"fee\":\"Amount in native token decimals to save to the contract as fees\",\"kappa\":\"kappa*\",\"minDy\":\"Minumum amount (in final asset decimals) that must be swapped for, otherwise the user will receive the SynERC20.\",\"pool\":\"Destination chain's pool to use to swap SynERC20 -> Asset. The nodes determine this by using PoolConfig.sol.\",\"to\":\"address on other chain to redeem underlying assets to\",\"token\":\"ERC20 compatible token to deposit into the bridge\",\"tokenIndexFrom\":\"Index of the SynERC20 asset in the pool\",\"tokenIndexTo\":\"Index of the desired final asset\"}},\"paused()\":{\"details\":\"Returns true if the contract is paused, and false otherwise.\"},\"redeem(address,uint256,address,uint256)\":{\"params\":{\"amount\":\"Amount in native token decimals to transfer cross-chain pre-fees*\",\"chainId\":\"which underlying chain to bridge assets onto\",\"to\":\"address on other chain to redeem underlying assets to\",\"token\":\"ERC20 compatible token to deposit into the bridge\"}},\"redeemAndRemove(address,uint256,address,uint256,uint8,uint256,uint256)\":{\"params\":{\"amount\":\"Amount in native token decimals to transfer cross-chain pre-fees\",\"chainId\":\"which underlying chain to bridge assets onto\",\"swapDeadline\":\"Specificies the deadline that the nodes are allowed to try to redeem/swap the LP token*\",\"swapMinAmount\":\"Specifies the minimum amount of the underlying asset needed for the nodes to execute the redeem/swap\",\"swapTokenIndex\":\"Specifies which of the underlying LP assets the nodes should attempt to redeem for\",\"to\":\"address on other chain to redeem underlying assets to\",\"token\":\"ERC20 compatible token to deposit into the bridge\"}},\"redeemAndSwap(address,uint256,address,uint256,uint8,uint8,uint256,uint256)\":{\"params\":{\"amount\":\"Amount in native token decimals to transfer cross-chain pre-fees\",\"chainId\":\"which underlying chain to bridge assets onto\",\"deadline\":\"latest timestamp to accept this transaction*\",\"minDy\":\"the min amount the user would like to receive, or revert to only minting the SynERC20 token crosschain.\",\"to\":\"address on other chain to redeem underlying assets to\",\"token\":\"ERC20 compatible token to deposit into the bridge\",\"tokenIndexFrom\":\"the token the user wants to swap from\",\"tokenIndexTo\":\"the token the user wants to swap to\"}},\"redeemV2(bytes32,uint256,address,uint256)\":{\"params\":{\"amount\":\"Amount in native token decimals to transfer cross-chain pre-fees*\",\"chainId\":\"which underlying chain to bridge assets onto\",\"to\":\"address on other chain to redeem underlying assets to\",\"token\":\"ERC20 compatible token to deposit into the bridge\"}},\"renounceRole(bytes32,address)\":{\"details\":\"Revokes `role` from the calling account. Roles are often managed via {grantRole} and {revokeRole}: this function's purpose is to provide a mechanism for accounts to lose their privileges if they are compromised (such as when a trusted device is misplaced). If the calling account had been granted `role`, emits a {RoleRevoked} event. Requirements: - the caller must be `account`.\"},\"revokeRole(bytes32,address)\":{\"details\":\"Revokes `role` from `account`. If `account` had been granted `role`, emits a {RoleRevoked} event. Requirements: - the caller must have ``role``'s admin role.\"},\"withdraw(address,address,uint256,uint256,bytes32)\":{\"params\":{\"amount\":\"Amount in native token decimals to withdraw\",\"fee\":\"Amount in native token decimals to save to the contract as fees\",\"kappa\":\"kappa*\",\"to\":\"address on chain to send underlying assets to\",\"token\":\"ERC20 compatible token to withdraw from the bridge\"}},\"withdrawAndRemove(address,address,uint256,uint256,address,uint8,uint256,uint256,bytes32)\":{\"params\":{\"amount\":\"Amount in native token decimals to withdraw\",\"fee\":\"Amount in native token decimals to save to the contract as fees\",\"kappa\":\"kappa*\",\"pool\":\"Destination chain's pool to use to swap SynERC20 -> Asset. The nodes determine this by using PoolConfig.sol.\",\"swapDeadline\":\"Specificies the deadline that the nodes are allowed to try to redeem/swap the LP token\",\"swapMinAmount\":\"Specifies the minimum amount of the underlying asset needed for the nodes to execute the redeem/swap\",\"swapTokenIndex\":\"Specifies which of the underlying LP assets the nodes should attempt to redeem for\",\"to\":\"address on chain to send underlying assets to\",\"token\":\"ERC20 compatible token to withdraw from the bridge\"}},\"withdrawFees(address,address)\":{\"params\":{\"to\":\"Address to send the fees to\",\"token\":\"ERC20 token in which fees acccumulated to transfer\"}}},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{\"deposit(address,uint256,address,uint256)\":{\"notice\":\"Relays to nodes to transfers an ERC20 token cross-chain\"},\"depositAndSwap(address,uint256,address,uint256,uint8,uint8,uint256,uint256)\":{\"notice\":\"Relays to nodes to both transfer an ERC20 token cross-chain, and then have the nodes execute a swap through a liquidity pool on behalf of the user.\"},\"mint(address,address,uint256,uint256,bytes32)\":{\"notice\":\"Nodes call this function to mint a SynERC20 (or any asset that the bridge is given minter access to). This is called by the nodes after a TokenDeposit event is emitted.\"},\"mintAndSwap(address,address,uint256,uint256,address,uint8,uint8,uint256,uint256,bytes32)\":{\"notice\":\"Nodes call this function to mint a SynERC20 (or any asset that the bridge is given minter access to), and then attempt to swap the SynERC20 into the desired destination asset. This is called by the nodes after a TokenDepositAndSwap event is emitted.\"},\"redeem(address,uint256,address,uint256)\":{\"notice\":\"Relays to nodes that (typically) a wrapped synAsset ERC20 token has been burned and the underlying needs to be redeeemed on the native chain\"},\"redeemAndRemove(address,uint256,address,uint256,uint8,uint256,uint256)\":{\"notice\":\"Relays to nodes that (typically) a wrapped synAsset ERC20 token has been burned and the underlying needs to be redeeemed on the native chain. This function indicates to the nodes that they should attempt to redeem the LP token for the underlying assets (E.g \\\"swap\\\" out of the LP token)\"},\"redeemAndSwap(address,uint256,address,uint256,uint8,uint8,uint256,uint256)\":{\"notice\":\"Relays to nodes that (typically) a wrapped synAsset ERC20 token has been burned and the underlying needs to be redeeemed on the native chain. This function indicates to the nodes that they should attempt to redeem the LP token for the underlying assets (E.g \\\"swap\\\" out of the LP token)\"},\"redeemV2(bytes32,uint256,address,uint256)\":{\"notice\":\"Relays to nodes that (typically) a wrapped synAsset ERC20 token has been burned and the underlying needs to be redeeemed on the native chain\"},\"withdraw(address,address,uint256,uint256,bytes32)\":{\"notice\":\"Function to be called by the node group to withdraw the underlying assets from the contract\"},\"withdrawAndRemove(address,address,uint256,uint256,address,uint8,uint256,uint256,bytes32)\":{\"notice\":\"Function to be called by the node group to withdraw the underlying assets from the contract\"},\"withdrawFees(address,address)\":{\"notice\":\"withdraw specified ERC20 token fees to a given address\"}},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/bridge/SynapseBridge.sol\":\"SynapseBridge\"},\"evmVersion\":\"istanbul\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":10000},\"remappings\":[]},\"sources\":{\"@openzeppelin/contracts-upgradeable/access/AccessControlUpgradeable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity >=0.6.0 <0.8.0;\\n\\nimport \\\"../utils/EnumerableSetUpgradeable.sol\\\";\\nimport \\\"../utils/AddressUpgradeable.sol\\\";\\nimport \\\"../utils/ContextUpgradeable.sol\\\";\\nimport \\\"../proxy/Initializable.sol\\\";\\n\\n/**\\n * @dev Contract module that allows children to implement role-based access\\n * control mechanisms.\\n *\\n * Roles are referred to by their `bytes32` identifier. These should be exposed\\n * in the external API and be unique. The best way to achieve this is by\\n * using `public constant` hash digests:\\n *\\n * ```\\n * bytes32 public constant MY_ROLE = keccak256(\\\"MY_ROLE\\\");\\n * ```\\n *\\n * Roles can be used to represent a set of permissions. To restrict access to a\\n * function call, use {hasRole}:\\n *\\n * ```\\n * function foo() public {\\n * require(hasRole(MY_ROLE, msg.sender));\\n * ...\\n * }\\n * ```\\n *\\n * Roles can be granted and revoked dynamically via the {grantRole} and\\n * {revokeRole} functions. Each role has an associated admin role, and only\\n * accounts that have a role's admin role can call {grantRole} and {revokeRole}.\\n *\\n * By default, the admin role for all roles is `DEFAULT_ADMIN_ROLE`, which means\\n * that only accounts with this role will be able to grant or revoke other\\n * roles. More complex role relationships can be created by using\\n * {_setRoleAdmin}.\\n *\\n * WARNING: The `DEFAULT_ADMIN_ROLE` is also its own admin: it has permission to\\n * grant and revoke this role. Extra precautions should be taken to secure\\n * accounts that have been granted it.\\n */\\nabstract contract AccessControlUpgradeable is Initializable, ContextUpgradeable {\\n function __AccessControl_init() internal initializer {\\n __Context_init_unchained();\\n __AccessControl_init_unchained();\\n }\\n\\n function __AccessControl_init_unchained() internal initializer {\\n }\\n using EnumerableSetUpgradeable for EnumerableSetUpgradeable.AddressSet;\\n using AddressUpgradeable for address;\\n\\n struct RoleData {\\n EnumerableSetUpgradeable.AddressSet members;\\n bytes32 adminRole;\\n }\\n\\n mapping (bytes32 => RoleData) private _roles;\\n\\n bytes32 public constant DEFAULT_ADMIN_ROLE = 0x00;\\n\\n /**\\n * @dev Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole`\\n *\\n * `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite\\n * {RoleAdminChanged} not being emitted signaling this.\\n *\\n * _Available since v3.1._\\n */\\n event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole);\\n\\n /**\\n * @dev Emitted when `account` is granted `role`.\\n *\\n * `sender` is the account that originated the contract call, an admin role\\n * bearer except when using {_setupRole}.\\n */\\n event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender);\\n\\n /**\\n * @dev Emitted when `account` is revoked `role`.\\n *\\n * `sender` is the account that originated the contract call:\\n * - if using `revokeRole`, it is the admin role bearer\\n * - if using `renounceRole`, it is the role bearer (i.e. `account`)\\n */\\n event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender);\\n\\n /**\\n * @dev Returns `true` if `account` has been granted `role`.\\n */\\n function hasRole(bytes32 role, address account) public view returns (bool) {\\n return _roles[role].members.contains(account);\\n }\\n\\n /**\\n * @dev Returns the number of accounts that have `role`. Can be used\\n * together with {getRoleMember} to enumerate all bearers of a role.\\n */\\n function getRoleMemberCount(bytes32 role) public view returns (uint256) {\\n return _roles[role].members.length();\\n }\\n\\n /**\\n * @dev Returns one of the accounts that have `role`. `index` must be a\\n * value between 0 and {getRoleMemberCount}, non-inclusive.\\n *\\n * Role bearers are not sorted in any particular way, and their ordering may\\n * change at any point.\\n *\\n * WARNING: When using {getRoleMember} and {getRoleMemberCount}, make sure\\n * you perform all queries on the same block. See the following\\n * https://forum.openzeppelin.com/t/iterating-over-elements-on-enumerableset-in-openzeppelin-contracts/2296[forum post]\\n * for more information.\\n */\\n function getRoleMember(bytes32 role, uint256 index) public view returns (address) {\\n return _roles[role].members.at(index);\\n }\\n\\n /**\\n * @dev Returns the admin role that controls `role`. See {grantRole} and\\n * {revokeRole}.\\n *\\n * To change a role's admin, use {_setRoleAdmin}.\\n */\\n function getRoleAdmin(bytes32 role) public view returns (bytes32) {\\n return _roles[role].adminRole;\\n }\\n\\n /**\\n * @dev Grants `role` to `account`.\\n *\\n * If `account` had not been already granted `role`, emits a {RoleGranted}\\n * event.\\n *\\n * Requirements:\\n *\\n * - the caller must have ``role``'s admin role.\\n */\\n function grantRole(bytes32 role, address account) public virtual {\\n require(hasRole(_roles[role].adminRole, _msgSender()), \\\"AccessControl: sender must be an admin to grant\\\");\\n\\n _grantRole(role, account);\\n }\\n\\n /**\\n * @dev Revokes `role` from `account`.\\n *\\n * If `account` had been granted `role`, emits a {RoleRevoked} event.\\n *\\n * Requirements:\\n *\\n * - the caller must have ``role``'s admin role.\\n */\\n function revokeRole(bytes32 role, address account) public virtual {\\n require(hasRole(_roles[role].adminRole, _msgSender()), \\\"AccessControl: sender must be an admin to revoke\\\");\\n\\n _revokeRole(role, account);\\n }\\n\\n /**\\n * @dev Revokes `role` from the calling account.\\n *\\n * Roles are often managed via {grantRole} and {revokeRole}: this function's\\n * purpose is to provide a mechanism for accounts to lose their privileges\\n * if they are compromised (such as when a trusted device is misplaced).\\n *\\n * If the calling account had been granted `role`, emits a {RoleRevoked}\\n * event.\\n *\\n * Requirements:\\n *\\n * - the caller must be `account`.\\n */\\n function renounceRole(bytes32 role, address account) public virtual {\\n require(account == _msgSender(), \\\"AccessControl: can only renounce roles for self\\\");\\n\\n _revokeRole(role, account);\\n }\\n\\n /**\\n * @dev Grants `role` to `account`.\\n *\\n * If `account` had not been already granted `role`, emits a {RoleGranted}\\n * event. Note that unlike {grantRole}, this function doesn't perform any\\n * checks on the calling account.\\n *\\n * [WARNING]\\n * ====\\n * This function should only be called from the constructor when setting\\n * up the initial roles for the system.\\n *\\n * Using this function in any other way is effectively circumventing the admin\\n * system imposed by {AccessControl}.\\n * ====\\n */\\n function _setupRole(bytes32 role, address account) internal virtual {\\n _grantRole(role, account);\\n }\\n\\n /**\\n * @dev Sets `adminRole` as ``role``'s admin role.\\n *\\n * Emits a {RoleAdminChanged} event.\\n */\\n function _setRoleAdmin(bytes32 role, bytes32 adminRole) internal virtual {\\n emit RoleAdminChanged(role, _roles[role].adminRole, adminRole);\\n _roles[role].adminRole = adminRole;\\n }\\n\\n function _grantRole(bytes32 role, address account) private {\\n if (_roles[role].members.add(account)) {\\n emit RoleGranted(role, account, _msgSender());\\n }\\n }\\n\\n function _revokeRole(bytes32 role, address account) private {\\n if (_roles[role].members.remove(account)) {\\n emit RoleRevoked(role, account, _msgSender());\\n }\\n }\\n uint256[49] private __gap;\\n}\\n\",\"keccak256\":\"0xa3c77c9ea6b47301c7ab5bf3addc1d809d13a27a179c4629a1b55308e8633d14\",\"license\":\"MIT\"},\"@openzeppelin/contracts-upgradeable/proxy/Initializable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\n// solhint-disable-next-line compiler-version\\npragma solidity >=0.4.24 <0.8.0;\\n\\nimport \\\"../utils/AddressUpgradeable.sol\\\";\\n\\n/**\\n * @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed\\n * behind a proxy. Since a proxied contract can't have a constructor, it's common to move constructor logic to an\\n * external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer\\n * function so it can only be called once. The {initializer} modifier provided by this contract will have this effect.\\n *\\n * TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as\\n * possible by providing the encoded function call as the `_data` argument to {UpgradeableProxy-constructor}.\\n *\\n * CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure\\n * that all initializers are idempotent. This is not verified automatically as constructors are by Solidity.\\n */\\nabstract contract Initializable {\\n\\n /**\\n * @dev Indicates that the contract has been initialized.\\n */\\n bool private _initialized;\\n\\n /**\\n * @dev Indicates that the contract is in the process of being initialized.\\n */\\n bool private _initializing;\\n\\n /**\\n * @dev Modifier to protect an initializer function from being invoked twice.\\n */\\n modifier initializer() {\\n require(_initializing || _isConstructor() || !_initialized, \\\"Initializable: contract is already initialized\\\");\\n\\n bool isTopLevelCall = !_initializing;\\n if (isTopLevelCall) {\\n _initializing = true;\\n _initialized = true;\\n }\\n\\n _;\\n\\n if (isTopLevelCall) {\\n _initializing = false;\\n }\\n }\\n\\n /// @dev Returns true if and only if the function is running in the constructor\\n function _isConstructor() private view returns (bool) {\\n return !AddressUpgradeable.isContract(address(this));\\n }\\n}\\n\",\"keccak256\":\"0xd8e4eb08dcc1d1860fb347ba5ffd595242b9a1b66d49a47f2b4cb51c3f35017e\",\"license\":\"MIT\"},\"@openzeppelin/contracts-upgradeable/utils/AddressUpgradeable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity >=0.6.2 <0.8.0;\\n\\n/**\\n * @dev Collection of functions related to the address type\\n */\\nlibrary AddressUpgradeable {\\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 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\",\"keccak256\":\"0xfc5ea91fa9ceb1961023b2a6c978b902888c52b90847ac7813fe3b79524165f6\",\"license\":\"MIT\"},\"@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity >=0.6.0 <0.8.0;\\nimport \\\"../proxy/Initializable.sol\\\";\\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 ContextUpgradeable is Initializable {\\n function __Context_init() internal initializer {\\n __Context_init_unchained();\\n }\\n\\n function __Context_init_unchained() internal initializer {\\n }\\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 uint256[50] private __gap;\\n}\\n\",\"keccak256\":\"0xbbf8a21b9a66c48d45ff771b8563c6df19ba451d63dfb8380a865c1e1f29d1a0\",\"license\":\"MIT\"},\"@openzeppelin/contracts-upgradeable/utils/EnumerableSetUpgradeable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity >=0.6.0 <0.8.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 EnumerableSetUpgradeable {\\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\",\"keccak256\":\"0x20714cf126a1a984613579156d3cbc726db8025d8400e1db1d2bb714edaba335\",\"license\":\"MIT\"},\"@openzeppelin/contracts-upgradeable/utils/PausableUpgradeable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity >=0.6.0 <0.8.0;\\n\\nimport \\\"./ContextUpgradeable.sol\\\";\\nimport \\\"../proxy/Initializable.sol\\\";\\n\\n/**\\n * @dev Contract module which allows children to implement an emergency stop\\n * mechanism that can be triggered by an authorized account.\\n *\\n * This module is used through inheritance. It will make available the\\n * modifiers `whenNotPaused` and `whenPaused`, which can be applied to\\n * the functions of your contract. Note that they will not be pausable by\\n * simply including this module, only once the modifiers are put in place.\\n */\\nabstract contract PausableUpgradeable is Initializable, ContextUpgradeable {\\n /**\\n * @dev Emitted when the pause is triggered by `account`.\\n */\\n event Paused(address account);\\n\\n /**\\n * @dev Emitted when the pause is lifted by `account`.\\n */\\n event Unpaused(address account);\\n\\n bool private _paused;\\n\\n /**\\n * @dev Initializes the contract in unpaused state.\\n */\\n function __Pausable_init() internal initializer {\\n __Context_init_unchained();\\n __Pausable_init_unchained();\\n }\\n\\n function __Pausable_init_unchained() internal initializer {\\n _paused = false;\\n }\\n\\n /**\\n * @dev Returns true if the contract is paused, and false otherwise.\\n */\\n function paused() public view virtual returns (bool) {\\n return _paused;\\n }\\n\\n /**\\n * @dev Modifier to make a function callable only when the contract is not paused.\\n *\\n * Requirements:\\n *\\n * - The contract must not be paused.\\n */\\n modifier whenNotPaused() {\\n require(!paused(), \\\"Pausable: paused\\\");\\n _;\\n }\\n\\n /**\\n * @dev Modifier to make a function callable only when the contract is paused.\\n *\\n * Requirements:\\n *\\n * - The contract must be paused.\\n */\\n modifier whenPaused() {\\n require(paused(), \\\"Pausable: not paused\\\");\\n _;\\n }\\n\\n /**\\n * @dev Triggers stopped state.\\n *\\n * Requirements:\\n *\\n * - The contract must not be paused.\\n */\\n function _pause() internal virtual whenNotPaused {\\n _paused = true;\\n emit Paused(_msgSender());\\n }\\n\\n /**\\n * @dev Returns to normal state.\\n *\\n * Requirements:\\n *\\n * - The contract must be paused.\\n */\\n function _unpause() internal virtual whenPaused {\\n _paused = false;\\n emit Unpaused(_msgSender());\\n }\\n uint256[49] private __gap;\\n}\\n\",\"keccak256\":\"0x73bef0a5dec3efde8183c4858d90f683ed2771656c4329647b4d5b0f89498fd5\",\"license\":\"MIT\"},\"@openzeppelin/contracts-upgradeable/utils/ReentrancyGuardUpgradeable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity >=0.6.0 <0.8.0;\\nimport \\\"../proxy/Initializable.sol\\\";\\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 ReentrancyGuardUpgradeable is Initializable {\\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 function __ReentrancyGuard_init() internal initializer {\\n __ReentrancyGuard_init_unchained();\\n }\\n\\n function __ReentrancyGuard_init_unchained() internal initializer {\\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 uint256[49] private __gap;\\n}\\n\",\"keccak256\":\"0x46034cd5cca740f636345c8f7aebae0f78adfd4b70e31e6f888cccbe1086586e\",\"license\":\"MIT\"},\"@openzeppelin/contracts/math/SafeMath.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity >=0.6.0 <0.8.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\",\"keccak256\":\"0xcc78a17dd88fa5a2edc60c8489e2f405c0913b377216a5b26b35656b2d0dab52\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/ERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity >=0.6.0 <0.8.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_) public {\\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\",\"keccak256\":\"0xca0c2396dbeb3503b51abf4248ebf77a1461edad513c01529df51850a012bee3\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/ERC20Burnable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity >=0.6.0 <0.8.0;\\n\\nimport \\\"../../utils/Context.sol\\\";\\nimport \\\"./ERC20.sol\\\";\\n\\n/**\\n * @dev Extension of {ERC20} that allows token holders to destroy both their own\\n * tokens and those that they have an allowance for, in a way that can be\\n * recognized off-chain (via event analysis).\\n */\\nabstract contract ERC20Burnable is Context, ERC20 {\\n using SafeMath for uint256;\\n\\n /**\\n * @dev Destroys `amount` tokens from the caller.\\n *\\n * See {ERC20-_burn}.\\n */\\n function burn(uint256 amount) public virtual {\\n _burn(_msgSender(), amount);\\n }\\n\\n /**\\n * @dev Destroys `amount` tokens from `account`, deducting from the caller's\\n * allowance.\\n *\\n * See {ERC20-_burn} and {ERC20-allowance}.\\n *\\n * Requirements:\\n *\\n * - the caller must have allowance for ``accounts``'s tokens of at least\\n * `amount`.\\n */\\n function burnFrom(address account, uint256 amount) public virtual {\\n uint256 decreasedAllowance = allowance(account, _msgSender()).sub(amount, \\\"ERC20: burn amount exceeds allowance\\\");\\n\\n _approve(account, _msgSender(), decreasedAllowance);\\n _burn(account, amount);\\n }\\n}\\n\",\"keccak256\":\"0x9c0eb3b0e11d2480d49991dc384f1e5f9c9b9967cc81944d50916a9b9c6c4984\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/IERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity >=0.6.0 <0.8.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\",\"keccak256\":\"0x5f02220344881ce43204ae4a6281145a67bc52c2bb1290a791857df3d19d78f5\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/SafeERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity >=0.6.0 <0.8.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\",\"keccak256\":\"0xf12dfbe97e6276980b83d2830bb0eb75e0cf4f3e626c2471137f82158ae6a0fc\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/Address.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity >=0.6.2 <0.8.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\",\"keccak256\":\"0x28911e614500ae7c607a432a709d35da25f3bc5ddc8bd12b278b66358070c0ea\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/Context.sol\":{\"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\",\"keccak256\":\"0x8d3cb350f04ff49cfb10aef08d87f19dcbaecc8027b0bed12f3275cd12f38cf0\",\"license\":\"MIT\"},\"contracts/bridge/SynapseBridge.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity 0.6.12;\\n\\nimport \\\"@openzeppelin/contracts-upgradeable/proxy/Initializable.sol\\\";\\nimport \\\"@openzeppelin/contracts-upgradeable/access/AccessControlUpgradeable.sol\\\";\\nimport \\\"@openzeppelin/contracts-upgradeable/utils/ReentrancyGuardUpgradeable.sol\\\";\\nimport \\\"@openzeppelin/contracts-upgradeable/utils/PausableUpgradeable.sol\\\";\\nimport \\\"@openzeppelin/contracts/token/ERC20/SafeERC20.sol\\\";\\nimport \\\"@openzeppelin/contracts/token/ERC20/ERC20Burnable.sol\\\";\\nimport \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\nimport \\\"@openzeppelin/contracts/math/SafeMath.sol\\\";\\n\\nimport \\\"./interfaces/ISwap.sol\\\";\\nimport \\\"./interfaces/IWETH9.sol\\\";\\n\\ninterface IERC20Mintable is IERC20 {\\n function mint(address to, uint256 amount) external;\\n}\\n\\ncontract SynapseBridge is\\n Initializable,\\n AccessControlUpgradeable,\\n ReentrancyGuardUpgradeable,\\n PausableUpgradeable\\n{\\n using SafeERC20 for IERC20;\\n using SafeERC20 for IERC20Mintable;\\n using SafeMath for uint256;\\n\\n bytes32 public constant NODEGROUP_ROLE = keccak256(\\\"NODEGROUP_ROLE\\\");\\n bytes32 public constant GOVERNANCE_ROLE = keccak256(\\\"GOVERNANCE_ROLE\\\");\\n\\n mapping(address => uint256) private fees;\\n\\n uint256 public startBlockNumber;\\n uint256 public constant bridgeVersion = 6;\\n uint256 public chainGasAmount;\\n address payable public WETH_ADDRESS;\\n\\n mapping(bytes32 => bool) private kappaMap;\\n\\n receive() external payable {}\\n\\n function initialize() external initializer {\\n startBlockNumber = block.number;\\n _setupRole(DEFAULT_ADMIN_ROLE, msg.sender);\\n __AccessControl_init();\\n }\\n\\n function setChainGasAmount(uint256 amount) external {\\n require(hasRole(GOVERNANCE_ROLE, msg.sender), \\\"Not governance\\\");\\n chainGasAmount = amount;\\n }\\n\\n function setWethAddress(address payable _wethAddress) external {\\n require(hasRole(DEFAULT_ADMIN_ROLE, msg.sender), \\\"Not admin\\\");\\n WETH_ADDRESS = _wethAddress;\\n }\\n\\n function addKappas(bytes32[] calldata kappas) external {\\n require(hasRole(GOVERNANCE_ROLE, msg.sender), \\\"Not governance\\\");\\n for (uint256 i = 0; i < kappas.length; ++i) {\\n kappaMap[kappas[i]] = true;\\n }\\n }\\n\\n event TokenDeposit(\\n address indexed to,\\n uint256 chainId,\\n IERC20 token,\\n uint256 amount\\n );\\n event TokenRedeem(\\n address indexed to,\\n uint256 chainId,\\n IERC20 token,\\n uint256 amount\\n );\\n event TokenWithdraw(\\n address indexed to,\\n IERC20 token,\\n uint256 amount,\\n uint256 fee,\\n bytes32 indexed kappa\\n );\\n event TokenMint(\\n address indexed to,\\n IERC20Mintable token,\\n uint256 amount,\\n uint256 fee,\\n bytes32 indexed kappa\\n );\\n event TokenDepositAndSwap(\\n address indexed to,\\n uint256 chainId,\\n IERC20 token,\\n uint256 amount,\\n uint8 tokenIndexFrom,\\n uint8 tokenIndexTo,\\n uint256 minDy,\\n uint256 deadline\\n );\\n event TokenMintAndSwap(\\n address indexed to,\\n IERC20Mintable token,\\n uint256 amount,\\n uint256 fee,\\n uint8 tokenIndexFrom,\\n uint8 tokenIndexTo,\\n uint256 minDy,\\n uint256 deadline,\\n bool swapSuccess,\\n bytes32 indexed kappa\\n );\\n event TokenRedeemAndSwap(\\n address indexed to,\\n uint256 chainId,\\n IERC20 token,\\n uint256 amount,\\n uint8 tokenIndexFrom,\\n uint8 tokenIndexTo,\\n uint256 minDy,\\n uint256 deadline\\n );\\n event TokenRedeemAndRemove(\\n address indexed to,\\n uint256 chainId,\\n IERC20 token,\\n uint256 amount,\\n uint8 swapTokenIndex,\\n uint256 swapMinAmount,\\n uint256 swapDeadline\\n );\\n event TokenWithdrawAndRemove(\\n address indexed to,\\n IERC20 token,\\n uint256 amount,\\n uint256 fee,\\n uint8 swapTokenIndex,\\n uint256 swapMinAmount,\\n uint256 swapDeadline,\\n bool swapSuccess,\\n bytes32 indexed kappa\\n );\\n\\n // v2 events\\n event TokenRedeemV2(\\n bytes32 indexed to,\\n uint256 chainId,\\n IERC20 token,\\n uint256 amount\\n );\\n\\n // VIEW FUNCTIONS ***/\\n function getFeeBalance(address tokenAddress)\\n external\\n view\\n returns (uint256)\\n {\\n return fees[tokenAddress];\\n }\\n\\n function kappaExists(bytes32 kappa) external view returns (bool) {\\n return kappaMap[kappa];\\n }\\n\\n // FEE FUNCTIONS ***/\\n /**\\n * * @notice withdraw specified ERC20 token fees to a given address\\n * * @param token ERC20 token in which fees acccumulated to transfer\\n * * @param to Address to send the fees to\\n */\\n function withdrawFees(IERC20 token, address to) external whenNotPaused {\\n require(hasRole(GOVERNANCE_ROLE, msg.sender), \\\"Not governance\\\");\\n require(to != address(0), \\\"Address is 0x000\\\");\\n if (fees[address(token)] != 0) {\\n token.safeTransfer(to, fees[address(token)]);\\n fees[address(token)] = 0;\\n }\\n }\\n\\n // PAUSABLE FUNCTIONS ***/\\n function pause() external {\\n require(hasRole(GOVERNANCE_ROLE, msg.sender), \\\"Not governance\\\");\\n _pause();\\n }\\n\\n function unpause() external {\\n require(hasRole(GOVERNANCE_ROLE, msg.sender), \\\"Not governance\\\");\\n _unpause();\\n }\\n\\n /**\\n * @notice Relays to nodes to transfers an ERC20 token cross-chain\\n * @param to address on other chain to bridge assets to\\n * @param chainId which chain to bridge assets onto\\n * @param token ERC20 compatible token to deposit into the bridge\\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\\n **/\\n function deposit(\\n address to,\\n uint256 chainId,\\n IERC20 token,\\n uint256 amount\\n ) external nonReentrant whenNotPaused {\\n emit TokenDeposit(to, chainId, token, amount);\\n token.safeTransferFrom(msg.sender, address(this), amount);\\n }\\n\\n /**\\n * @notice Relays to nodes that (typically) a wrapped synAsset ERC20 token has been burned and the underlying needs to be redeeemed on the native chain\\n * @param to address on other chain to redeem underlying assets to\\n * @param chainId which underlying chain to bridge assets onto\\n * @param token ERC20 compatible token to deposit into the bridge\\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\\n **/\\n function redeem(\\n address to,\\n uint256 chainId,\\n ERC20Burnable token,\\n uint256 amount\\n ) external nonReentrant whenNotPaused {\\n emit TokenRedeem(to, chainId, token, amount);\\n token.burnFrom(msg.sender, amount);\\n }\\n\\n /**\\n * @notice Function to be called by the node group to withdraw the underlying assets from the contract\\n * @param to address on chain to send underlying assets to\\n * @param token ERC20 compatible token to withdraw from the bridge\\n * @param amount Amount in native token decimals to withdraw\\n * @param fee Amount in native token decimals to save to the contract as fees\\n * @param kappa kappa\\n **/\\n function withdraw(\\n address to,\\n IERC20 token,\\n uint256 amount,\\n uint256 fee,\\n bytes32 kappa\\n ) external nonReentrant whenNotPaused {\\n require(\\n hasRole(NODEGROUP_ROLE, msg.sender),\\n \\\"Caller is not a node group\\\"\\n );\\n require(amount > fee, \\\"Amount must be greater than fee\\\");\\n require(!kappaMap[kappa], \\\"Kappa is already present\\\");\\n kappaMap[kappa] = true;\\n fees[address(token)] = fees[address(token)].add(fee);\\n if (address(token) == WETH_ADDRESS && WETH_ADDRESS != address(0)) {\\n IWETH9(WETH_ADDRESS).withdraw(amount.sub(fee));\\n (bool success, ) = to.call{value: amount.sub(fee)}(\\\"\\\");\\n require(success, \\\"ETH_TRANSFER_FAILED\\\");\\n emit TokenWithdraw(to, token, amount, fee, kappa);\\n } else {\\n emit TokenWithdraw(to, token, amount, fee, kappa);\\n token.safeTransfer(to, amount.sub(fee));\\n }\\n }\\n\\n /**\\n * @notice Nodes call this function to mint a SynERC20 (or any asset that the bridge is given minter access to). This is called by the nodes after a TokenDeposit event is emitted.\\n * @dev This means the SynapseBridge.sol contract must have minter access to the token attempting to be minted\\n * @param to address on other chain to redeem underlying assets to\\n * @param token ERC20 compatible token to deposit into the bridge\\n * @param amount Amount in native token decimals to transfer cross-chain post-fees\\n * @param fee Amount in native token decimals to save to the contract as fees\\n * @param kappa kappa\\n **/\\n function mint(\\n address payable to,\\n IERC20Mintable token,\\n uint256 amount,\\n uint256 fee,\\n bytes32 kappa\\n ) external nonReentrant whenNotPaused {\\n require(\\n hasRole(NODEGROUP_ROLE, msg.sender),\\n \\\"Caller is not a node group\\\"\\n );\\n require(amount > fee, \\\"Amount must be greater than fee\\\");\\n require(!kappaMap[kappa], \\\"Kappa is already present\\\");\\n kappaMap[kappa] = true;\\n fees[address(token)] = fees[address(token)].add(fee);\\n emit TokenMint(to, token, amount.sub(fee), fee, kappa);\\n token.mint(address(this), amount);\\n IERC20(token).safeTransfer(to, amount.sub(fee));\\n if (chainGasAmount != 0 && address(this).balance > chainGasAmount) {\\n to.call.value(chainGasAmount)(\\\"\\\");\\n }\\n }\\n\\n /**\\n * @notice Relays to nodes to both transfer an ERC20 token cross-chain, and then have the nodes execute a swap through a liquidity pool on behalf of the user.\\n * @param to address on other chain to bridge assets to\\n * @param chainId which chain to bridge assets onto\\n * @param token ERC20 compatible token to deposit into the bridge\\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\\n * @param tokenIndexFrom the token the user wants to swap from\\n * @param tokenIndexTo the token the user wants to swap to\\n * @param minDy the min amount the user would like to receive, or revert to only minting the SynERC20 token crosschain.\\n * @param deadline latest timestamp to accept this transaction\\n **/\\n function depositAndSwap(\\n address to,\\n uint256 chainId,\\n IERC20 token,\\n uint256 amount,\\n uint8 tokenIndexFrom,\\n uint8 tokenIndexTo,\\n uint256 minDy,\\n uint256 deadline\\n ) external nonReentrant whenNotPaused {\\n emit TokenDepositAndSwap(\\n to,\\n chainId,\\n token,\\n amount,\\n tokenIndexFrom,\\n tokenIndexTo,\\n minDy,\\n deadline\\n );\\n token.safeTransferFrom(msg.sender, address(this), amount);\\n }\\n\\n /**\\n * @notice Relays to nodes that (typically) a wrapped synAsset ERC20 token has been burned and the underlying needs to be redeeemed on the native chain. This function indicates to the nodes that they should attempt to redeem the LP token for the underlying assets (E.g \\\"swap\\\" out of the LP token)\\n * @param to address on other chain to redeem underlying assets to\\n * @param chainId which underlying chain to bridge assets onto\\n * @param token ERC20 compatible token to deposit into the bridge\\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\\n * @param tokenIndexFrom the token the user wants to swap from\\n * @param tokenIndexTo the token the user wants to swap to\\n * @param minDy the min amount the user would like to receive, or revert to only minting the SynERC20 token crosschain.\\n * @param deadline latest timestamp to accept this transaction\\n **/\\n function redeemAndSwap(\\n address to,\\n uint256 chainId,\\n ERC20Burnable token,\\n uint256 amount,\\n uint8 tokenIndexFrom,\\n uint8 tokenIndexTo,\\n uint256 minDy,\\n uint256 deadline\\n ) external nonReentrant whenNotPaused {\\n emit TokenRedeemAndSwap(\\n to,\\n chainId,\\n token,\\n amount,\\n tokenIndexFrom,\\n tokenIndexTo,\\n minDy,\\n deadline\\n );\\n token.burnFrom(msg.sender, amount);\\n }\\n\\n /**\\n * @notice Relays to nodes that (typically) a wrapped synAsset ERC20 token has been burned and the underlying needs to be redeeemed on the native chain. This function indicates to the nodes that they should attempt to redeem the LP token for the underlying assets (E.g \\\"swap\\\" out of the LP token)\\n * @param to address on other chain to redeem underlying assets to\\n * @param chainId which underlying chain to bridge assets onto\\n * @param token ERC20 compatible token to deposit into the bridge\\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\\n * @param swapTokenIndex Specifies which of the underlying LP assets the nodes should attempt to redeem for\\n * @param swapMinAmount Specifies the minimum amount of the underlying asset needed for the nodes to execute the redeem/swap\\n * @param swapDeadline Specificies the deadline that the nodes are allowed to try to redeem/swap the LP token\\n **/\\n function redeemAndRemove(\\n address to,\\n uint256 chainId,\\n ERC20Burnable token,\\n uint256 amount,\\n uint8 swapTokenIndex,\\n uint256 swapMinAmount,\\n uint256 swapDeadline\\n ) external nonReentrant whenNotPaused {\\n emit TokenRedeemAndRemove(\\n to,\\n chainId,\\n token,\\n amount,\\n swapTokenIndex,\\n swapMinAmount,\\n swapDeadline\\n );\\n token.burnFrom(msg.sender, amount);\\n }\\n\\n /**\\n * @notice Nodes call this function to mint a SynERC20 (or any asset that the bridge is given minter access to), and then attempt to swap the SynERC20 into the desired destination asset. This is called by the nodes after a TokenDepositAndSwap event is emitted.\\n * @dev This means the BridgeDeposit.sol contract must have minter access to the token attempting to be minted\\n * @param to address on other chain to redeem underlying assets to\\n * @param token ERC20 compatible token to deposit into the bridge\\n * @param amount Amount in native token decimals to transfer cross-chain post-fees\\n * @param fee Amount in native token decimals to save to the contract as fees\\n * @param pool Destination chain's pool to use to swap SynERC20 -> Asset. The nodes determine this by using PoolConfig.sol.\\n * @param tokenIndexFrom Index of the SynERC20 asset in the pool\\n * @param tokenIndexTo Index of the desired final asset\\n * @param minDy Minumum amount (in final asset decimals) that must be swapped for, otherwise the user will receive the SynERC20.\\n * @param deadline Epoch time of the deadline that the swap is allowed to be executed.\\n * @param kappa kappa\\n **/\\n function mintAndSwap(\\n address payable to,\\n IERC20Mintable token,\\n uint256 amount,\\n uint256 fee,\\n ISwap pool,\\n uint8 tokenIndexFrom,\\n uint8 tokenIndexTo,\\n uint256 minDy,\\n uint256 deadline,\\n bytes32 kappa\\n ) external nonReentrant whenNotPaused {\\n require(\\n hasRole(NODEGROUP_ROLE, msg.sender),\\n \\\"Caller is not a node group\\\"\\n );\\n require(amount > fee, \\\"Amount must be greater than fee\\\");\\n require(!kappaMap[kappa], \\\"Kappa is already present\\\");\\n kappaMap[kappa] = true;\\n fees[address(token)] = fees[address(token)].add(fee);\\n // Transfer gas airdrop\\n if (chainGasAmount != 0 && address(this).balance > chainGasAmount) {\\n to.call.value(chainGasAmount)(\\\"\\\");\\n }\\n // first check to make sure more will be given than min amount required\\n uint256 expectedOutput = ISwap(pool).calculateSwap(\\n tokenIndexFrom,\\n tokenIndexTo,\\n amount.sub(fee)\\n );\\n\\n if (expectedOutput >= minDy) {\\n // proceed with swap\\n token.mint(address(this), amount);\\n token.safeIncreaseAllowance(address(pool), amount);\\n try\\n ISwap(pool).swap(\\n tokenIndexFrom,\\n tokenIndexTo,\\n amount.sub(fee),\\n minDy,\\n deadline\\n )\\n returns (uint256 finalSwappedAmount) {\\n // Swap succeeded, transfer swapped asset\\n IERC20 swappedTokenTo = ISwap(pool).getToken(tokenIndexTo);\\n if (\\n address(swappedTokenTo) == WETH_ADDRESS &&\\n WETH_ADDRESS != address(0)\\n ) {\\n IWETH9(WETH_ADDRESS).withdraw(finalSwappedAmount);\\n (bool success, ) = to.call{value: finalSwappedAmount}(\\\"\\\");\\n require(success, \\\"ETH_TRANSFER_FAILED\\\");\\n emit TokenMintAndSwap(\\n to,\\n token,\\n finalSwappedAmount,\\n fee,\\n tokenIndexFrom,\\n tokenIndexTo,\\n minDy,\\n deadline,\\n true,\\n kappa\\n );\\n } else {\\n swappedTokenTo.safeTransfer(to, finalSwappedAmount);\\n emit TokenMintAndSwap(\\n to,\\n token,\\n finalSwappedAmount,\\n fee,\\n tokenIndexFrom,\\n tokenIndexTo,\\n minDy,\\n deadline,\\n true,\\n kappa\\n );\\n }\\n } catch {\\n IERC20(token).safeTransfer(to, amount.sub(fee));\\n emit TokenMintAndSwap(\\n to,\\n token,\\n amount.sub(fee),\\n fee,\\n tokenIndexFrom,\\n tokenIndexTo,\\n minDy,\\n deadline,\\n false,\\n kappa\\n );\\n }\\n } else {\\n token.mint(address(this), amount);\\n IERC20(token).safeTransfer(to, amount.sub(fee));\\n emit TokenMintAndSwap(\\n to,\\n token,\\n amount.sub(fee),\\n fee,\\n tokenIndexFrom,\\n tokenIndexTo,\\n minDy,\\n deadline,\\n false,\\n kappa\\n );\\n }\\n }\\n\\n /**\\n * @notice Function to be called by the node group to withdraw the underlying assets from the contract\\n * @param to address on chain to send underlying assets to\\n * @param token ERC20 compatible token to withdraw from the bridge\\n * @param amount Amount in native token decimals to withdraw\\n * @param fee Amount in native token decimals to save to the contract as fees\\n * @param pool Destination chain's pool to use to swap SynERC20 -> Asset. The nodes determine this by using PoolConfig.sol.\\n * @param swapTokenIndex Specifies which of the underlying LP assets the nodes should attempt to redeem for\\n * @param swapMinAmount Specifies the minimum amount of the underlying asset needed for the nodes to execute the redeem/swap\\n * @param swapDeadline Specificies the deadline that the nodes are allowed to try to redeem/swap the LP token\\n * @param kappa kappa\\n **/\\n function withdrawAndRemove(\\n address to,\\n IERC20 token,\\n uint256 amount,\\n uint256 fee,\\n ISwap pool,\\n uint8 swapTokenIndex,\\n uint256 swapMinAmount,\\n uint256 swapDeadline,\\n bytes32 kappa\\n ) external nonReentrant whenNotPaused {\\n require(\\n hasRole(NODEGROUP_ROLE, msg.sender),\\n \\\"Caller is not a node group\\\"\\n );\\n require(amount > fee, \\\"Amount must be greater than fee\\\");\\n require(!kappaMap[kappa], \\\"Kappa is already present\\\");\\n kappaMap[kappa] = true;\\n fees[address(token)] = fees[address(token)].add(fee);\\n // first check to make sure more will be given than min amount required\\n uint256 expectedOutput = ISwap(pool).calculateRemoveLiquidityOneToken(\\n amount.sub(fee),\\n swapTokenIndex\\n );\\n\\n if (expectedOutput >= swapMinAmount) {\\n token.safeIncreaseAllowance(address(pool), amount.sub(fee));\\n try\\n ISwap(pool).removeLiquidityOneToken(\\n amount.sub(fee),\\n swapTokenIndex,\\n swapMinAmount,\\n swapDeadline\\n )\\n returns (uint256 finalSwappedAmount) {\\n // Swap succeeded, transfer swapped asset\\n IERC20 swappedTokenTo = ISwap(pool).getToken(swapTokenIndex);\\n swappedTokenTo.safeTransfer(to, finalSwappedAmount);\\n emit TokenWithdrawAndRemove(\\n to,\\n token,\\n finalSwappedAmount,\\n fee,\\n swapTokenIndex,\\n swapMinAmount,\\n swapDeadline,\\n true,\\n kappa\\n );\\n } catch {\\n IERC20(token).safeTransfer(to, amount.sub(fee));\\n emit TokenWithdrawAndRemove(\\n to,\\n token,\\n amount.sub(fee),\\n fee,\\n swapTokenIndex,\\n swapMinAmount,\\n swapDeadline,\\n false,\\n kappa\\n );\\n }\\n } else {\\n token.safeTransfer(to, amount.sub(fee));\\n emit TokenWithdrawAndRemove(\\n to,\\n token,\\n amount.sub(fee),\\n fee,\\n swapTokenIndex,\\n swapMinAmount,\\n swapDeadline,\\n false,\\n kappa\\n );\\n }\\n }\\n\\n // BRIDGE FUNCTIONS TO HANDLE DIFF ADDRESSES\\n /**\\n * @notice Relays to nodes that (typically) a wrapped synAsset ERC20 token has been burned and the underlying needs to be redeeemed on the native chain\\n * @param to address on other chain to redeem underlying assets to\\n * @param chainId which underlying chain to bridge assets onto\\n * @param token ERC20 compatible token to deposit into the bridge\\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\\n **/\\n function redeemV2(\\n bytes32 to,\\n uint256 chainId,\\n ERC20Burnable token,\\n uint256 amount\\n ) external nonReentrant whenNotPaused {\\n emit TokenRedeemV2(to, chainId, token, amount);\\n token.burnFrom(msg.sender, amount);\\n }\\n}\\n\",\"keccak256\":\"0xafc0c16c9cd37fe7a6b92f18e65d4084552bb27ea98ecba024b5f7fe83fbe252\",\"license\":\"MIT\"},\"contracts/bridge/interfaces/ISwap.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity 0.6.12;\\n\\nimport '@openzeppelin/contracts/token/ERC20/ERC20.sol';\\n\\ninterface ISwap {\\n // pool data view functions\\n function getA() external view returns (uint256);\\n\\n function getToken(uint8 index) external view returns (IERC20);\\n\\n function getTokenIndex(address tokenAddress) external view returns (uint8);\\n\\n function getTokenBalance(uint8 index) external view returns (uint256);\\n\\n function getVirtualPrice() external view returns (uint256);\\n\\n // min return calculation functions\\n function calculateSwap(\\n uint8 tokenIndexFrom,\\n uint8 tokenIndexTo,\\n uint256 dx\\n ) external view returns (uint256);\\n\\n function calculateTokenAmount(uint256[] calldata amounts, bool deposit)\\n external\\n view\\n returns (uint256);\\n\\n function calculateRemoveLiquidity(uint256 amount)\\n external\\n view\\n returns (uint256[] memory);\\n\\n function calculateRemoveLiquidityOneToken(\\n uint256 tokenAmount,\\n uint8 tokenIndex\\n ) external view returns (uint256 availableTokenAmount);\\n\\n // state modifying functions\\n function initialize(\\n IERC20[] memory pooledTokens,\\n uint8[] memory decimals,\\n string memory lpTokenName,\\n string memory lpTokenSymbol,\\n uint256 a,\\n uint256 fee,\\n uint256 adminFee,\\n address lpTokenTargetAddress\\n ) external;\\n\\n function swap(\\n uint8 tokenIndexFrom,\\n uint8 tokenIndexTo,\\n uint256 dx,\\n uint256 minDy,\\n uint256 deadline\\n ) external returns (uint256);\\n\\n function addLiquidity(\\n uint256[] calldata amounts,\\n uint256 minToMint,\\n uint256 deadline\\n ) external returns (uint256);\\n\\n function removeLiquidity(\\n uint256 amount,\\n uint256[] calldata minAmounts,\\n uint256 deadline\\n ) external returns (uint256[] memory);\\n\\n function removeLiquidityOneToken(\\n uint256 tokenAmount,\\n uint8 tokenIndex,\\n uint256 minAmount,\\n uint256 deadline\\n ) external returns (uint256);\\n\\n function removeLiquidityImbalance(\\n uint256[] calldata amounts,\\n uint256 maxBurnAmount,\\n uint256 deadline\\n ) external returns (uint256);\\n}\\n\",\"keccak256\":\"0xb51eb389637b2b595a09cd95ea4167a6d945719be1bc127eafae07c06abd8ca8\",\"license\":\"MIT\"},\"contracts/bridge/interfaces/IWETH9.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity >=0.4.0;\\n\\ninterface IWETH9 {\\n function name() external view returns (string memory);\\n\\n function symbol() external view returns (string memory);\\n\\n function decimals() external view returns (uint8);\\n\\n function balanceOf(address) external view returns (uint256);\\n\\n function allowance(address, address) external view returns (uint256);\\n\\n receive() external payable;\\n\\n function deposit() external payable;\\n\\n function withdraw(uint256 wad) external;\\n\\n function totalSupply() external view returns (uint256);\\n\\n function approve(address guy, uint256 wad) external returns (bool);\\n\\n function transfer(address dst, uint256 wad) external returns (bool);\\n\\n function transferFrom(\\n address src,\\n address dst,\\n uint256 wad\\n ) external returns (bool);\\n}\",\"keccak256\":\"0x081ebde11dad2210d382564d40336f914d3d621750645f23707ca1a92139dbe2\",\"license\":\"MIT\"}},\"version\":1}", + "bytecode": "0x608060405234801561001057600080fd5b50613dcd806100206000396000f3fe60806040526004361061021d5760003560e01c806391d148541161011d578063ca15c873116100b0578063e7a599981161007f578063f36c8f5c11610064578063f36c8f5c1461093b578063f3befd0114610950578063f3f094a11461096557610224565b8063e7a5999814610883578063f25552781461090057610224565b8063ca15c8731461079f578063d547741f146107c9578063d57eafac14610802578063e00a83e01461086e57610224565b8063a96e2423116100ec578063a96e2423146106fa578063ac8656261461072d578063b250fe6b14610742578063c78f68031461076c57610224565b806391d1485414610600578063a07ed97514610639578063a217fddf1461067e578063a2a2af0b1461069357610224565b806336e712ed116101b05780638129fc1c1161017f5780638456cb59116101645780638456cb59146105745780639010d07c1461058957806390d25074146105b957610224565b80638129fc1c146104f8578063839ed90a1461050d57610224565b806336e712ed1461045d5780633f4ba83a146104b9578063498a4c2d146104ce5780635c975abb146104e357610224565b8063248a9ca3116101ec578063248a9ca3146103715780632f2ff15d146103ad5780632fe87b95146103e657806336568abe1461042457610224565b8063040141e514610229578063173578921461025a5780631cf5f07f146102d357806320d7b3271461032257610224565b3661022457005b600080fd5b34801561023557600080fd5b5061023e6109ac565b604080516001600160a01b039092168252519081900360200190f35b34801561026657600080fd5b506102d1600480360361014081101561027e57600080fd5b506001600160a01b03813581169160208101358216916040820135916060810135916080820135169060ff60a082013581169160c08101359091169060e0810135906101008101359061012001356109bb565b005b3480156102df57600080fd5b506102d1600480360360a08110156102f657600080fd5b506001600160a01b03813581169160208101359091169060408101359060608101359060800135611315565b34801561032e57600080fd5b506102d1600480360360a081101561034557600080fd5b506001600160a01b0381358116916020810135909116906040810135906060810135906080013561175e565b34801561037d57600080fd5b5061039b6004803603602081101561039457600080fd5b5035611b04565b60408051918252519081900360200190f35b3480156103b957600080fd5b506102d1600480360360408110156103d057600080fd5b50803590602001356001600160a01b0316611b19565b3480156103f257600080fd5b506104106004803603602081101561040957600080fd5b5035611b85565b604080519115158252519081900360200190f35b34801561043057600080fd5b506102d16004803603604081101561044757600080fd5b50803590602001356001600160a01b0316611b9a565b34801561046957600080fd5b506102d1600480360360e081101561048057600080fd5b506001600160a01b0381358116916020810135916040820135169060608101359060ff6080820135169060a08101359060c00135611bfb565b3480156104c557600080fd5b506102d1611d91565b3480156104da57600080fd5b5061039b611e16565b3480156104ef57600080fd5b50610410611e1c565b34801561050457600080fd5b506102d1611e25565b34801561051957600080fd5b506102d1600480360361010081101561053157600080fd5b506001600160a01b0381358116916020810135916040820135169060608101359060ff608082013581169160a08101359091169060c08101359060e00135611f18565b34801561058057600080fd5b506102d16120c9565b34801561059557600080fd5b5061023e600480360360408110156105ac57600080fd5b508035906020013561214c565b3480156105c557600080fd5b506102d1600480360360808110156105dc57600080fd5b506001600160a01b038135811691602081013591604082013516906060013561216d565b34801561060c57600080fd5b506104106004803603604081101561062357600080fd5b50803590602001356001600160a01b0316612291565b34801561064557600080fd5b506102d16004803603608081101561065c57600080fd5b508035906020810135906001600160a01b0360408201351690606001356122a9565b34801561068a57600080fd5b5061039b612435565b34801561069f57600080fd5b506102d160048036036101008110156106b757600080fd5b506001600160a01b0381358116916020810135916040820135169060608101359060ff608082013581169160a08101359091169060c08101359060e0013561243a565b34801561070657600080fd5b506102d16004803603602081101561071d57600080fd5b50356001600160a01b0316612572565b34801561073957600080fd5b5061039b612608565b34801561074e57600080fd5b506102d16004803603602081101561076557600080fd5b503561260d565b34801561077857600080fd5b5061039b6004803603602081101561078f57600080fd5b50356001600160a01b031661268d565b3480156107ab57600080fd5b5061039b600480360360208110156107c257600080fd5b50356126a8565b3480156107d557600080fd5b506102d1600480360360408110156107ec57600080fd5b50803590602001356001600160a01b03166126bf565b34801561080e57600080fd5b506102d1600480360361012081101561082657600080fd5b506001600160a01b03813581169160208101358216916040820135916060810135916080820135169060ff60a0820135169060c08101359060e0810135906101000135612718565b34801561087a57600080fd5b5061039b612cd1565b34801561088f57600080fd5b506102d1600480360360208110156108a657600080fd5b8101906020810181356401000000008111156108c157600080fd5b8201836020820111156108d357600080fd5b803590602001918460208302840111640100000000831117156108f557600080fd5b509092509050612cd7565b34801561090c57600080fd5b506102d16004803603604081101561092357600080fd5b506001600160a01b0381358116916020013516612da4565b34801561094757600080fd5b5061039b612f32565b34801561095c57600080fd5b5061039b612f56565b34801561097157600080fd5b506102d16004803603608081101561098857600080fd5b506001600160a01b0381358116916020810135916040820135169060600135612f7a565b60cc546001600160a01b031681565b60026065541415610a13576040805162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604482015290519081900360640190fd5b6002606555610a20611e1c565b15610a72576040805162461bcd60e51b815260206004820152601060248201527f5061757361626c653a2070617573656400000000000000000000000000000000604482015290519081900360640190fd5b610a9c7fb5c00e6706c3d213edd70ff33717fac657eacc5fe161f07180cf1fcab13cc4cd33612291565b610aed576040805162461bcd60e51b815260206004820152601a60248201527f43616c6c6572206973206e6f742061206e6f64652067726f7570000000000000604482015290519081900360640190fd5b868811610b41576040805162461bcd60e51b815260206004820152601f60248201527f416d6f756e74206d7573742062652067726561746572207468616e2066656500604482015290519081900360640190fd5b600081815260cd602052604090205460ff1615610ba5576040805162461bcd60e51b815260206004820152601860248201527f4b6170706120697320616c72656164792070726573656e740000000000000000604482015290519081900360640190fd5b600081815260cd60209081526040808320805460ff191660011790556001600160a01b038c16835260c9909152902054610bdf90886130e5565b6001600160a01b038a16600090815260c9602052604090205560cb5415801590610c0a575060cb5447115b15610c635760cb546040516001600160a01b038c169190600081818185875af1925050503d8060008114610c5a576040519150601f19603f3d011682016040523d82523d6000602084013e610c5f565b606091505b5050505b60006001600160a01b03871663a95b089f8787610c808d8d61313f565b6040518463ffffffff1660e01b8152600401808460ff1681526020018360ff168152602001828152602001935050505060206040518083038186803b158015610cc857600080fd5b505afa158015610cdc573d6000803e3d6000fd5b505050506040513d6020811015610cf257600080fd5b505190508381106111e557604080517f40c10f19000000000000000000000000000000000000000000000000000000008152306004820152602481018b905290516001600160a01b038c16916340c10f1991604480830192600092919082900301818387803b158015610d6457600080fd5b505af1158015610d78573d6000803e3d6000fd5b50610d91925050506001600160a01b038b16888b61319c565b6001600160a01b03871663916955868787610dac8d8d61313f565b88886040518663ffffffff1660e01b8152600401808660ff1681526020018560ff16815260200184815260200183815260200182815260200195505050505050602060405180830381600087803b158015610e0657600080fd5b505af1925050508015610e2b57506040513d6020811015610e2657600080fd5b505160015b610eda57610e4e8b610e3d8b8b61313f565b6001600160a01b038d1691906132bb565b816001600160a01b038c167f4f56ec39e98539920503fd54ee56ae0cbebe9eb15aa778f18de67701eeae7c658c610e858d8d61313f565b604080516001600160a01b03909316835260208301919091528181018d905260ff808c1660608401528a16608083015260a0820189905260c08201889052600060e083015251908190036101000190a36111e0565b6000886001600160a01b03166382b86600886040518263ffffffff1660e01b8152600401808260ff16815260200191505060206040518083038186803b158015610f2357600080fd5b505afa158015610f37573d6000803e3d6000fd5b505050506040513d6020811015610f4d57600080fd5b505160cc549091506001600160a01b038083169116148015610f79575060cc546001600160a01b031615155b1561113c5760cc54604080517f2e1a7d4d0000000000000000000000000000000000000000000000000000000081526004810185905290516001600160a01b0390921691632e1a7d4d9160248082019260009290919082900301818387803b158015610fe457600080fd5b505af1158015610ff8573d6000803e3d6000fd5b5050505060008d6001600160a01b03168360405180600001905060006040518083038185875af1925050503d806000811461104f576040519150601f19603f3d011682016040523d82523d6000602084013e611054565b606091505b50509050806110aa576040805162461bcd60e51b815260206004820152601360248201527f4554485f5452414e534645525f4641494c454400000000000000000000000000604482015290519081900360640190fd5b848e6001600160a01b03167f4f56ec39e98539920503fd54ee56ae0cbebe9eb15aa778f18de67701eeae7c658f868f8e8e8e8e600160405180896001600160a01b031681526020018881526020018781526020018660ff1681526020018560ff16815260200184815260200183815260200182151581526020019850505050505050505060405180910390a3506111dd565b6111506001600160a01b0382168e846132bb565b838d6001600160a01b03167f4f56ec39e98539920503fd54ee56ae0cbebe9eb15aa778f18de67701eeae7c658e858e8d8d8d8d600160405180896001600160a01b031681526020018881526020018781526020018660ff1681526020018560ff16815260200184815260200183815260200182151581526020019850505050505050505060405180910390a35b50505b611303565b604080517f40c10f19000000000000000000000000000000000000000000000000000000008152306004820152602481018b905290516001600160a01b038c16916340c10f1991604480830192600092919082900301818387803b15801561124c57600080fd5b505af1158015611260573d6000803e3d6000fd5b5050505061127b8b610e3d8a8c61313f90919063ffffffff16565b816001600160a01b038c167f4f56ec39e98539920503fd54ee56ae0cbebe9eb15aa778f18de67701eeae7c658c6112b28d8d61313f565b604080516001600160a01b03909316835260208301919091528181018d905260ff808c1660608401528a16608083015260a0820189905260c08201889052600060e083015251908190036101000190a35b50506001606555505050505050505050565b6002606554141561136d576040805162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604482015290519081900360640190fd5b600260655561137a611e1c565b156113cc576040805162461bcd60e51b815260206004820152601060248201527f5061757361626c653a2070617573656400000000000000000000000000000000604482015290519081900360640190fd5b6113f67fb5c00e6706c3d213edd70ff33717fac657eacc5fe161f07180cf1fcab13cc4cd33612291565b611447576040805162461bcd60e51b815260206004820152601a60248201527f43616c6c6572206973206e6f742061206e6f64652067726f7570000000000000604482015290519081900360640190fd5b81831161149b576040805162461bcd60e51b815260206004820152601f60248201527f416d6f756e74206d7573742062652067726561746572207468616e2066656500604482015290519081900360640190fd5b600081815260cd602052604090205460ff16156114ff576040805162461bcd60e51b815260206004820152601860248201527f4b6170706120697320616c72656164792070726573656e740000000000000000604482015290519081900360640190fd5b600081815260cd60209081526040808320805460ff191660011790556001600160a01b038716835260c990915290205461153990836130e5565b6001600160a01b03808616600081815260c9602052604090209290925560cc5416148015611571575060cc546001600160a01b031615155b156116e35760cc546001600160a01b0316632e1a7d4d611591858561313f565b6040518263ffffffff1660e01b815260040180828152602001915050600060405180830381600087803b1580156115c757600080fd5b505af11580156115db573d6000803e3d6000fd5b506000925050506001600160a01b0386166115f6858561313f565b604051600081818185875af1925050503d8060008114611632576040519150601f19603f3d011682016040523d82523d6000602084013e611637565b606091505b505090508061168d576040805162461bcd60e51b815260206004820152601360248201527f4554485f5452414e534645525f4641494c454400000000000000000000000000604482015290519081900360640190fd5b604080516001600160a01b03878116825260208201879052818301869052915184928916917f8b0afdc777af6946e53045a4a75212769075d30455a212ac51c9b16f9c5c9b26919081900360600190a350611752565b604080516001600160a01b03868116825260208201869052818301859052915183928816917f8b0afdc777af6946e53045a4a75212769075d30455a212ac51c9b16f9c5c9b26919081900360600190a361175285611741858561313f565b6001600160a01b03871691906132bb565b50506001606555505050565b600260655414156117b6576040805162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604482015290519081900360640190fd5b60026065556117c3611e1c565b15611815576040805162461bcd60e51b815260206004820152601060248201527f5061757361626c653a2070617573656400000000000000000000000000000000604482015290519081900360640190fd5b61183f7fb5c00e6706c3d213edd70ff33717fac657eacc5fe161f07180cf1fcab13cc4cd33612291565b611890576040805162461bcd60e51b815260206004820152601a60248201527f43616c6c6572206973206e6f742061206e6f64652067726f7570000000000000604482015290519081900360640190fd5b8183116118e4576040805162461bcd60e51b815260206004820152601f60248201527f416d6f756e74206d7573742062652067726561746572207468616e2066656500604482015290519081900360640190fd5b600081815260cd602052604090205460ff1615611948576040805162461bcd60e51b815260206004820152601860248201527f4b6170706120697320616c72656164792070726573656e740000000000000000604482015290519081900360640190fd5b600081815260cd60209081526040808320805460ff191660011790556001600160a01b038716835260c990915290205461198290836130e5565b6001600160a01b03808616600090815260c96020526040902091909155819086167fbf14b9fde87f6e1c29a7e0787ad1d0d64b4648d8ae63da21524d9fd0f283dd38866119cf878761313f565b604080516001600160a01b0390931683526020830191909152818101879052519081900360600190a3604080517f40c10f190000000000000000000000000000000000000000000000000000000081523060048201526024810185905290516001600160a01b038616916340c10f1991604480830192600092919082900301818387803b158015611a5f57600080fd5b505af1158015611a73573d6000803e3d6000fd5b50505050611a8e85611741848661313f90919063ffffffff16565b60cb5415801590611aa0575060cb5447115b156117525760cb546040516001600160a01b0387169190600081818185875af1925050503d8060008114611af0576040519150601f19603f3d011682016040523d82523d6000602084013e611af5565b606091505b50505050506001606555505050565b60009081526033602052604090206002015490565b600082815260336020526040902060020154611b3c90611b3761333b565b612291565b611b775760405162461bcd60e51b815260040180806020018281038252602f815260200180613c8c602f913960400191505060405180910390fd5b611b81828261333f565b5050565b600090815260cd602052604090205460ff1690565b611ba261333b565b6001600160a01b0316816001600160a01b031614611bf15760405162461bcd60e51b815260040180806020018281038252602f815260200180613d69602f913960400191505060405180910390fd5b611b8182826133a8565b60026065541415611c53576040805162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604482015290519081900360640190fd5b6002606555611c60611e1c565b15611cb2576040805162461bcd60e51b815260206004820152601060248201527f5061757361626c653a2070617573656400000000000000000000000000000000604482015290519081900360640190fd5b604080518781526001600160a01b03878116602083015281830187905260ff861660608301526080820185905260a082018490529151918916917f9a7024cde1920aa50cdde09ca396229e8c4d530d5cfdc6233590def70a94408c9181900360c00190a2604080517f79cc67900000000000000000000000000000000000000000000000000000000081523360048201526024810186905290516001600160a01b038716916379cc679091604480830192600092919082900301818387803b158015611d7d57600080fd5b505af1158015611303573d6000803e3d6000fd5b611dbb7f71840dc4906352362b0cdaf79870196c8e42acafade72d5d5a6d59291253ceb133612291565b611e0c576040805162461bcd60e51b815260206004820152600e60248201527f4e6f7420676f7665726e616e6365000000000000000000000000000000000000604482015290519081900360640190fd5b611e14613411565b565b60ca5481565b60975460ff1690565b600054610100900460ff1680611e3e5750611e3e6134ba565b80611e4c575060005460ff16155b611e875760405162461bcd60e51b815260040180806020018281038252602e815260200180613d11602e913960400191505060405180910390fd5b600054610100900460ff16158015611ecf576000805460ff197fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff909116610100171660011790555b4360ca55611ede600033611b77565b611ee66134cb565b8015611f1557600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff1690555b50565b60026065541415611f70576040805162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604482015290519081900360640190fd5b6002606555611f7d611e1c565b15611fcf576040805162461bcd60e51b815260206004820152601060248201527f5061757361626c653a2070617573656400000000000000000000000000000000604482015290519081900360640190fd5b604080518881526001600160a01b03888116602083015281830188905260ff80881660608401528616608083015260a0820185905260c082018490529151918a16917f91f25e9be0134ec851830e0e76dc71e06f9dade75a9b84e9524071dbbc3194259181900360e00190a2604080517f79cc67900000000000000000000000000000000000000000000000000000000081523360048201526024810187905290516001600160a01b038816916379cc679091604480830192600092919082900301818387803b1580156120a257600080fd5b505af11580156120b6573d6000803e3d6000fd5b5050600160655550505050505050505050565b6120f37f71840dc4906352362b0cdaf79870196c8e42acafade72d5d5a6d59291253ceb133612291565b612144576040805162461bcd60e51b815260206004820152600e60248201527f4e6f7420676f7665726e616e6365000000000000000000000000000000000000604482015290519081900360640190fd5b611e14613585565b60008281526033602052604081206121649083613615565b90505b92915050565b600260655414156121c5576040805162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604482015290519081900360640190fd5b60026065556121d2611e1c565b15612224576040805162461bcd60e51b815260206004820152601060248201527f5061757361626c653a2070617573656400000000000000000000000000000000604482015290519081900360640190fd5b604080518481526001600160a01b0384811660208301528183018490529151918616917fda5273705dbef4bf1b902a131c2eac086b7e1476a8ab0cb4da08af1fe1bd8e3b9181900360600190a26122866001600160a01b038316333084613621565b505060016065555050565b600082815260336020526040812061216490836136a9565b60026065541415612301576040805162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604482015290519081900360640190fd5b600260655561230e611e1c565b15612360576040805162461bcd60e51b815260206004820152601060248201527f5061757361626c653a2070617573656400000000000000000000000000000000604482015290519081900360640190fd5b604080518481526001600160a01b0384166020820152808201839052905185917f8e57e8c5fea426159af69d47eda6c5052c7605c9f70967cf749d4aa55b70b499919081900360600190a2604080517f79cc67900000000000000000000000000000000000000000000000000000000081523360048201526024810183905290516001600160a01b038416916379cc679091604480830192600092919082900301818387803b15801561241257600080fd5b505af1158015612426573d6000803e3d6000fd5b50506001606555505050505050565b600081565b60026065541415612492576040805162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604482015290519081900360640190fd5b600260655561249f611e1c565b156124f1576040805162461bcd60e51b815260206004820152601060248201527f5061757361626c653a2070617573656400000000000000000000000000000000604482015290519081900360640190fd5b604080518881526001600160a01b03888116602083015281830188905260ff80881660608401528616608083015260a0820185905260c082018490529151918a16917f79c15604b92ef54d3f61f0c40caab8857927ca3d5092367163b4562c1699eb5f9181900360e00190a26124266001600160a01b038716333088613621565b61257d600033612291565b6125ce576040805162461bcd60e51b815260206004820152600960248201527f4e6f742061646d696e0000000000000000000000000000000000000000000000604482015290519081900360640190fd5b60cc80547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0392909216919091179055565b600681565b6126377f71840dc4906352362b0cdaf79870196c8e42acafade72d5d5a6d59291253ceb133612291565b612688576040805162461bcd60e51b815260206004820152600e60248201527f4e6f7420676f7665726e616e6365000000000000000000000000000000000000604482015290519081900360640190fd5b60cb55565b6001600160a01b0316600090815260c9602052604090205490565b6000818152603360205260408120612167906136be565b6000828152603360205260409020600201546126dd90611b3761333b565b611bf15760405162461bcd60e51b8152600401808060200182810382526030815260200180613ce16030913960400191505060405180910390fd5b60026065541415612770576040805162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604482015290519081900360640190fd5b600260655561277d611e1c565b156127cf576040805162461bcd60e51b815260206004820152601060248201527f5061757361626c653a2070617573656400000000000000000000000000000000604482015290519081900360640190fd5b6127f97fb5c00e6706c3d213edd70ff33717fac657eacc5fe161f07180cf1fcab13cc4cd33612291565b61284a576040805162461bcd60e51b815260206004820152601a60248201527f43616c6c6572206973206e6f742061206e6f64652067726f7570000000000000604482015290519081900360640190fd5b85871161289e576040805162461bcd60e51b815260206004820152601f60248201527f416d6f756e74206d7573742062652067726561746572207468616e2066656500604482015290519081900360640190fd5b600081815260cd602052604090205460ff1615612902576040805162461bcd60e51b815260206004820152601860248201527f4b6170706120697320616c72656164792070726573656e740000000000000000604482015290519081900360640190fd5b600081815260cd60209081526040808320805460ff191660011790556001600160a01b038b16835260c990915290205461293c90876130e5565b6001600160a01b03808a16600090815260c96020526040812092909255861663342a87a161296a8a8a61313f565b876040518363ffffffff1660e01b8152600401808381526020018260ff1681526020019250505060206040518083038186803b1580156129a957600080fd5b505afa1580156129bd573d6000803e3d6000fd5b505050506040513d60208110156129d357600080fd5b50519050838110612c33576129fd866129ec8a8a61313f565b6001600160a01b038c16919061319c565b6001600160a01b038616633e3a1560612a168a8a61313f565b8787876040518563ffffffff1660e01b8152600401808581526020018460ff168152602001838152602001828152602001945050505050602060405180830381600087803b158015612a6757600080fd5b505af1925050508015612a8c57506040513d6020811015612a8757600080fd5b505160015b612b3257612aaf8a612a9e8a8a61313f565b6001600160a01b038c1691906132bb565b816001600160a01b038b167fc1a608d0f8122d014d03cc915a91d98cef4ebaf31ea3552320430cba05211b6d8b612ae68c8c61313f565b604080516001600160a01b03909316835260208301919091528181018c905260ff8a1660608301526080820189905260a08201889052600060c0830152519081900360e00190a3612c2e565b6000876001600160a01b03166382b86600886040518263ffffffff1660e01b8152600401808260ff16815260200191505060206040518083038186803b158015612b7b57600080fd5b505afa158015612b8f573d6000803e3d6000fd5b505050506040513d6020811015612ba557600080fd5b50519050612bbd6001600160a01b0382168d846132bb565b604080516001600160a01b038d81168252602082018590528183018c905260ff8a1660608301526080820189905260a08201889052600160c0830152915186928f16917fc1a608d0f8122d014d03cc915a91d98cef4ebaf31ea3552320430cba05211b6d919081900360e00190a350505b612cc0565b612c418a612a9e8a8a61313f565b816001600160a01b038b167fc1a608d0f8122d014d03cc915a91d98cef4ebaf31ea3552320430cba05211b6d8b612c788c8c61313f565b604080516001600160a01b03909316835260208301919091528181018c905260ff8a1660608301526080820189905260a08201889052600060c0830152519081900360e00190a35b505060016065555050505050505050565b60cb5481565b612d017f71840dc4906352362b0cdaf79870196c8e42acafade72d5d5a6d59291253ceb133612291565b612d52576040805162461bcd60e51b815260206004820152600e60248201527f4e6f7420676f7665726e616e6365000000000000000000000000000000000000604482015290519081900360640190fd5b60005b81811015612d9f57600160cd6000858585818110612d6f57fe5b60209081029290920135835250810191909152604001600020805460ff1916911515919091179055600101612d55565b505050565b612dac611e1c565b15612dfe576040805162461bcd60e51b815260206004820152601060248201527f5061757361626c653a2070617573656400000000000000000000000000000000604482015290519081900360640190fd5b612e287f71840dc4906352362b0cdaf79870196c8e42acafade72d5d5a6d59291253ceb133612291565b612e79576040805162461bcd60e51b815260206004820152600e60248201527f4e6f7420676f7665726e616e6365000000000000000000000000000000000000604482015290519081900360640190fd5b6001600160a01b038116612ed4576040805162461bcd60e51b815260206004820152601060248201527f4164647265737320697320307830303000000000000000000000000000000000604482015290519081900360640190fd5b6001600160a01b038216600090815260c9602052604090205415611b81576001600160a01b038216600081815260c96020526040902054612f17919083906132bb565b506001600160a01b0316600090815260c96020526040812055565b7f71840dc4906352362b0cdaf79870196c8e42acafade72d5d5a6d59291253ceb181565b7fb5c00e6706c3d213edd70ff33717fac657eacc5fe161f07180cf1fcab13cc4cd81565b60026065541415612fd2576040805162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604482015290519081900360640190fd5b6002606555612fdf611e1c565b15613031576040805162461bcd60e51b815260206004820152601060248201527f5061757361626c653a2070617573656400000000000000000000000000000000604482015290519081900360640190fd5b604080518481526001600160a01b0384811660208301528183018490529151918616917fdc5bad4651c5fbe9977a696aadc65996c468cde1448dd468ec0d83bf61c4b57c9181900360600190a2604080517f79cc67900000000000000000000000000000000000000000000000000000000081523360048201526024810183905290516001600160a01b038416916379cc679091604480830192600092919082900301818387803b15801561241257600080fd5b600082820183811015612164576040805162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b600082821115613196576040805162461bcd60e51b815260206004820152601e60248201527f536166654d6174683a207375627472616374696f6e206f766572666c6f770000604482015290519081900360640190fd5b50900390565b600061323282856001600160a01b031663dd62ed3e30876040518363ffffffff1660e01b815260040180836001600160a01b03168152602001826001600160a01b031681526020019250505060206040518083038186803b15801561320057600080fd5b505afa158015613214573d6000803e3d6000fd5b505050506040513d602081101561322a57600080fd5b5051906130e5565b604080516001600160a01b038616602482015260448082018490528251808303909101815260649091019091526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f095ea7b3000000000000000000000000000000000000000000000000000000001790529091506132b59085906136c9565b50505050565b604080516001600160a01b038416602482015260448082018490528251808303909101815260649091019091526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fa9059cbb00000000000000000000000000000000000000000000000000000000179052612d9f9084906136c9565b3390565b6000828152603360205260409020613357908261377a565b15611b815761336461333b565b6001600160a01b0316816001600160a01b0316837f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a45050565b60008281526033602052604090206133c0908261378f565b15611b81576133cd61333b565b6001600160a01b0316816001600160a01b0316837ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b60405160405180910390a45050565b613419611e1c565b61346a576040805162461bcd60e51b815260206004820152601460248201527f5061757361626c653a206e6f7420706175736564000000000000000000000000604482015290519081900360640190fd5b6097805460ff191690557f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa61349d61333b565b604080516001600160a01b039092168252519081900360200190a1565b60006134c5306137a4565b15905090565b600054610100900460ff16806134e457506134e46134ba565b806134f2575060005460ff16155b61352d5760405162461bcd60e51b815260040180806020018281038252602e815260200180613d11602e913960400191505060405180910390fd5b600054610100900460ff16158015613575576000805460ff197fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff909116610100171660011790555b61357d6137aa565b611ee66137aa565b61358d611e1c565b156135df576040805162461bcd60e51b815260206004820152601060248201527f5061757361626c653a2070617573656400000000000000000000000000000000604482015290519081900360640190fd5b6097805460ff191660011790557f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a25861349d61333b565b60006121648383613884565b604080516001600160a01b0380861660248301528416604482015260648082018490528251808303909101815260849091019091526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f23b872dd000000000000000000000000000000000000000000000000000000001790526132b59085906136c9565b6000612164836001600160a01b0384166138e8565b600061216782613900565b606061371e826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b03166139049092919063ffffffff16565b805190915015612d9f5780806020019051602081101561373d57600080fd5b5051612d9f5760405162461bcd60e51b815260040180806020018281038252602a815260200180613d3f602a913960400191505060405180910390fd5b6000612164836001600160a01b03841661391d565b6000612164836001600160a01b038416613967565b3b151590565b600054610100900460ff16806137c357506137c36134ba565b806137d1575060005460ff16155b61380c5760405162461bcd60e51b815260040180806020018281038252602e815260200180613d11602e913960400191505060405180910390fd5b600054610100900460ff16158015611ee6576000805460ff197fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff909116610100171660011790558015611f1557600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff16905550565b815460009082106138c65760405162461bcd60e51b8152600401808060200182810382526022815260200180613c6a6022913960400191505060405180910390fd5b8260000182815481106138d557fe5b9060005260206000200154905092915050565b60009081526001919091016020526040902054151590565b5490565b60606139138484600085613a4b565b90505b9392505050565b600061392983836138e8565b61395f57508154600181810184556000848152602080822090930184905584548482528286019093526040902091909155612167565b506000612167565b60008181526001830160205260408120548015613a415783547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff80830191908101906000908790839081106139b857fe5b90600052602060002001549050808760000184815481106139d557fe5b600091825260208083209091019290925582815260018981019092526040902090840190558654879080613a0557fe5b60019003818190600052602060002001600090559055866001016000878152602001908152602001600020600090556001945050505050612167565b6000915050612167565b606082471015613a8c5760405162461bcd60e51b8152600401808060200182810382526026815260200180613cbb6026913960400191505060405180910390fd5b613a95856137a4565b613ae6576040805162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000604482015290519081900360640190fd5b60006060866001600160a01b031685876040518082805190602001908083835b60208310613b4357805182527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe09092019160209182019101613b06565b6001836020036101000a03801982511681845116808217855250505050505090500191505060006040518083038185875af1925050503d8060008114613ba5576040519150601f19603f3d011682016040523d82523d6000602084013e613baa565b606091505b5091509150613bba828286613bc5565b979650505050505050565b60608315613bd4575081613916565b825115613be45782518084602001fd5b8160405162461bcd60e51b81526004018080602001828103825283818151815260200191508051906020019080838360005b83811015613c2e578181015183820152602001613c16565b50505050905090810190601f168015613c5b5780820380516001836020036101000a031916815260200191505b509250505060405180910390fdfe456e756d657261626c655365743a20696e646578206f7574206f6620626f756e6473416363657373436f6e74726f6c3a2073656e646572206d75737420626520616e2061646d696e20746f206772616e74416464726573733a20696e73756666696369656e742062616c616e636520666f722063616c6c416363657373436f6e74726f6c3a2073656e646572206d75737420626520616e2061646d696e20746f207265766f6b65496e697469616c697a61626c653a20636f6e747261637420697320616c726561647920696e697469616c697a65645361666545524332303a204552433230206f7065726174696f6e20646964206e6f742073756363656564416363657373436f6e74726f6c3a2063616e206f6e6c792072656e6f756e636520726f6c657320666f722073656c66a2646970667358221220c7ddf348db774832685d2f2e6488cabd308328f57ce2f579e76377741d2db00f64736f6c634300060c0033", + "deployedBytecode": "0x60806040526004361061021d5760003560e01c806391d148541161011d578063ca15c873116100b0578063e7a599981161007f578063f36c8f5c11610064578063f36c8f5c1461093b578063f3befd0114610950578063f3f094a11461096557610224565b8063e7a5999814610883578063f25552781461090057610224565b8063ca15c8731461079f578063d547741f146107c9578063d57eafac14610802578063e00a83e01461086e57610224565b8063a96e2423116100ec578063a96e2423146106fa578063ac8656261461072d578063b250fe6b14610742578063c78f68031461076c57610224565b806391d1485414610600578063a07ed97514610639578063a217fddf1461067e578063a2a2af0b1461069357610224565b806336e712ed116101b05780638129fc1c1161017f5780638456cb59116101645780638456cb59146105745780639010d07c1461058957806390d25074146105b957610224565b80638129fc1c146104f8578063839ed90a1461050d57610224565b806336e712ed1461045d5780633f4ba83a146104b9578063498a4c2d146104ce5780635c975abb146104e357610224565b8063248a9ca3116101ec578063248a9ca3146103715780632f2ff15d146103ad5780632fe87b95146103e657806336568abe1461042457610224565b8063040141e514610229578063173578921461025a5780631cf5f07f146102d357806320d7b3271461032257610224565b3661022457005b600080fd5b34801561023557600080fd5b5061023e6109ac565b604080516001600160a01b039092168252519081900360200190f35b34801561026657600080fd5b506102d1600480360361014081101561027e57600080fd5b506001600160a01b03813581169160208101358216916040820135916060810135916080820135169060ff60a082013581169160c08101359091169060e0810135906101008101359061012001356109bb565b005b3480156102df57600080fd5b506102d1600480360360a08110156102f657600080fd5b506001600160a01b03813581169160208101359091169060408101359060608101359060800135611315565b34801561032e57600080fd5b506102d1600480360360a081101561034557600080fd5b506001600160a01b0381358116916020810135909116906040810135906060810135906080013561175e565b34801561037d57600080fd5b5061039b6004803603602081101561039457600080fd5b5035611b04565b60408051918252519081900360200190f35b3480156103b957600080fd5b506102d1600480360360408110156103d057600080fd5b50803590602001356001600160a01b0316611b19565b3480156103f257600080fd5b506104106004803603602081101561040957600080fd5b5035611b85565b604080519115158252519081900360200190f35b34801561043057600080fd5b506102d16004803603604081101561044757600080fd5b50803590602001356001600160a01b0316611b9a565b34801561046957600080fd5b506102d1600480360360e081101561048057600080fd5b506001600160a01b0381358116916020810135916040820135169060608101359060ff6080820135169060a08101359060c00135611bfb565b3480156104c557600080fd5b506102d1611d91565b3480156104da57600080fd5b5061039b611e16565b3480156104ef57600080fd5b50610410611e1c565b34801561050457600080fd5b506102d1611e25565b34801561051957600080fd5b506102d1600480360361010081101561053157600080fd5b506001600160a01b0381358116916020810135916040820135169060608101359060ff608082013581169160a08101359091169060c08101359060e00135611f18565b34801561058057600080fd5b506102d16120c9565b34801561059557600080fd5b5061023e600480360360408110156105ac57600080fd5b508035906020013561214c565b3480156105c557600080fd5b506102d1600480360360808110156105dc57600080fd5b506001600160a01b038135811691602081013591604082013516906060013561216d565b34801561060c57600080fd5b506104106004803603604081101561062357600080fd5b50803590602001356001600160a01b0316612291565b34801561064557600080fd5b506102d16004803603608081101561065c57600080fd5b508035906020810135906001600160a01b0360408201351690606001356122a9565b34801561068a57600080fd5b5061039b612435565b34801561069f57600080fd5b506102d160048036036101008110156106b757600080fd5b506001600160a01b0381358116916020810135916040820135169060608101359060ff608082013581169160a08101359091169060c08101359060e0013561243a565b34801561070657600080fd5b506102d16004803603602081101561071d57600080fd5b50356001600160a01b0316612572565b34801561073957600080fd5b5061039b612608565b34801561074e57600080fd5b506102d16004803603602081101561076557600080fd5b503561260d565b34801561077857600080fd5b5061039b6004803603602081101561078f57600080fd5b50356001600160a01b031661268d565b3480156107ab57600080fd5b5061039b600480360360208110156107c257600080fd5b50356126a8565b3480156107d557600080fd5b506102d1600480360360408110156107ec57600080fd5b50803590602001356001600160a01b03166126bf565b34801561080e57600080fd5b506102d1600480360361012081101561082657600080fd5b506001600160a01b03813581169160208101358216916040820135916060810135916080820135169060ff60a0820135169060c08101359060e0810135906101000135612718565b34801561087a57600080fd5b5061039b612cd1565b34801561088f57600080fd5b506102d1600480360360208110156108a657600080fd5b8101906020810181356401000000008111156108c157600080fd5b8201836020820111156108d357600080fd5b803590602001918460208302840111640100000000831117156108f557600080fd5b509092509050612cd7565b34801561090c57600080fd5b506102d16004803603604081101561092357600080fd5b506001600160a01b0381358116916020013516612da4565b34801561094757600080fd5b5061039b612f32565b34801561095c57600080fd5b5061039b612f56565b34801561097157600080fd5b506102d16004803603608081101561098857600080fd5b506001600160a01b0381358116916020810135916040820135169060600135612f7a565b60cc546001600160a01b031681565b60026065541415610a13576040805162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604482015290519081900360640190fd5b6002606555610a20611e1c565b15610a72576040805162461bcd60e51b815260206004820152601060248201527f5061757361626c653a2070617573656400000000000000000000000000000000604482015290519081900360640190fd5b610a9c7fb5c00e6706c3d213edd70ff33717fac657eacc5fe161f07180cf1fcab13cc4cd33612291565b610aed576040805162461bcd60e51b815260206004820152601a60248201527f43616c6c6572206973206e6f742061206e6f64652067726f7570000000000000604482015290519081900360640190fd5b868811610b41576040805162461bcd60e51b815260206004820152601f60248201527f416d6f756e74206d7573742062652067726561746572207468616e2066656500604482015290519081900360640190fd5b600081815260cd602052604090205460ff1615610ba5576040805162461bcd60e51b815260206004820152601860248201527f4b6170706120697320616c72656164792070726573656e740000000000000000604482015290519081900360640190fd5b600081815260cd60209081526040808320805460ff191660011790556001600160a01b038c16835260c9909152902054610bdf90886130e5565b6001600160a01b038a16600090815260c9602052604090205560cb5415801590610c0a575060cb5447115b15610c635760cb546040516001600160a01b038c169190600081818185875af1925050503d8060008114610c5a576040519150601f19603f3d011682016040523d82523d6000602084013e610c5f565b606091505b5050505b60006001600160a01b03871663a95b089f8787610c808d8d61313f565b6040518463ffffffff1660e01b8152600401808460ff1681526020018360ff168152602001828152602001935050505060206040518083038186803b158015610cc857600080fd5b505afa158015610cdc573d6000803e3d6000fd5b505050506040513d6020811015610cf257600080fd5b505190508381106111e557604080517f40c10f19000000000000000000000000000000000000000000000000000000008152306004820152602481018b905290516001600160a01b038c16916340c10f1991604480830192600092919082900301818387803b158015610d6457600080fd5b505af1158015610d78573d6000803e3d6000fd5b50610d91925050506001600160a01b038b16888b61319c565b6001600160a01b03871663916955868787610dac8d8d61313f565b88886040518663ffffffff1660e01b8152600401808660ff1681526020018560ff16815260200184815260200183815260200182815260200195505050505050602060405180830381600087803b158015610e0657600080fd5b505af1925050508015610e2b57506040513d6020811015610e2657600080fd5b505160015b610eda57610e4e8b610e3d8b8b61313f565b6001600160a01b038d1691906132bb565b816001600160a01b038c167f4f56ec39e98539920503fd54ee56ae0cbebe9eb15aa778f18de67701eeae7c658c610e858d8d61313f565b604080516001600160a01b03909316835260208301919091528181018d905260ff808c1660608401528a16608083015260a0820189905260c08201889052600060e083015251908190036101000190a36111e0565b6000886001600160a01b03166382b86600886040518263ffffffff1660e01b8152600401808260ff16815260200191505060206040518083038186803b158015610f2357600080fd5b505afa158015610f37573d6000803e3d6000fd5b505050506040513d6020811015610f4d57600080fd5b505160cc549091506001600160a01b038083169116148015610f79575060cc546001600160a01b031615155b1561113c5760cc54604080517f2e1a7d4d0000000000000000000000000000000000000000000000000000000081526004810185905290516001600160a01b0390921691632e1a7d4d9160248082019260009290919082900301818387803b158015610fe457600080fd5b505af1158015610ff8573d6000803e3d6000fd5b5050505060008d6001600160a01b03168360405180600001905060006040518083038185875af1925050503d806000811461104f576040519150601f19603f3d011682016040523d82523d6000602084013e611054565b606091505b50509050806110aa576040805162461bcd60e51b815260206004820152601360248201527f4554485f5452414e534645525f4641494c454400000000000000000000000000604482015290519081900360640190fd5b848e6001600160a01b03167f4f56ec39e98539920503fd54ee56ae0cbebe9eb15aa778f18de67701eeae7c658f868f8e8e8e8e600160405180896001600160a01b031681526020018881526020018781526020018660ff1681526020018560ff16815260200184815260200183815260200182151581526020019850505050505050505060405180910390a3506111dd565b6111506001600160a01b0382168e846132bb565b838d6001600160a01b03167f4f56ec39e98539920503fd54ee56ae0cbebe9eb15aa778f18de67701eeae7c658e858e8d8d8d8d600160405180896001600160a01b031681526020018881526020018781526020018660ff1681526020018560ff16815260200184815260200183815260200182151581526020019850505050505050505060405180910390a35b50505b611303565b604080517f40c10f19000000000000000000000000000000000000000000000000000000008152306004820152602481018b905290516001600160a01b038c16916340c10f1991604480830192600092919082900301818387803b15801561124c57600080fd5b505af1158015611260573d6000803e3d6000fd5b5050505061127b8b610e3d8a8c61313f90919063ffffffff16565b816001600160a01b038c167f4f56ec39e98539920503fd54ee56ae0cbebe9eb15aa778f18de67701eeae7c658c6112b28d8d61313f565b604080516001600160a01b03909316835260208301919091528181018d905260ff808c1660608401528a16608083015260a0820189905260c08201889052600060e083015251908190036101000190a35b50506001606555505050505050505050565b6002606554141561136d576040805162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604482015290519081900360640190fd5b600260655561137a611e1c565b156113cc576040805162461bcd60e51b815260206004820152601060248201527f5061757361626c653a2070617573656400000000000000000000000000000000604482015290519081900360640190fd5b6113f67fb5c00e6706c3d213edd70ff33717fac657eacc5fe161f07180cf1fcab13cc4cd33612291565b611447576040805162461bcd60e51b815260206004820152601a60248201527f43616c6c6572206973206e6f742061206e6f64652067726f7570000000000000604482015290519081900360640190fd5b81831161149b576040805162461bcd60e51b815260206004820152601f60248201527f416d6f756e74206d7573742062652067726561746572207468616e2066656500604482015290519081900360640190fd5b600081815260cd602052604090205460ff16156114ff576040805162461bcd60e51b815260206004820152601860248201527f4b6170706120697320616c72656164792070726573656e740000000000000000604482015290519081900360640190fd5b600081815260cd60209081526040808320805460ff191660011790556001600160a01b038716835260c990915290205461153990836130e5565b6001600160a01b03808616600081815260c9602052604090209290925560cc5416148015611571575060cc546001600160a01b031615155b156116e35760cc546001600160a01b0316632e1a7d4d611591858561313f565b6040518263ffffffff1660e01b815260040180828152602001915050600060405180830381600087803b1580156115c757600080fd5b505af11580156115db573d6000803e3d6000fd5b506000925050506001600160a01b0386166115f6858561313f565b604051600081818185875af1925050503d8060008114611632576040519150601f19603f3d011682016040523d82523d6000602084013e611637565b606091505b505090508061168d576040805162461bcd60e51b815260206004820152601360248201527f4554485f5452414e534645525f4641494c454400000000000000000000000000604482015290519081900360640190fd5b604080516001600160a01b03878116825260208201879052818301869052915184928916917f8b0afdc777af6946e53045a4a75212769075d30455a212ac51c9b16f9c5c9b26919081900360600190a350611752565b604080516001600160a01b03868116825260208201869052818301859052915183928816917f8b0afdc777af6946e53045a4a75212769075d30455a212ac51c9b16f9c5c9b26919081900360600190a361175285611741858561313f565b6001600160a01b03871691906132bb565b50506001606555505050565b600260655414156117b6576040805162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604482015290519081900360640190fd5b60026065556117c3611e1c565b15611815576040805162461bcd60e51b815260206004820152601060248201527f5061757361626c653a2070617573656400000000000000000000000000000000604482015290519081900360640190fd5b61183f7fb5c00e6706c3d213edd70ff33717fac657eacc5fe161f07180cf1fcab13cc4cd33612291565b611890576040805162461bcd60e51b815260206004820152601a60248201527f43616c6c6572206973206e6f742061206e6f64652067726f7570000000000000604482015290519081900360640190fd5b8183116118e4576040805162461bcd60e51b815260206004820152601f60248201527f416d6f756e74206d7573742062652067726561746572207468616e2066656500604482015290519081900360640190fd5b600081815260cd602052604090205460ff1615611948576040805162461bcd60e51b815260206004820152601860248201527f4b6170706120697320616c72656164792070726573656e740000000000000000604482015290519081900360640190fd5b600081815260cd60209081526040808320805460ff191660011790556001600160a01b038716835260c990915290205461198290836130e5565b6001600160a01b03808616600090815260c96020526040902091909155819086167fbf14b9fde87f6e1c29a7e0787ad1d0d64b4648d8ae63da21524d9fd0f283dd38866119cf878761313f565b604080516001600160a01b0390931683526020830191909152818101879052519081900360600190a3604080517f40c10f190000000000000000000000000000000000000000000000000000000081523060048201526024810185905290516001600160a01b038616916340c10f1991604480830192600092919082900301818387803b158015611a5f57600080fd5b505af1158015611a73573d6000803e3d6000fd5b50505050611a8e85611741848661313f90919063ffffffff16565b60cb5415801590611aa0575060cb5447115b156117525760cb546040516001600160a01b0387169190600081818185875af1925050503d8060008114611af0576040519150601f19603f3d011682016040523d82523d6000602084013e611af5565b606091505b50505050506001606555505050565b60009081526033602052604090206002015490565b600082815260336020526040902060020154611b3c90611b3761333b565b612291565b611b775760405162461bcd60e51b815260040180806020018281038252602f815260200180613c8c602f913960400191505060405180910390fd5b611b81828261333f565b5050565b600090815260cd602052604090205460ff1690565b611ba261333b565b6001600160a01b0316816001600160a01b031614611bf15760405162461bcd60e51b815260040180806020018281038252602f815260200180613d69602f913960400191505060405180910390fd5b611b8182826133a8565b60026065541415611c53576040805162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604482015290519081900360640190fd5b6002606555611c60611e1c565b15611cb2576040805162461bcd60e51b815260206004820152601060248201527f5061757361626c653a2070617573656400000000000000000000000000000000604482015290519081900360640190fd5b604080518781526001600160a01b03878116602083015281830187905260ff861660608301526080820185905260a082018490529151918916917f9a7024cde1920aa50cdde09ca396229e8c4d530d5cfdc6233590def70a94408c9181900360c00190a2604080517f79cc67900000000000000000000000000000000000000000000000000000000081523360048201526024810186905290516001600160a01b038716916379cc679091604480830192600092919082900301818387803b158015611d7d57600080fd5b505af1158015611303573d6000803e3d6000fd5b611dbb7f71840dc4906352362b0cdaf79870196c8e42acafade72d5d5a6d59291253ceb133612291565b611e0c576040805162461bcd60e51b815260206004820152600e60248201527f4e6f7420676f7665726e616e6365000000000000000000000000000000000000604482015290519081900360640190fd5b611e14613411565b565b60ca5481565b60975460ff1690565b600054610100900460ff1680611e3e5750611e3e6134ba565b80611e4c575060005460ff16155b611e875760405162461bcd60e51b815260040180806020018281038252602e815260200180613d11602e913960400191505060405180910390fd5b600054610100900460ff16158015611ecf576000805460ff197fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff909116610100171660011790555b4360ca55611ede600033611b77565b611ee66134cb565b8015611f1557600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff1690555b50565b60026065541415611f70576040805162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604482015290519081900360640190fd5b6002606555611f7d611e1c565b15611fcf576040805162461bcd60e51b815260206004820152601060248201527f5061757361626c653a2070617573656400000000000000000000000000000000604482015290519081900360640190fd5b604080518881526001600160a01b03888116602083015281830188905260ff80881660608401528616608083015260a0820185905260c082018490529151918a16917f91f25e9be0134ec851830e0e76dc71e06f9dade75a9b84e9524071dbbc3194259181900360e00190a2604080517f79cc67900000000000000000000000000000000000000000000000000000000081523360048201526024810187905290516001600160a01b038816916379cc679091604480830192600092919082900301818387803b1580156120a257600080fd5b505af11580156120b6573d6000803e3d6000fd5b5050600160655550505050505050505050565b6120f37f71840dc4906352362b0cdaf79870196c8e42acafade72d5d5a6d59291253ceb133612291565b612144576040805162461bcd60e51b815260206004820152600e60248201527f4e6f7420676f7665726e616e6365000000000000000000000000000000000000604482015290519081900360640190fd5b611e14613585565b60008281526033602052604081206121649083613615565b90505b92915050565b600260655414156121c5576040805162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604482015290519081900360640190fd5b60026065556121d2611e1c565b15612224576040805162461bcd60e51b815260206004820152601060248201527f5061757361626c653a2070617573656400000000000000000000000000000000604482015290519081900360640190fd5b604080518481526001600160a01b0384811660208301528183018490529151918616917fda5273705dbef4bf1b902a131c2eac086b7e1476a8ab0cb4da08af1fe1bd8e3b9181900360600190a26122866001600160a01b038316333084613621565b505060016065555050565b600082815260336020526040812061216490836136a9565b60026065541415612301576040805162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604482015290519081900360640190fd5b600260655561230e611e1c565b15612360576040805162461bcd60e51b815260206004820152601060248201527f5061757361626c653a2070617573656400000000000000000000000000000000604482015290519081900360640190fd5b604080518481526001600160a01b0384166020820152808201839052905185917f8e57e8c5fea426159af69d47eda6c5052c7605c9f70967cf749d4aa55b70b499919081900360600190a2604080517f79cc67900000000000000000000000000000000000000000000000000000000081523360048201526024810183905290516001600160a01b038416916379cc679091604480830192600092919082900301818387803b15801561241257600080fd5b505af1158015612426573d6000803e3d6000fd5b50506001606555505050505050565b600081565b60026065541415612492576040805162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604482015290519081900360640190fd5b600260655561249f611e1c565b156124f1576040805162461bcd60e51b815260206004820152601060248201527f5061757361626c653a2070617573656400000000000000000000000000000000604482015290519081900360640190fd5b604080518881526001600160a01b03888116602083015281830188905260ff80881660608401528616608083015260a0820185905260c082018490529151918a16917f79c15604b92ef54d3f61f0c40caab8857927ca3d5092367163b4562c1699eb5f9181900360e00190a26124266001600160a01b038716333088613621565b61257d600033612291565b6125ce576040805162461bcd60e51b815260206004820152600960248201527f4e6f742061646d696e0000000000000000000000000000000000000000000000604482015290519081900360640190fd5b60cc80547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0392909216919091179055565b600681565b6126377f71840dc4906352362b0cdaf79870196c8e42acafade72d5d5a6d59291253ceb133612291565b612688576040805162461bcd60e51b815260206004820152600e60248201527f4e6f7420676f7665726e616e6365000000000000000000000000000000000000604482015290519081900360640190fd5b60cb55565b6001600160a01b0316600090815260c9602052604090205490565b6000818152603360205260408120612167906136be565b6000828152603360205260409020600201546126dd90611b3761333b565b611bf15760405162461bcd60e51b8152600401808060200182810382526030815260200180613ce16030913960400191505060405180910390fd5b60026065541415612770576040805162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604482015290519081900360640190fd5b600260655561277d611e1c565b156127cf576040805162461bcd60e51b815260206004820152601060248201527f5061757361626c653a2070617573656400000000000000000000000000000000604482015290519081900360640190fd5b6127f97fb5c00e6706c3d213edd70ff33717fac657eacc5fe161f07180cf1fcab13cc4cd33612291565b61284a576040805162461bcd60e51b815260206004820152601a60248201527f43616c6c6572206973206e6f742061206e6f64652067726f7570000000000000604482015290519081900360640190fd5b85871161289e576040805162461bcd60e51b815260206004820152601f60248201527f416d6f756e74206d7573742062652067726561746572207468616e2066656500604482015290519081900360640190fd5b600081815260cd602052604090205460ff1615612902576040805162461bcd60e51b815260206004820152601860248201527f4b6170706120697320616c72656164792070726573656e740000000000000000604482015290519081900360640190fd5b600081815260cd60209081526040808320805460ff191660011790556001600160a01b038b16835260c990915290205461293c90876130e5565b6001600160a01b03808a16600090815260c96020526040812092909255861663342a87a161296a8a8a61313f565b876040518363ffffffff1660e01b8152600401808381526020018260ff1681526020019250505060206040518083038186803b1580156129a957600080fd5b505afa1580156129bd573d6000803e3d6000fd5b505050506040513d60208110156129d357600080fd5b50519050838110612c33576129fd866129ec8a8a61313f565b6001600160a01b038c16919061319c565b6001600160a01b038616633e3a1560612a168a8a61313f565b8787876040518563ffffffff1660e01b8152600401808581526020018460ff168152602001838152602001828152602001945050505050602060405180830381600087803b158015612a6757600080fd5b505af1925050508015612a8c57506040513d6020811015612a8757600080fd5b505160015b612b3257612aaf8a612a9e8a8a61313f565b6001600160a01b038c1691906132bb565b816001600160a01b038b167fc1a608d0f8122d014d03cc915a91d98cef4ebaf31ea3552320430cba05211b6d8b612ae68c8c61313f565b604080516001600160a01b03909316835260208301919091528181018c905260ff8a1660608301526080820189905260a08201889052600060c0830152519081900360e00190a3612c2e565b6000876001600160a01b03166382b86600886040518263ffffffff1660e01b8152600401808260ff16815260200191505060206040518083038186803b158015612b7b57600080fd5b505afa158015612b8f573d6000803e3d6000fd5b505050506040513d6020811015612ba557600080fd5b50519050612bbd6001600160a01b0382168d846132bb565b604080516001600160a01b038d81168252602082018590528183018c905260ff8a1660608301526080820189905260a08201889052600160c0830152915186928f16917fc1a608d0f8122d014d03cc915a91d98cef4ebaf31ea3552320430cba05211b6d919081900360e00190a350505b612cc0565b612c418a612a9e8a8a61313f565b816001600160a01b038b167fc1a608d0f8122d014d03cc915a91d98cef4ebaf31ea3552320430cba05211b6d8b612c788c8c61313f565b604080516001600160a01b03909316835260208301919091528181018c905260ff8a1660608301526080820189905260a08201889052600060c0830152519081900360e00190a35b505060016065555050505050505050565b60cb5481565b612d017f71840dc4906352362b0cdaf79870196c8e42acafade72d5d5a6d59291253ceb133612291565b612d52576040805162461bcd60e51b815260206004820152600e60248201527f4e6f7420676f7665726e616e6365000000000000000000000000000000000000604482015290519081900360640190fd5b60005b81811015612d9f57600160cd6000858585818110612d6f57fe5b60209081029290920135835250810191909152604001600020805460ff1916911515919091179055600101612d55565b505050565b612dac611e1c565b15612dfe576040805162461bcd60e51b815260206004820152601060248201527f5061757361626c653a2070617573656400000000000000000000000000000000604482015290519081900360640190fd5b612e287f71840dc4906352362b0cdaf79870196c8e42acafade72d5d5a6d59291253ceb133612291565b612e79576040805162461bcd60e51b815260206004820152600e60248201527f4e6f7420676f7665726e616e6365000000000000000000000000000000000000604482015290519081900360640190fd5b6001600160a01b038116612ed4576040805162461bcd60e51b815260206004820152601060248201527f4164647265737320697320307830303000000000000000000000000000000000604482015290519081900360640190fd5b6001600160a01b038216600090815260c9602052604090205415611b81576001600160a01b038216600081815260c96020526040902054612f17919083906132bb565b506001600160a01b0316600090815260c96020526040812055565b7f71840dc4906352362b0cdaf79870196c8e42acafade72d5d5a6d59291253ceb181565b7fb5c00e6706c3d213edd70ff33717fac657eacc5fe161f07180cf1fcab13cc4cd81565b60026065541415612fd2576040805162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604482015290519081900360640190fd5b6002606555612fdf611e1c565b15613031576040805162461bcd60e51b815260206004820152601060248201527f5061757361626c653a2070617573656400000000000000000000000000000000604482015290519081900360640190fd5b604080518481526001600160a01b0384811660208301528183018490529151918616917fdc5bad4651c5fbe9977a696aadc65996c468cde1448dd468ec0d83bf61c4b57c9181900360600190a2604080517f79cc67900000000000000000000000000000000000000000000000000000000081523360048201526024810183905290516001600160a01b038416916379cc679091604480830192600092919082900301818387803b15801561241257600080fd5b600082820183811015612164576040805162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b600082821115613196576040805162461bcd60e51b815260206004820152601e60248201527f536166654d6174683a207375627472616374696f6e206f766572666c6f770000604482015290519081900360640190fd5b50900390565b600061323282856001600160a01b031663dd62ed3e30876040518363ffffffff1660e01b815260040180836001600160a01b03168152602001826001600160a01b031681526020019250505060206040518083038186803b15801561320057600080fd5b505afa158015613214573d6000803e3d6000fd5b505050506040513d602081101561322a57600080fd5b5051906130e5565b604080516001600160a01b038616602482015260448082018490528251808303909101815260649091019091526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f095ea7b3000000000000000000000000000000000000000000000000000000001790529091506132b59085906136c9565b50505050565b604080516001600160a01b038416602482015260448082018490528251808303909101815260649091019091526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fa9059cbb00000000000000000000000000000000000000000000000000000000179052612d9f9084906136c9565b3390565b6000828152603360205260409020613357908261377a565b15611b815761336461333b565b6001600160a01b0316816001600160a01b0316837f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a45050565b60008281526033602052604090206133c0908261378f565b15611b81576133cd61333b565b6001600160a01b0316816001600160a01b0316837ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b60405160405180910390a45050565b613419611e1c565b61346a576040805162461bcd60e51b815260206004820152601460248201527f5061757361626c653a206e6f7420706175736564000000000000000000000000604482015290519081900360640190fd5b6097805460ff191690557f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa61349d61333b565b604080516001600160a01b039092168252519081900360200190a1565b60006134c5306137a4565b15905090565b600054610100900460ff16806134e457506134e46134ba565b806134f2575060005460ff16155b61352d5760405162461bcd60e51b815260040180806020018281038252602e815260200180613d11602e913960400191505060405180910390fd5b600054610100900460ff16158015613575576000805460ff197fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff909116610100171660011790555b61357d6137aa565b611ee66137aa565b61358d611e1c565b156135df576040805162461bcd60e51b815260206004820152601060248201527f5061757361626c653a2070617573656400000000000000000000000000000000604482015290519081900360640190fd5b6097805460ff191660011790557f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a25861349d61333b565b60006121648383613884565b604080516001600160a01b0380861660248301528416604482015260648082018490528251808303909101815260849091019091526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f23b872dd000000000000000000000000000000000000000000000000000000001790526132b59085906136c9565b6000612164836001600160a01b0384166138e8565b600061216782613900565b606061371e826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b03166139049092919063ffffffff16565b805190915015612d9f5780806020019051602081101561373d57600080fd5b5051612d9f5760405162461bcd60e51b815260040180806020018281038252602a815260200180613d3f602a913960400191505060405180910390fd5b6000612164836001600160a01b03841661391d565b6000612164836001600160a01b038416613967565b3b151590565b600054610100900460ff16806137c357506137c36134ba565b806137d1575060005460ff16155b61380c5760405162461bcd60e51b815260040180806020018281038252602e815260200180613d11602e913960400191505060405180910390fd5b600054610100900460ff16158015611ee6576000805460ff197fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff909116610100171660011790558015611f1557600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff16905550565b815460009082106138c65760405162461bcd60e51b8152600401808060200182810382526022815260200180613c6a6022913960400191505060405180910390fd5b8260000182815481106138d557fe5b9060005260206000200154905092915050565b60009081526001919091016020526040902054151590565b5490565b60606139138484600085613a4b565b90505b9392505050565b600061392983836138e8565b61395f57508154600181810184556000848152602080822090930184905584548482528286019093526040902091909155612167565b506000612167565b60008181526001830160205260408120548015613a415783547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff80830191908101906000908790839081106139b857fe5b90600052602060002001549050808760000184815481106139d557fe5b600091825260208083209091019290925582815260018981019092526040902090840190558654879080613a0557fe5b60019003818190600052602060002001600090559055866001016000878152602001908152602001600020600090556001945050505050612167565b6000915050612167565b606082471015613a8c5760405162461bcd60e51b8152600401808060200182810382526026815260200180613cbb6026913960400191505060405180910390fd5b613a95856137a4565b613ae6576040805162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000604482015290519081900360640190fd5b60006060866001600160a01b031685876040518082805190602001908083835b60208310613b4357805182527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe09092019160209182019101613b06565b6001836020036101000a03801982511681845116808217855250505050505090500191505060006040518083038185875af1925050503d8060008114613ba5576040519150601f19603f3d011682016040523d82523d6000602084013e613baa565b606091505b5091509150613bba828286613bc5565b979650505050505050565b60608315613bd4575081613916565b825115613be45782518084602001fd5b8160405162461bcd60e51b81526004018080602001828103825283818151815260200191508051906020019080838360005b83811015613c2e578181015183820152602001613c16565b50505050905090810190601f168015613c5b5780820380516001836020036101000a031916815260200191505b509250505060405180910390fdfe456e756d657261626c655365743a20696e646578206f7574206f6620626f756e6473416363657373436f6e74726f6c3a2073656e646572206d75737420626520616e2061646d696e20746f206772616e74416464726573733a20696e73756666696369656e742062616c616e636520666f722063616c6c416363657373436f6e74726f6c3a2073656e646572206d75737420626520616e2061646d696e20746f207265766f6b65496e697469616c697a61626c653a20636f6e747261637420697320616c726561647920696e697469616c697a65645361666545524332303a204552433230206f7065726174696f6e20646964206e6f742073756363656564416363657373436f6e74726f6c3a2063616e206f6e6c792072656e6f756e636520726f6c657320666f722073656c66a2646970667358221220c7ddf348db774832685d2f2e6488cabd308328f57ce2f579e76377741d2db00f64736f6c634300060c0033", + "devdoc": { + "kind": "dev", + "methods": { + "deposit(address,uint256,address,uint256)": { + "params": { + "amount": "Amount in native token decimals to transfer cross-chain pre-fees*", + "chainId": "which chain to bridge assets onto", + "to": "address on other chain to bridge assets to", + "token": "ERC20 compatible token to deposit into the bridge" + } + }, + "depositAndSwap(address,uint256,address,uint256,uint8,uint8,uint256,uint256)": { + "params": { + "amount": "Amount in native token decimals to transfer cross-chain pre-fees", + "chainId": "which chain to bridge assets onto", + "deadline": "latest timestamp to accept this transaction*", + "minDy": "the min amount the user would like to receive, or revert to only minting the SynERC20 token crosschain.", + "to": "address on other chain to bridge assets to", + "token": "ERC20 compatible token to deposit into the bridge", + "tokenIndexFrom": "the token the user wants to swap from", + "tokenIndexTo": "the token the user wants to swap to" + } + }, + "getRoleAdmin(bytes32)": { + "details": "Returns the admin role that controls `role`. See {grantRole} and {revokeRole}. To change a role's admin, use {_setRoleAdmin}." + }, + "getRoleMember(bytes32,uint256)": { + "details": "Returns one of the accounts that have `role`. `index` must be a value between 0 and {getRoleMemberCount}, non-inclusive. Role bearers are not sorted in any particular way, and their ordering may change at any point. WARNING: When using {getRoleMember} and {getRoleMemberCount}, make sure you perform all queries on the same block. See the following https://forum.openzeppelin.com/t/iterating-over-elements-on-enumerableset-in-openzeppelin-contracts/2296[forum post] for more information." + }, + "getRoleMemberCount(bytes32)": { + "details": "Returns the number of accounts that have `role`. Can be used together with {getRoleMember} to enumerate all bearers of a role." + }, + "grantRole(bytes32,address)": { + "details": "Grants `role` to `account`. If `account` had not been already granted `role`, emits a {RoleGranted} event. Requirements: - the caller must have ``role``'s admin role." + }, + "hasRole(bytes32,address)": { + "details": "Returns `true` if `account` has been granted `role`." + }, + "mint(address,address,uint256,uint256,bytes32)": { + "details": "This means the SynapseBridge.sol contract must have minter access to the token attempting to be minted", + "params": { + "amount": "Amount in native token decimals to transfer cross-chain post-fees", + "fee": "Amount in native token decimals to save to the contract as fees", + "kappa": "kappa*", + "to": "address on other chain to redeem underlying assets to", + "token": "ERC20 compatible token to deposit into the bridge" + } + }, + "mintAndSwap(address,address,uint256,uint256,address,uint8,uint8,uint256,uint256,bytes32)": { + "details": "This means the BridgeDeposit.sol contract must have minter access to the token attempting to be minted", + "params": { + "amount": "Amount in native token decimals to transfer cross-chain post-fees", + "deadline": "Epoch time of the deadline that the swap is allowed to be executed.", + "fee": "Amount in native token decimals to save to the contract as fees", + "kappa": "kappa*", + "minDy": "Minumum amount (in final asset decimals) that must be swapped for, otherwise the user will receive the SynERC20.", + "pool": "Destination chain's pool to use to swap SynERC20 -> Asset. The nodes determine this by using PoolConfig.sol.", + "to": "address on other chain to redeem underlying assets to", + "token": "ERC20 compatible token to deposit into the bridge", + "tokenIndexFrom": "Index of the SynERC20 asset in the pool", + "tokenIndexTo": "Index of the desired final asset" + } + }, + "paused()": { + "details": "Returns true if the contract is paused, and false otherwise." + }, + "redeem(address,uint256,address,uint256)": { + "params": { + "amount": "Amount in native token decimals to transfer cross-chain pre-fees*", + "chainId": "which underlying chain to bridge assets onto", + "to": "address on other chain to redeem underlying assets to", + "token": "ERC20 compatible token to deposit into the bridge" + } + }, + "redeemAndRemove(address,uint256,address,uint256,uint8,uint256,uint256)": { + "params": { + "amount": "Amount in native token decimals to transfer cross-chain pre-fees", + "chainId": "which underlying chain to bridge assets onto", + "swapDeadline": "Specificies the deadline that the nodes are allowed to try to redeem/swap the LP token*", + "swapMinAmount": "Specifies the minimum amount of the underlying asset needed for the nodes to execute the redeem/swap", + "swapTokenIndex": "Specifies which of the underlying LP assets the nodes should attempt to redeem for", + "to": "address on other chain to redeem underlying assets to", + "token": "ERC20 compatible token to deposit into the bridge" + } + }, + "redeemAndSwap(address,uint256,address,uint256,uint8,uint8,uint256,uint256)": { + "params": { + "amount": "Amount in native token decimals to transfer cross-chain pre-fees", + "chainId": "which underlying chain to bridge assets onto", + "deadline": "latest timestamp to accept this transaction*", + "minDy": "the min amount the user would like to receive, or revert to only minting the SynERC20 token crosschain.", + "to": "address on other chain to redeem underlying assets to", + "token": "ERC20 compatible token to deposit into the bridge", + "tokenIndexFrom": "the token the user wants to swap from", + "tokenIndexTo": "the token the user wants to swap to" + } + }, + "redeemV2(bytes32,uint256,address,uint256)": { + "params": { + "amount": "Amount in native token decimals to transfer cross-chain pre-fees*", + "chainId": "which underlying chain to bridge assets onto", + "to": "address on other chain to redeem underlying assets to", + "token": "ERC20 compatible token to deposit into the bridge" + } + }, + "renounceRole(bytes32,address)": { + "details": "Revokes `role` from the calling account. Roles are often managed via {grantRole} and {revokeRole}: this function's purpose is to provide a mechanism for accounts to lose their privileges if they are compromised (such as when a trusted device is misplaced). If the calling account had been granted `role`, emits a {RoleRevoked} event. Requirements: - the caller must be `account`." + }, + "revokeRole(bytes32,address)": { + "details": "Revokes `role` from `account`. If `account` had been granted `role`, emits a {RoleRevoked} event. Requirements: - the caller must have ``role``'s admin role." + }, + "withdraw(address,address,uint256,uint256,bytes32)": { + "params": { + "amount": "Amount in native token decimals to withdraw", + "fee": "Amount in native token decimals to save to the contract as fees", + "kappa": "kappa*", + "to": "address on chain to send underlying assets to", + "token": "ERC20 compatible token to withdraw from the bridge" + } + }, + "withdrawAndRemove(address,address,uint256,uint256,address,uint8,uint256,uint256,bytes32)": { + "params": { + "amount": "Amount in native token decimals to withdraw", + "fee": "Amount in native token decimals to save to the contract as fees", + "kappa": "kappa*", + "pool": "Destination chain's pool to use to swap SynERC20 -> Asset. The nodes determine this by using PoolConfig.sol.", + "swapDeadline": "Specificies the deadline that the nodes are allowed to try to redeem/swap the LP token", + "swapMinAmount": "Specifies the minimum amount of the underlying asset needed for the nodes to execute the redeem/swap", + "swapTokenIndex": "Specifies which of the underlying LP assets the nodes should attempt to redeem for", + "to": "address on chain to send underlying assets to", + "token": "ERC20 compatible token to withdraw from the bridge" + } + }, + "withdrawFees(address,address)": { + "params": { + "to": "Address to send the fees to", + "token": "ERC20 token in which fees acccumulated to transfer" + } + } + }, + "version": 1 + }, + "userdoc": { + "kind": "user", + "methods": { + "deposit(address,uint256,address,uint256)": { + "notice": "Relays to nodes to transfers an ERC20 token cross-chain" + }, + "depositAndSwap(address,uint256,address,uint256,uint8,uint8,uint256,uint256)": { + "notice": "Relays to nodes to both transfer an ERC20 token cross-chain, and then have the nodes execute a swap through a liquidity pool on behalf of the user." + }, + "mint(address,address,uint256,uint256,bytes32)": { + "notice": "Nodes call this function to mint a SynERC20 (or any asset that the bridge is given minter access to). This is called by the nodes after a TokenDeposit event is emitted." + }, + "mintAndSwap(address,address,uint256,uint256,address,uint8,uint8,uint256,uint256,bytes32)": { + "notice": "Nodes call this function to mint a SynERC20 (or any asset that the bridge is given minter access to), and then attempt to swap the SynERC20 into the desired destination asset. This is called by the nodes after a TokenDepositAndSwap event is emitted." + }, + "redeem(address,uint256,address,uint256)": { + "notice": "Relays to nodes that (typically) a wrapped synAsset ERC20 token has been burned and the underlying needs to be redeeemed on the native chain" + }, + "redeemAndRemove(address,uint256,address,uint256,uint8,uint256,uint256)": { + "notice": "Relays to nodes that (typically) a wrapped synAsset ERC20 token has been burned and the underlying needs to be redeeemed on the native chain. This function indicates to the nodes that they should attempt to redeem the LP token for the underlying assets (E.g \"swap\" out of the LP token)" + }, + "redeemAndSwap(address,uint256,address,uint256,uint8,uint8,uint256,uint256)": { + "notice": "Relays to nodes that (typically) a wrapped synAsset ERC20 token has been burned and the underlying needs to be redeeemed on the native chain. This function indicates to the nodes that they should attempt to redeem the LP token for the underlying assets (E.g \"swap\" out of the LP token)" + }, + "redeemV2(bytes32,uint256,address,uint256)": { + "notice": "Relays to nodes that (typically) a wrapped synAsset ERC20 token has been burned and the underlying needs to be redeeemed on the native chain" + }, + "withdraw(address,address,uint256,uint256,bytes32)": { + "notice": "Function to be called by the node group to withdraw the underlying assets from the contract" + }, + "withdrawAndRemove(address,address,uint256,uint256,address,uint8,uint256,uint256,bytes32)": { + "notice": "Function to be called by the node group to withdraw the underlying assets from the contract" + }, + "withdrawFees(address,address)": { + "notice": "withdraw specified ERC20 token fees to a given address" + } + }, + "version": 1 + }, + "storageLayout": { + "storage": [ + { + "astId": 1286, + "contract": "contracts/bridge/SynapseBridge.sol:SynapseBridge", + "label": "_initialized", + "offset": 0, + "slot": "0", + "type": "t_bool" + }, + { + "astId": 1289, + "contract": "contracts/bridge/SynapseBridge.sol:SynapseBridge", + "label": "_initializing", + "offset": 1, + "slot": "0", + "type": "t_bool" + }, + { + "astId": 2325, + "contract": "contracts/bridge/SynapseBridge.sol:SynapseBridge", + "label": "__gap", + "offset": 0, + "slot": "1", + "type": "t_array(t_uint256)50_storage" + }, + { + "astId": 43, + "contract": "contracts/bridge/SynapseBridge.sol:SynapseBridge", + "label": "_roles", + "offset": 0, + "slot": "51", + "type": "t_mapping(t_bytes32,t_struct(RoleData)39_storage)" + }, + { + "astId": 306, + "contract": "contracts/bridge/SynapseBridge.sol:SynapseBridge", + "label": "__gap", + "offset": 0, + "slot": "52", + "type": "t_array(t_uint256)49_storage" + }, + { + "astId": 2995, + "contract": "contracts/bridge/SynapseBridge.sol:SynapseBridge", + "label": "_status", + "offset": 0, + "slot": "101", + "type": "t_uint256" + }, + { + "astId": 3038, + "contract": "contracts/bridge/SynapseBridge.sol:SynapseBridge", + "label": "__gap", + "offset": 0, + "slot": "102", + "type": "t_array(t_uint256)49_storage" + }, + { + "astId": 2889, + "contract": "contracts/bridge/SynapseBridge.sol:SynapseBridge", + "label": "_paused", + "offset": 0, + "slot": "151", + "type": "t_bool" + }, + { + "astId": 2980, + "contract": "contracts/bridge/SynapseBridge.sol:SynapseBridge", + "label": "__gap", + "offset": 0, + "slot": "152", + "type": "t_array(t_uint256)49_storage" + }, + { + "astId": 19139, + "contract": "contracts/bridge/SynapseBridge.sol:SynapseBridge", + "label": "fees", + "offset": 0, + "slot": "201", + "type": "t_mapping(t_address,t_uint256)" + }, + { + "astId": 19141, + "contract": "contracts/bridge/SynapseBridge.sol:SynapseBridge", + "label": "startBlockNumber", + "offset": 0, + "slot": "202", + "type": "t_uint256" + }, + { + "astId": 19146, + "contract": "contracts/bridge/SynapseBridge.sol:SynapseBridge", + "label": "chainGasAmount", + "offset": 0, + "slot": "203", + "type": "t_uint256" + }, + { + "astId": 19148, + "contract": "contracts/bridge/SynapseBridge.sol:SynapseBridge", + "label": "WETH_ADDRESS", + "offset": 0, + "slot": "204", + "type": "t_address_payable" + }, + { + "astId": 19152, + "contract": "contracts/bridge/SynapseBridge.sol:SynapseBridge", + "label": "kappaMap", + "offset": 0, + "slot": "205", + "type": "t_mapping(t_bytes32,t_bool)" + } + ], + "types": { + "t_address": { + "encoding": "inplace", + "label": "address", + "numberOfBytes": "20" + }, + "t_address_payable": { + "encoding": "inplace", + "label": "address payable", + "numberOfBytes": "20" + }, + "t_array(t_bytes32)dyn_storage": { + "base": "t_bytes32", + "encoding": "dynamic_array", + "label": "bytes32[]", + "numberOfBytes": "32" + }, + "t_array(t_uint256)49_storage": { + "base": "t_uint256", + "encoding": "inplace", + "label": "uint256[49]", + "numberOfBytes": "1568" + }, + "t_array(t_uint256)50_storage": { + "base": "t_uint256", + "encoding": "inplace", + "label": "uint256[50]", + "numberOfBytes": "1600" + }, + "t_bool": { + "encoding": "inplace", + "label": "bool", + "numberOfBytes": "1" + }, + "t_bytes32": { + "encoding": "inplace", + "label": "bytes32", + "numberOfBytes": "32" + }, + "t_mapping(t_address,t_uint256)": { + "encoding": "mapping", + "key": "t_address", + "label": "mapping(address => uint256)", + "numberOfBytes": "32", + "value": "t_uint256" + }, + "t_mapping(t_bytes32,t_bool)": { + "encoding": "mapping", + "key": "t_bytes32", + "label": "mapping(bytes32 => bool)", + "numberOfBytes": "32", + "value": "t_bool" + }, + "t_mapping(t_bytes32,t_struct(RoleData)39_storage)": { + "encoding": "mapping", + "key": "t_bytes32", + "label": "mapping(bytes32 => struct AccessControlUpgradeable.RoleData)", + "numberOfBytes": "32", + "value": "t_struct(RoleData)39_storage" + }, + "t_mapping(t_bytes32,t_uint256)": { + "encoding": "mapping", + "key": "t_bytes32", + "label": "mapping(bytes32 => uint256)", + "numberOfBytes": "32", + "value": "t_uint256" + }, + "t_struct(AddressSet)2652_storage": { + "encoding": "inplace", + "label": "struct EnumerableSetUpgradeable.AddressSet", + "members": [ + { + "astId": 2651, + "contract": "contracts/bridge/SynapseBridge.sol:SynapseBridge", + "label": "_inner", + "offset": 0, + "slot": "0", + "type": "t_struct(Set)2387_storage" + } + ], + "numberOfBytes": "64" + }, + "t_struct(RoleData)39_storage": { + "encoding": "inplace", + "label": "struct AccessControlUpgradeable.RoleData", + "members": [ + { + "astId": 36, + "contract": "contracts/bridge/SynapseBridge.sol:SynapseBridge", + "label": "members", + "offset": 0, + "slot": "0", + "type": "t_struct(AddressSet)2652_storage" + }, + { + "astId": 38, + "contract": "contracts/bridge/SynapseBridge.sol:SynapseBridge", + "label": "adminRole", + "offset": 0, + "slot": "2", + "type": "t_bytes32" + } + ], + "numberOfBytes": "96" + }, + "t_struct(Set)2387_storage": { + "encoding": "inplace", + "label": "struct EnumerableSetUpgradeable.Set", + "members": [ + { + "astId": 2382, + "contract": "contracts/bridge/SynapseBridge.sol:SynapseBridge", + "label": "_values", + "offset": 0, + "slot": "0", + "type": "t_array(t_bytes32)dyn_storage" + }, + { + "astId": 2386, + "contract": "contracts/bridge/SynapseBridge.sol:SynapseBridge", + "label": "_indexes", + "offset": 0, + "slot": "1", + "type": "t_mapping(t_bytes32,t_uint256)" + } + ], + "numberOfBytes": "64" + }, + "t_uint256": { + "encoding": "inplace", + "label": "uint256", + "numberOfBytes": "32" + } + } + } +} \ No newline at end of file diff --git a/deployments/dfk/SynapseBridge_Proxy.json b/deployments/dfk/SynapseBridge_Proxy.json new file mode 100644 index 000000000..675f37684 --- /dev/null +++ b/deployments/dfk/SynapseBridge_Proxy.json @@ -0,0 +1,205 @@ +{ + "address": "0xE05c976d3f045D0E6E7A6f61083d98A15603cF6A", + "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "initialLogic", + "type": "address" + }, + { + "internalType": "address", + "name": "initialAdmin", + "type": "address" + }, + { + "internalType": "bytes", + "name": "_data", + "type": "bytes" + } + ], + "stateMutability": "payable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "previousAdmin", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "newAdmin", + "type": "address" + } + ], + "name": "AdminChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "implementation", + "type": "address" + } + ], + "name": "Upgraded", + "type": "event" + }, + { + "stateMutability": "payable", + "type": "fallback" + }, + { + "inputs": [], + "name": "admin", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newAdmin", + "type": "address" + } + ], + "name": "changeAdmin", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "implementation", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newImplementation", + "type": "address" + } + ], + "name": "upgradeTo", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newImplementation", + "type": "address" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "upgradeToAndCall", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "stateMutability": "payable", + "type": "receive" + } + ], + "transactionHash": "0x1e4968b76cc2ed65f244bc976b248049b6078c9b37822eb2ee304070faee818e", + "receipt": { + "to": null, + "from": "0x235AF07E770f474d24F5bf73074735892371b40D", + "contractAddress": "0xE05c976d3f045D0E6E7A6f61083d98A15603cF6A", + "transactionIndex": 0, + "gasUsed": "544341", + "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "blockHash": "0x87e00cb166ddf14c9303439a632dbb7803111f5a2ffb35cf28f64f8499723024", + "transactionHash": "0x1e4968b76cc2ed65f244bc976b248049b6078c9b37822eb2ee304070faee818e", + "logs": [], + "blockNumber": 66, + "cumulativeGasUsed": "544341", + "status": 1, + "byzantium": true + }, + "args": [ + "0x159F2A9D7304Da210bE99F3d704B9823486DE24E", + "0x587AEf47a56224B5775Ff289Fb259d59F35ADdF9", + "0x" + ], + "solcInputHash": "1635d55d57a0a2552952c0d22586ed23", + "metadata": "{\"compiler\":{\"version\":\"0.7.6+commit.7338295f\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"initialLogic\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"initialAdmin\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"_data\",\"type\":\"bytes\"}],\"stateMutability\":\"payable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"previousAdmin\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"newAdmin\",\"type\":\"address\"}],\"name\":\"AdminChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"implementation\",\"type\":\"address\"}],\"name\":\"Upgraded\",\"type\":\"event\"},{\"stateMutability\":\"payable\",\"type\":\"fallback\"},{\"inputs\":[],\"name\":\"admin\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newAdmin\",\"type\":\"address\"}],\"name\":\"changeAdmin\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"implementation\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newImplementation\",\"type\":\"address\"}],\"name\":\"upgradeTo\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newImplementation\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"upgradeToAndCall\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"stateMutability\":\"payable\",\"type\":\"receive\"}],\"devdoc\":{\"details\":\"This contract implements a proxy that is upgradeable by an admin. To avoid https://medium.com/nomic-labs-blog/malicious-backdoors-in-ethereum-proxies-62629adf3357[proxy selector clashing], which can potentially be used in an attack, this contract uses the https://blog.openzeppelin.com/the-transparent-proxy-pattern/[transparent proxy pattern]. This pattern implies two things that go hand in hand: 1. If any account other than the admin calls the proxy, the call will be forwarded to the implementation, even if that call matches one of the admin functions exposed by the proxy itself. 2. If the admin calls the proxy, it can access the admin functions, but its calls will never be forwarded to the implementation. If the admin tries to call a function on the implementation it will fail with an error that says \\\"admin cannot fallback to proxy target\\\". These properties mean that the admin account can only be used for admin actions like upgrading the proxy or changing the admin, so it's best if it's a dedicated account that is not used for anything else. This will avoid headaches due to sudden errors when trying to call a function from the proxy implementation. Our recommendation is for the dedicated account to be an instance of the {ProxyAdmin} contract. If set up this way, you should think of the `ProxyAdmin` instance as the real administrative inerface of your proxy.\",\"events\":{\"AdminChanged(address,address)\":{\"details\":\"Emitted when the admin account has changed.\"}},\"kind\":\"dev\",\"methods\":{\"admin()\":{\"details\":\"Returns the current admin. NOTE: Only the admin can call this function. See {ProxyAdmin-getProxyAdmin}. TIP: To get this value clients can read directly from the storage slot shown below (specified by EIP1967) using the https://eth.wiki/json-rpc/API#eth_getstorageat[`eth_getStorageAt`] RPC call. `0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103`\"},\"changeAdmin(address)\":{\"details\":\"Changes the admin of the proxy. Emits an {AdminChanged} event. NOTE: Only the admin can call this function. See {ProxyAdmin-changeProxyAdmin}.\"},\"constructor\":{\"details\":\"Initializes an upgradeable proxy managed by `_admin`, backed by the implementation at `_logic`, and optionally initialized with `_data` as explained in {UpgradeableProxy-constructor}.\"},\"implementation()\":{\"details\":\"Returns the current implementation. NOTE: Only the admin can call this function. See {ProxyAdmin-getProxyImplementation}. TIP: To get this value clients can read directly from the storage slot shown below (specified by EIP1967) using the https://eth.wiki/json-rpc/API#eth_getstorageat[`eth_getStorageAt`] RPC call. `0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc`\"},\"upgradeTo(address)\":{\"details\":\"Upgrade the implementation of the proxy. NOTE: Only the admin can call this function. See {ProxyAdmin-upgrade}.\"},\"upgradeToAndCall(address,bytes)\":{\"details\":\"Upgrade the implementation of the proxy, and then call a function from the new implementation as specified by `data`, which should be an encoded function call. This is useful to initialize new storage variables in the proxied contract. NOTE: Only the admin can call this function. See {ProxyAdmin-upgradeAndCall}.\"}},\"stateVariables\":{\"_ADMIN_SLOT\":{\"details\":\"Storage slot with the admin of the contract. This is the keccak-256 hash of \\\"eip1967.proxy.admin\\\" subtracted by 1, and is validated in the constructor.\"}},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"solc_0.7/openzeppelin/proxy/TransparentUpgradeableProxy.sol\":\"TransparentUpgradeableProxy\"},\"evmVersion\":\"istanbul\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":999999},\"remappings\":[]},\"sources\":{\"solc_0.7/openzeppelin/proxy/Proxy.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\n/**\\n * @dev This abstract contract provides a fallback function that delegates all calls to another contract using the EVM\\n * instruction `delegatecall`. We refer to the second contract as the _implementation_ behind the proxy, and it has to\\n * be specified by overriding the virtual {_implementation} function.\\n * \\n * Additionally, delegation to the implementation can be triggered manually through the {_fallback} function, or to a\\n * different contract through the {_delegate} function.\\n * \\n * The success and return data of the delegated call will be returned back to the caller of the proxy.\\n */\\nabstract contract Proxy {\\n /**\\n * @dev Delegates the current call to `implementation`.\\n * \\n * This function does not return to its internall call site, it will return directly to the external caller.\\n */\\n function _delegate(address implementation) internal {\\n // solhint-disable-next-line no-inline-assembly\\n assembly {\\n // Copy msg.data. We take full control of memory in this inline assembly\\n // block because it will not return to Solidity code. We overwrite the\\n // Solidity scratch pad at memory position 0.\\n calldatacopy(0, 0, calldatasize())\\n\\n // Call the implementation.\\n // out and outsize are 0 because we don't know the size yet.\\n let result := delegatecall(gas(), implementation, 0, calldatasize(), 0, 0)\\n\\n // Copy the returned data.\\n returndatacopy(0, 0, returndatasize())\\n\\n switch result\\n // delegatecall returns 0 on error.\\n case 0 { revert(0, returndatasize()) }\\n default { return(0, returndatasize()) }\\n }\\n }\\n\\n /**\\n * @dev This is a virtual function that should be overriden so it returns the address to which the fallback function\\n * and {_fallback} should delegate.\\n */\\n function _implementation() internal virtual view returns (address);\\n\\n /**\\n * @dev Delegates the current call to the address returned by `_implementation()`.\\n * \\n * This function does not return to its internall call site, it will return directly to the external caller.\\n */\\n function _fallback() internal {\\n _beforeFallback();\\n _delegate(_implementation());\\n }\\n\\n /**\\n * @dev Fallback function that delegates calls to the address returned by `_implementation()`. Will run if no other\\n * function in the contract matches the call data.\\n */\\n fallback () payable external {\\n _fallback();\\n }\\n\\n /**\\n * @dev Fallback function that delegates calls to the address returned by `_implementation()`. Will run if call data\\n * is empty.\\n */\\n receive () payable external {\\n _fallback();\\n }\\n\\n /**\\n * @dev Hook that is called before falling back to the implementation. Can happen as part of a manual `_fallback`\\n * call, or as part of the Solidity `fallback` or `receive` functions.\\n * \\n * If overriden should call `super._beforeFallback()`.\\n */\\n function _beforeFallback() internal virtual {\\n }\\n}\\n\",\"keccak256\":\"0xc33f9858a67e34c77831163d5611d21fc627dfd2c303806a98a6c9db5a01b034\",\"license\":\"MIT\"},\"solc_0.7/openzeppelin/proxy/TransparentUpgradeableProxy.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\nimport \\\"./UpgradeableProxy.sol\\\";\\n\\n/**\\n * @dev This contract implements a proxy that is upgradeable by an admin.\\n * \\n * To avoid https://medium.com/nomic-labs-blog/malicious-backdoors-in-ethereum-proxies-62629adf3357[proxy selector\\n * clashing], which can potentially be used in an attack, this contract uses the\\n * https://blog.openzeppelin.com/the-transparent-proxy-pattern/[transparent proxy pattern]. This pattern implies two\\n * things that go hand in hand:\\n * \\n * 1. If any account other than the admin calls the proxy, the call will be forwarded to the implementation, even if\\n * that call matches one of the admin functions exposed by the proxy itself.\\n * 2. If the admin calls the proxy, it can access the admin functions, but its calls will never be forwarded to the\\n * implementation. If the admin tries to call a function on the implementation it will fail with an error that says\\n * \\\"admin cannot fallback to proxy target\\\".\\n * \\n * These properties mean that the admin account can only be used for admin actions like upgrading the proxy or changing\\n * the admin, so it's best if it's a dedicated account that is not used for anything else. This will avoid headaches due\\n * to sudden errors when trying to call a function from the proxy implementation.\\n * \\n * Our recommendation is for the dedicated account to be an instance of the {ProxyAdmin} contract. If set up this way,\\n * you should think of the `ProxyAdmin` instance as the real administrative inerface of your proxy.\\n */\\ncontract TransparentUpgradeableProxy is UpgradeableProxy {\\n /**\\n * @dev Initializes an upgradeable proxy managed by `_admin`, backed by the implementation at `_logic`, and\\n * optionally initialized with `_data` as explained in {UpgradeableProxy-constructor}.\\n */\\n constructor(address initialLogic, address initialAdmin, bytes memory _data) payable UpgradeableProxy(initialLogic, _data) {\\n assert(_ADMIN_SLOT == bytes32(uint256(keccak256(\\\"eip1967.proxy.admin\\\")) - 1));\\n _setAdmin(initialAdmin);\\n }\\n\\n /**\\n * @dev Emitted when the admin account has changed.\\n */\\n event AdminChanged(address previousAdmin, address newAdmin);\\n\\n /**\\n * @dev Storage slot with the admin of the contract.\\n * This is the keccak-256 hash of \\\"eip1967.proxy.admin\\\" subtracted by 1, and is\\n * validated in the constructor.\\n */\\n bytes32 private constant _ADMIN_SLOT = 0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103;\\n\\n /**\\n * @dev Modifier used internally that will delegate the call to the implementation unless the sender is the admin.\\n */\\n modifier ifAdmin() {\\n if (msg.sender == _admin()) {\\n _;\\n } else {\\n _fallback();\\n }\\n }\\n\\n /**\\n * @dev Returns the current admin.\\n * \\n * NOTE: Only the admin can call this function. See {ProxyAdmin-getProxyAdmin}.\\n * \\n * TIP: To get this value clients can read directly from the storage slot shown below (specified by EIP1967) using the\\n * https://eth.wiki/json-rpc/API#eth_getstorageat[`eth_getStorageAt`] RPC call.\\n * `0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103`\\n */\\n function admin() external ifAdmin returns (address) {\\n return _admin();\\n }\\n\\n /**\\n * @dev Returns the current implementation.\\n * \\n * NOTE: Only the admin can call this function. See {ProxyAdmin-getProxyImplementation}.\\n * \\n * TIP: To get this value clients can read directly from the storage slot shown below (specified by EIP1967) using the\\n * https://eth.wiki/json-rpc/API#eth_getstorageat[`eth_getStorageAt`] RPC call.\\n * `0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc`\\n */\\n function implementation() external ifAdmin returns (address) {\\n return _implementation();\\n }\\n\\n /**\\n * @dev Changes the admin of the proxy.\\n * \\n * Emits an {AdminChanged} event.\\n * \\n * NOTE: Only the admin can call this function. See {ProxyAdmin-changeProxyAdmin}.\\n */\\n function changeAdmin(address newAdmin) external ifAdmin {\\n require(newAdmin != address(0), \\\"TransparentUpgradeableProxy: new admin is the zero address\\\");\\n emit AdminChanged(_admin(), newAdmin);\\n _setAdmin(newAdmin);\\n }\\n\\n /**\\n * @dev Upgrade the implementation of the proxy.\\n * \\n * NOTE: Only the admin can call this function. See {ProxyAdmin-upgrade}.\\n */\\n function upgradeTo(address newImplementation) external ifAdmin {\\n _upgradeTo(newImplementation);\\n }\\n\\n /**\\n * @dev Upgrade the implementation of the proxy, and then call a function from the new implementation as specified\\n * by `data`, which should be an encoded function call. This is useful to initialize new storage variables in the\\n * proxied contract.\\n * \\n * NOTE: Only the admin can call this function. See {ProxyAdmin-upgradeAndCall}.\\n */\\n function upgradeToAndCall(address newImplementation, bytes calldata data) external payable ifAdmin {\\n _upgradeTo(newImplementation);\\n // solhint-disable-next-line avoid-low-level-calls\\n (bool success,) = newImplementation.delegatecall(data);\\n require(success);\\n }\\n\\n /**\\n * @dev Returns the current admin.\\n */\\n function _admin() internal view returns (address adm) {\\n bytes32 slot = _ADMIN_SLOT;\\n // solhint-disable-next-line no-inline-assembly\\n assembly {\\n adm := sload(slot)\\n }\\n }\\n\\n /**\\n * @dev Stores a new address in the EIP1967 admin slot.\\n */\\n function _setAdmin(address newAdmin) private {\\n bytes32 slot = _ADMIN_SLOT;\\n\\n // solhint-disable-next-line no-inline-assembly\\n assembly {\\n sstore(slot, newAdmin)\\n }\\n }\\n\\n /**\\n * @dev Makes sure the admin cannot access the fallback function. See {Proxy-_beforeFallback}.\\n */\\n function _beforeFallback() internal override virtual {\\n require(msg.sender != _admin(), \\\"TransparentUpgradeableProxy: admin cannot fallback to proxy target\\\");\\n super._beforeFallback();\\n }\\n}\\n\",\"keccak256\":\"0xd6cecbe00dc78355aff1a16d83487bb73c54701004d61a2e48cdb81e2bcacc26\",\"license\":\"MIT\"},\"solc_0.7/openzeppelin/proxy/UpgradeableProxy.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\nimport \\\"./Proxy.sol\\\";\\nimport \\\"../utils/Address.sol\\\";\\n\\n/**\\n * @dev This contract implements an upgradeable proxy. It is upgradeable because calls are delegated to an\\n * implementation address that can be changed. This address is stored in storage in the location specified by\\n * https://eips.ethereum.org/EIPS/eip-1967[EIP1967], so that it doesn't conflict with the storage layout of the\\n * implementation behind the proxy.\\n * \\n * Upgradeability is only provided internally through {_upgradeTo}. For an externally upgradeable proxy see\\n * {TransparentUpgradeableProxy}.\\n */\\ncontract UpgradeableProxy is Proxy {\\n /**\\n * @dev Initializes the upgradeable proxy with an initial implementation specified by `_logic`.\\n * \\n * If `_data` is nonempty, it's used as data in a delegate call to `_logic`. This will typically be an encoded\\n * function call, and allows initializating the storage of the proxy like a Solidity constructor.\\n */\\n constructor(address _logic, bytes memory _data) payable {\\n assert(_IMPLEMENTATION_SLOT == bytes32(uint256(keccak256(\\\"eip1967.proxy.implementation\\\")) - 1));\\n _setImplementation(_logic);\\n if(_data.length > 0) {\\n // solhint-disable-next-line avoid-low-level-calls\\n (bool success,) = _logic.delegatecall(_data);\\n require(success);\\n }\\n }\\n\\n /**\\n * @dev Emitted when the implementation is upgraded.\\n */\\n event Upgraded(address indexed implementation);\\n\\n /**\\n * @dev Storage slot with the address of the current implementation.\\n * This is the keccak-256 hash of \\\"eip1967.proxy.implementation\\\" subtracted by 1, and is\\n * validated in the constructor.\\n */\\n bytes32 private constant _IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc;\\n\\n /**\\n * @dev Returns the current implementation address.\\n */\\n function _implementation() internal override view returns (address impl) {\\n bytes32 slot = _IMPLEMENTATION_SLOT;\\n // solhint-disable-next-line no-inline-assembly\\n assembly {\\n impl := sload(slot)\\n }\\n }\\n\\n /**\\n * @dev Upgrades the proxy to a new implementation.\\n * \\n * Emits an {Upgraded} event.\\n */\\n function _upgradeTo(address newImplementation) internal {\\n _setImplementation(newImplementation);\\n emit Upgraded(newImplementation);\\n }\\n\\n /**\\n * @dev Stores a new address in the EIP1967 implementation slot.\\n */\\n function _setImplementation(address newImplementation) private {\\n require(Address.isContract(newImplementation), \\\"UpgradeableProxy: new implementation is not a contract\\\");\\n\\n bytes32 slot = _IMPLEMENTATION_SLOT;\\n\\n // solhint-disable-next-line no-inline-assembly\\n assembly {\\n sstore(slot, newImplementation)\\n }\\n }\\n}\\n\",\"keccak256\":\"0xd68f4c11941712db79a61b9dca81a5db663cfacec3d7bb19f8d2c23bb1ab8afe\",\"license\":\"MIT\"},\"solc_0.7/openzeppelin/utils/Address.sol\":{\"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 // According to EIP-1052, 0x0 is the value returned for not-yet created accounts\\n // and 0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470 is returned\\n // for accounts without code, i.e. `keccak256('')`\\n bytes32 codehash;\\n bytes32 accountHash = 0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470;\\n // solhint-disable-next-line no-inline-assembly\\n assembly { codehash := extcodehash(account) }\\n return (codehash != accountHash && codehash != 0x0);\\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 return _functionCallWithValue(target, data, value, errorMessage);\\n }\\n\\n function _functionCallWithValue(address target, bytes memory data, uint256 weiValue, string memory errorMessage) private returns (bytes memory) {\\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: weiValue }(data);\\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\",\"keccak256\":\"0x698f929f1097637d051976b322a2d532c27df022b09010e8d091e2888a5ebdf8\",\"license\":\"MIT\"}},\"version\":1}", + "bytecode": "0x6080604052604051610aaa380380610aaa8339818101604052606081101561002657600080fd5b8151602083015160408085018051915193959294830192918464010000000082111561005157600080fd5b90830190602082018581111561006657600080fd5b825164010000000081118282018810171561008057600080fd5b82525081516020918201929091019080838360005b838110156100ad578181015183820152602001610095565b50505050905090810190601f1680156100da5780820380516001836020036101000a031916815260200191505b50604052508491508290506100ee826101bf565b8051156101a6576000826001600160a01b0316826040518082805190602001908083835b602083106101315780518252601f199092019160209182019101610112565b6001836020036101000a038019825116818451168082178552505050505050905001915050600060405180830381855af49150503d8060008114610191576040519150601f19603f3d011682016040523d82523d6000602084013e610196565b606091505b50509050806101a457600080fd5b505b506101ae9050565b6101b782610231565b505050610291565b6101d28161025560201b6104bb1760201c565b61020d5760405162461bcd60e51b8152600401808060200182810382526036815260200180610a746036913960400191505060405180910390fd5b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc55565b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d610355565b6000813f7fc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a47081811480159061028957508115155b949350505050565b6107d4806102a06000396000f3fe60806040526004361061005e5760003560e01c80635c60da1b116100435780635c60da1b146101425780638f28397014610180578063f851a440146101c05761006d565b80633659cfe6146100755780634f1ef286146100b55761006d565b3661006d5761006b6101d5565b005b61006b6101d5565b34801561008157600080fd5b5061006b6004803603602081101561009857600080fd5b503573ffffffffffffffffffffffffffffffffffffffff166101ef565b61006b600480360360408110156100cb57600080fd5b73ffffffffffffffffffffffffffffffffffffffff823516919081019060408101602082013564010000000081111561010357600080fd5b82018360208201111561011557600080fd5b8035906020019184600183028401116401000000008311171561013757600080fd5b509092509050610243565b34801561014e57600080fd5b50610157610317565b6040805173ffffffffffffffffffffffffffffffffffffffff9092168252519081900360200190f35b34801561018c57600080fd5b5061006b600480360360208110156101a357600080fd5b503573ffffffffffffffffffffffffffffffffffffffff1661036e565b3480156101cc57600080fd5b50610157610476565b6101dd6104f7565b6101ed6101e861058b565b6105b0565b565b6101f76105d4565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16141561023857610233816105f9565b610240565b6102406101d5565b50565b61024b6105d4565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16141561030a57610287836105f9565b60008373ffffffffffffffffffffffffffffffffffffffff1683836040518083838082843760405192019450600093509091505080830381855af49150503d80600081146102f1576040519150601f19603f3d011682016040523d82523d6000602084013e6102f6565b606091505b505090508061030457600080fd5b50610312565b6103126101d5565b505050565b60006103216105d4565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614156103635761035c61058b565b905061036b565b61036b6101d5565b90565b6103766105d4565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614156102385773ffffffffffffffffffffffffffffffffffffffff8116610415576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252603a8152602001806106ed603a913960400191505060405180910390fd5b7f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f61043e6105d4565b6040805173ffffffffffffffffffffffffffffffffffffffff928316815291841660208301528051918290030190a161023381610646565b60006104806105d4565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614156103635761035c6105d4565b6000813f7fc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a4708181148015906104ef57508115155b949350505050565b6104ff6105d4565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161415610583576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252604281526020018061075d6042913960600191505060405180910390fd5b6101ed6101ed565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b3660008037600080366000845af43d6000803e8080156105cf573d6000f35b3d6000fd5b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b6106028161066a565b60405173ffffffffffffffffffffffffffffffffffffffff8216907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a250565b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d610355565b610673816104bb565b6106c8576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260368152602001806107276036913960400191505060405180910390fd5b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5556fe5472616e73706172656e745570677261646561626c6550726f78793a206e65772061646d696e20697320746865207a65726f20616464726573735570677261646561626c6550726f78793a206e657720696d706c656d656e746174696f6e206973206e6f74206120636f6e74726163745472616e73706172656e745570677261646561626c6550726f78793a2061646d696e2063616e6e6f742066616c6c6261636b20746f2070726f787920746172676574a2646970667358221220b141ef72de179b8b56cef31601d40ff2875391088197e73cac39eba1ddcd0fdd64736f6c634300070600335570677261646561626c6550726f78793a206e657720696d706c656d656e746174696f6e206973206e6f74206120636f6e7472616374", + "deployedBytecode": "0x60806040526004361061005e5760003560e01c80635c60da1b116100435780635c60da1b146101425780638f28397014610180578063f851a440146101c05761006d565b80633659cfe6146100755780634f1ef286146100b55761006d565b3661006d5761006b6101d5565b005b61006b6101d5565b34801561008157600080fd5b5061006b6004803603602081101561009857600080fd5b503573ffffffffffffffffffffffffffffffffffffffff166101ef565b61006b600480360360408110156100cb57600080fd5b73ffffffffffffffffffffffffffffffffffffffff823516919081019060408101602082013564010000000081111561010357600080fd5b82018360208201111561011557600080fd5b8035906020019184600183028401116401000000008311171561013757600080fd5b509092509050610243565b34801561014e57600080fd5b50610157610317565b6040805173ffffffffffffffffffffffffffffffffffffffff9092168252519081900360200190f35b34801561018c57600080fd5b5061006b600480360360208110156101a357600080fd5b503573ffffffffffffffffffffffffffffffffffffffff1661036e565b3480156101cc57600080fd5b50610157610476565b6101dd6104f7565b6101ed6101e861058b565b6105b0565b565b6101f76105d4565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16141561023857610233816105f9565b610240565b6102406101d5565b50565b61024b6105d4565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16141561030a57610287836105f9565b60008373ffffffffffffffffffffffffffffffffffffffff1683836040518083838082843760405192019450600093509091505080830381855af49150503d80600081146102f1576040519150601f19603f3d011682016040523d82523d6000602084013e6102f6565b606091505b505090508061030457600080fd5b50610312565b6103126101d5565b505050565b60006103216105d4565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614156103635761035c61058b565b905061036b565b61036b6101d5565b90565b6103766105d4565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614156102385773ffffffffffffffffffffffffffffffffffffffff8116610415576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252603a8152602001806106ed603a913960400191505060405180910390fd5b7f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f61043e6105d4565b6040805173ffffffffffffffffffffffffffffffffffffffff928316815291841660208301528051918290030190a161023381610646565b60006104806105d4565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614156103635761035c6105d4565b6000813f7fc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a4708181148015906104ef57508115155b949350505050565b6104ff6105d4565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161415610583576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252604281526020018061075d6042913960600191505060405180910390fd5b6101ed6101ed565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b3660008037600080366000845af43d6000803e8080156105cf573d6000f35b3d6000fd5b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b6106028161066a565b60405173ffffffffffffffffffffffffffffffffffffffff8216907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a250565b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d610355565b610673816104bb565b6106c8576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260368152602001806107276036913960400191505060405180910390fd5b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5556fe5472616e73706172656e745570677261646561626c6550726f78793a206e65772061646d696e20697320746865207a65726f20616464726573735570677261646561626c6550726f78793a206e657720696d706c656d656e746174696f6e206973206e6f74206120636f6e74726163745472616e73706172656e745570677261646561626c6550726f78793a2061646d696e2063616e6e6f742066616c6c6261636b20746f2070726f787920746172676574a2646970667358221220b141ef72de179b8b56cef31601d40ff2875391088197e73cac39eba1ddcd0fdd64736f6c63430007060033", + "devdoc": { + "details": "This contract implements a proxy that is upgradeable by an admin. To avoid https://medium.com/nomic-labs-blog/malicious-backdoors-in-ethereum-proxies-62629adf3357[proxy selector clashing], which can potentially be used in an attack, this contract uses the https://blog.openzeppelin.com/the-transparent-proxy-pattern/[transparent proxy pattern]. This pattern implies two things that go hand in hand: 1. If any account other than the admin calls the proxy, the call will be forwarded to the implementation, even if that call matches one of the admin functions exposed by the proxy itself. 2. If the admin calls the proxy, it can access the admin functions, but its calls will never be forwarded to the implementation. If the admin tries to call a function on the implementation it will fail with an error that says \"admin cannot fallback to proxy target\". These properties mean that the admin account can only be used for admin actions like upgrading the proxy or changing the admin, so it's best if it's a dedicated account that is not used for anything else. This will avoid headaches due to sudden errors when trying to call a function from the proxy implementation. Our recommendation is for the dedicated account to be an instance of the {ProxyAdmin} contract. If set up this way, you should think of the `ProxyAdmin` instance as the real administrative inerface of your proxy.", + "events": { + "AdminChanged(address,address)": { + "details": "Emitted when the admin account has changed." + } + }, + "kind": "dev", + "methods": { + "admin()": { + "details": "Returns the current admin. NOTE: Only the admin can call this function. See {ProxyAdmin-getProxyAdmin}. TIP: To get this value clients can read directly from the storage slot shown below (specified by EIP1967) using the https://eth.wiki/json-rpc/API#eth_getstorageat[`eth_getStorageAt`] RPC call. `0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103`" + }, + "changeAdmin(address)": { + "details": "Changes the admin of the proxy. Emits an {AdminChanged} event. NOTE: Only the admin can call this function. See {ProxyAdmin-changeProxyAdmin}." + }, + "constructor": { + "details": "Initializes an upgradeable proxy managed by `_admin`, backed by the implementation at `_logic`, and optionally initialized with `_data` as explained in {UpgradeableProxy-constructor}." + }, + "implementation()": { + "details": "Returns the current implementation. NOTE: Only the admin can call this function. See {ProxyAdmin-getProxyImplementation}. TIP: To get this value clients can read directly from the storage slot shown below (specified by EIP1967) using the https://eth.wiki/json-rpc/API#eth_getstorageat[`eth_getStorageAt`] RPC call. `0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc`" + }, + "upgradeTo(address)": { + "details": "Upgrade the implementation of the proxy. NOTE: Only the admin can call this function. See {ProxyAdmin-upgrade}." + }, + "upgradeToAndCall(address,bytes)": { + "details": "Upgrade the implementation of the proxy, and then call a function from the new implementation as specified by `data`, which should be an encoded function call. This is useful to initialize new storage variables in the proxied contract. NOTE: Only the admin can call this function. See {ProxyAdmin-upgradeAndCall}." + } + }, + "stateVariables": { + "_ADMIN_SLOT": { + "details": "Storage slot with the admin of the contract. This is the keccak-256 hash of \"eip1967.proxy.admin\" subtracted by 1, and is validated in the constructor." + } + }, + "version": 1 + }, + "userdoc": { + "kind": "user", + "methods": {}, + "version": 1 + }, + "storageLayout": { + "storage": [], + "types": null + } +} \ No newline at end of file diff --git a/deployments/dfk/SynapseERC20.json b/deployments/dfk/SynapseERC20.json new file mode 100644 index 000000000..e9d90c6c8 --- /dev/null +++ b/deployments/dfk/SynapseERC20.json @@ -0,0 +1,1104 @@ +{ + "address": "0x3a01521F8E7F012eB37eAAf1cb9490a5d9e18249", + "abi": [ + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "Approval", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "bytes32", + "name": "previousAdminRole", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "bytes32", + "name": "newAdminRole", + "type": "bytes32" + } + ], + "name": "RoleAdminChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "sender", + "type": "address" + } + ], + "name": "RoleGranted", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "sender", + "type": "address" + } + ], + "name": "RoleRevoked", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "Transfer", + "type": "event" + }, + { + "inputs": [], + "name": "DEFAULT_ADMIN_ROLE", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "DOMAIN_SEPARATOR", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "MINTER_ROLE", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "address", + "name": "spender", + "type": "address" + } + ], + "name": "allowance", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "approve", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "balanceOf", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "burn", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "burnFrom", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "decimals", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "subtractedValue", + "type": "uint256" + } + ], + "name": "decreaseAllowance", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + } + ], + "name": "getRoleAdmin", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "internalType": "uint256", + "name": "index", + "type": "uint256" + } + ], + "name": "getRoleMember", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + } + ], + "name": "getRoleMemberCount", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "grantRole", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "hasRole", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "addedValue", + "type": "uint256" + } + ], + "name": "increaseAllowance", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "name", + "type": "string" + }, + { + "internalType": "string", + "name": "symbol", + "type": "string" + }, + { + "internalType": "uint8", + "name": "decimals", + "type": "uint8" + }, + { + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "initialize", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "mint", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "name", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "nonces", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" + }, + { + "internalType": "uint8", + "name": "v", + "type": "uint8" + }, + { + "internalType": "bytes32", + "name": "r", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "s", + "type": "bytes32" + } + ], + "name": "permit", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "renounceRole", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "revokeRole", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "symbol", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "totalSupply", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "recipient", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "transfer", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "internalType": "address", + "name": "recipient", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "transferFrom", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + } + ], + "transactionHash": "0x193b083427543567bdf498b37e83a322c7b4c1ca4cd5804108a500131924f980", + "receipt": { + "to": null, + "from": "0x235AF07E770f474d24F5bf73074735892371b40D", + "contractAddress": "0x3a01521F8E7F012eB37eAAf1cb9490a5d9e18249", + "transactionIndex": 0, + "gasUsed": "1935674", + "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "blockHash": "0xfdcb07aeca62f5f3f153e424218a17e432ada825a1b79ed3bb355ecc105c76ae", + "transactionHash": "0x193b083427543567bdf498b37e83a322c7b4c1ca4cd5804108a500131924f980", + "logs": [], + "blockNumber": 26, + "cumulativeGasUsed": "1935674", + "status": 1, + "byzantium": true + }, + "args": [], + "solcInputHash": "d9ddc44152056b9c2865111aa614cbcf", + "metadata": "{\"compiler\":{\"version\":\"0.6.12+commit.27d51765\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"spender\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"Approval\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"previousAdminRole\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"newAdminRole\",\"type\":\"bytes32\"}],\"name\":\"RoleAdminChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"RoleGranted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"RoleRevoked\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"Transfer\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"DEFAULT_ADMIN_ROLE\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"DOMAIN_SEPARATOR\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"MINTER_ROLE\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"spender\",\"type\":\"address\"}],\"name\":\"allowance\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"spender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"approve\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"balanceOf\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"burn\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"burnFrom\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"decimals\",\"outputs\":[{\"internalType\":\"uint8\",\"name\":\"\",\"type\":\"uint8\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"spender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"subtractedValue\",\"type\":\"uint256\"}],\"name\":\"decreaseAllowance\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"}],\"name\":\"getRoleAdmin\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"internalType\":\"uint256\",\"name\":\"index\",\"type\":\"uint256\"}],\"name\":\"getRoleMember\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"}],\"name\":\"getRoleMemberCount\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"grantRole\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"hasRole\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"spender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"addedValue\",\"type\":\"uint256\"}],\"name\":\"increaseAllowance\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"string\",\"name\":\"name\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"symbol\",\"type\":\"string\"},{\"internalType\":\"uint8\",\"name\":\"decimals\",\"type\":\"uint8\"},{\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"}],\"name\":\"initialize\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"mint\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"name\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"}],\"name\":\"nonces\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"spender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"deadline\",\"type\":\"uint256\"},{\"internalType\":\"uint8\",\"name\":\"v\",\"type\":\"uint8\"},{\"internalType\":\"bytes32\",\"name\":\"r\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"s\",\"type\":\"bytes32\"}],\"name\":\"permit\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"renounceRole\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"revokeRole\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"symbol\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"totalSupply\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"recipient\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"transfer\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"recipient\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"transferFrom\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{\"DOMAIN_SEPARATOR()\":{\"details\":\"See {IERC20Permit-DOMAIN_SEPARATOR}.\"},\"allowance(address,address)\":{\"details\":\"See {IERC20-allowance}.\"},\"approve(address,uint256)\":{\"details\":\"See {IERC20-approve}. Requirements: - `spender` cannot be the zero address.\"},\"balanceOf(address)\":{\"details\":\"See {IERC20-balanceOf}.\"},\"burn(uint256)\":{\"details\":\"Destroys `amount` tokens from the caller. See {ERC20-_burn}.\"},\"burnFrom(address,uint256)\":{\"details\":\"Destroys `amount` tokens from `account`, deducting from the caller's allowance. See {ERC20-_burn} and {ERC20-allowance}. Requirements: - the caller must have allowance for ``accounts``'s tokens of at least `amount`.\"},\"decimals()\":{\"details\":\"Returns the number of decimals used to get its user representation. For example, if `decimals` equals `2`, a balance of `505` tokens should be displayed to a user as `5,05` (`505 / 10 ** 2`). Tokens usually opt for a value of 18, imitating the relationship between Ether and Wei. This is the value {ERC20} uses, unless {_setupDecimals} is called. NOTE: This information is only used for _display_ purposes: it in no way affects any of the arithmetic of the contract, including {IERC20-balanceOf} and {IERC20-transfer}.\"},\"decreaseAllowance(address,uint256)\":{\"details\":\"Atomically decreases the allowance granted to `spender` by the caller. This is an alternative to {approve} that can be used as a mitigation for problems described in {IERC20-approve}. Emits an {Approval} event indicating the updated allowance. Requirements: - `spender` cannot be the zero address. - `spender` must have allowance for the caller of at least `subtractedValue`.\"},\"getRoleAdmin(bytes32)\":{\"details\":\"Returns the admin role that controls `role`. See {grantRole} and {revokeRole}. To change a role's admin, use {_setRoleAdmin}.\"},\"getRoleMember(bytes32,uint256)\":{\"details\":\"Returns one of the accounts that have `role`. `index` must be a value between 0 and {getRoleMemberCount}, non-inclusive. Role bearers are not sorted in any particular way, and their ordering may change at any point. WARNING: When using {getRoleMember} and {getRoleMemberCount}, make sure you perform all queries on the same block. See the following https://forum.openzeppelin.com/t/iterating-over-elements-on-enumerableset-in-openzeppelin-contracts/2296[forum post] for more information.\"},\"getRoleMemberCount(bytes32)\":{\"details\":\"Returns the number of accounts that have `role`. Can be used together with {getRoleMember} to enumerate all bearers of a role.\"},\"grantRole(bytes32,address)\":{\"details\":\"Grants `role` to `account`. If `account` had not been already granted `role`, emits a {RoleGranted} event. Requirements: - the caller must have ``role``'s admin role.\"},\"hasRole(bytes32,address)\":{\"details\":\"Returns `true` if `account` has been granted `role`.\"},\"increaseAllowance(address,uint256)\":{\"details\":\"Atomically increases the allowance granted to `spender` by the caller. This is an alternative to {approve} that can be used as a mitigation for problems described in {IERC20-approve}. Emits an {Approval} event indicating the updated allowance. Requirements: - `spender` cannot be the zero address.\"},\"initialize(string,string,uint8,address)\":{\"params\":{\"decimals\":\"Token name\",\"name\":\"Token name\",\"owner\":\"admin address to be initialized with\",\"symbol\":\"Token symbol\"}},\"name()\":{\"details\":\"Returns the name of the token.\"},\"nonces(address)\":{\"details\":\"See {IERC20Permit-nonces}.\"},\"permit(address,address,uint256,uint256,uint8,bytes32,bytes32)\":{\"details\":\"See {IERC20Permit-permit}.\"},\"renounceRole(bytes32,address)\":{\"details\":\"Revokes `role` from the calling account. Roles are often managed via {grantRole} and {revokeRole}: this function's purpose is to provide a mechanism for accounts to lose their privileges if they are compromised (such as when a trusted device is misplaced). If the calling account had been granted `role`, emits a {RoleRevoked} event. Requirements: - the caller must be `account`.\"},\"revokeRole(bytes32,address)\":{\"details\":\"Revokes `role` from `account`. If `account` had been granted `role`, emits a {RoleRevoked} event. Requirements: - the caller must have ``role``'s admin role.\"},\"symbol()\":{\"details\":\"Returns the symbol of the token, usually a shorter version of the name.\"},\"totalSupply()\":{\"details\":\"See {IERC20-totalSupply}.\"},\"transfer(address,uint256)\":{\"details\":\"See {IERC20-transfer}. Requirements: - `recipient` cannot be the zero address. - the caller must have a balance of at least `amount`.\"},\"transferFrom(address,address,uint256)\":{\"details\":\"See {IERC20-transferFrom}. Emits an {Approval} event indicating the updated allowance. This is not required by the EIP. See the note at the beginning of {ERC20}. Requirements: - `sender` and `recipient` cannot be the zero address. - `sender` must have a balance of at least `amount`. - the caller must have allowance for ``sender``'s tokens of at least `amount`.\"}},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{\"initialize(string,string,uint8,address)\":{\"notice\":\"Initializes this ERC20 contract with the given parameters.\"}},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/bridge/SynapseERC20.sol\":\"SynapseERC20\"},\"evmVersion\":\"istanbul\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":10000},\"remappings\":[]},\"sources\":{\"@openzeppelin/contracts-upgradeable/access/AccessControlUpgradeable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity >=0.6.0 <0.8.0;\\n\\nimport \\\"../utils/EnumerableSetUpgradeable.sol\\\";\\nimport \\\"../utils/AddressUpgradeable.sol\\\";\\nimport \\\"../utils/ContextUpgradeable.sol\\\";\\nimport \\\"../proxy/Initializable.sol\\\";\\n\\n/**\\n * @dev Contract module that allows children to implement role-based access\\n * control mechanisms.\\n *\\n * Roles are referred to by their `bytes32` identifier. These should be exposed\\n * in the external API and be unique. The best way to achieve this is by\\n * using `public constant` hash digests:\\n *\\n * ```\\n * bytes32 public constant MY_ROLE = keccak256(\\\"MY_ROLE\\\");\\n * ```\\n *\\n * Roles can be used to represent a set of permissions. To restrict access to a\\n * function call, use {hasRole}:\\n *\\n * ```\\n * function foo() public {\\n * require(hasRole(MY_ROLE, msg.sender));\\n * ...\\n * }\\n * ```\\n *\\n * Roles can be granted and revoked dynamically via the {grantRole} and\\n * {revokeRole} functions. Each role has an associated admin role, and only\\n * accounts that have a role's admin role can call {grantRole} and {revokeRole}.\\n *\\n * By default, the admin role for all roles is `DEFAULT_ADMIN_ROLE`, which means\\n * that only accounts with this role will be able to grant or revoke other\\n * roles. More complex role relationships can be created by using\\n * {_setRoleAdmin}.\\n *\\n * WARNING: The `DEFAULT_ADMIN_ROLE` is also its own admin: it has permission to\\n * grant and revoke this role. Extra precautions should be taken to secure\\n * accounts that have been granted it.\\n */\\nabstract contract AccessControlUpgradeable is Initializable, ContextUpgradeable {\\n function __AccessControl_init() internal initializer {\\n __Context_init_unchained();\\n __AccessControl_init_unchained();\\n }\\n\\n function __AccessControl_init_unchained() internal initializer {\\n }\\n using EnumerableSetUpgradeable for EnumerableSetUpgradeable.AddressSet;\\n using AddressUpgradeable for address;\\n\\n struct RoleData {\\n EnumerableSetUpgradeable.AddressSet members;\\n bytes32 adminRole;\\n }\\n\\n mapping (bytes32 => RoleData) private _roles;\\n\\n bytes32 public constant DEFAULT_ADMIN_ROLE = 0x00;\\n\\n /**\\n * @dev Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole`\\n *\\n * `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite\\n * {RoleAdminChanged} not being emitted signaling this.\\n *\\n * _Available since v3.1._\\n */\\n event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole);\\n\\n /**\\n * @dev Emitted when `account` is granted `role`.\\n *\\n * `sender` is the account that originated the contract call, an admin role\\n * bearer except when using {_setupRole}.\\n */\\n event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender);\\n\\n /**\\n * @dev Emitted when `account` is revoked `role`.\\n *\\n * `sender` is the account that originated the contract call:\\n * - if using `revokeRole`, it is the admin role bearer\\n * - if using `renounceRole`, it is the role bearer (i.e. `account`)\\n */\\n event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender);\\n\\n /**\\n * @dev Returns `true` if `account` has been granted `role`.\\n */\\n function hasRole(bytes32 role, address account) public view returns (bool) {\\n return _roles[role].members.contains(account);\\n }\\n\\n /**\\n * @dev Returns the number of accounts that have `role`. Can be used\\n * together with {getRoleMember} to enumerate all bearers of a role.\\n */\\n function getRoleMemberCount(bytes32 role) public view returns (uint256) {\\n return _roles[role].members.length();\\n }\\n\\n /**\\n * @dev Returns one of the accounts that have `role`. `index` must be a\\n * value between 0 and {getRoleMemberCount}, non-inclusive.\\n *\\n * Role bearers are not sorted in any particular way, and their ordering may\\n * change at any point.\\n *\\n * WARNING: When using {getRoleMember} and {getRoleMemberCount}, make sure\\n * you perform all queries on the same block. See the following\\n * https://forum.openzeppelin.com/t/iterating-over-elements-on-enumerableset-in-openzeppelin-contracts/2296[forum post]\\n * for more information.\\n */\\n function getRoleMember(bytes32 role, uint256 index) public view returns (address) {\\n return _roles[role].members.at(index);\\n }\\n\\n /**\\n * @dev Returns the admin role that controls `role`. See {grantRole} and\\n * {revokeRole}.\\n *\\n * To change a role's admin, use {_setRoleAdmin}.\\n */\\n function getRoleAdmin(bytes32 role) public view returns (bytes32) {\\n return _roles[role].adminRole;\\n }\\n\\n /**\\n * @dev Grants `role` to `account`.\\n *\\n * If `account` had not been already granted `role`, emits a {RoleGranted}\\n * event.\\n *\\n * Requirements:\\n *\\n * - the caller must have ``role``'s admin role.\\n */\\n function grantRole(bytes32 role, address account) public virtual {\\n require(hasRole(_roles[role].adminRole, _msgSender()), \\\"AccessControl: sender must be an admin to grant\\\");\\n\\n _grantRole(role, account);\\n }\\n\\n /**\\n * @dev Revokes `role` from `account`.\\n *\\n * If `account` had been granted `role`, emits a {RoleRevoked} event.\\n *\\n * Requirements:\\n *\\n * - the caller must have ``role``'s admin role.\\n */\\n function revokeRole(bytes32 role, address account) public virtual {\\n require(hasRole(_roles[role].adminRole, _msgSender()), \\\"AccessControl: sender must be an admin to revoke\\\");\\n\\n _revokeRole(role, account);\\n }\\n\\n /**\\n * @dev Revokes `role` from the calling account.\\n *\\n * Roles are often managed via {grantRole} and {revokeRole}: this function's\\n * purpose is to provide a mechanism for accounts to lose their privileges\\n * if they are compromised (such as when a trusted device is misplaced).\\n *\\n * If the calling account had been granted `role`, emits a {RoleRevoked}\\n * event.\\n *\\n * Requirements:\\n *\\n * - the caller must be `account`.\\n */\\n function renounceRole(bytes32 role, address account) public virtual {\\n require(account == _msgSender(), \\\"AccessControl: can only renounce roles for self\\\");\\n\\n _revokeRole(role, account);\\n }\\n\\n /**\\n * @dev Grants `role` to `account`.\\n *\\n * If `account` had not been already granted `role`, emits a {RoleGranted}\\n * event. Note that unlike {grantRole}, this function doesn't perform any\\n * checks on the calling account.\\n *\\n * [WARNING]\\n * ====\\n * This function should only be called from the constructor when setting\\n * up the initial roles for the system.\\n *\\n * Using this function in any other way is effectively circumventing the admin\\n * system imposed by {AccessControl}.\\n * ====\\n */\\n function _setupRole(bytes32 role, address account) internal virtual {\\n _grantRole(role, account);\\n }\\n\\n /**\\n * @dev Sets `adminRole` as ``role``'s admin role.\\n *\\n * Emits a {RoleAdminChanged} event.\\n */\\n function _setRoleAdmin(bytes32 role, bytes32 adminRole) internal virtual {\\n emit RoleAdminChanged(role, _roles[role].adminRole, adminRole);\\n _roles[role].adminRole = adminRole;\\n }\\n\\n function _grantRole(bytes32 role, address account) private {\\n if (_roles[role].members.add(account)) {\\n emit RoleGranted(role, account, _msgSender());\\n }\\n }\\n\\n function _revokeRole(bytes32 role, address account) private {\\n if (_roles[role].members.remove(account)) {\\n emit RoleRevoked(role, account, _msgSender());\\n }\\n }\\n uint256[49] private __gap;\\n}\\n\",\"keccak256\":\"0xa3c77c9ea6b47301c7ab5bf3addc1d809d13a27a179c4629a1b55308e8633d14\",\"license\":\"MIT\"},\"@openzeppelin/contracts-upgradeable/cryptography/ECDSAUpgradeable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity >=0.6.0 <0.8.0;\\n\\n/**\\n * @dev Elliptic Curve Digital Signature Algorithm (ECDSA) operations.\\n *\\n * These functions can be used to verify that a message was signed by the holder\\n * of the private keys of a given address.\\n */\\nlibrary ECDSAUpgradeable {\\n /**\\n * @dev Returns the address that signed a hashed message (`hash`) with\\n * `signature`. This address can then be used for verification purposes.\\n *\\n * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:\\n * this function rejects them by requiring the `s` value to be in the lower\\n * half order, and the `v` value to be either 27 or 28.\\n *\\n * IMPORTANT: `hash` _must_ be the result of a hash operation for the\\n * verification to be secure: it is possible to craft signatures that\\n * recover to arbitrary addresses for non-hashed data. A safe way to ensure\\n * this is by receiving a hash of the original message (which may otherwise\\n * be too long), and then calling {toEthSignedMessageHash} on it.\\n */\\n function recover(bytes32 hash, bytes memory signature) internal pure returns (address) {\\n // Check the signature length\\n if (signature.length != 65) {\\n revert(\\\"ECDSA: invalid signature length\\\");\\n }\\n\\n // Divide the signature in r, s and v variables\\n bytes32 r;\\n bytes32 s;\\n uint8 v;\\n\\n // ecrecover takes the signature parameters, and the only way to get them\\n // currently is to use assembly.\\n // solhint-disable-next-line no-inline-assembly\\n assembly {\\n r := mload(add(signature, 0x20))\\n s := mload(add(signature, 0x40))\\n v := byte(0, mload(add(signature, 0x60)))\\n }\\n\\n return recover(hash, v, r, s);\\n }\\n\\n /**\\n * @dev Overload of {ECDSA-recover-bytes32-bytes-} that receives the `v`,\\n * `r` and `s` signature fields separately.\\n */\\n function recover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) internal pure returns (address) {\\n // EIP-2 still allows signature malleability for ecrecover(). Remove this possibility and make the signature\\n // unique. Appendix F in the Ethereum Yellow paper (https://ethereum.github.io/yellowpaper/paper.pdf), defines\\n // the valid range for s in (281): 0 < s < secp256k1n \\u00f7 2 + 1, and for v in (282): v \\u2208 {27, 28}. Most\\n // signatures from current libraries generate a unique signature with an s-value in the lower half order.\\n //\\n // If your library generates malleable signatures, such as s-values in the upper range, calculate a new s-value\\n // with 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 - s1 and flip v from 27 to 28 or\\n // vice versa. If your library also generates signatures with 0/1 for v instead 27/28, add 27 to v to accept\\n // these malleable signatures as well.\\n require(uint256(s) <= 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0, \\\"ECDSA: invalid signature 's' value\\\");\\n require(v == 27 || v == 28, \\\"ECDSA: invalid signature 'v' value\\\");\\n\\n // If the signature is valid (and not malleable), return the signer address\\n address signer = ecrecover(hash, v, r, s);\\n require(signer != address(0), \\\"ECDSA: invalid signature\\\");\\n\\n return signer;\\n }\\n\\n /**\\n * @dev Returns an Ethereum Signed Message, created from a `hash`. This\\n * replicates the behavior of the\\n * https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_sign[`eth_sign`]\\n * JSON-RPC method.\\n *\\n * See {recover}.\\n */\\n function toEthSignedMessageHash(bytes32 hash) internal pure returns (bytes32) {\\n // 32 is the length in bytes of hash,\\n // enforced by the type signature above\\n return keccak256(abi.encodePacked(\\\"\\\\x19Ethereum Signed Message:\\\\n32\\\", hash));\\n }\\n}\\n\",\"keccak256\":\"0xe348c45df01e0705c50ede5063d77111a996722ffb83f0a22979338a32b06887\",\"license\":\"MIT\"},\"@openzeppelin/contracts-upgradeable/drafts/EIP712Upgradeable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity >=0.6.0 <0.8.0;\\nimport \\\"../proxy/Initializable.sol\\\";\\n\\n/**\\n * @dev https://eips.ethereum.org/EIPS/eip-712[EIP 712] is a standard for hashing and signing of typed structured data.\\n *\\n * The encoding specified in the EIP is very generic, and such a generic implementation in Solidity is not feasible,\\n * thus this contract does not implement the encoding itself. Protocols need to implement the type-specific encoding\\n * they need in their contracts using a combination of `abi.encode` and `keccak256`.\\n *\\n * This contract implements the EIP 712 domain separator ({_domainSeparatorV4}) that is used as part of the encoding\\n * scheme, and the final step of the encoding to obtain the message digest that is then signed via ECDSA\\n * ({_hashTypedDataV4}).\\n *\\n * The implementation of the domain separator was designed to be as efficient as possible while still properly updating\\n * the chain id to protect against replay attacks on an eventual fork of the chain.\\n *\\n * NOTE: This contract implements the version of the encoding known as \\\"v4\\\", as implemented by the JSON RPC method\\n * https://docs.metamask.io/guide/signing-data.html[`eth_signTypedDataV4` in MetaMask].\\n *\\n * _Available since v3.4._\\n */\\nabstract contract EIP712Upgradeable is Initializable {\\n /* solhint-disable var-name-mixedcase */\\n bytes32 private _HASHED_NAME;\\n bytes32 private _HASHED_VERSION;\\n bytes32 private constant _TYPE_HASH = keccak256(\\\"EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)\\\");\\n /* solhint-enable var-name-mixedcase */\\n\\n /**\\n * @dev Initializes the domain separator and parameter caches.\\n *\\n * The meaning of `name` and `version` is specified in\\n * https://eips.ethereum.org/EIPS/eip-712#definition-of-domainseparator[EIP 712]:\\n *\\n * - `name`: the user readable name of the signing domain, i.e. the name of the DApp or the protocol.\\n * - `version`: the current major version of the signing domain.\\n *\\n * NOTE: These parameters cannot be changed except through a xref:learn::upgrading-smart-contracts.adoc[smart\\n * contract upgrade].\\n */\\n function __EIP712_init(string memory name, string memory version) internal initializer {\\n __EIP712_init_unchained(name, version);\\n }\\n\\n function __EIP712_init_unchained(string memory name, string memory version) internal initializer {\\n bytes32 hashedName = keccak256(bytes(name));\\n bytes32 hashedVersion = keccak256(bytes(version));\\n _HASHED_NAME = hashedName;\\n _HASHED_VERSION = hashedVersion;\\n }\\n\\n /**\\n * @dev Returns the domain separator for the current chain.\\n */\\n function _domainSeparatorV4() internal view returns (bytes32) {\\n return _buildDomainSeparator(_TYPE_HASH, _EIP712NameHash(), _EIP712VersionHash());\\n }\\n\\n function _buildDomainSeparator(bytes32 typeHash, bytes32 name, bytes32 version) private view returns (bytes32) {\\n return keccak256(\\n abi.encode(\\n typeHash,\\n name,\\n version,\\n _getChainId(),\\n address(this)\\n )\\n );\\n }\\n\\n /**\\n * @dev Given an already https://eips.ethereum.org/EIPS/eip-712#definition-of-hashstruct[hashed struct], this\\n * function returns the hash of the fully encoded EIP712 message for this domain.\\n *\\n * This hash can be used together with {ECDSA-recover} to obtain the signer of a message. For example:\\n *\\n * ```solidity\\n * bytes32 digest = _hashTypedDataV4(keccak256(abi.encode(\\n * keccak256(\\\"Mail(address to,string contents)\\\"),\\n * mailTo,\\n * keccak256(bytes(mailContents))\\n * )));\\n * address signer = ECDSA.recover(digest, signature);\\n * ```\\n */\\n function _hashTypedDataV4(bytes32 structHash) internal view virtual returns (bytes32) {\\n return keccak256(abi.encodePacked(\\\"\\\\x19\\\\x01\\\", _domainSeparatorV4(), structHash));\\n }\\n\\n function _getChainId() private view returns (uint256 chainId) {\\n this; // silence state mutability warning without generating bytecode - see https://github.com/ethereum/solidity/issues/2691\\n // solhint-disable-next-line no-inline-assembly\\n assembly {\\n chainId := chainid()\\n }\\n }\\n\\n /**\\n * @dev The hash of the name parameter for the EIP712 domain.\\n *\\n * NOTE: This function reads from storage by default, but can be redefined to return a constant value if gas costs\\n * are a concern.\\n */\\n function _EIP712NameHash() internal virtual view returns (bytes32) {\\n return _HASHED_NAME;\\n }\\n\\n /**\\n * @dev The hash of the version parameter for the EIP712 domain.\\n *\\n * NOTE: This function reads from storage by default, but can be redefined to return a constant value if gas costs\\n * are a concern.\\n */\\n function _EIP712VersionHash() internal virtual view returns (bytes32) {\\n return _HASHED_VERSION;\\n }\\n uint256[50] private __gap;\\n}\\n\",\"keccak256\":\"0x6cd0bc8c149150614ca3d4a3d3d21f844a0ab3032625f34fcfcf1c2c8b351638\",\"license\":\"MIT\"},\"@openzeppelin/contracts-upgradeable/drafts/ERC20PermitUpgradeable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity >=0.6.5 <0.8.0;\\n\\nimport \\\"../token/ERC20/ERC20Upgradeable.sol\\\";\\nimport \\\"./IERC20PermitUpgradeable.sol\\\";\\nimport \\\"../cryptography/ECDSAUpgradeable.sol\\\";\\nimport \\\"../utils/CountersUpgradeable.sol\\\";\\nimport \\\"./EIP712Upgradeable.sol\\\";\\nimport \\\"../proxy/Initializable.sol\\\";\\n\\n/**\\n * @dev Implementation of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in\\n * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612].\\n *\\n * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by\\n * presenting a message signed by the account. By not relying on `{IERC20-approve}`, the token holder account doesn't\\n * need to send a transaction, and thus is not required to hold Ether at all.\\n *\\n * _Available since v3.4._\\n */\\nabstract contract ERC20PermitUpgradeable is Initializable, ERC20Upgradeable, IERC20PermitUpgradeable, EIP712Upgradeable {\\n using CountersUpgradeable for CountersUpgradeable.Counter;\\n\\n mapping (address => CountersUpgradeable.Counter) private _nonces;\\n\\n // solhint-disable-next-line var-name-mixedcase\\n bytes32 private _PERMIT_TYPEHASH;\\n\\n /**\\n * @dev Initializes the {EIP712} domain separator using the `name` parameter, and setting `version` to `\\\"1\\\"`.\\n *\\n * It's a good idea to use the same `name` that is defined as the ERC20 token name.\\n */\\n function __ERC20Permit_init(string memory name) internal initializer {\\n __Context_init_unchained();\\n __EIP712_init_unchained(name, \\\"1\\\");\\n __ERC20Permit_init_unchained(name);\\n }\\n\\n function __ERC20Permit_init_unchained(string memory name) internal initializer {\\n _PERMIT_TYPEHASH = keccak256(\\\"Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)\\\");\\n }\\n\\n /**\\n * @dev See {IERC20Permit-permit}.\\n */\\n function permit(address owner, address spender, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s) public virtual override {\\n // solhint-disable-next-line not-rely-on-time\\n require(block.timestamp <= deadline, \\\"ERC20Permit: expired deadline\\\");\\n\\n bytes32 structHash = keccak256(\\n abi.encode(\\n _PERMIT_TYPEHASH,\\n owner,\\n spender,\\n value,\\n _nonces[owner].current(),\\n deadline\\n )\\n );\\n\\n bytes32 hash = _hashTypedDataV4(structHash);\\n\\n address signer = ECDSAUpgradeable.recover(hash, v, r, s);\\n require(signer == owner, \\\"ERC20Permit: invalid signature\\\");\\n\\n _nonces[owner].increment();\\n _approve(owner, spender, value);\\n }\\n\\n /**\\n * @dev See {IERC20Permit-nonces}.\\n */\\n function nonces(address owner) public view override returns (uint256) {\\n return _nonces[owner].current();\\n }\\n\\n /**\\n * @dev See {IERC20Permit-DOMAIN_SEPARATOR}.\\n */\\n // solhint-disable-next-line func-name-mixedcase\\n function DOMAIN_SEPARATOR() external view override returns (bytes32) {\\n return _domainSeparatorV4();\\n }\\n uint256[49] private __gap;\\n}\\n\",\"keccak256\":\"0xb30c40eb91411e29d23c8184b19fd37e6c2447f685631b798af2871ede483157\",\"license\":\"MIT\"},\"@openzeppelin/contracts-upgradeable/drafts/IERC20PermitUpgradeable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity >=0.6.0 <0.8.0;\\n\\n/**\\n * @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in\\n * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612].\\n *\\n * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by\\n * presenting a message signed by the account. By not relying on `{IERC20-approve}`, the token holder account doesn't\\n * need to send a transaction, and thus is not required to hold Ether at all.\\n */\\ninterface IERC20PermitUpgradeable {\\n /**\\n * @dev Sets `value` as the allowance of `spender` over `owner`'s tokens,\\n * given `owner`'s signed approval.\\n *\\n * IMPORTANT: The same issues {IERC20-approve} has related to transaction\\n * ordering also apply here.\\n *\\n * Emits an {Approval} event.\\n *\\n * Requirements:\\n *\\n * - `spender` cannot be the zero address.\\n * - `deadline` must be a timestamp in the future.\\n * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner`\\n * over the EIP712-formatted function arguments.\\n * - the signature must use ``owner``'s current nonce (see {nonces}).\\n *\\n * For more information on the signature format, see the\\n * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP\\n * section].\\n */\\n function permit(address owner, address spender, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s) external;\\n\\n /**\\n * @dev Returns the current nonce for `owner`. This value must be\\n * included whenever a signature is generated for {permit}.\\n *\\n * Every successful call to {permit} increases ``owner``'s nonce by one. This\\n * prevents a signature from being used multiple times.\\n */\\n function nonces(address owner) external view returns (uint256);\\n\\n /**\\n * @dev Returns the domain separator used in the encoding of the signature for `permit`, as defined by {EIP712}.\\n */\\n // solhint-disable-next-line func-name-mixedcase\\n function DOMAIN_SEPARATOR() external view returns (bytes32);\\n}\\n\",\"keccak256\":\"0x30c000f3a68d252b09a738c782e0fc9dbf168b81021a195de6102f8d095681ae\",\"license\":\"MIT\"},\"@openzeppelin/contracts-upgradeable/math/SafeMathUpgradeable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity >=0.6.0 <0.8.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 SafeMathUpgradeable {\\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\",\"keccak256\":\"0x0dd1e9b19801e3e7d900fbf4182d81e1afd23ad7be39504e33df6bbcba91d724\",\"license\":\"MIT\"},\"@openzeppelin/contracts-upgradeable/proxy/Initializable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\n// solhint-disable-next-line compiler-version\\npragma solidity >=0.4.24 <0.8.0;\\n\\nimport \\\"../utils/AddressUpgradeable.sol\\\";\\n\\n/**\\n * @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed\\n * behind a proxy. Since a proxied contract can't have a constructor, it's common to move constructor logic to an\\n * external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer\\n * function so it can only be called once. The {initializer} modifier provided by this contract will have this effect.\\n *\\n * TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as\\n * possible by providing the encoded function call as the `_data` argument to {UpgradeableProxy-constructor}.\\n *\\n * CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure\\n * that all initializers are idempotent. This is not verified automatically as constructors are by Solidity.\\n */\\nabstract contract Initializable {\\n\\n /**\\n * @dev Indicates that the contract has been initialized.\\n */\\n bool private _initialized;\\n\\n /**\\n * @dev Indicates that the contract is in the process of being initialized.\\n */\\n bool private _initializing;\\n\\n /**\\n * @dev Modifier to protect an initializer function from being invoked twice.\\n */\\n modifier initializer() {\\n require(_initializing || _isConstructor() || !_initialized, \\\"Initializable: contract is already initialized\\\");\\n\\n bool isTopLevelCall = !_initializing;\\n if (isTopLevelCall) {\\n _initializing = true;\\n _initialized = true;\\n }\\n\\n _;\\n\\n if (isTopLevelCall) {\\n _initializing = false;\\n }\\n }\\n\\n /// @dev Returns true if and only if the function is running in the constructor\\n function _isConstructor() private view returns (bool) {\\n return !AddressUpgradeable.isContract(address(this));\\n }\\n}\\n\",\"keccak256\":\"0xd8e4eb08dcc1d1860fb347ba5ffd595242b9a1b66d49a47f2b4cb51c3f35017e\",\"license\":\"MIT\"},\"@openzeppelin/contracts-upgradeable/token/ERC20/ERC20BurnableUpgradeable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity >=0.6.0 <0.8.0;\\n\\nimport \\\"../../utils/ContextUpgradeable.sol\\\";\\nimport \\\"./ERC20Upgradeable.sol\\\";\\nimport \\\"../../proxy/Initializable.sol\\\";\\n\\n/**\\n * @dev Extension of {ERC20} that allows token holders to destroy both their own\\n * tokens and those that they have an allowance for, in a way that can be\\n * recognized off-chain (via event analysis).\\n */\\nabstract contract ERC20BurnableUpgradeable is Initializable, ContextUpgradeable, ERC20Upgradeable {\\n function __ERC20Burnable_init() internal initializer {\\n __Context_init_unchained();\\n __ERC20Burnable_init_unchained();\\n }\\n\\n function __ERC20Burnable_init_unchained() internal initializer {\\n }\\n using SafeMathUpgradeable for uint256;\\n\\n /**\\n * @dev Destroys `amount` tokens from the caller.\\n *\\n * See {ERC20-_burn}.\\n */\\n function burn(uint256 amount) public virtual {\\n _burn(_msgSender(), amount);\\n }\\n\\n /**\\n * @dev Destroys `amount` tokens from `account`, deducting from the caller's\\n * allowance.\\n *\\n * See {ERC20-_burn} and {ERC20-allowance}.\\n *\\n * Requirements:\\n *\\n * - the caller must have allowance for ``accounts``'s tokens of at least\\n * `amount`.\\n */\\n function burnFrom(address account, uint256 amount) public virtual {\\n uint256 decreasedAllowance = allowance(account, _msgSender()).sub(amount, \\\"ERC20: burn amount exceeds allowance\\\");\\n\\n _approve(account, _msgSender(), decreasedAllowance);\\n _burn(account, amount);\\n }\\n uint256[50] private __gap;\\n}\\n\",\"keccak256\":\"0xd0359e87fe2618573f49a95e13d9dbc31521ad64526b135618abb2a2dc362fbe\",\"license\":\"MIT\"},\"@openzeppelin/contracts-upgradeable/token/ERC20/ERC20Upgradeable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity >=0.6.0 <0.8.0;\\n\\nimport \\\"../../utils/ContextUpgradeable.sol\\\";\\nimport \\\"./IERC20Upgradeable.sol\\\";\\nimport \\\"../../math/SafeMathUpgradeable.sol\\\";\\nimport \\\"../../proxy/Initializable.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 ERC20Upgradeable is Initializable, ContextUpgradeable, IERC20Upgradeable {\\n using SafeMathUpgradeable 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 function __ERC20_init(string memory name_, string memory symbol_) internal initializer {\\n __Context_init_unchained();\\n __ERC20_init_unchained(name_, symbol_);\\n }\\n\\n function __ERC20_init_unchained(string memory name_, string memory symbol_) internal initializer {\\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 uint256[44] private __gap;\\n}\\n\",\"keccak256\":\"0x506dd0718f9ace50588c13848167df5e04ae16abb56341afb10c31ff149bc79b\",\"license\":\"MIT\"},\"@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity >=0.6.0 <0.8.0;\\n\\n/**\\n * @dev Interface of the ERC20 standard as defined in the EIP.\\n */\\ninterface IERC20Upgradeable {\\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\",\"keccak256\":\"0xa1931c47a617014f858580db625aa0dcf343796f39acd4b5b51effc092a1f0a9\",\"license\":\"MIT\"},\"@openzeppelin/contracts-upgradeable/utils/AddressUpgradeable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity >=0.6.2 <0.8.0;\\n\\n/**\\n * @dev Collection of functions related to the address type\\n */\\nlibrary AddressUpgradeable {\\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 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\",\"keccak256\":\"0xfc5ea91fa9ceb1961023b2a6c978b902888c52b90847ac7813fe3b79524165f6\",\"license\":\"MIT\"},\"@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity >=0.6.0 <0.8.0;\\nimport \\\"../proxy/Initializable.sol\\\";\\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 ContextUpgradeable is Initializable {\\n function __Context_init() internal initializer {\\n __Context_init_unchained();\\n }\\n\\n function __Context_init_unchained() internal initializer {\\n }\\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 uint256[50] private __gap;\\n}\\n\",\"keccak256\":\"0xbbf8a21b9a66c48d45ff771b8563c6df19ba451d63dfb8380a865c1e1f29d1a0\",\"license\":\"MIT\"},\"@openzeppelin/contracts-upgradeable/utils/CountersUpgradeable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity >=0.6.0 <0.8.0;\\n\\nimport \\\"../math/SafeMathUpgradeable.sol\\\";\\n\\n/**\\n * @title Counters\\n * @author Matt Condon (@shrugs)\\n * @dev Provides counters that can only be incremented or decremented by one. This can be used e.g. to track the number\\n * of elements in a mapping, issuing ERC721 ids, or counting request ids.\\n *\\n * Include with `using Counters for Counters.Counter;`\\n * Since it is not possible to overflow a 256 bit integer with increments of one, `increment` can skip the {SafeMath}\\n * overflow check, thereby saving gas. This does assume however correct usage, in that the underlying `_value` is never\\n * directly accessed.\\n */\\nlibrary CountersUpgradeable {\\n using SafeMathUpgradeable for uint256;\\n\\n struct Counter {\\n // This variable should never be directly accessed by users of the library: interactions must be restricted to\\n // the library's function. As of Solidity v0.5.2, this cannot be enforced, though there is a proposal to add\\n // this feature: see https://github.com/ethereum/solidity/issues/4637\\n uint256 _value; // default: 0\\n }\\n\\n function current(Counter storage counter) internal view returns (uint256) {\\n return counter._value;\\n }\\n\\n function increment(Counter storage counter) internal {\\n // The {SafeMath} overflow check can be skipped here, see the comment at the top\\n counter._value += 1;\\n }\\n\\n function decrement(Counter storage counter) internal {\\n counter._value = counter._value.sub(1);\\n }\\n}\\n\",\"keccak256\":\"0xe0162cc9b4d619790be38ce4c184a1cd33d41698629ae6bcac00049f24f6cce8\",\"license\":\"MIT\"},\"@openzeppelin/contracts-upgradeable/utils/EnumerableSetUpgradeable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity >=0.6.0 <0.8.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 EnumerableSetUpgradeable {\\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\",\"keccak256\":\"0x20714cf126a1a984613579156d3cbc726db8025d8400e1db1d2bb714edaba335\",\"license\":\"MIT\"},\"contracts/bridge/SynapseERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.6.12;\\n\\nimport \\\"@openzeppelin/contracts-upgradeable/token/ERC20/ERC20Upgradeable.sol\\\";\\nimport \\\"@openzeppelin/contracts-upgradeable/token/ERC20/ERC20BurnableUpgradeable.sol\\\";\\nimport \\\"@openzeppelin/contracts-upgradeable/drafts/ERC20PermitUpgradeable.sol\\\";\\nimport \\\"@openzeppelin/contracts-upgradeable/access/AccessControlUpgradeable.sol\\\";\\nimport \\\"@openzeppelin/contracts-upgradeable/proxy/Initializable.sol\\\";\\n\\ncontract SynapseERC20 is\\n Initializable,\\n ContextUpgradeable,\\n AccessControlUpgradeable,\\n ERC20BurnableUpgradeable,\\n ERC20PermitUpgradeable\\n{\\n bytes32 public constant MINTER_ROLE = keccak256(\\\"MINTER_ROLE\\\");\\n\\n /**\\n * @notice Initializes this ERC20 contract with the given parameters.\\n * @param name Token name\\n * @param symbol Token symbol\\n * @param decimals Token name\\n * @param owner admin address to be initialized with\\n */\\n function initialize(\\n string memory name,\\n string memory symbol,\\n uint8 decimals,\\n address owner\\n ) external initializer {\\n __Context_init_unchained();\\n __AccessControl_init_unchained();\\n __ERC20_init_unchained(name, symbol);\\n __ERC20Burnable_init_unchained();\\n _setupDecimals(decimals);\\n __ERC20Permit_init(name);\\n _setupRole(DEFAULT_ADMIN_ROLE, owner);\\n }\\n\\n function mint(address to, uint256 amount) external {\\n require(hasRole(MINTER_ROLE, msg.sender), \\\"Not a minter\\\");\\n _mint(to, amount);\\n }\\n}\\n\",\"keccak256\":\"0x62201e7f62c9954664d7250cd5d6997729ff226d8eb246be911e3b59b3d976f7\",\"license\":\"MIT\"}},\"version\":1}", + "bytecode": "0x608060405234801561001057600080fd5b50612213806100206000396000f3fe608060405234801561001057600080fd5b50600436106101b95760003560e01c806379cc6790116100f9578063a9059cbb11610097578063d539139311610071578063d539139314610596578063d547741f1461059e578063dd62ed3e146105ca578063de7ea79d146105f8576101b9565b8063a9059cbb146104fc578063ca15c87314610528578063d505accf14610545576101b9565b806391d14854116100d357806391d148541461049457806395d89b41146104c0578063a217fddf146104c8578063a457c2d7146104d0576101b9565b806379cc6790146104035780637ecebe001461042f5780639010d07c14610455576101b9565b8063313ce567116101665780633950935111610140578063395093511461036857806340c10f191461039457806342966c68146103c057806370a08231146103dd576101b9565b8063313ce567146103165780633644e5151461033457806336568abe1461033c576101b9565b806323b872dd1161019757806323b872dd14610295578063248a9ca3146102cb5780632f2ff15d146102e8576101b9565b806306fdde03146101be578063095ea7b31461023b57806318160ddd1461027b575b600080fd5b6101c6610736565b6040805160208082528351818301528351919283929083019185019080838360005b838110156102005781810151838201526020016101e8565b50505050905090810190601f16801561022d5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b6102676004803603604081101561025157600080fd5b506001600160a01b0381351690602001356107ea565b604080519115158252519081900360200190f35b610283610808565b60408051918252519081900360200190f35b610267600480360360608110156102ab57600080fd5b506001600160a01b0381358116916020810135909116906040013561080e565b610283600480360360208110156102e157600080fd5b5035610895565b610314600480360360408110156102fe57600080fd5b50803590602001356001600160a01b03166108aa565b005b61031e610916565b6040805160ff9092168252519081900360200190f35b61028361091f565b6103146004803603604081101561035257600080fd5b50803590602001356001600160a01b031661092e565b6102676004803603604081101561037e57600080fd5b506001600160a01b03813516906020013561098f565b610314600480360360408110156103aa57600080fd5b506001600160a01b0381351690602001356109dd565b610314600480360360208110156103d657600080fd5b5035610a62565b610283600480360360208110156103f357600080fd5b50356001600160a01b0316610a76565b6103146004803603604081101561041957600080fd5b506001600160a01b038135169060200135610a91565b6102836004803603602081101561044557600080fd5b50356001600160a01b0316610aeb565b6104786004803603604081101561046b57600080fd5b5080359060200135610b0c565b604080516001600160a01b039092168252519081900360200190f35b610267600480360360408110156104aa57600080fd5b50803590602001356001600160a01b0316610b2b565b6101c6610b43565b610283610bc2565b610267600480360360408110156104e657600080fd5b506001600160a01b038135169060200135610bc7565b6102676004803603604081101561051257600080fd5b506001600160a01b038135169060200135610c2f565b6102836004803603602081101561053e57600080fd5b5035610c43565b610314600480360360e081101561055b57600080fd5b506001600160a01b03813581169160208101359091169060408101359060608101359060ff6080820135169060a08101359060c00135610c5a565b610283610dfd565b610314600480360360408110156105b457600080fd5b50803590602001356001600160a01b0316610e21565b610283600480360360408110156105e057600080fd5b506001600160a01b0381358116916020013516610e7a565b6103146004803603608081101561060e57600080fd5b81019060208101813564010000000081111561062957600080fd5b82018360208201111561063b57600080fd5b8035906020019184600183028401116401000000008311171561065d57600080fd5b91908080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525092959493602081019350359150506401000000008111156106b057600080fd5b8201836020820111156106c257600080fd5b803590602001918460018302840111640100000000831117156106e457600080fd5b91908080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509295505050813560ff16925050602001356001600160a01b0316610ea5565b60688054604080516020601f60027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6101006001881615020190951694909404938401819004810282018101909252828152606093909290918301828280156107e05780601f106107b5576101008083540402835291602001916107e0565b820191906000526020600020905b8154815290600101906020018083116107c357829003601f168201915b5050505050905090565b60006107fe6107f7610f8a565b8484610f8e565b5060015b92915050565b60675490565b600061081b84848461107a565b61088b84610827610f8a565b610886856040518060600160405280602881526020016120d4602891396001600160a01b038a16600090815260666020526040812090610865610f8a565b6001600160a01b0316815260208101919091526040016000205491906111d7565b610f8e565b5060019392505050565b60009081526033602052604090206002015490565b6000828152603360205260409020600201546108cd906108c8610f8a565b610b2b565b6109085760405162461bcd60e51b815260040180806020018281038252602f815260200180611f99602f913960400191505060405180910390fd5b610912828261126e565b5050565b606a5460ff1690565b60006109296112d7565b905090565b610936610f8a565b6001600160a01b0316816001600160a01b0316146109855760405162461bcd60e51b815260040180806020018281038252602f8152602001806121af602f913960400191505060405180910390fd5b6109128282611312565b60006107fe61099c610f8a565b8461088685606660006109ad610f8a565b6001600160a01b03908116825260208083019390935260409182016000908120918c16815292529020549061137b565b610a077f9f2df0fed2c77648de5860a4cc508cd0818c85b8b8a1ab4ceeef8d981c8956a633610b2b565b610a58576040805162461bcd60e51b815260206004820152600c60248201527f4e6f742061206d696e7465720000000000000000000000000000000000000000604482015290519081900360640190fd5b61091282826113d5565b610a73610a6d610f8a565b826114c7565b50565b6001600160a01b031660009081526065602052604090205490565b6000610ac8826040518060600160405280602481526020016120fc60249139610ac186610abc610f8a565b610e7a565b91906111d7565b9050610adc83610ad6610f8a565b83610f8e565b610ae683836114c7565b505050565b6001600160a01b038116600090815260fd60205260408120610802906115c3565b6000828152603360205260408120610b2490836115c7565b9392505050565b6000828152603360205260408120610b2490836115d3565b60698054604080516020601f60027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6101006001881615020190951694909404938401819004810282018101909252828152606093909290918301828280156107e05780601f106107b5576101008083540402835291602001916107e0565b600081565b60006107fe610bd4610f8a565b846108868560405180606001604052806025815260200161218a6025913960666000610bfe610f8a565b6001600160a01b03908116825260208083019390935260409182016000908120918d168152925290205491906111d7565b60006107fe610c3c610f8a565b848461107a565b6000818152603360205260408120610802906115e8565b83421115610caf576040805162461bcd60e51b815260206004820152601d60248201527f45524332305065726d69743a206578706972656420646561646c696e65000000604482015290519081900360640190fd5b600060fe54888888610ce460fd60008e6001600160a01b03166001600160a01b031681526020019081526020016000206115c3565b8960405160200180878152602001866001600160a01b03168152602001856001600160a01b0316815260200184815260200183815260200182815260200196505050505050506040516020818303038152906040528051906020012090506000610d4d826115f3565b90506000610d5d8287878761165a565b9050896001600160a01b0316816001600160a01b031614610dc5576040805162461bcd60e51b815260206004820152601e60248201527f45524332305065726d69743a20696e76616c6964207369676e61747572650000604482015290519081900360640190fd5b6001600160a01b038a16600090815260fd60205260409020610de6906117f6565b610df18a8a8a610f8e565b50505050505050505050565b7f9f2df0fed2c77648de5860a4cc508cd0818c85b8b8a1ab4ceeef8d981c8956a681565b600082815260336020526040902060020154610e3f906108c8610f8a565b6109855760405162461bcd60e51b81526004018080602001828103825260308152602001806120546030913960400191505060405180910390fd5b6001600160a01b03918216600090815260666020908152604080832093909416825291909152205490565b600054610100900460ff1680610ebe5750610ebe6117ff565b80610ecc575060005460ff16155b610f075760405162461bcd60e51b815260040180806020018281038252602e815260200180612084602e913960400191505060405180910390fd5b600054610100900460ff16158015610f32576000805460ff1961ff0019909116610100171660011790555b610f3a611810565b610f42611810565b610f4c85856118b1565b610f54611810565b610f5d83611989565b610f668561199f565b610f71600083610908565b8015610f83576000805461ff00191690555b5050505050565b3390565b6001600160a01b038316610fd35760405162461bcd60e51b81526004018080602001828103825260248152602001806121666024913960400191505060405180910390fd5b6001600160a01b0382166110185760405162461bcd60e51b8152600401808060200182810382526022815260200180611fea6022913960400191505060405180910390fd5b6001600160a01b03808416600081815260666020908152604080832094871680845294825291829020859055815185815291517f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b9259281900390910190a3505050565b6001600160a01b0383166110bf5760405162461bcd60e51b81526004018080602001828103825260258152602001806121416025913960400191505060405180910390fd5b6001600160a01b0382166111045760405162461bcd60e51b8152600401808060200182810382526023815260200180611f766023913960400191505060405180910390fd5b61110f838383610ae6565b61114c8160405180606001604052806026815260200161200c602691396001600160a01b03861660009081526065602052604090205491906111d7565b6001600160a01b03808516600090815260656020526040808220939093559084168152205461117b908261137b565b6001600160a01b0380841660008181526065602090815260409182902094909455805185815290519193928716927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef92918290030190a3505050565b600081848411156112665760405162461bcd60e51b81526004018080602001828103825283818151815260200191508051906020019080838360005b8381101561122b578181015183820152602001611213565b50505050905090810190601f1680156112585780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b505050900390565b60008281526033602052604090206112869082611a91565b1561091257611293610f8a565b6001600160a01b0316816001600160a01b0316837f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a45050565b60006109297f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f611305611aa6565b61130d611aac565b611ab2565b600082815260336020526040902061132a9082611b14565b1561091257611337610f8a565b6001600160a01b0316816001600160a01b0316837ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b60405160405180910390a45050565b600082820183811015610b24576040805162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b6001600160a01b038216611430576040805162461bcd60e51b815260206004820152601f60248201527f45524332303a206d696e7420746f20746865207a65726f206164647265737300604482015290519081900360640190fd5b61143c60008383610ae6565b606754611449908261137b565b6067556001600160a01b03821660009081526065602052604090205461146f908261137b565b6001600160a01b03831660008181526065602090815260408083209490945583518581529351929391927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9281900390910190a35050565b6001600160a01b03821661150c5760405162461bcd60e51b81526004018080602001828103825260218152602001806121206021913960400191505060405180910390fd5b61151882600083610ae6565b61155581604051806060016040528060228152602001611fc8602291396001600160a01b03851660009081526065602052604090205491906111d7565b6001600160a01b03831660009081526065602052604090205560675461157b9082611b29565b6067556040805182815290516000916001600160a01b038516917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9181900360200190a35050565b5490565b6000610b248383611b86565b6000610b24836001600160a01b038416611bea565b6000610802826115c3565b60006115fd6112d7565b8260405160200180807f190100000000000000000000000000000000000000000000000000000000000081525060020183815260200182815260200192505050604051602081830303815290604052805190602001209050919050565b60007f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a08211156116bb5760405162461bcd60e51b81526004018080602001828103825260228152602001806120326022913960400191505060405180910390fd5b8360ff16601b14806116d057508360ff16601c145b61170b5760405162461bcd60e51b81526004018080602001828103825260228152602001806120b26022913960400191505060405180910390fd5b600060018686868660405160008152602001604052604051808581526020018460ff1681526020018381526020018281526020019450505050506020604051602081039080840390855afa158015611767573d6000803e3d6000fd5b50506040517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe001519150506001600160a01b0381166117ed576040805162461bcd60e51b815260206004820152601860248201527f45434453413a20696e76616c6964207369676e61747572650000000000000000604482015290519081900360640190fd5b95945050505050565b80546001019055565b600061180a30611c02565b15905090565b600054610100900460ff168061182957506118296117ff565b80611837575060005460ff16155b6118725760405162461bcd60e51b815260040180806020018281038252602e815260200180612084602e913960400191505060405180910390fd5b600054610100900460ff1615801561189d576000805460ff1961ff0019909116610100171660011790555b8015610a73576000805461ff001916905550565b600054610100900460ff16806118ca57506118ca6117ff565b806118d8575060005460ff16155b6119135760405162461bcd60e51b815260040180806020018281038252602e815260200180612084602e913960400191505060405180910390fd5b600054610100900460ff1615801561193e576000805460ff1961ff0019909116610100171660011790555b8251611951906068906020860190611ec0565b508151611965906069906020850190611ec0565b50606a805460ff191660121790558015610ae6576000805461ff0019169055505050565b606a805460ff191660ff92909216919091179055565b600054610100900460ff16806119b857506119b86117ff565b806119c6575060005460ff16155b611a015760405162461bcd60e51b815260040180806020018281038252602e815260200180612084602e913960400191505060405180910390fd5b600054610100900460ff16158015611a2c576000805460ff1961ff0019909116610100171660011790555b611a34611810565b611a73826040518060400160405280600181526020017f3100000000000000000000000000000000000000000000000000000000000000815250611c08565b611a7c82611cc8565b8015610912576000805461ff00191690555050565b6000610b24836001600160a01b038416611d8e565b60c95490565b60ca5490565b6000838383611abf611dd8565b3060405160200180868152602001858152602001848152602001838152602001826001600160a01b03168152602001955050505050506040516020818303038152906040528051906020012090509392505050565b6000610b24836001600160a01b038416611ddc565b600082821115611b80576040805162461bcd60e51b815260206004820152601e60248201527f536166654d6174683a207375627472616374696f6e206f766572666c6f770000604482015290519081900360640190fd5b50900390565b81546000908210611bc85760405162461bcd60e51b8152600401808060200182810382526022815260200180611f546022913960400191505060405180910390fd5b826000018281548110611bd757fe5b9060005260206000200154905092915050565b60009081526001919091016020526040902054151590565b3b151590565b600054610100900460ff1680611c215750611c216117ff565b80611c2f575060005460ff16155b611c6a5760405162461bcd60e51b815260040180806020018281038252602e815260200180612084602e913960400191505060405180910390fd5b600054610100900460ff16158015611c95576000805460ff1961ff0019909116610100171660011790555b825160208085019190912083519184019190912060c99190915560ca558015610ae6576000805461ff0019169055505050565b600054610100900460ff1680611ce15750611ce16117ff565b80611cef575060005460ff16155b611d2a5760405162461bcd60e51b815260040180806020018281038252602e815260200180612084602e913960400191505060405180910390fd5b600054610100900460ff16158015611d55576000805460ff1961ff0019909116610100171660011790555b7f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c960fe558015610912576000805461ff00191690555050565b6000611d9a8383611bea565b611dd057508154600181810184556000848152602080822090930184905584548482528286019093526040902091909155610802565b506000610802565b4690565b60008181526001830160205260408120548015611eb65783547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8083019190810190600090879083908110611e2d57fe5b9060005260206000200154905080876000018481548110611e4a57fe5b600091825260208083209091019290925582815260018981019092526040902090840190558654879080611e7a57fe5b60019003818190600052602060002001600090559055866001016000878152602001908152602001600020600090556001945050505050610802565b6000915050610802565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f10611f0157805160ff1916838001178555611f2e565b82800160010185558215611f2e579182015b82811115611f2e578251825591602001919060010190611f13565b50611f3a929150611f3e565b5090565b5b80821115611f3a5760008155600101611f3f56fe456e756d657261626c655365743a20696e646578206f7574206f6620626f756e647345524332303a207472616e7366657220746f20746865207a65726f2061646472657373416363657373436f6e74726f6c3a2073656e646572206d75737420626520616e2061646d696e20746f206772616e7445524332303a206275726e20616d6f756e7420657863656564732062616c616e636545524332303a20617070726f766520746f20746865207a65726f206164647265737345524332303a207472616e7366657220616d6f756e7420657863656564732062616c616e636545434453413a20696e76616c6964207369676e6174757265202773272076616c7565416363657373436f6e74726f6c3a2073656e646572206d75737420626520616e2061646d696e20746f207265766f6b65496e697469616c697a61626c653a20636f6e747261637420697320616c726561647920696e697469616c697a656445434453413a20696e76616c6964207369676e6174757265202776272076616c756545524332303a207472616e7366657220616d6f756e74206578636565647320616c6c6f77616e636545524332303a206275726e20616d6f756e74206578636565647320616c6c6f77616e636545524332303a206275726e2066726f6d20746865207a65726f206164647265737345524332303a207472616e736665722066726f6d20746865207a65726f206164647265737345524332303a20617070726f76652066726f6d20746865207a65726f206164647265737345524332303a2064656372656173656420616c6c6f77616e63652062656c6f77207a65726f416363657373436f6e74726f6c3a2063616e206f6e6c792072656e6f756e636520726f6c657320666f722073656c66a2646970667358221220e7c3753b08173a11ca96acfac750f90800b1683e662b545723723a1385793bd164736f6c634300060c0033", + "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106101b95760003560e01c806379cc6790116100f9578063a9059cbb11610097578063d539139311610071578063d539139314610596578063d547741f1461059e578063dd62ed3e146105ca578063de7ea79d146105f8576101b9565b8063a9059cbb146104fc578063ca15c87314610528578063d505accf14610545576101b9565b806391d14854116100d357806391d148541461049457806395d89b41146104c0578063a217fddf146104c8578063a457c2d7146104d0576101b9565b806379cc6790146104035780637ecebe001461042f5780639010d07c14610455576101b9565b8063313ce567116101665780633950935111610140578063395093511461036857806340c10f191461039457806342966c68146103c057806370a08231146103dd576101b9565b8063313ce567146103165780633644e5151461033457806336568abe1461033c576101b9565b806323b872dd1161019757806323b872dd14610295578063248a9ca3146102cb5780632f2ff15d146102e8576101b9565b806306fdde03146101be578063095ea7b31461023b57806318160ddd1461027b575b600080fd5b6101c6610736565b6040805160208082528351818301528351919283929083019185019080838360005b838110156102005781810151838201526020016101e8565b50505050905090810190601f16801561022d5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b6102676004803603604081101561025157600080fd5b506001600160a01b0381351690602001356107ea565b604080519115158252519081900360200190f35b610283610808565b60408051918252519081900360200190f35b610267600480360360608110156102ab57600080fd5b506001600160a01b0381358116916020810135909116906040013561080e565b610283600480360360208110156102e157600080fd5b5035610895565b610314600480360360408110156102fe57600080fd5b50803590602001356001600160a01b03166108aa565b005b61031e610916565b6040805160ff9092168252519081900360200190f35b61028361091f565b6103146004803603604081101561035257600080fd5b50803590602001356001600160a01b031661092e565b6102676004803603604081101561037e57600080fd5b506001600160a01b03813516906020013561098f565b610314600480360360408110156103aa57600080fd5b506001600160a01b0381351690602001356109dd565b610314600480360360208110156103d657600080fd5b5035610a62565b610283600480360360208110156103f357600080fd5b50356001600160a01b0316610a76565b6103146004803603604081101561041957600080fd5b506001600160a01b038135169060200135610a91565b6102836004803603602081101561044557600080fd5b50356001600160a01b0316610aeb565b6104786004803603604081101561046b57600080fd5b5080359060200135610b0c565b604080516001600160a01b039092168252519081900360200190f35b610267600480360360408110156104aa57600080fd5b50803590602001356001600160a01b0316610b2b565b6101c6610b43565b610283610bc2565b610267600480360360408110156104e657600080fd5b506001600160a01b038135169060200135610bc7565b6102676004803603604081101561051257600080fd5b506001600160a01b038135169060200135610c2f565b6102836004803603602081101561053e57600080fd5b5035610c43565b610314600480360360e081101561055b57600080fd5b506001600160a01b03813581169160208101359091169060408101359060608101359060ff6080820135169060a08101359060c00135610c5a565b610283610dfd565b610314600480360360408110156105b457600080fd5b50803590602001356001600160a01b0316610e21565b610283600480360360408110156105e057600080fd5b506001600160a01b0381358116916020013516610e7a565b6103146004803603608081101561060e57600080fd5b81019060208101813564010000000081111561062957600080fd5b82018360208201111561063b57600080fd5b8035906020019184600183028401116401000000008311171561065d57600080fd5b91908080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525092959493602081019350359150506401000000008111156106b057600080fd5b8201836020820111156106c257600080fd5b803590602001918460018302840111640100000000831117156106e457600080fd5b91908080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509295505050813560ff16925050602001356001600160a01b0316610ea5565b60688054604080516020601f60027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6101006001881615020190951694909404938401819004810282018101909252828152606093909290918301828280156107e05780601f106107b5576101008083540402835291602001916107e0565b820191906000526020600020905b8154815290600101906020018083116107c357829003601f168201915b5050505050905090565b60006107fe6107f7610f8a565b8484610f8e565b5060015b92915050565b60675490565b600061081b84848461107a565b61088b84610827610f8a565b610886856040518060600160405280602881526020016120d4602891396001600160a01b038a16600090815260666020526040812090610865610f8a565b6001600160a01b0316815260208101919091526040016000205491906111d7565b610f8e565b5060019392505050565b60009081526033602052604090206002015490565b6000828152603360205260409020600201546108cd906108c8610f8a565b610b2b565b6109085760405162461bcd60e51b815260040180806020018281038252602f815260200180611f99602f913960400191505060405180910390fd5b610912828261126e565b5050565b606a5460ff1690565b60006109296112d7565b905090565b610936610f8a565b6001600160a01b0316816001600160a01b0316146109855760405162461bcd60e51b815260040180806020018281038252602f8152602001806121af602f913960400191505060405180910390fd5b6109128282611312565b60006107fe61099c610f8a565b8461088685606660006109ad610f8a565b6001600160a01b03908116825260208083019390935260409182016000908120918c16815292529020549061137b565b610a077f9f2df0fed2c77648de5860a4cc508cd0818c85b8b8a1ab4ceeef8d981c8956a633610b2b565b610a58576040805162461bcd60e51b815260206004820152600c60248201527f4e6f742061206d696e7465720000000000000000000000000000000000000000604482015290519081900360640190fd5b61091282826113d5565b610a73610a6d610f8a565b826114c7565b50565b6001600160a01b031660009081526065602052604090205490565b6000610ac8826040518060600160405280602481526020016120fc60249139610ac186610abc610f8a565b610e7a565b91906111d7565b9050610adc83610ad6610f8a565b83610f8e565b610ae683836114c7565b505050565b6001600160a01b038116600090815260fd60205260408120610802906115c3565b6000828152603360205260408120610b2490836115c7565b9392505050565b6000828152603360205260408120610b2490836115d3565b60698054604080516020601f60027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6101006001881615020190951694909404938401819004810282018101909252828152606093909290918301828280156107e05780601f106107b5576101008083540402835291602001916107e0565b600081565b60006107fe610bd4610f8a565b846108868560405180606001604052806025815260200161218a6025913960666000610bfe610f8a565b6001600160a01b03908116825260208083019390935260409182016000908120918d168152925290205491906111d7565b60006107fe610c3c610f8a565b848461107a565b6000818152603360205260408120610802906115e8565b83421115610caf576040805162461bcd60e51b815260206004820152601d60248201527f45524332305065726d69743a206578706972656420646561646c696e65000000604482015290519081900360640190fd5b600060fe54888888610ce460fd60008e6001600160a01b03166001600160a01b031681526020019081526020016000206115c3565b8960405160200180878152602001866001600160a01b03168152602001856001600160a01b0316815260200184815260200183815260200182815260200196505050505050506040516020818303038152906040528051906020012090506000610d4d826115f3565b90506000610d5d8287878761165a565b9050896001600160a01b0316816001600160a01b031614610dc5576040805162461bcd60e51b815260206004820152601e60248201527f45524332305065726d69743a20696e76616c6964207369676e61747572650000604482015290519081900360640190fd5b6001600160a01b038a16600090815260fd60205260409020610de6906117f6565b610df18a8a8a610f8e565b50505050505050505050565b7f9f2df0fed2c77648de5860a4cc508cd0818c85b8b8a1ab4ceeef8d981c8956a681565b600082815260336020526040902060020154610e3f906108c8610f8a565b6109855760405162461bcd60e51b81526004018080602001828103825260308152602001806120546030913960400191505060405180910390fd5b6001600160a01b03918216600090815260666020908152604080832093909416825291909152205490565b600054610100900460ff1680610ebe5750610ebe6117ff565b80610ecc575060005460ff16155b610f075760405162461bcd60e51b815260040180806020018281038252602e815260200180612084602e913960400191505060405180910390fd5b600054610100900460ff16158015610f32576000805460ff1961ff0019909116610100171660011790555b610f3a611810565b610f42611810565b610f4c85856118b1565b610f54611810565b610f5d83611989565b610f668561199f565b610f71600083610908565b8015610f83576000805461ff00191690555b5050505050565b3390565b6001600160a01b038316610fd35760405162461bcd60e51b81526004018080602001828103825260248152602001806121666024913960400191505060405180910390fd5b6001600160a01b0382166110185760405162461bcd60e51b8152600401808060200182810382526022815260200180611fea6022913960400191505060405180910390fd5b6001600160a01b03808416600081815260666020908152604080832094871680845294825291829020859055815185815291517f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b9259281900390910190a3505050565b6001600160a01b0383166110bf5760405162461bcd60e51b81526004018080602001828103825260258152602001806121416025913960400191505060405180910390fd5b6001600160a01b0382166111045760405162461bcd60e51b8152600401808060200182810382526023815260200180611f766023913960400191505060405180910390fd5b61110f838383610ae6565b61114c8160405180606001604052806026815260200161200c602691396001600160a01b03861660009081526065602052604090205491906111d7565b6001600160a01b03808516600090815260656020526040808220939093559084168152205461117b908261137b565b6001600160a01b0380841660008181526065602090815260409182902094909455805185815290519193928716927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef92918290030190a3505050565b600081848411156112665760405162461bcd60e51b81526004018080602001828103825283818151815260200191508051906020019080838360005b8381101561122b578181015183820152602001611213565b50505050905090810190601f1680156112585780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b505050900390565b60008281526033602052604090206112869082611a91565b1561091257611293610f8a565b6001600160a01b0316816001600160a01b0316837f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a45050565b60006109297f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f611305611aa6565b61130d611aac565b611ab2565b600082815260336020526040902061132a9082611b14565b1561091257611337610f8a565b6001600160a01b0316816001600160a01b0316837ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b60405160405180910390a45050565b600082820183811015610b24576040805162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b6001600160a01b038216611430576040805162461bcd60e51b815260206004820152601f60248201527f45524332303a206d696e7420746f20746865207a65726f206164647265737300604482015290519081900360640190fd5b61143c60008383610ae6565b606754611449908261137b565b6067556001600160a01b03821660009081526065602052604090205461146f908261137b565b6001600160a01b03831660008181526065602090815260408083209490945583518581529351929391927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9281900390910190a35050565b6001600160a01b03821661150c5760405162461bcd60e51b81526004018080602001828103825260218152602001806121206021913960400191505060405180910390fd5b61151882600083610ae6565b61155581604051806060016040528060228152602001611fc8602291396001600160a01b03851660009081526065602052604090205491906111d7565b6001600160a01b03831660009081526065602052604090205560675461157b9082611b29565b6067556040805182815290516000916001600160a01b038516917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9181900360200190a35050565b5490565b6000610b248383611b86565b6000610b24836001600160a01b038416611bea565b6000610802826115c3565b60006115fd6112d7565b8260405160200180807f190100000000000000000000000000000000000000000000000000000000000081525060020183815260200182815260200192505050604051602081830303815290604052805190602001209050919050565b60007f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a08211156116bb5760405162461bcd60e51b81526004018080602001828103825260228152602001806120326022913960400191505060405180910390fd5b8360ff16601b14806116d057508360ff16601c145b61170b5760405162461bcd60e51b81526004018080602001828103825260228152602001806120b26022913960400191505060405180910390fd5b600060018686868660405160008152602001604052604051808581526020018460ff1681526020018381526020018281526020019450505050506020604051602081039080840390855afa158015611767573d6000803e3d6000fd5b50506040517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe001519150506001600160a01b0381166117ed576040805162461bcd60e51b815260206004820152601860248201527f45434453413a20696e76616c6964207369676e61747572650000000000000000604482015290519081900360640190fd5b95945050505050565b80546001019055565b600061180a30611c02565b15905090565b600054610100900460ff168061182957506118296117ff565b80611837575060005460ff16155b6118725760405162461bcd60e51b815260040180806020018281038252602e815260200180612084602e913960400191505060405180910390fd5b600054610100900460ff1615801561189d576000805460ff1961ff0019909116610100171660011790555b8015610a73576000805461ff001916905550565b600054610100900460ff16806118ca57506118ca6117ff565b806118d8575060005460ff16155b6119135760405162461bcd60e51b815260040180806020018281038252602e815260200180612084602e913960400191505060405180910390fd5b600054610100900460ff1615801561193e576000805460ff1961ff0019909116610100171660011790555b8251611951906068906020860190611ec0565b508151611965906069906020850190611ec0565b50606a805460ff191660121790558015610ae6576000805461ff0019169055505050565b606a805460ff191660ff92909216919091179055565b600054610100900460ff16806119b857506119b86117ff565b806119c6575060005460ff16155b611a015760405162461bcd60e51b815260040180806020018281038252602e815260200180612084602e913960400191505060405180910390fd5b600054610100900460ff16158015611a2c576000805460ff1961ff0019909116610100171660011790555b611a34611810565b611a73826040518060400160405280600181526020017f3100000000000000000000000000000000000000000000000000000000000000815250611c08565b611a7c82611cc8565b8015610912576000805461ff00191690555050565b6000610b24836001600160a01b038416611d8e565b60c95490565b60ca5490565b6000838383611abf611dd8565b3060405160200180868152602001858152602001848152602001838152602001826001600160a01b03168152602001955050505050506040516020818303038152906040528051906020012090509392505050565b6000610b24836001600160a01b038416611ddc565b600082821115611b80576040805162461bcd60e51b815260206004820152601e60248201527f536166654d6174683a207375627472616374696f6e206f766572666c6f770000604482015290519081900360640190fd5b50900390565b81546000908210611bc85760405162461bcd60e51b8152600401808060200182810382526022815260200180611f546022913960400191505060405180910390fd5b826000018281548110611bd757fe5b9060005260206000200154905092915050565b60009081526001919091016020526040902054151590565b3b151590565b600054610100900460ff1680611c215750611c216117ff565b80611c2f575060005460ff16155b611c6a5760405162461bcd60e51b815260040180806020018281038252602e815260200180612084602e913960400191505060405180910390fd5b600054610100900460ff16158015611c95576000805460ff1961ff0019909116610100171660011790555b825160208085019190912083519184019190912060c99190915560ca558015610ae6576000805461ff0019169055505050565b600054610100900460ff1680611ce15750611ce16117ff565b80611cef575060005460ff16155b611d2a5760405162461bcd60e51b815260040180806020018281038252602e815260200180612084602e913960400191505060405180910390fd5b600054610100900460ff16158015611d55576000805460ff1961ff0019909116610100171660011790555b7f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c960fe558015610912576000805461ff00191690555050565b6000611d9a8383611bea565b611dd057508154600181810184556000848152602080822090930184905584548482528286019093526040902091909155610802565b506000610802565b4690565b60008181526001830160205260408120548015611eb65783547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8083019190810190600090879083908110611e2d57fe5b9060005260206000200154905080876000018481548110611e4a57fe5b600091825260208083209091019290925582815260018981019092526040902090840190558654879080611e7a57fe5b60019003818190600052602060002001600090559055866001016000878152602001908152602001600020600090556001945050505050610802565b6000915050610802565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f10611f0157805160ff1916838001178555611f2e565b82800160010185558215611f2e579182015b82811115611f2e578251825591602001919060010190611f13565b50611f3a929150611f3e565b5090565b5b80821115611f3a5760008155600101611f3f56fe456e756d657261626c655365743a20696e646578206f7574206f6620626f756e647345524332303a207472616e7366657220746f20746865207a65726f2061646472657373416363657373436f6e74726f6c3a2073656e646572206d75737420626520616e2061646d696e20746f206772616e7445524332303a206275726e20616d6f756e7420657863656564732062616c616e636545524332303a20617070726f766520746f20746865207a65726f206164647265737345524332303a207472616e7366657220616d6f756e7420657863656564732062616c616e636545434453413a20696e76616c6964207369676e6174757265202773272076616c7565416363657373436f6e74726f6c3a2073656e646572206d75737420626520616e2061646d696e20746f207265766f6b65496e697469616c697a61626c653a20636f6e747261637420697320616c726561647920696e697469616c697a656445434453413a20696e76616c6964207369676e6174757265202776272076616c756545524332303a207472616e7366657220616d6f756e74206578636565647320616c6c6f77616e636545524332303a206275726e20616d6f756e74206578636565647320616c6c6f77616e636545524332303a206275726e2066726f6d20746865207a65726f206164647265737345524332303a207472616e736665722066726f6d20746865207a65726f206164647265737345524332303a20617070726f76652066726f6d20746865207a65726f206164647265737345524332303a2064656372656173656420616c6c6f77616e63652062656c6f77207a65726f416363657373436f6e74726f6c3a2063616e206f6e6c792072656e6f756e636520726f6c657320666f722073656c66a2646970667358221220e7c3753b08173a11ca96acfac750f90800b1683e662b545723723a1385793bd164736f6c634300060c0033", + "devdoc": { + "kind": "dev", + "methods": { + "DOMAIN_SEPARATOR()": { + "details": "See {IERC20Permit-DOMAIN_SEPARATOR}." + }, + "allowance(address,address)": { + "details": "See {IERC20-allowance}." + }, + "approve(address,uint256)": { + "details": "See {IERC20-approve}. Requirements: - `spender` cannot be the zero address." + }, + "balanceOf(address)": { + "details": "See {IERC20-balanceOf}." + }, + "burn(uint256)": { + "details": "Destroys `amount` tokens from the caller. See {ERC20-_burn}." + }, + "burnFrom(address,uint256)": { + "details": "Destroys `amount` tokens from `account`, deducting from the caller's allowance. See {ERC20-_burn} and {ERC20-allowance}. Requirements: - the caller must have allowance for ``accounts``'s tokens of at least `amount`." + }, + "decimals()": { + "details": "Returns the number of decimals used to get its user representation. For example, if `decimals` equals `2`, a balance of `505` tokens should be displayed to a user as `5,05` (`505 / 10 ** 2`). Tokens usually opt for a value of 18, imitating the relationship between Ether and Wei. This is the value {ERC20} uses, unless {_setupDecimals} is called. NOTE: This information is only used for _display_ purposes: it in no way affects any of the arithmetic of the contract, including {IERC20-balanceOf} and {IERC20-transfer}." + }, + "decreaseAllowance(address,uint256)": { + "details": "Atomically decreases the allowance granted to `spender` by the caller. This is an alternative to {approve} that can be used as a mitigation for problems described in {IERC20-approve}. Emits an {Approval} event indicating the updated allowance. Requirements: - `spender` cannot be the zero address. - `spender` must have allowance for the caller of at least `subtractedValue`." + }, + "getRoleAdmin(bytes32)": { + "details": "Returns the admin role that controls `role`. See {grantRole} and {revokeRole}. To change a role's admin, use {_setRoleAdmin}." + }, + "getRoleMember(bytes32,uint256)": { + "details": "Returns one of the accounts that have `role`. `index` must be a value between 0 and {getRoleMemberCount}, non-inclusive. Role bearers are not sorted in any particular way, and their ordering may change at any point. WARNING: When using {getRoleMember} and {getRoleMemberCount}, make sure you perform all queries on the same block. See the following https://forum.openzeppelin.com/t/iterating-over-elements-on-enumerableset-in-openzeppelin-contracts/2296[forum post] for more information." + }, + "getRoleMemberCount(bytes32)": { + "details": "Returns the number of accounts that have `role`. Can be used together with {getRoleMember} to enumerate all bearers of a role." + }, + "grantRole(bytes32,address)": { + "details": "Grants `role` to `account`. If `account` had not been already granted `role`, emits a {RoleGranted} event. Requirements: - the caller must have ``role``'s admin role." + }, + "hasRole(bytes32,address)": { + "details": "Returns `true` if `account` has been granted `role`." + }, + "increaseAllowance(address,uint256)": { + "details": "Atomically increases the allowance granted to `spender` by the caller. This is an alternative to {approve} that can be used as a mitigation for problems described in {IERC20-approve}. Emits an {Approval} event indicating the updated allowance. Requirements: - `spender` cannot be the zero address." + }, + "initialize(string,string,uint8,address)": { + "params": { + "decimals": "Token name", + "name": "Token name", + "owner": "admin address to be initialized with", + "symbol": "Token symbol" + } + }, + "name()": { + "details": "Returns the name of the token." + }, + "nonces(address)": { + "details": "See {IERC20Permit-nonces}." + }, + "permit(address,address,uint256,uint256,uint8,bytes32,bytes32)": { + "details": "See {IERC20Permit-permit}." + }, + "renounceRole(bytes32,address)": { + "details": "Revokes `role` from the calling account. Roles are often managed via {grantRole} and {revokeRole}: this function's purpose is to provide a mechanism for accounts to lose their privileges if they are compromised (such as when a trusted device is misplaced). If the calling account had been granted `role`, emits a {RoleRevoked} event. Requirements: - the caller must be `account`." + }, + "revokeRole(bytes32,address)": { + "details": "Revokes `role` from `account`. If `account` had been granted `role`, emits a {RoleRevoked} event. Requirements: - the caller must have ``role``'s admin role." + }, + "symbol()": { + "details": "Returns the symbol of the token, usually a shorter version of the name." + }, + "totalSupply()": { + "details": "See {IERC20-totalSupply}." + }, + "transfer(address,uint256)": { + "details": "See {IERC20-transfer}. Requirements: - `recipient` cannot be the zero address. - the caller must have a balance of at least `amount`." + }, + "transferFrom(address,address,uint256)": { + "details": "See {IERC20-transferFrom}. Emits an {Approval} event indicating the updated allowance. This is not required by the EIP. See the note at the beginning of {ERC20}. Requirements: - `sender` and `recipient` cannot be the zero address. - `sender` must have a balance of at least `amount`. - the caller must have allowance for ``sender``'s tokens of at least `amount`." + } + }, + "version": 1 + }, + "userdoc": { + "kind": "user", + "methods": { + "initialize(string,string,uint8,address)": { + "notice": "Initializes this ERC20 contract with the given parameters." + } + }, + "version": 1 + }, + "storageLayout": { + "storage": [ + { + "astId": 1286, + "contract": "contracts/bridge/SynapseERC20.sol:SynapseERC20", + "label": "_initialized", + "offset": 0, + "slot": "0", + "type": "t_bool" + }, + { + "astId": 1289, + "contract": "contracts/bridge/SynapseERC20.sol:SynapseERC20", + "label": "_initializing", + "offset": 1, + "slot": "0", + "type": "t_bool" + }, + { + "astId": 2325, + "contract": "contracts/bridge/SynapseERC20.sol:SynapseERC20", + "label": "__gap", + "offset": 0, + "slot": "1", + "type": "t_array(t_uint256)50_storage" + }, + { + "astId": 43, + "contract": "contracts/bridge/SynapseERC20.sol:SynapseERC20", + "label": "_roles", + "offset": 0, + "slot": "51", + "type": "t_mapping(t_bytes32,t_struct(RoleData)39_storage)" + }, + { + "astId": 306, + "contract": "contracts/bridge/SynapseERC20.sol:SynapseERC20", + "label": "__gap", + "offset": 0, + "slot": "52", + "type": "t_array(t_uint256)49_storage" + }, + { + "astId": 1449, + "contract": "contracts/bridge/SynapseERC20.sol:SynapseERC20", + "label": "_balances", + "offset": 0, + "slot": "101", + "type": "t_mapping(t_address,t_uint256)" + }, + { + "astId": 1455, + "contract": "contracts/bridge/SynapseERC20.sol:SynapseERC20", + "label": "_allowances", + "offset": 0, + "slot": "102", + "type": "t_mapping(t_address,t_mapping(t_address,t_uint256))" + }, + { + "astId": 1457, + "contract": "contracts/bridge/SynapseERC20.sol:SynapseERC20", + "label": "_totalSupply", + "offset": 0, + "slot": "103", + "type": "t_uint256" + }, + { + "astId": 1459, + "contract": "contracts/bridge/SynapseERC20.sol:SynapseERC20", + "label": "_name", + "offset": 0, + "slot": "104", + "type": "t_string_storage" + }, + { + "astId": 1461, + "contract": "contracts/bridge/SynapseERC20.sol:SynapseERC20", + "label": "_symbol", + "offset": 0, + "slot": "105", + "type": "t_string_storage" + }, + { + "astId": 1463, + "contract": "contracts/bridge/SynapseERC20.sol:SynapseERC20", + "label": "_decimals", + "offset": 0, + "slot": "106", + "type": "t_uint8" + }, + { + "astId": 1958, + "contract": "contracts/bridge/SynapseERC20.sol:SynapseERC20", + "label": "__gap", + "offset": 0, + "slot": "107", + "type": "t_array(t_uint256)44_storage" + }, + { + "astId": 1428, + "contract": "contracts/bridge/SynapseERC20.sol:SynapseERC20", + "label": "__gap", + "offset": 0, + "slot": "151", + "type": "t_array(t_uint256)50_storage" + }, + { + "astId": 562, + "contract": "contracts/bridge/SynapseERC20.sol:SynapseERC20", + "label": "_HASHED_NAME", + "offset": 0, + "slot": "201", + "type": "t_bytes32" + }, + { + "astId": 564, + "contract": "contracts/bridge/SynapseERC20.sol:SynapseERC20", + "label": "_HASHED_VERSION", + "offset": 0, + "slot": "202", + "type": "t_bytes32" + }, + { + "astId": 713, + "contract": "contracts/bridge/SynapseERC20.sol:SynapseERC20", + "label": "__gap", + "offset": 0, + "slot": "203", + "type": "t_array(t_uint256)50_storage" + }, + { + "astId": 738, + "contract": "contracts/bridge/SynapseERC20.sol:SynapseERC20", + "label": "_nonces", + "offset": 0, + "slot": "253", + "type": "t_mapping(t_address,t_struct(Counter)2336_storage)" + }, + { + "astId": 740, + "contract": "contracts/bridge/SynapseERC20.sol:SynapseERC20", + "label": "_PERMIT_TYPEHASH", + "offset": 0, + "slot": "254", + "type": "t_bytes32" + }, + { + "astId": 887, + "contract": "contracts/bridge/SynapseERC20.sol:SynapseERC20", + "label": "__gap", + "offset": 0, + "slot": "255", + "type": "t_array(t_uint256)49_storage" + } + ], + "types": { + "t_address": { + "encoding": "inplace", + "label": "address", + "numberOfBytes": "20" + }, + "t_array(t_bytes32)dyn_storage": { + "base": "t_bytes32", + "encoding": "dynamic_array", + "label": "bytes32[]", + "numberOfBytes": "32" + }, + "t_array(t_uint256)44_storage": { + "base": "t_uint256", + "encoding": "inplace", + "label": "uint256[44]", + "numberOfBytes": "1408" + }, + "t_array(t_uint256)49_storage": { + "base": "t_uint256", + "encoding": "inplace", + "label": "uint256[49]", + "numberOfBytes": "1568" + }, + "t_array(t_uint256)50_storage": { + "base": "t_uint256", + "encoding": "inplace", + "label": "uint256[50]", + "numberOfBytes": "1600" + }, + "t_bool": { + "encoding": "inplace", + "label": "bool", + "numberOfBytes": "1" + }, + "t_bytes32": { + "encoding": "inplace", + "label": "bytes32", + "numberOfBytes": "32" + }, + "t_mapping(t_address,t_mapping(t_address,t_uint256))": { + "encoding": "mapping", + "key": "t_address", + "label": "mapping(address => mapping(address => uint256))", + "numberOfBytes": "32", + "value": "t_mapping(t_address,t_uint256)" + }, + "t_mapping(t_address,t_struct(Counter)2336_storage)": { + "encoding": "mapping", + "key": "t_address", + "label": "mapping(address => struct CountersUpgradeable.Counter)", + "numberOfBytes": "32", + "value": "t_struct(Counter)2336_storage" + }, + "t_mapping(t_address,t_uint256)": { + "encoding": "mapping", + "key": "t_address", + "label": "mapping(address => uint256)", + "numberOfBytes": "32", + "value": "t_uint256" + }, + "t_mapping(t_bytes32,t_struct(RoleData)39_storage)": { + "encoding": "mapping", + "key": "t_bytes32", + "label": "mapping(bytes32 => struct AccessControlUpgradeable.RoleData)", + "numberOfBytes": "32", + "value": "t_struct(RoleData)39_storage" + }, + "t_mapping(t_bytes32,t_uint256)": { + "encoding": "mapping", + "key": "t_bytes32", + "label": "mapping(bytes32 => uint256)", + "numberOfBytes": "32", + "value": "t_uint256" + }, + "t_string_storage": { + "encoding": "bytes", + "label": "string", + "numberOfBytes": "32" + }, + "t_struct(AddressSet)2652_storage": { + "encoding": "inplace", + "label": "struct EnumerableSetUpgradeable.AddressSet", + "members": [ + { + "astId": 2651, + "contract": "contracts/bridge/SynapseERC20.sol:SynapseERC20", + "label": "_inner", + "offset": 0, + "slot": "0", + "type": "t_struct(Set)2387_storage" + } + ], + "numberOfBytes": "64" + }, + "t_struct(Counter)2336_storage": { + "encoding": "inplace", + "label": "struct CountersUpgradeable.Counter", + "members": [ + { + "astId": 2335, + "contract": "contracts/bridge/SynapseERC20.sol:SynapseERC20", + "label": "_value", + "offset": 0, + "slot": "0", + "type": "t_uint256" + } + ], + "numberOfBytes": "32" + }, + "t_struct(RoleData)39_storage": { + "encoding": "inplace", + "label": "struct AccessControlUpgradeable.RoleData", + "members": [ + { + "astId": 36, + "contract": "contracts/bridge/SynapseERC20.sol:SynapseERC20", + "label": "members", + "offset": 0, + "slot": "0", + "type": "t_struct(AddressSet)2652_storage" + }, + { + "astId": 38, + "contract": "contracts/bridge/SynapseERC20.sol:SynapseERC20", + "label": "adminRole", + "offset": 0, + "slot": "2", + "type": "t_bytes32" + } + ], + "numberOfBytes": "96" + }, + "t_struct(Set)2387_storage": { + "encoding": "inplace", + "label": "struct EnumerableSetUpgradeable.Set", + "members": [ + { + "astId": 2382, + "contract": "contracts/bridge/SynapseERC20.sol:SynapseERC20", + "label": "_values", + "offset": 0, + "slot": "0", + "type": "t_array(t_bytes32)dyn_storage" + }, + { + "astId": 2386, + "contract": "contracts/bridge/SynapseERC20.sol:SynapseERC20", + "label": "_indexes", + "offset": 0, + "slot": "1", + "type": "t_mapping(t_bytes32,t_uint256)" + } + ], + "numberOfBytes": "64" + }, + "t_uint256": { + "encoding": "inplace", + "label": "uint256", + "numberOfBytes": "32" + }, + "t_uint8": { + "encoding": "inplace", + "label": "uint8", + "numberOfBytes": "1" + } + } + } +} \ No newline at end of file diff --git a/deployments/dfk/SynapseERC20Factory.json b/deployments/dfk/SynapseERC20Factory.json new file mode 100644 index 000000000..2b4cd81c0 --- /dev/null +++ b/deployments/dfk/SynapseERC20Factory.json @@ -0,0 +1,114 @@ +{ + "address": "0x42c08394E5491B3065CDae1eD1a31D069114CfE8", + "abi": [ + { + "inputs": [], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "contractAddress", + "type": "address" + } + ], + "name": "SynapseERC20Created", + "type": "event" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "synapseERC20Address", + "type": "address" + }, + { + "internalType": "string", + "name": "name", + "type": "string" + }, + { + "internalType": "string", + "name": "symbol", + "type": "string" + }, + { + "internalType": "uint8", + "name": "decimals", + "type": "uint8" + }, + { + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "deploy", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "function" + } + ], + "transactionHash": "0xefe0e12ff82dc1e3d66bf5cd04b1efc964a6afbe5c29b354c3145d42e1a8b775", + "receipt": { + "to": null, + "from": "0x235AF07E770f474d24F5bf73074735892371b40D", + "contractAddress": "0x42c08394E5491B3065CDae1eD1a31D069114CfE8", + "transactionIndex": 0, + "gasUsed": "307419", + "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "blockHash": "0xc5e284ea1c2b56619ea8af1e81285851cc9384ef0a6db3883e2933b580f081b4", + "transactionHash": "0xefe0e12ff82dc1e3d66bf5cd04b1efc964a6afbe5c29b354c3145d42e1a8b775", + "logs": [], + "blockNumber": 27, + "cumulativeGasUsed": "307419", + "status": 1, + "byzantium": true + }, + "args": [], + "solcInputHash": "d9ddc44152056b9c2865111aa614cbcf", + "metadata": "{\"compiler\":{\"version\":\"0.6.12+commit.27d51765\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"contractAddress\",\"type\":\"address\"}],\"name\":\"SynapseERC20Created\",\"type\":\"event\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"synapseERC20Address\",\"type\":\"address\"},{\"internalType\":\"string\",\"name\":\"name\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"symbol\",\"type\":\"string\"},{\"internalType\":\"uint8\",\"name\":\"decimals\",\"type\":\"uint8\"},{\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"}],\"name\":\"deploy\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{\"deploy(address,string,string,uint8,address)\":{\"params\":{\"decimals\":\"Token name\",\"name\":\"Token name\",\"owner\":\"admin address to be initialized with\",\"symbol\":\"Token symbol\",\"synapseERC20Address\":\"address of the synapseERC20Address contract to initialize with\"},\"returns\":{\"_0\":\"Address of the newest node management contract created*\"}}},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{\"deploy(address,string,string,uint8,address)\":{\"notice\":\"Deploys a new node\"}},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/bridge/SynapseERC20Factory.sol\":\"SynapseERC20Factory\"},\"evmVersion\":\"istanbul\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":10000},\"remappings\":[]},\"sources\":{\"@openzeppelin/contracts/access/Ownable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity >=0.6.0 <0.8.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 () internal {\\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\",\"keccak256\":\"0x15e2d5bd4c28a88548074c54d220e8086f638a71ed07e6b3ba5a70066fcf458d\",\"license\":\"MIT\"},\"@openzeppelin/contracts/proxy/Clones.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity >=0.6.0 <0.8.0;\\n\\n/**\\n * @dev https://eips.ethereum.org/EIPS/eip-1167[EIP 1167] is a standard for\\n * deploying minimal proxy contracts, also known as \\\"clones\\\".\\n *\\n * > To simply and cheaply clone contract functionality in an immutable way, this standard specifies\\n * > a minimal bytecode implementation that delegates all calls to a known, fixed address.\\n *\\n * The library includes functions to deploy a proxy using either `create` (traditional deployment) or `create2`\\n * (salted deterministic deployment). It also includes functions to predict the addresses of clones deployed using the\\n * deterministic method.\\n *\\n * _Available since v3.4._\\n */\\nlibrary Clones {\\n /**\\n * @dev Deploys and returns the address of a clone that mimics the behaviour of `master`.\\n *\\n * This function uses the create opcode, which should never revert.\\n */\\n function clone(address master) internal returns (address instance) {\\n // solhint-disable-next-line no-inline-assembly\\n assembly {\\n let ptr := mload(0x40)\\n mstore(ptr, 0x3d602d80600a3d3981f3363d3d373d3d3d363d73000000000000000000000000)\\n mstore(add(ptr, 0x14), shl(0x60, master))\\n mstore(add(ptr, 0x28), 0x5af43d82803e903d91602b57fd5bf30000000000000000000000000000000000)\\n instance := create(0, ptr, 0x37)\\n }\\n require(instance != address(0), \\\"ERC1167: create failed\\\");\\n }\\n\\n /**\\n * @dev Deploys and returns the address of a clone that mimics the behaviour of `master`.\\n *\\n * This function uses the create2 opcode and a `salt` to deterministically deploy\\n * the clone. Using the same `master` and `salt` multiple time will revert, since\\n * the clones cannot be deployed twice at the same address.\\n */\\n function cloneDeterministic(address master, bytes32 salt) internal returns (address instance) {\\n // solhint-disable-next-line no-inline-assembly\\n assembly {\\n let ptr := mload(0x40)\\n mstore(ptr, 0x3d602d80600a3d3981f3363d3d373d3d3d363d73000000000000000000000000)\\n mstore(add(ptr, 0x14), shl(0x60, master))\\n mstore(add(ptr, 0x28), 0x5af43d82803e903d91602b57fd5bf30000000000000000000000000000000000)\\n instance := create2(0, ptr, 0x37, salt)\\n }\\n require(instance != address(0), \\\"ERC1167: create2 failed\\\");\\n }\\n\\n /**\\n * @dev Computes the address of a clone deployed using {Clones-cloneDeterministic}.\\n */\\n function predictDeterministicAddress(address master, bytes32 salt, address deployer) internal pure returns (address predicted) {\\n // solhint-disable-next-line no-inline-assembly\\n assembly {\\n let ptr := mload(0x40)\\n mstore(ptr, 0x3d602d80600a3d3981f3363d3d373d3d3d363d73000000000000000000000000)\\n mstore(add(ptr, 0x14), shl(0x60, master))\\n mstore(add(ptr, 0x28), 0x5af43d82803e903d91602b57fd5bf3ff00000000000000000000000000000000)\\n mstore(add(ptr, 0x38), shl(0x60, deployer))\\n mstore(add(ptr, 0x4c), salt)\\n mstore(add(ptr, 0x6c), keccak256(ptr, 0x37))\\n predicted := keccak256(add(ptr, 0x37), 0x55)\\n }\\n }\\n\\n /**\\n * @dev Computes the address of a clone deployed using {Clones-cloneDeterministic}.\\n */\\n function predictDeterministicAddress(address master, bytes32 salt) internal view returns (address predicted) {\\n return predictDeterministicAddress(master, salt, address(this));\\n }\\n}\\n\",\"keccak256\":\"0x0d24348f536f928d8b42789737bf34762faee065667ab530ea20969a9d9920d1\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/Context.sol\":{\"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\",\"keccak256\":\"0x8d3cb350f04ff49cfb10aef08d87f19dcbaecc8027b0bed12f3275cd12f38cf0\",\"license\":\"MIT\"},\"contracts/bridge/SynapseERC20Factory.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity 0.6.12;\\n\\nimport \\\"@openzeppelin/contracts/access/Ownable.sol\\\";\\nimport \\\"@openzeppelin/contracts/proxy/Clones.sol\\\";\\nimport \\\"./interfaces/ISynapseERC20.sol\\\";\\n\\ncontract SynapseERC20Factory {\\n constructor() public {}\\n\\n event SynapseERC20Created(address contractAddress);\\n\\n /**\\n * @notice Deploys a new node\\n * @param synapseERC20Address address of the synapseERC20Address contract to initialize with\\n * @param name Token name\\n * @param symbol Token symbol\\n * @param decimals Token name\\n * @param owner admin address to be initialized with\\n * @return Address of the newest node management contract created\\n **/\\n function deploy(\\n address synapseERC20Address,\\n string memory name,\\n string memory symbol,\\n uint8 decimals,\\n address owner\\n ) external returns (address) {\\n address synERC20Clone = Clones.clone(synapseERC20Address);\\n ISynapseERC20(synERC20Clone).initialize(name, symbol, decimals, owner);\\n\\n emit SynapseERC20Created(synERC20Clone);\\n\\n return synERC20Clone;\\n }\\n}\\n\",\"keccak256\":\"0x5a26f9f84c8f31acb391fc7e646cb1efd26fd5729b48fe7df4e291e3ee0dd612\",\"license\":\"MIT\"},\"contracts/bridge/interfaces/ISynapseERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\n\\npragma solidity 0.6.12;\\n\\ninterface ISynapseERC20 { \\n function initialize(\\n string memory _name, string memory _symbol, uint8 _decimals, address owner) external;\\n\\n function mint(address to, uint256 amount) external;\\n}\\n\\n\",\"keccak256\":\"0xb5a7988713578e514edcee9dd1cd9466c64f9e8cf80509b3c9a7f3be3949fcc8\",\"license\":\"MIT\"}},\"version\":1}", + "bytecode": "0x608060405234801561001057600080fd5b5061049d806100206000396000f3fe608060405234801561001057600080fd5b506004361061002b5760003560e01c80635d58ce2414610030575b600080fd5b610198600480360360a081101561004657600080fd5b73ffffffffffffffffffffffffffffffffffffffff823516919081019060408101602082013564010000000081111561007e57600080fd5b82018360208201111561009057600080fd5b803590602001918460018302840111640100000000831117156100b257600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250929594936020810193503591505064010000000081111561010557600080fd5b82018360208201111561011757600080fd5b8035906020019184600183028401116401000000008311171561013957600080fd5b91908080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509295505050813560ff169250506020013573ffffffffffffffffffffffffffffffffffffffff166101c1565b6040805173ffffffffffffffffffffffffffffffffffffffff9092168252519081900360200190f35b6000806101cd87610380565b90508073ffffffffffffffffffffffffffffffffffffffff1663de7ea79d878787876040518563ffffffff1660e01b81526004018080602001806020018560ff1681526020018473ffffffffffffffffffffffffffffffffffffffff168152602001838103835287818151815260200191508051906020019080838360005b8381101561026457818101518382015260200161024c565b50505050905090810190601f1680156102915780820380516001836020036101000a031916815260200191505b50838103825286518152865160209182019188019080838360005b838110156102c45781810151838201526020016102ac565b50505050905090810190601f1680156102f15780820380516001836020036101000a031916815260200191505b509650505050505050600060405180830381600087803b15801561031457600080fd5b505af1158015610328573d6000803e3d6000fd5b50506040805173ffffffffffffffffffffffffffffffffffffffff8516815290517f3f53e2db82c60058131913739ee1bca25955b597586645b6043f9902e9bdf0dd9350908190036020019150a19695505050505050565b60006040517f3d602d80600a3d3981f3363d3d373d3d3d363d7300000000000000000000000081528260601b60148201527f5af43d82803e903d91602b57fd5bf3000000000000000000000000000000000060288201526037816000f091505073ffffffffffffffffffffffffffffffffffffffff811661046257604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f455243313136373a20637265617465206661696c656400000000000000000000604482015290519081900360640190fd5b91905056fea26469706673582212208898a688704c18c50aee29a5d143dcc15c05f3ac350d3266d2aae8a32d4bedfa64736f6c634300060c0033", + "deployedBytecode": "0x608060405234801561001057600080fd5b506004361061002b5760003560e01c80635d58ce2414610030575b600080fd5b610198600480360360a081101561004657600080fd5b73ffffffffffffffffffffffffffffffffffffffff823516919081019060408101602082013564010000000081111561007e57600080fd5b82018360208201111561009057600080fd5b803590602001918460018302840111640100000000831117156100b257600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250929594936020810193503591505064010000000081111561010557600080fd5b82018360208201111561011757600080fd5b8035906020019184600183028401116401000000008311171561013957600080fd5b91908080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509295505050813560ff169250506020013573ffffffffffffffffffffffffffffffffffffffff166101c1565b6040805173ffffffffffffffffffffffffffffffffffffffff9092168252519081900360200190f35b6000806101cd87610380565b90508073ffffffffffffffffffffffffffffffffffffffff1663de7ea79d878787876040518563ffffffff1660e01b81526004018080602001806020018560ff1681526020018473ffffffffffffffffffffffffffffffffffffffff168152602001838103835287818151815260200191508051906020019080838360005b8381101561026457818101518382015260200161024c565b50505050905090810190601f1680156102915780820380516001836020036101000a031916815260200191505b50838103825286518152865160209182019188019080838360005b838110156102c45781810151838201526020016102ac565b50505050905090810190601f1680156102f15780820380516001836020036101000a031916815260200191505b509650505050505050600060405180830381600087803b15801561031457600080fd5b505af1158015610328573d6000803e3d6000fd5b50506040805173ffffffffffffffffffffffffffffffffffffffff8516815290517f3f53e2db82c60058131913739ee1bca25955b597586645b6043f9902e9bdf0dd9350908190036020019150a19695505050505050565b60006040517f3d602d80600a3d3981f3363d3d373d3d3d363d7300000000000000000000000081528260601b60148201527f5af43d82803e903d91602b57fd5bf3000000000000000000000000000000000060288201526037816000f091505073ffffffffffffffffffffffffffffffffffffffff811661046257604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f455243313136373a20637265617465206661696c656400000000000000000000604482015290519081900360640190fd5b91905056fea26469706673582212208898a688704c18c50aee29a5d143dcc15c05f3ac350d3266d2aae8a32d4bedfa64736f6c634300060c0033", + "devdoc": { + "kind": "dev", + "methods": { + "deploy(address,string,string,uint8,address)": { + "params": { + "decimals": "Token name", + "name": "Token name", + "owner": "admin address to be initialized with", + "symbol": "Token symbol", + "synapseERC20Address": "address of the synapseERC20Address contract to initialize with" + }, + "returns": { + "_0": "Address of the newest node management contract created*" + } + } + }, + "version": 1 + }, + "userdoc": { + "kind": "user", + "methods": { + "deploy(address,string,string,uint8,address)": { + "notice": "Deploys a new node" + } + }, + "version": 1 + }, + "storageLayout": { + "storage": [], + "types": null + } +} \ No newline at end of file diff --git a/deployments/dfk/SynapseToken.json b/deployments/dfk/SynapseToken.json new file mode 100644 index 000000000..e359d3b5e --- /dev/null +++ b/deployments/dfk/SynapseToken.json @@ -0,0 +1,668 @@ +{ + "address": "0xB6b5C854a8f71939556d4f3a2e5829F7FcC1bf2A", + "abi": [ + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "Approval", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "bytes32", + "name": "previousAdminRole", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "bytes32", + "name": "newAdminRole", + "type": "bytes32" + } + ], + "name": "RoleAdminChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "sender", + "type": "address" + } + ], + "name": "RoleGranted", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "sender", + "type": "address" + } + ], + "name": "RoleRevoked", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "Transfer", + "type": "event" + }, + { + "inputs": [], + "name": "DEFAULT_ADMIN_ROLE", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "DOMAIN_SEPARATOR", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "MINTER_ROLE", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "address", + "name": "spender", + "type": "address" + } + ], + "name": "allowance", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "approve", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "balanceOf", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "burn", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "burnFrom", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "decimals", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "subtractedValue", + "type": "uint256" + } + ], + "name": "decreaseAllowance", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + } + ], + "name": "getRoleAdmin", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "internalType": "uint256", + "name": "index", + "type": "uint256" + } + ], + "name": "getRoleMember", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + } + ], + "name": "getRoleMemberCount", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "grantRole", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "hasRole", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "addedValue", + "type": "uint256" + } + ], + "name": "increaseAllowance", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "name", + "type": "string" + }, + { + "internalType": "string", + "name": "symbol", + "type": "string" + }, + { + "internalType": "uint8", + "name": "decimals", + "type": "uint8" + }, + { + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "initialize", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "mint", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "name", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "nonces", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" + }, + { + "internalType": "uint8", + "name": "v", + "type": "uint8" + }, + { + "internalType": "bytes32", + "name": "r", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "s", + "type": "bytes32" + } + ], + "name": "permit", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "renounceRole", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "revokeRole", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "symbol", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "totalSupply", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "recipient", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "transfer", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "internalType": "address", + "name": "recipient", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "transferFrom", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + } + ] +} \ No newline at end of file diff --git a/deployments/dfk/TimelockController.json b/deployments/dfk/TimelockController.json new file mode 100644 index 000000000..210e40006 --- /dev/null +++ b/deployments/dfk/TimelockController.json @@ -0,0 +1,1075 @@ +{ + "address": "0x1BFE50bb2A8a75fefa46892dB10313898dDbFf8F", + "abi": [ + { + "inputs": [ + { + "internalType": "uint256", + "name": "minDelay", + "type": "uint256" + }, + { + "internalType": "address[]", + "name": "proposers", + "type": "address[]" + }, + { + "internalType": "address[]", + "name": "executors", + "type": "address[]" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "id", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "index", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "address", + "name": "target", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "value", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "CallExecuted", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "id", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "index", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "address", + "name": "target", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "value", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "data", + "type": "bytes" + }, + { + "indexed": false, + "internalType": "bytes32", + "name": "predecessor", + "type": "bytes32" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "delay", + "type": "uint256" + } + ], + "name": "CallScheduled", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "id", + "type": "bytes32" + } + ], + "name": "Cancelled", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "oldDuration", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newDuration", + "type": "uint256" + } + ], + "name": "MinDelayChange", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "bytes32", + "name": "previousAdminRole", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "bytes32", + "name": "newAdminRole", + "type": "bytes32" + } + ], + "name": "RoleAdminChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "sender", + "type": "address" + } + ], + "name": "RoleGranted", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "sender", + "type": "address" + } + ], + "name": "RoleRevoked", + "type": "event" + }, + { + "inputs": [], + "name": "DEFAULT_ADMIN_ROLE", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "EXECUTOR_ROLE", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "PROPOSER_ROLE", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "TIMELOCK_ADMIN_ROLE", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "id", + "type": "bytes32" + } + ], + "name": "cancel", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "target", + "type": "address" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + }, + { + "internalType": "bytes32", + "name": "predecessor", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "salt", + "type": "bytes32" + } + ], + "name": "execute", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address[]", + "name": "targets", + "type": "address[]" + }, + { + "internalType": "uint256[]", + "name": "values", + "type": "uint256[]" + }, + { + "internalType": "bytes[]", + "name": "datas", + "type": "bytes[]" + }, + { + "internalType": "bytes32", + "name": "predecessor", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "salt", + "type": "bytes32" + } + ], + "name": "executeBatch", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [], + "name": "getMinDelay", + "outputs": [ + { + "internalType": "uint256", + "name": "duration", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + } + ], + "name": "getRoleAdmin", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "id", + "type": "bytes32" + } + ], + "name": "getTimestamp", + "outputs": [ + { + "internalType": "uint256", + "name": "timestamp", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "grantRole", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "hasRole", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "target", + "type": "address" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + }, + { + "internalType": "bytes32", + "name": "predecessor", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "salt", + "type": "bytes32" + } + ], + "name": "hashOperation", + "outputs": [ + { + "internalType": "bytes32", + "name": "hash", + "type": "bytes32" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address[]", + "name": "targets", + "type": "address[]" + }, + { + "internalType": "uint256[]", + "name": "values", + "type": "uint256[]" + }, + { + "internalType": "bytes[]", + "name": "datas", + "type": "bytes[]" + }, + { + "internalType": "bytes32", + "name": "predecessor", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "salt", + "type": "bytes32" + } + ], + "name": "hashOperationBatch", + "outputs": [ + { + "internalType": "bytes32", + "name": "hash", + "type": "bytes32" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "id", + "type": "bytes32" + } + ], + "name": "isOperation", + "outputs": [ + { + "internalType": "bool", + "name": "pending", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "id", + "type": "bytes32" + } + ], + "name": "isOperationDone", + "outputs": [ + { + "internalType": "bool", + "name": "done", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "id", + "type": "bytes32" + } + ], + "name": "isOperationPending", + "outputs": [ + { + "internalType": "bool", + "name": "pending", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "id", + "type": "bytes32" + } + ], + "name": "isOperationReady", + "outputs": [ + { + "internalType": "bool", + "name": "ready", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "renounceRole", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "revokeRole", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "target", + "type": "address" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + }, + { + "internalType": "bytes32", + "name": "predecessor", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "salt", + "type": "bytes32" + }, + { + "internalType": "uint256", + "name": "delay", + "type": "uint256" + } + ], + "name": "schedule", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address[]", + "name": "targets", + "type": "address[]" + }, + { + "internalType": "uint256[]", + "name": "values", + "type": "uint256[]" + }, + { + "internalType": "bytes[]", + "name": "datas", + "type": "bytes[]" + }, + { + "internalType": "bytes32", + "name": "predecessor", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "salt", + "type": "bytes32" + }, + { + "internalType": "uint256", + "name": "delay", + "type": "uint256" + } + ], + "name": "scheduleBatch", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes4", + "name": "interfaceId", + "type": "bytes4" + } + ], + "name": "supportsInterface", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "newDelay", + "type": "uint256" + } + ], + "name": "updateDelay", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "stateMutability": "payable", + "type": "receive" + } + ], + "transactionHash": "0x2325e186fe62016a91620e558cde52e23b04283cb763fd5b49c8b07f80c63da2", + "receipt": { + "to": null, + "from": "0x235AF07E770f474d24F5bf73074735892371b40D", + "contractAddress": "0x1BFE50bb2A8a75fefa46892dB10313898dDbFf8F", + "transactionIndex": 0, + "gasUsed": "2109054", + "logsBloom": "0x000000040000000008000000000000000a0000000000000000000000000000000040000000000000000000000001000000000000000000000200000010200000004000000000000000000000000000000000000000000000000000000001000000000000020000404000000000000800000000000000000000020004000000000000000100000400000000000000000000000000000000080000000000000000000000000020000000000000000000000000000000000000001000000000000000000000000000004000000000000000000200000000000100000002000020000000000000021000000000000042000800000000000000000000000000000000", + "blockHash": "0x3b3b98801a85737fd02d766220a4c7d27328a3540922792c8c4c72b1b169a082", + "transactionHash": "0x2325e186fe62016a91620e558cde52e23b04283cb763fd5b49c8b07f80c63da2", + "logs": [ + { + "transactionIndex": 0, + "blockNumber": 22, + "transactionHash": "0x2325e186fe62016a91620e558cde52e23b04283cb763fd5b49c8b07f80c63da2", + "address": "0x1BFE50bb2A8a75fefa46892dB10313898dDbFf8F", + "topics": [ + "0xbd79b86ffe0ab8e8776151514217cd7cacd52c909f66475c3af44e129f0b00ff", + "0x5f58e3a2316349923ce3780f8d587db2d72378aed66a8261c916544fa6846ca5", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x5f58e3a2316349923ce3780f8d587db2d72378aed66a8261c916544fa6846ca5" + ], + "data": "0x", + "logIndex": 0, + "blockHash": "0x3b3b98801a85737fd02d766220a4c7d27328a3540922792c8c4c72b1b169a082" + }, + { + "transactionIndex": 0, + "blockNumber": 22, + "transactionHash": "0x2325e186fe62016a91620e558cde52e23b04283cb763fd5b49c8b07f80c63da2", + "address": "0x1BFE50bb2A8a75fefa46892dB10313898dDbFf8F", + "topics": [ + "0xbd79b86ffe0ab8e8776151514217cd7cacd52c909f66475c3af44e129f0b00ff", + "0xb09aa5aeb3702cfd50b6b62bc4532604938f21248a27a1d5ca736082b6819cc1", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x5f58e3a2316349923ce3780f8d587db2d72378aed66a8261c916544fa6846ca5" + ], + "data": "0x", + "logIndex": 1, + "blockHash": "0x3b3b98801a85737fd02d766220a4c7d27328a3540922792c8c4c72b1b169a082" + }, + { + "transactionIndex": 0, + "blockNumber": 22, + "transactionHash": "0x2325e186fe62016a91620e558cde52e23b04283cb763fd5b49c8b07f80c63da2", + "address": "0x1BFE50bb2A8a75fefa46892dB10313898dDbFf8F", + "topics": [ + "0xbd79b86ffe0ab8e8776151514217cd7cacd52c909f66475c3af44e129f0b00ff", + "0xd8aa0f3194971a2a116679f7c2090f6939c8d4e01a2a8d7e41d55e5351469e63", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x5f58e3a2316349923ce3780f8d587db2d72378aed66a8261c916544fa6846ca5" + ], + "data": "0x", + "logIndex": 2, + "blockHash": "0x3b3b98801a85737fd02d766220a4c7d27328a3540922792c8c4c72b1b169a082" + }, + { + "transactionIndex": 0, + "blockNumber": 22, + "transactionHash": "0x2325e186fe62016a91620e558cde52e23b04283cb763fd5b49c8b07f80c63da2", + "address": "0x1BFE50bb2A8a75fefa46892dB10313898dDbFf8F", + "topics": [ + "0x2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d", + "0x5f58e3a2316349923ce3780f8d587db2d72378aed66a8261c916544fa6846ca5", + "0x000000000000000000000000235af07e770f474d24f5bf73074735892371b40d", + "0x000000000000000000000000235af07e770f474d24f5bf73074735892371b40d" + ], + "data": "0x", + "logIndex": 3, + "blockHash": "0x3b3b98801a85737fd02d766220a4c7d27328a3540922792c8c4c72b1b169a082" + }, + { + "transactionIndex": 0, + "blockNumber": 22, + "transactionHash": "0x2325e186fe62016a91620e558cde52e23b04283cb763fd5b49c8b07f80c63da2", + "address": "0x1BFE50bb2A8a75fefa46892dB10313898dDbFf8F", + "topics": [ + "0x2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d", + "0x5f58e3a2316349923ce3780f8d587db2d72378aed66a8261c916544fa6846ca5", + "0x0000000000000000000000001bfe50bb2a8a75fefa46892db10313898ddbff8f", + "0x000000000000000000000000235af07e770f474d24f5bf73074735892371b40d" + ], + "data": "0x", + "logIndex": 4, + "blockHash": "0x3b3b98801a85737fd02d766220a4c7d27328a3540922792c8c4c72b1b169a082" + }, + { + "transactionIndex": 0, + "blockNumber": 22, + "transactionHash": "0x2325e186fe62016a91620e558cde52e23b04283cb763fd5b49c8b07f80c63da2", + "address": "0x1BFE50bb2A8a75fefa46892dB10313898dDbFf8F", + "topics": [ + "0x2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d", + "0xb09aa5aeb3702cfd50b6b62bc4532604938f21248a27a1d5ca736082b6819cc1", + "0x0000000000000000000000002e62c47f502f512c75bd5ecd70799efb0fe7baa3", + "0x000000000000000000000000235af07e770f474d24f5bf73074735892371b40d" + ], + "data": "0x", + "logIndex": 5, + "blockHash": "0x3b3b98801a85737fd02d766220a4c7d27328a3540922792c8c4c72b1b169a082" + }, + { + "transactionIndex": 0, + "blockNumber": 22, + "transactionHash": "0x2325e186fe62016a91620e558cde52e23b04283cb763fd5b49c8b07f80c63da2", + "address": "0x1BFE50bb2A8a75fefa46892dB10313898dDbFf8F", + "topics": [ + "0x2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d", + "0xd8aa0f3194971a2a116679f7c2090f6939c8d4e01a2a8d7e41d55e5351469e63", + "0x0000000000000000000000002e62c47f502f512c75bd5ecd70799efb0fe7baa3", + "0x000000000000000000000000235af07e770f474d24f5bf73074735892371b40d" + ], + "data": "0x", + "logIndex": 6, + "blockHash": "0x3b3b98801a85737fd02d766220a4c7d27328a3540922792c8c4c72b1b169a082" + }, + { + "transactionIndex": 0, + "blockNumber": 22, + "transactionHash": "0x2325e186fe62016a91620e558cde52e23b04283cb763fd5b49c8b07f80c63da2", + "address": "0x1BFE50bb2A8a75fefa46892dB10313898dDbFf8F", + "topics": [ + "0x11c24f4ead16507c69ac467fbd5e4eed5fb5c699626d2cc6d66421df253886d5" + ], + "data": "0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000b4", + "logIndex": 7, + "blockHash": "0x3b3b98801a85737fd02d766220a4c7d27328a3540922792c8c4c72b1b169a082" + } + ], + "blockNumber": 22, + "cumulativeGasUsed": "2109054", + "status": 1, + "byzantium": true + }, + "args": [ + 180, + [ + "0x2E62c47f502f512C75bd5Ecd70799EFB0Fe7BAA3" + ], + [ + "0x2E62c47f502f512C75bd5Ecd70799EFB0Fe7BAA3" + ] + ], + "solcInputHash": "4081879ecbcad532ab272d265ceb1761", + "metadata": "{\"compiler\":{\"version\":\"0.8.11+commit.d7f03943\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"minDelay\",\"type\":\"uint256\"},{\"internalType\":\"address[]\",\"name\":\"proposers\",\"type\":\"address[]\"},{\"internalType\":\"address[]\",\"name\":\"executors\",\"type\":\"address[]\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"id\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"index\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"target\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"CallExecuted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"id\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"index\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"target\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"predecessor\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"delay\",\"type\":\"uint256\"}],\"name\":\"CallScheduled\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"id\",\"type\":\"bytes32\"}],\"name\":\"Cancelled\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"oldDuration\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newDuration\",\"type\":\"uint256\"}],\"name\":\"MinDelayChange\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"previousAdminRole\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"newAdminRole\",\"type\":\"bytes32\"}],\"name\":\"RoleAdminChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"RoleGranted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"RoleRevoked\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"DEFAULT_ADMIN_ROLE\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"EXECUTOR_ROLE\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"PROPOSER_ROLE\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"TIMELOCK_ADMIN_ROLE\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"id\",\"type\":\"bytes32\"}],\"name\":\"cancel\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"target\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"internalType\":\"bytes32\",\"name\":\"predecessor\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"salt\",\"type\":\"bytes32\"}],\"name\":\"execute\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"targets\",\"type\":\"address[]\"},{\"internalType\":\"uint256[]\",\"name\":\"values\",\"type\":\"uint256[]\"},{\"internalType\":\"bytes[]\",\"name\":\"datas\",\"type\":\"bytes[]\"},{\"internalType\":\"bytes32\",\"name\":\"predecessor\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"salt\",\"type\":\"bytes32\"}],\"name\":\"executeBatch\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getMinDelay\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"duration\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"}],\"name\":\"getRoleAdmin\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"id\",\"type\":\"bytes32\"}],\"name\":\"getTimestamp\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"timestamp\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"grantRole\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"hasRole\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"target\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"internalType\":\"bytes32\",\"name\":\"predecessor\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"salt\",\"type\":\"bytes32\"}],\"name\":\"hashOperation\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"hash\",\"type\":\"bytes32\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"targets\",\"type\":\"address[]\"},{\"internalType\":\"uint256[]\",\"name\":\"values\",\"type\":\"uint256[]\"},{\"internalType\":\"bytes[]\",\"name\":\"datas\",\"type\":\"bytes[]\"},{\"internalType\":\"bytes32\",\"name\":\"predecessor\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"salt\",\"type\":\"bytes32\"}],\"name\":\"hashOperationBatch\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"hash\",\"type\":\"bytes32\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"id\",\"type\":\"bytes32\"}],\"name\":\"isOperation\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"pending\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"id\",\"type\":\"bytes32\"}],\"name\":\"isOperationDone\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"done\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"id\",\"type\":\"bytes32\"}],\"name\":\"isOperationPending\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"pending\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"id\",\"type\":\"bytes32\"}],\"name\":\"isOperationReady\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"ready\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"renounceRole\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"revokeRole\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"target\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"internalType\":\"bytes32\",\"name\":\"predecessor\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"salt\",\"type\":\"bytes32\"},{\"internalType\":\"uint256\",\"name\":\"delay\",\"type\":\"uint256\"}],\"name\":\"schedule\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"targets\",\"type\":\"address[]\"},{\"internalType\":\"uint256[]\",\"name\":\"values\",\"type\":\"uint256[]\"},{\"internalType\":\"bytes[]\",\"name\":\"datas\",\"type\":\"bytes[]\"},{\"internalType\":\"bytes32\",\"name\":\"predecessor\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"salt\",\"type\":\"bytes32\"},{\"internalType\":\"uint256\",\"name\":\"delay\",\"type\":\"uint256\"}],\"name\":\"scheduleBatch\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes4\",\"name\":\"interfaceId\",\"type\":\"bytes4\"}],\"name\":\"supportsInterface\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"newDelay\",\"type\":\"uint256\"}],\"name\":\"updateDelay\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"stateMutability\":\"payable\",\"type\":\"receive\"}],\"devdoc\":{\"details\":\"Contract module which acts as a timelocked controller. When set as the owner of an `Ownable` smart contract, it enforces a timelock on all `onlyOwner` maintenance operations. This gives time for users of the controlled contract to exit before a potentially dangerous maintenance operation is applied. By default, this contract is self administered, meaning administration tasks have to go through the timelock process. The proposer (resp executor) role is in charge of proposing (resp executing) operations. A common use case is to position this {TimelockController} as the owner of a smart contract, with a multisig or a DAO as the sole proposer. _Available since v3.3._\",\"events\":{\"CallExecuted(bytes32,uint256,address,uint256,bytes)\":{\"details\":\"Emitted when a call is performed as part of operation `id`.\"},\"CallScheduled(bytes32,uint256,address,uint256,bytes,bytes32,uint256)\":{\"details\":\"Emitted when a call is scheduled as part of operation `id`.\"},\"Cancelled(bytes32)\":{\"details\":\"Emitted when operation `id` is cancelled.\"},\"MinDelayChange(uint256,uint256)\":{\"details\":\"Emitted when the minimum delay for future operations is modified.\"}},\"kind\":\"dev\",\"methods\":{\"cancel(bytes32)\":{\"details\":\"Cancel an operation. Requirements: - the caller must have the 'proposer' role.\"},\"constructor\":{\"details\":\"Initializes the contract with a given `minDelay`.\"},\"execute(address,uint256,bytes,bytes32,bytes32)\":{\"details\":\"Execute an (ready) operation containing a single transaction. Emits a {CallExecuted} event. Requirements: - the caller must have the 'executor' role.\"},\"executeBatch(address[],uint256[],bytes[],bytes32,bytes32)\":{\"details\":\"Execute an (ready) operation containing a batch of transactions. Emits one {CallExecuted} event per transaction in the batch. Requirements: - the caller must have the 'executor' role.\"},\"getMinDelay()\":{\"details\":\"Returns the minimum delay for an operation to become valid. This value can be changed by executing an operation that calls `updateDelay`.\"},\"getRoleAdmin(bytes32)\":{\"details\":\"Returns the admin role that controls `role`. See {grantRole} and {revokeRole}. To change a role's admin, use {_setRoleAdmin}.\"},\"getTimestamp(bytes32)\":{\"details\":\"Returns the timestamp at with an operation becomes ready (0 for unset operations, 1 for done operations).\"},\"grantRole(bytes32,address)\":{\"details\":\"Grants `role` to `account`. If `account` had not been already granted `role`, emits a {RoleGranted} event. Requirements: - the caller must have ``role``'s admin role.\"},\"hasRole(bytes32,address)\":{\"details\":\"Returns `true` if `account` has been granted `role`.\"},\"hashOperation(address,uint256,bytes,bytes32,bytes32)\":{\"details\":\"Returns the identifier of an operation containing a single transaction.\"},\"hashOperationBatch(address[],uint256[],bytes[],bytes32,bytes32)\":{\"details\":\"Returns the identifier of an operation containing a batch of transactions.\"},\"isOperation(bytes32)\":{\"details\":\"Returns whether an id correspond to a registered operation. This includes both Pending, Ready and Done operations.\"},\"isOperationDone(bytes32)\":{\"details\":\"Returns whether an operation is done or not.\"},\"isOperationPending(bytes32)\":{\"details\":\"Returns whether an operation is pending or not.\"},\"isOperationReady(bytes32)\":{\"details\":\"Returns whether an operation is ready or not.\"},\"renounceRole(bytes32,address)\":{\"details\":\"Revokes `role` from the calling account. Roles are often managed via {grantRole} and {revokeRole}: this function's purpose is to provide a mechanism for accounts to lose their privileges if they are compromised (such as when a trusted device is misplaced). If the calling account had been revoked `role`, emits a {RoleRevoked} event. Requirements: - the caller must be `account`.\"},\"revokeRole(bytes32,address)\":{\"details\":\"Revokes `role` from `account`. If `account` had been granted `role`, emits a {RoleRevoked} event. Requirements: - the caller must have ``role``'s admin role.\"},\"schedule(address,uint256,bytes,bytes32,bytes32,uint256)\":{\"details\":\"Schedule an operation containing a single transaction. Emits a {CallScheduled} event. Requirements: - the caller must have the 'proposer' role.\"},\"scheduleBatch(address[],uint256[],bytes[],bytes32,bytes32,uint256)\":{\"details\":\"Schedule an operation containing a batch of transactions. Emits one {CallScheduled} event per transaction in the batch. Requirements: - the caller must have the 'proposer' role.\"},\"supportsInterface(bytes4)\":{\"details\":\"See {IERC165-supportsInterface}.\"},\"updateDelay(uint256)\":{\"details\":\"Changes the minimum timelock duration for future operations. Emits a {MinDelayChange} event. Requirements: - the caller must be the timelock itself. This can only be achieved by scheduling and later executing an operation where the timelock is the target and the data is the ABI-encoded call to this function.\"}},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/bridge/utils/TimelockController.sol\":\"TimelockController\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":5000000},\"remappings\":[]},\"sources\":{\"@openzeppelin/contracts-4.3.1/access/AccessControl.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (access/AccessControl.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"./IAccessControl.sol\\\";\\nimport \\\"../utils/Context.sol\\\";\\nimport \\\"../utils/Strings.sol\\\";\\nimport \\\"../utils/introspection/ERC165.sol\\\";\\n\\n/**\\n * @dev Contract module that allows children to implement role-based access\\n * control mechanisms. This is a lightweight version that doesn't allow enumerating role\\n * members except through off-chain means by accessing the contract event logs. Some\\n * applications may benefit from on-chain enumerability, for those cases see\\n * {AccessControlEnumerable}.\\n *\\n * Roles are referred to by their `bytes32` identifier. These should be exposed\\n * in the external API and be unique. The best way to achieve this is by\\n * using `public constant` hash digests:\\n *\\n * ```\\n * bytes32 public constant MY_ROLE = keccak256(\\\"MY_ROLE\\\");\\n * ```\\n *\\n * Roles can be used to represent a set of permissions. To restrict access to a\\n * function call, use {hasRole}:\\n *\\n * ```\\n * function foo() public {\\n * require(hasRole(MY_ROLE, msg.sender));\\n * ...\\n * }\\n * ```\\n *\\n * Roles can be granted and revoked dynamically via the {grantRole} and\\n * {revokeRole} functions. Each role has an associated admin role, and only\\n * accounts that have a role's admin role can call {grantRole} and {revokeRole}.\\n *\\n * By default, the admin role for all roles is `DEFAULT_ADMIN_ROLE`, which means\\n * that only accounts with this role will be able to grant or revoke other\\n * roles. More complex role relationships can be created by using\\n * {_setRoleAdmin}.\\n *\\n * WARNING: The `DEFAULT_ADMIN_ROLE` is also its own admin: it has permission to\\n * grant and revoke this role. Extra precautions should be taken to secure\\n * accounts that have been granted it.\\n */\\nabstract contract AccessControl is Context, IAccessControl, ERC165 {\\n struct RoleData {\\n mapping(address => bool) members;\\n bytes32 adminRole;\\n }\\n\\n mapping(bytes32 => RoleData) private _roles;\\n\\n bytes32 public constant DEFAULT_ADMIN_ROLE = 0x00;\\n\\n /**\\n * @dev Modifier that checks that an account has a specific role. Reverts\\n * with a standardized message including the required role.\\n *\\n * The format of the revert reason is given by the following regular expression:\\n *\\n * /^AccessControl: account (0x[0-9a-f]{40}) is missing role (0x[0-9a-f]{64})$/\\n *\\n * _Available since v4.1._\\n */\\n modifier onlyRole(bytes32 role) {\\n _checkRole(role, _msgSender());\\n _;\\n }\\n\\n /**\\n * @dev See {IERC165-supportsInterface}.\\n */\\n function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\\n return interfaceId == type(IAccessControl).interfaceId || super.supportsInterface(interfaceId);\\n }\\n\\n /**\\n * @dev Returns `true` if `account` has been granted `role`.\\n */\\n function hasRole(bytes32 role, address account) public view override returns (bool) {\\n return _roles[role].members[account];\\n }\\n\\n /**\\n * @dev Revert with a standard message if `account` is missing `role`.\\n *\\n * The format of the revert reason is given by the following regular expression:\\n *\\n * /^AccessControl: account (0x[0-9a-f]{40}) is missing role (0x[0-9a-f]{64})$/\\n */\\n function _checkRole(bytes32 role, address account) internal view {\\n if (!hasRole(role, account)) {\\n revert(\\n string(\\n abi.encodePacked(\\n \\\"AccessControl: account \\\",\\n Strings.toHexString(uint160(account), 20),\\n \\\" is missing role \\\",\\n Strings.toHexString(uint256(role), 32)\\n )\\n )\\n );\\n }\\n }\\n\\n /**\\n * @dev Returns the admin role that controls `role`. See {grantRole} and\\n * {revokeRole}.\\n *\\n * To change a role's admin, use {_setRoleAdmin}.\\n */\\n function getRoleAdmin(bytes32 role) public view override returns (bytes32) {\\n return _roles[role].adminRole;\\n }\\n\\n /**\\n * @dev Grants `role` to `account`.\\n *\\n * If `account` had not been already granted `role`, emits a {RoleGranted}\\n * event.\\n *\\n * Requirements:\\n *\\n * - the caller must have ``role``'s admin role.\\n */\\n function grantRole(bytes32 role, address account) public virtual override onlyRole(getRoleAdmin(role)) {\\n _grantRole(role, account);\\n }\\n\\n /**\\n * @dev Revokes `role` from `account`.\\n *\\n * If `account` had been granted `role`, emits a {RoleRevoked} event.\\n *\\n * Requirements:\\n *\\n * - the caller must have ``role``'s admin role.\\n */\\n function revokeRole(bytes32 role, address account) public virtual override onlyRole(getRoleAdmin(role)) {\\n _revokeRole(role, account);\\n }\\n\\n /**\\n * @dev Revokes `role` from the calling account.\\n *\\n * Roles are often managed via {grantRole} and {revokeRole}: this function's\\n * purpose is to provide a mechanism for accounts to lose their privileges\\n * if they are compromised (such as when a trusted device is misplaced).\\n *\\n * If the calling account had been revoked `role`, emits a {RoleRevoked}\\n * event.\\n *\\n * Requirements:\\n *\\n * - the caller must be `account`.\\n */\\n function renounceRole(bytes32 role, address account) public virtual override {\\n require(account == _msgSender(), \\\"AccessControl: can only renounce roles for self\\\");\\n\\n _revokeRole(role, account);\\n }\\n\\n /**\\n * @dev Grants `role` to `account`.\\n *\\n * If `account` had not been already granted `role`, emits a {RoleGranted}\\n * event. Note that unlike {grantRole}, this function doesn't perform any\\n * checks on the calling account.\\n *\\n * [WARNING]\\n * ====\\n * This function should only be called from the constructor when setting\\n * up the initial roles for the system.\\n *\\n * Using this function in any other way is effectively circumventing the admin\\n * system imposed by {AccessControl}.\\n * ====\\n *\\n * NOTE: This function is deprecated in favor of {_grantRole}.\\n */\\n function _setupRole(bytes32 role, address account) internal virtual {\\n _grantRole(role, account);\\n }\\n\\n /**\\n * @dev Sets `adminRole` as ``role``'s admin role.\\n *\\n * Emits a {RoleAdminChanged} event.\\n */\\n function _setRoleAdmin(bytes32 role, bytes32 adminRole) internal virtual {\\n bytes32 previousAdminRole = getRoleAdmin(role);\\n _roles[role].adminRole = adminRole;\\n emit RoleAdminChanged(role, previousAdminRole, adminRole);\\n }\\n\\n /**\\n * @dev Grants `role` to `account`.\\n *\\n * Internal function without access restriction.\\n */\\n function _grantRole(bytes32 role, address account) internal virtual {\\n if (!hasRole(role, account)) {\\n _roles[role].members[account] = true;\\n emit RoleGranted(role, account, _msgSender());\\n }\\n }\\n\\n /**\\n * @dev Revokes `role` from `account`.\\n *\\n * Internal function without access restriction.\\n */\\n function _revokeRole(bytes32 role, address account) internal virtual {\\n if (hasRole(role, account)) {\\n _roles[role].members[account] = false;\\n emit RoleRevoked(role, account, _msgSender());\\n }\\n }\\n}\\n\",\"keccak256\":\"0xb9a137b317dc4806805f2259686186c0c053c32d80fe9c15ecdbf2eb1cf52849\",\"license\":\"MIT\"},\"@openzeppelin/contracts-4.3.1/access/IAccessControl.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (access/IAccessControl.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev External interface of AccessControl declared to support ERC165 detection.\\n */\\ninterface IAccessControl {\\n /**\\n * @dev Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole`\\n *\\n * `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite\\n * {RoleAdminChanged} not being emitted signaling this.\\n *\\n * _Available since v3.1._\\n */\\n event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole);\\n\\n /**\\n * @dev Emitted when `account` is granted `role`.\\n *\\n * `sender` is the account that originated the contract call, an admin role\\n * bearer except when using {AccessControl-_setupRole}.\\n */\\n event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender);\\n\\n /**\\n * @dev Emitted when `account` is revoked `role`.\\n *\\n * `sender` is the account that originated the contract call:\\n * - if using `revokeRole`, it is the admin role bearer\\n * - if using `renounceRole`, it is the role bearer (i.e. `account`)\\n */\\n event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender);\\n\\n /**\\n * @dev Returns `true` if `account` has been granted `role`.\\n */\\n function hasRole(bytes32 role, address account) external view returns (bool);\\n\\n /**\\n * @dev Returns the admin role that controls `role`. See {grantRole} and\\n * {revokeRole}.\\n *\\n * To change a role's admin, use {AccessControl-_setRoleAdmin}.\\n */\\n function getRoleAdmin(bytes32 role) external view returns (bytes32);\\n\\n /**\\n * @dev Grants `role` to `account`.\\n *\\n * If `account` had not been already granted `role`, emits a {RoleGranted}\\n * event.\\n *\\n * Requirements:\\n *\\n * - the caller must have ``role``'s admin role.\\n */\\n function grantRole(bytes32 role, address account) external;\\n\\n /**\\n * @dev Revokes `role` from `account`.\\n *\\n * If `account` had been granted `role`, emits a {RoleRevoked} event.\\n *\\n * Requirements:\\n *\\n * - the caller must have ``role``'s admin role.\\n */\\n function revokeRole(bytes32 role, address account) external;\\n\\n /**\\n * @dev Revokes `role` from the calling account.\\n *\\n * Roles are often managed via {grantRole} and {revokeRole}: this function's\\n * purpose is to provide a mechanism for accounts to lose their privileges\\n * if they are compromised (such as when a trusted device is misplaced).\\n *\\n * If the calling account had been granted `role`, emits a {RoleRevoked}\\n * event.\\n *\\n * Requirements:\\n *\\n * - the caller must be `account`.\\n */\\n function renounceRole(bytes32 role, address account) external;\\n}\\n\",\"keccak256\":\"0x59ce320a585d7e1f163cd70390a0ef2ff9cec832e2aa544293a00692465a7a57\",\"license\":\"MIT\"},\"@openzeppelin/contracts-4.3.1/utils/Context.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)\\n\\npragma solidity ^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 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) {\\n return msg.sender;\\n }\\n\\n function _msgData() internal view virtual returns (bytes calldata) {\\n return msg.data;\\n }\\n}\\n\",\"keccak256\":\"0xe2e337e6dde9ef6b680e07338c493ebea1b5fd09b43424112868e9cc1706bca7\",\"license\":\"MIT\"},\"@openzeppelin/contracts-4.3.1/utils/Strings.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (utils/Strings.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev String operations.\\n */\\nlibrary Strings {\\n bytes16 private constant _HEX_SYMBOLS = \\\"0123456789abcdef\\\";\\n\\n /**\\n * @dev Converts a `uint256` to its ASCII `string` decimal representation.\\n */\\n function toString(uint256 value) internal pure returns (string memory) {\\n // Inspired by OraclizeAPI's implementation - MIT licence\\n // https://github.com/oraclize/ethereum-api/blob/b42146b063c7d6ee1358846c198246239e9360e8/oraclizeAPI_0.4.25.sol\\n\\n if (value == 0) {\\n return \\\"0\\\";\\n }\\n uint256 temp = value;\\n uint256 digits;\\n while (temp != 0) {\\n digits++;\\n temp /= 10;\\n }\\n bytes memory buffer = new bytes(digits);\\n while (value != 0) {\\n digits -= 1;\\n buffer[digits] = bytes1(uint8(48 + uint256(value % 10)));\\n value /= 10;\\n }\\n return string(buffer);\\n }\\n\\n /**\\n * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation.\\n */\\n function toHexString(uint256 value) internal pure returns (string memory) {\\n if (value == 0) {\\n return \\\"0x00\\\";\\n }\\n uint256 temp = value;\\n uint256 length = 0;\\n while (temp != 0) {\\n length++;\\n temp >>= 8;\\n }\\n return toHexString(value, length);\\n }\\n\\n /**\\n * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length.\\n */\\n function toHexString(uint256 value, uint256 length) internal pure returns (string memory) {\\n bytes memory buffer = new bytes(2 * length + 2);\\n buffer[0] = \\\"0\\\";\\n buffer[1] = \\\"x\\\";\\n for (uint256 i = 2 * length + 1; i > 1; --i) {\\n buffer[i] = _HEX_SYMBOLS[value & 0xf];\\n value >>= 4;\\n }\\n require(value == 0, \\\"Strings: hex length insufficient\\\");\\n return string(buffer);\\n }\\n}\\n\",\"keccak256\":\"0x32c202bd28995dd20c4347b7c6467a6d3241c74c8ad3edcbb610cd9205916c45\",\"license\":\"MIT\"},\"@openzeppelin/contracts-4.3.1/utils/introspection/ERC165.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (utils/introspection/ERC165.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"./IERC165.sol\\\";\\n\\n/**\\n * @dev Implementation of the {IERC165} interface.\\n *\\n * Contracts that want to implement ERC165 should inherit from this contract and override {supportsInterface} to check\\n * for the additional interface id that will be supported. For example:\\n *\\n * ```solidity\\n * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\\n * return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);\\n * }\\n * ```\\n *\\n * Alternatively, {ERC165Storage} provides an easier to use but more expensive implementation.\\n */\\nabstract contract ERC165 is IERC165 {\\n /**\\n * @dev See {IERC165-supportsInterface}.\\n */\\n function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\\n return interfaceId == type(IERC165).interfaceId;\\n }\\n}\\n\",\"keccak256\":\"0xd10975de010d89fd1c78dc5e8a9a7e7f496198085c151648f20cba166b32582b\",\"license\":\"MIT\"},\"@openzeppelin/contracts-4.3.1/utils/introspection/IERC165.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Interface of the ERC165 standard, as defined in the\\n * https://eips.ethereum.org/EIPS/eip-165[EIP].\\n *\\n * Implementers can declare support of contract interfaces, which can then be\\n * queried by others ({ERC165Checker}).\\n *\\n * For an implementation, see {ERC165}.\\n */\\ninterface IERC165 {\\n /**\\n * @dev Returns true if this contract implements the interface defined by\\n * `interfaceId`. See the corresponding\\n * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]\\n * to learn more about how these ids are created.\\n *\\n * This function call must use less than 30 000 gas.\\n */\\n function supportsInterface(bytes4 interfaceId) external view returns (bool);\\n}\\n\",\"keccak256\":\"0x447a5f3ddc18419d41ff92b3773fb86471b1db25773e07f877f548918a185bf1\",\"license\":\"MIT\"},\"@openzeppelin/contracts-4.3.1/utils/math/SafeMath.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (utils/math/SafeMath.sol)\\n\\npragma solidity ^0.8.0;\\n\\n// CAUTION\\n// This version of SafeMath should only be used with Solidity 0.8 or later,\\n// because it relies on the compiler's built in overflow checks.\\n\\n/**\\n * @dev Wrappers over Solidity's arithmetic operations.\\n *\\n * NOTE: `SafeMath` is generally not needed starting with Solidity 0.8, since the compiler\\n * now has built in overflow checking.\\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 unchecked {\\n uint256 c = a + b;\\n if (c < a) return (false, 0);\\n return (true, c);\\n }\\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 unchecked {\\n if (b > a) return (false, 0);\\n return (true, a - b);\\n }\\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 unchecked {\\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 /**\\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 unchecked {\\n if (b == 0) return (false, 0);\\n return (true, a / b);\\n }\\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 unchecked {\\n if (b == 0) return (false, 0);\\n return (true, a % b);\\n }\\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 return a + b;\\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 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 return a * b;\\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.\\n *\\n * Requirements:\\n *\\n * - The divisor cannot be zero.\\n */\\n function div(uint256 a, uint256 b) internal pure returns (uint256) {\\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 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(\\n uint256 a,\\n uint256 b,\\n string memory errorMessage\\n ) internal pure returns (uint256) {\\n unchecked {\\n require(b <= a, errorMessage);\\n return a - b;\\n }\\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 * 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(\\n uint256 a,\\n uint256 b,\\n string memory errorMessage\\n ) internal pure returns (uint256) {\\n unchecked {\\n require(b > 0, errorMessage);\\n return a / b;\\n }\\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(\\n uint256 a,\\n uint256 b,\\n string memory errorMessage\\n ) internal pure returns (uint256) {\\n unchecked {\\n require(b > 0, errorMessage);\\n return a % b;\\n }\\n }\\n}\\n\",\"keccak256\":\"0xa2f576be637946f767aa56601c26d717f48a0aff44f82e46f13807eea1009a21\",\"license\":\"MIT\"},\"contracts/bridge/utils/TimelockController.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.8.0;\\n\\nimport '@openzeppelin/contracts-4.3.1/access/AccessControl.sol';\\nimport '@openzeppelin/contracts-4.3.1/utils/math/SafeMath.sol';\\n\\n/**\\n * @dev Contract module which acts as a timelocked controller. When set as the\\n * owner of an `Ownable` smart contract, it enforces a timelock on all\\n * `onlyOwner` maintenance operations. This gives time for users of the\\n * controlled contract to exit before a potentially dangerous maintenance\\n * operation is applied.\\n *\\n * By default, this contract is self administered, meaning administration tasks\\n * have to go through the timelock process. The proposer (resp executor) role\\n * is in charge of proposing (resp executing) operations. A common use case is\\n * to position this {TimelockController} as the owner of a smart contract, with\\n * a multisig or a DAO as the sole proposer.\\n *\\n * _Available since v3.3._\\n */\\ncontract TimelockController is AccessControl {\\n bytes32 public constant TIMELOCK_ADMIN_ROLE = keccak256(\\\"TIMELOCK_ADMIN_ROLE\\\");\\n bytes32 public constant PROPOSER_ROLE = keccak256(\\\"PROPOSER_ROLE\\\");\\n bytes32 public constant EXECUTOR_ROLE = keccak256(\\\"EXECUTOR_ROLE\\\");\\n uint256 internal constant _DONE_TIMESTAMP = uint256(1);\\n\\n mapping(bytes32 => uint256) private _timestamps;\\n uint256 private _minDelay;\\n\\n /**\\n * @dev Emitted when a call is scheduled as part of operation `id`.\\n */\\n event CallScheduled(\\n bytes32 indexed id,\\n uint256 indexed index,\\n address target,\\n uint256 value,\\n bytes data,\\n bytes32 predecessor,\\n uint256 delay\\n );\\n\\n /**\\n * @dev Emitted when a call is performed as part of operation `id`.\\n */\\n event CallExecuted(bytes32 indexed id, uint256 indexed index, address target, uint256 value, bytes data);\\n\\n /**\\n * @dev Emitted when operation `id` is cancelled.\\n */\\n event Cancelled(bytes32 indexed id);\\n\\n /**\\n * @dev Emitted when the minimum delay for future operations is modified.\\n */\\n event MinDelayChange(uint256 oldDuration, uint256 newDuration);\\n\\n /**\\n * @dev Initializes the contract with a given `minDelay`.\\n */\\n constructor(\\n uint256 minDelay,\\n address[] memory proposers,\\n address[] memory executors\\n ) {\\n _setRoleAdmin(TIMELOCK_ADMIN_ROLE, TIMELOCK_ADMIN_ROLE);\\n _setRoleAdmin(PROPOSER_ROLE, TIMELOCK_ADMIN_ROLE);\\n _setRoleAdmin(EXECUTOR_ROLE, TIMELOCK_ADMIN_ROLE);\\n\\n // deployer + self administration\\n _setupRole(TIMELOCK_ADMIN_ROLE, _msgSender());\\n _setupRole(TIMELOCK_ADMIN_ROLE, address(this));\\n\\n // register proposers\\n for (uint256 i = 0; i < proposers.length; ++i) {\\n _setupRole(PROPOSER_ROLE, proposers[i]);\\n }\\n\\n // register executors\\n for (uint256 i = 0; i < executors.length; ++i) {\\n _setupRole(EXECUTOR_ROLE, executors[i]);\\n }\\n\\n _minDelay = minDelay;\\n emit MinDelayChange(0, minDelay);\\n }\\n\\n /**\\n * @dev Modifier to make a function callable only by a certain role. In\\n * addition to checking the sender's role, `address(0)` 's role is also\\n * considered. Granting a role to `address(0)` is equivalent to enabling\\n * this role for everyone.\\n */\\n modifier onlyRoleOrOpenRole(bytes32 role) {\\n if (!hasRole(role, address(0))) {\\n _checkRole(role, _msgSender());\\n }\\n _;\\n }\\n\\n /**\\n * @dev Contract might receive/hold ETH as part of the maintenance process.\\n */\\n receive() external payable {}\\n\\n /**\\n * @dev Returns whether an id correspond to a registered operation. This\\n * includes both Pending, Ready and Done operations.\\n */\\n function isOperation(bytes32 id) public view virtual returns (bool pending) {\\n return getTimestamp(id) > 0;\\n }\\n\\n /**\\n * @dev Returns whether an operation is pending or not.\\n */\\n function isOperationPending(bytes32 id) public view virtual returns (bool pending) {\\n return getTimestamp(id) > _DONE_TIMESTAMP;\\n }\\n\\n /**\\n * @dev Returns whether an operation is ready or not.\\n */\\n function isOperationReady(bytes32 id) public view virtual returns (bool ready) {\\n uint256 timestamp = getTimestamp(id);\\n return timestamp > _DONE_TIMESTAMP && timestamp <= block.timestamp;\\n }\\n\\n /**\\n * @dev Returns whether an operation is done or not.\\n */\\n function isOperationDone(bytes32 id) public view virtual returns (bool done) {\\n return getTimestamp(id) == _DONE_TIMESTAMP;\\n }\\n\\n /**\\n * @dev Returns the timestamp at with an operation becomes ready (0 for\\n * unset operations, 1 for done operations).\\n */\\n function getTimestamp(bytes32 id) public view virtual returns (uint256 timestamp) {\\n return _timestamps[id];\\n }\\n\\n /**\\n * @dev Returns the minimum delay for an operation to become valid.\\n *\\n * This value can be changed by executing an operation that calls `updateDelay`.\\n */\\n function getMinDelay() public view virtual returns (uint256 duration) {\\n return _minDelay;\\n }\\n\\n /**\\n * @dev Returns the identifier of an operation containing a single\\n * transaction.\\n */\\n function hashOperation(\\n address target,\\n uint256 value,\\n bytes calldata data,\\n bytes32 predecessor,\\n bytes32 salt\\n ) public pure virtual returns (bytes32 hash) {\\n return keccak256(abi.encode(target, value, data, predecessor, salt));\\n }\\n\\n /**\\n * @dev Returns the identifier of an operation containing a batch of\\n * transactions.\\n */\\n function hashOperationBatch(\\n address[] calldata targets,\\n uint256[] calldata values,\\n bytes[] calldata datas,\\n bytes32 predecessor,\\n bytes32 salt\\n ) public pure virtual returns (bytes32 hash) {\\n return keccak256(abi.encode(targets, values, datas, predecessor, salt));\\n }\\n\\n /**\\n * @dev Schedule an operation containing a single transaction.\\n *\\n * Emits a {CallScheduled} event.\\n *\\n * Requirements:\\n *\\n * - the caller must have the 'proposer' role.\\n */\\n function schedule(\\n address target,\\n uint256 value,\\n bytes calldata data,\\n bytes32 predecessor,\\n bytes32 salt,\\n uint256 delay\\n ) public virtual onlyRole(PROPOSER_ROLE) {\\n bytes32 id = hashOperation(target, value, data, predecessor, salt);\\n _schedule(id, delay);\\n emit CallScheduled(id, 0, target, value, data, predecessor, delay);\\n }\\n\\n /**\\n * @dev Schedule an operation containing a batch of transactions.\\n *\\n * Emits one {CallScheduled} event per transaction in the batch.\\n *\\n * Requirements:\\n *\\n * - the caller must have the 'proposer' role.\\n */\\n function scheduleBatch(\\n address[] calldata targets,\\n uint256[] calldata values,\\n bytes[] calldata datas,\\n bytes32 predecessor,\\n bytes32 salt,\\n uint256 delay\\n ) public virtual onlyRole(PROPOSER_ROLE) {\\n require(targets.length == values.length, \\\"TimelockController: length mismatch\\\");\\n require(targets.length == datas.length, \\\"TimelockController: length mismatch\\\");\\n\\n bytes32 id = hashOperationBatch(targets, values, datas, predecessor, salt);\\n _schedule(id, delay);\\n for (uint256 i = 0; i < targets.length; ++i) {\\n emit CallScheduled(id, i, targets[i], values[i], datas[i], predecessor, delay);\\n }\\n }\\n\\n /**\\n * @dev Schedule an operation that is to becomes valid after a given delay.\\n */\\n function _schedule(bytes32 id, uint256 delay) private {\\n require(!isOperation(id), \\\"TimelockController: operation already scheduled\\\");\\n require(delay >= getMinDelay(), \\\"TimelockController: insufficient delay\\\");\\n _timestamps[id] = block.timestamp + delay;\\n }\\n\\n /**\\n * @dev Cancel an operation.\\n *\\n * Requirements:\\n *\\n * - the caller must have the 'proposer' role.\\n */\\n function cancel(bytes32 id) public virtual onlyRole(PROPOSER_ROLE) {\\n require(isOperationPending(id), \\\"TimelockController: operation cannot be cancelled\\\");\\n delete _timestamps[id];\\n\\n emit Cancelled(id);\\n }\\n\\n /**\\n * @dev Execute an (ready) operation containing a single transaction.\\n *\\n * Emits a {CallExecuted} event.\\n *\\n * Requirements:\\n *\\n * - the caller must have the 'executor' role.\\n */\\n function execute(\\n address target,\\n uint256 value,\\n bytes calldata data,\\n bytes32 predecessor,\\n bytes32 salt\\n ) public payable virtual onlyRoleOrOpenRole(EXECUTOR_ROLE) {\\n bytes32 id = hashOperation(target, value, data, predecessor, salt);\\n _beforeCall(id, predecessor);\\n _call(id, 0, target, value, data);\\n _afterCall(id);\\n }\\n\\n /**\\n * @dev Execute an (ready) operation containing a batch of transactions.\\n *\\n * Emits one {CallExecuted} event per transaction in the batch.\\n *\\n * Requirements:\\n *\\n * - the caller must have the 'executor' role.\\n */\\n function executeBatch(\\n address[] calldata targets,\\n uint256[] calldata values,\\n bytes[] calldata datas,\\n bytes32 predecessor,\\n bytes32 salt\\n ) public payable virtual onlyRoleOrOpenRole(EXECUTOR_ROLE) {\\n require(targets.length == values.length, \\\"TimelockController: length mismatch\\\");\\n require(targets.length == datas.length, \\\"TimelockController: length mismatch\\\");\\n\\n bytes32 id = hashOperationBatch(targets, values, datas, predecessor, salt);\\n _beforeCall(id, predecessor);\\n for (uint256 i = 0; i < targets.length; ++i) {\\n _call(id, i, targets[i], values[i], datas[i]);\\n }\\n _afterCall(id);\\n }\\n\\n /**\\n * @dev Checks before execution of an operation's calls.\\n */\\n function _beforeCall(bytes32 id, bytes32 predecessor) private view {\\n require(isOperationReady(id), \\\"TimelockController: operation is not ready\\\");\\n require(predecessor == bytes32(0) || isOperationDone(predecessor), \\\"TimelockController: missing dependency\\\");\\n }\\n\\n /**\\n * @dev Checks after execution of an operation's calls.\\n */\\n function _afterCall(bytes32 id) private {\\n require(isOperationReady(id), \\\"TimelockController: operation is not ready\\\");\\n _timestamps[id] = _DONE_TIMESTAMP;\\n }\\n\\n /**\\n * @dev Execute an operation's call.\\n *\\n * Emits a {CallExecuted} event.\\n */\\n function _call(\\n bytes32 id,\\n uint256 index,\\n address target,\\n uint256 value,\\n bytes calldata data\\n ) private {\\n (bool success, ) = target.call{value: value}(data);\\n require(success, \\\"TimelockController: underlying transaction reverted\\\");\\n\\n emit CallExecuted(id, index, target, value, data);\\n }\\n\\n /**\\n * @dev Changes the minimum timelock duration for future operations.\\n *\\n * Emits a {MinDelayChange} event.\\n *\\n * Requirements:\\n *\\n * - the caller must be the timelock itself. This can only be achieved by scheduling and later executing\\n * an operation where the timelock is the target and the data is the ABI-encoded call to this function.\\n */\\n function updateDelay(uint256 newDelay) external virtual {\\n require(msg.sender == address(this), \\\"TimelockController: caller must be timelock\\\");\\n emit MinDelayChange(_minDelay, newDelay);\\n _minDelay = newDelay;\\n }\\n}\",\"keccak256\":\"0xd552dea81496f35f72d19a77b4e6a6aa7505678be98716aff0780468750d2fa4\",\"license\":\"MIT\"}},\"version\":1}", + "bytecode": "0x60806040523480156200001157600080fd5b506040516200264a3803806200264a8339810160408190526200003491620003a4565b6200004f600080516020620025ea83398151915280620001c9565b620000796000805160206200260a833981519152600080516020620025ea833981519152620001c9565b620000a36000805160206200262a833981519152600080516020620025ea833981519152620001c9565b620000be600080516020620025ea8339815191523362000214565b620000d9600080516020620025ea8339815191523062000214565b60005b82518110156200013657620001236000805160206200260a8339815191528483815181106200010f576200010f62000418565b60200260200101516200021460201b60201c565b6200012e816200042e565b9050620000dc565b5060005b815181101562000180576200016d6000805160206200262a8339815191528383815181106200010f576200010f62000418565b62000178816200042e565b90506200013a565b5060028390556040805160008152602081018590527f11c24f4ead16507c69ac467fbd5e4eed5fb5c699626d2cc6d66421df253886d5910160405180910390a150505062000458565b600082815260208190526040808220600101805490849055905190918391839186917fbd79b86ffe0ab8e8776151514217cd7cacd52c909f66475c3af44e129f0b00ff9190a4505050565b62000220828262000224565b5050565b6000828152602081815260408083206001600160a01b038516845290915290205460ff1662000220576000828152602081815260408083206001600160a01b03851684529091529020805460ff19166001179055620002803390565b6001600160a01b0316816001600160a01b0316837f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a45050565b634e487b7160e01b600052604160045260246000fd5b80516001600160a01b0381168114620002f257600080fd5b919050565b600082601f8301126200030957600080fd5b815160206001600160401b0380831115620003285762000328620002c4565b8260051b604051601f19603f83011681018181108482111715620003505762000350620002c4565b6040529384528581018301938381019250878511156200036f57600080fd5b83870191505b8482101562000399576200038982620002da565b8352918301919083019062000375565b979650505050505050565b600080600060608486031215620003ba57600080fd5b835160208501519093506001600160401b0380821115620003da57600080fd5b620003e887838801620002f7565b93506040860151915080821115620003ff57600080fd5b506200040e86828701620002f7565b9150509250925092565b634e487b7160e01b600052603260045260246000fd5b60006000198214156200045157634e487b7160e01b600052601160045260246000fd5b5060010190565b61218280620004686000396000f3fe60806040526004361061018f5760003560e01c806364d62353116100d6578063b1c5f4271161007f578063d547741f11610059578063d547741f146104e3578063e38335e514610503578063f27a0c921461051657600080fd5b8063b1c5f42714610476578063c4d252f514610496578063d45c4435146104b657600080fd5b80638f61f4f5116100b05780638f61f4f5146103dc57806391d1485414610410578063a217fddf1461046157600080fd5b806364d623531461037c5780638065657f1461039c5780638f2a0bb0146103bc57600080fd5b8063248a9ca31161013857806331d507501161011257806331d507501461031c57806336568abe1461033c578063584b153e1461035c57600080fd5b8063248a9ca31461029b5780632ab0f529146102cb5780632f2ff15d146102fc57600080fd5b80630d3cf6fc116101695780630d3cf6fc14610234578063134008d31461026857806313bc9f201461027b57600080fd5b806301d5062a1461019b57806301ffc9a7146101bd57806307bd0265146101f257600080fd5b3661019657005b600080fd5b3480156101a757600080fd5b506101bb6101b63660046118ed565b61052b565b005b3480156101c957600080fd5b506101dd6101d8366004611962565b6105c1565b60405190151581526020015b60405180910390f35b3480156101fe57600080fd5b506102267fd8aa0f3194971a2a116679f7c2090f6939c8d4e01a2a8d7e41d55e5351469e6381565b6040519081526020016101e9565b34801561024057600080fd5b506102267f5f58e3a2316349923ce3780f8d587db2d72378aed66a8261c916544fa6846ca581565b6101bb6102763660046119a4565b61065a565b34801561028757600080fd5b506101dd610296366004611a10565b610715565b3480156102a757600080fd5b506102266102b6366004611a10565b60009081526020819052604090206001015490565b3480156102d757600080fd5b506101dd6102e6366004611a10565b6000908152600160208190526040909120541490565b34801561030857600080fd5b506101bb610317366004611a29565b61073b565b34801561032857600080fd5b506101dd610337366004611a10565b610766565b34801561034857600080fd5b506101bb610357366004611a29565b61077f565b34801561036857600080fd5b506101dd610377366004611a10565b610837565b34801561038857600080fd5b506101bb610397366004611a10565b61084d565b3480156103a857600080fd5b506102266103b73660046119a4565b61091d565b3480156103c857600080fd5b506101bb6103d7366004611a9a565b61095c565b3480156103e857600080fd5b506102267fb09aa5aeb3702cfd50b6b62bc4532604938f21248a27a1d5ca736082b6819cc181565b34801561041c57600080fd5b506101dd61042b366004611a29565b60009182526020828152604080842073ffffffffffffffffffffffffffffffffffffffff93909316845291905290205460ff1690565b34801561046d57600080fd5b50610226600081565b34801561048257600080fd5b50610226610491366004611b4c565b610b8f565b3480156104a257600080fd5b506101bb6104b1366004611a10565b610bd4565b3480156104c257600080fd5b506102266104d1366004611a10565b60009081526001602052604090205490565b3480156104ef57600080fd5b506101bb6104fe366004611a29565b610cd0565b6101bb610511366004611b4c565b610cf6565b34801561052257600080fd5b50600254610226565b7fb09aa5aeb3702cfd50b6b62bc4532604938f21248a27a1d5ca736082b6819cc16105568133610f4e565b600061056689898989898961091d565b9050610572818461101e565b6000817f4cf4410cc57040e44862ef0f45f3dd5a5e02db8eb8add648d4b0e236f1d07dca8b8b8b8b8b8a6040516105ae96959493929190611c3e565b60405180910390a3505050505050505050565b60007fffffffff0000000000000000000000000000000000000000000000000000000082167f7965db0b00000000000000000000000000000000000000000000000000000000148061065457507f01ffc9a7000000000000000000000000000000000000000000000000000000007fffffffff000000000000000000000000000000000000000000000000000000008316145b92915050565b600080527fdae2aa361dfd1ca020a396615627d436107c35eff9fe7738a3512819782d70696020527f5ba6852781629bcdcd4bdaa6de76d786f1c64b16acdac474e55bebc0ea157951547fd8aa0f3194971a2a116679f7c2090f6939c8d4e01a2a8d7e41d55e5351469e639060ff166106d7576106d78133610f4e565b60006106e788888888888861091d565b90506106f38185611166565b6107028160008a8a8a8a6112a3565b61070b816113e8565b5050505050505050565b6000818152600160205260408120546001811180156107345750428111155b9392505050565b6000828152602081905260409020600101546107578133610f4e565b6107618383611491565b505050565b60008181526001602052604081205481905b1192915050565b73ffffffffffffffffffffffffffffffffffffffff81163314610829576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602f60248201527f416363657373436f6e74726f6c3a2063616e206f6e6c792072656e6f756e636560448201527f20726f6c657320666f722073656c66000000000000000000000000000000000060648201526084015b60405180910390fd5b6108338282611581565b5050565b6000818152600160208190526040822054610778565b3330146108dc576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f54696d656c6f636b436f6e74726f6c6c65723a2063616c6c6572206d7573742060448201527f62652074696d656c6f636b0000000000000000000000000000000000000000006064820152608401610820565b60025460408051918252602082018390527f11c24f4ead16507c69ac467fbd5e4eed5fb5c699626d2cc6d66421df253886d5910160405180910390a1600255565b600086868686868660405160200161093a96959493929190611c3e565b6040516020818303038152906040528051906020012090509695505050505050565b7fb09aa5aeb3702cfd50b6b62bc4532604938f21248a27a1d5ca736082b6819cc16109878133610f4e565b888714610a16576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602360248201527f54696d656c6f636b436f6e74726f6c6c65723a206c656e677468206d69736d6160448201527f74636800000000000000000000000000000000000000000000000000000000006064820152608401610820565b888514610aa5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602360248201527f54696d656c6f636b436f6e74726f6c6c65723a206c656e677468206d69736d6160448201527f74636800000000000000000000000000000000000000000000000000000000006064820152608401610820565b6000610ab78b8b8b8b8b8b8b8b610b8f565b9050610ac3818461101e565b60005b8a811015610b815780827f4cf4410cc57040e44862ef0f45f3dd5a5e02db8eb8add648d4b0e236f1d07dca8e8e85818110610b0357610b03611c89565b9050602002016020810190610b189190611cb8565b8d8d86818110610b2a57610b2a611c89565b905060200201358c8c87818110610b4357610b43611c89565b9050602002810190610b559190611cd3565b8c8b604051610b6996959493929190611c3e565b60405180910390a3610b7a81611d67565b9050610ac6565b505050505050505050505050565b60008888888888888888604051602001610bb0989796959493929190611e70565b60405160208183030381529060405280519060200120905098975050505050505050565b7fb09aa5aeb3702cfd50b6b62bc4532604938f21248a27a1d5ca736082b6819cc1610bff8133610f4e565b610c0882610837565b610c94576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603160248201527f54696d656c6f636b436f6e74726f6c6c65723a206f7065726174696f6e20636160448201527f6e6e6f742062652063616e63656c6c65640000000000000000000000000000006064820152608401610820565b6000828152600160205260408082208290555183917fbaa1eb22f2a492ba1a5fea61b8df4d27c6c8b5f3971e63bb58fa14ff72eedb7091a25050565b600082815260208190526040902060010154610cec8133610f4e565b6107618383611581565b600080527fdae2aa361dfd1ca020a396615627d436107c35eff9fe7738a3512819782d70696020527f5ba6852781629bcdcd4bdaa6de76d786f1c64b16acdac474e55bebc0ea157951547fd8aa0f3194971a2a116679f7c2090f6939c8d4e01a2a8d7e41d55e5351469e639060ff16610d7357610d738133610f4e565b878614610e02576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602360248201527f54696d656c6f636b436f6e74726f6c6c65723a206c656e677468206d69736d6160448201527f74636800000000000000000000000000000000000000000000000000000000006064820152608401610820565b878414610e91576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602360248201527f54696d656c6f636b436f6e74726f6c6c65723a206c656e677468206d69736d6160448201527f74636800000000000000000000000000000000000000000000000000000000006064820152608401610820565b6000610ea38a8a8a8a8a8a8a8a610b8f565b9050610eaf8185611166565b60005b89811015610f3857610f2882828d8d85818110610ed157610ed1611c89565b9050602002016020810190610ee69190611cb8565b8c8c86818110610ef857610ef8611c89565b905060200201358b8b87818110610f1157610f11611c89565b9050602002810190610f239190611cd3565b6112a3565b610f3181611d67565b9050610eb2565b50610f42816113e8565b50505050505050505050565b60008281526020818152604080832073ffffffffffffffffffffffffffffffffffffffff8516845290915290205460ff1661083357610fa48173ffffffffffffffffffffffffffffffffffffffff166014611638565b610faf836020611638565b604051602001610fc0929190611f71565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152908290527f08c379a000000000000000000000000000000000000000000000000000000000825261082091600401611ff2565b61102782610766565b156110b4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602f60248201527f54696d656c6f636b436f6e74726f6c6c65723a206f7065726174696f6e20616c60448201527f7265616479207363686564756c656400000000000000000000000000000000006064820152608401610820565b600254811015611146576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f54696d656c6f636b436f6e74726f6c6c65723a20696e73756666696369656e7460448201527f2064656c617900000000000000000000000000000000000000000000000000006064820152608401610820565b6111508142612043565b6000928352600160205260409092209190915550565b61116f82610715565b6111fb576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f54696d656c6f636b436f6e74726f6c6c65723a206f7065726174696f6e20697360448201527f206e6f74207265616479000000000000000000000000000000000000000000006064820152608401610820565b8015806112175750600081815260016020819052604090912054145b610833576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f54696d656c6f636b436f6e74726f6c6c65723a206d697373696e67206465706560448201527f6e64656e637900000000000000000000000000000000000000000000000000006064820152608401610820565b60008473ffffffffffffffffffffffffffffffffffffffff168484846040516112cd92919061205b565b60006040518083038185875af1925050503d806000811461130a576040519150601f19603f3d011682016040523d82523d6000602084013e61130f565b606091505b50509050806113a0576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603360248201527f54696d656c6f636b436f6e74726f6c6c65723a20756e6465726c79696e67207460448201527f72616e73616374696f6e207265766572746564000000000000000000000000006064820152608401610820565b85877fc2617efa69bab66782fa219543714338489c4e9e178271560a91b82c3f612b58878787876040516113d7949392919061206b565b60405180910390a350505050505050565b6113f181610715565b61147d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f54696d656c6f636b436f6e74726f6c6c65723a206f7065726174696f6e20697360448201527f206e6f74207265616479000000000000000000000000000000000000000000006064820152608401610820565b600090815260016020819052604090912055565b60008281526020818152604080832073ffffffffffffffffffffffffffffffffffffffff8516845290915290205460ff166108335760008281526020818152604080832073ffffffffffffffffffffffffffffffffffffffff85168452909152902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790556115233390565b73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16837f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a45050565b60008281526020818152604080832073ffffffffffffffffffffffffffffffffffffffff8516845290915290205460ff16156108335760008281526020818152604080832073ffffffffffffffffffffffffffffffffffffffff8516808552925280832080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016905551339285917ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b9190a45050565b606060006116478360026120ab565b611652906002612043565b67ffffffffffffffff81111561166a5761166a6120e8565b6040519080825280601f01601f191660200182016040528015611694576020820181803683370190505b5090507f3000000000000000000000000000000000000000000000000000000000000000816000815181106116cb576116cb611c89565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a9053507f78000000000000000000000000000000000000000000000000000000000000008160018151811061172e5761172e611c89565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350600061176a8460026120ab565b611775906001612043565b90505b6001811115611812577f303132333435363738396162636465660000000000000000000000000000000085600f16601081106117b6576117b6611c89565b1a60f81b8282815181106117cc576117cc611c89565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a90535060049490941c9361180b81612117565b9050611778565b508315610734576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f537472696e67733a20686578206c656e67746820696e73756666696369656e746044820152606401610820565b803573ffffffffffffffffffffffffffffffffffffffff8116811461189f57600080fd5b919050565b60008083601f8401126118b657600080fd5b50813567ffffffffffffffff8111156118ce57600080fd5b6020830191508360208285010111156118e657600080fd5b9250929050565b600080600080600080600060c0888a03121561190857600080fd5b6119118861187b565b965060208801359550604088013567ffffffffffffffff81111561193457600080fd5b6119408a828b016118a4565b989b979a50986060810135976080820135975060a09091013595509350505050565b60006020828403121561197457600080fd5b81357fffffffff000000000000000000000000000000000000000000000000000000008116811461073457600080fd5b60008060008060008060a087890312156119bd57600080fd5b6119c68761187b565b955060208701359450604087013567ffffffffffffffff8111156119e957600080fd5b6119f589828a016118a4565b979a9699509760608101359660809091013595509350505050565b600060208284031215611a2257600080fd5b5035919050565b60008060408385031215611a3c57600080fd5b82359150611a4c6020840161187b565b90509250929050565b60008083601f840112611a6757600080fd5b50813567ffffffffffffffff811115611a7f57600080fd5b6020830191508360208260051b85010111156118e657600080fd5b600080600080600080600080600060c08a8c031215611ab857600080fd5b893567ffffffffffffffff80821115611ad057600080fd5b611adc8d838e01611a55565b909b50995060208c0135915080821115611af557600080fd5b611b018d838e01611a55565b909950975060408c0135915080821115611b1a57600080fd5b50611b278c828d01611a55565b9a9d999c50979a969997986060880135976080810135975060a0013595509350505050565b60008060008060008060008060a0898b031215611b6857600080fd5b883567ffffffffffffffff80821115611b8057600080fd5b611b8c8c838d01611a55565b909a50985060208b0135915080821115611ba557600080fd5b611bb18c838d01611a55565b909850965060408b0135915080821115611bca57600080fd5b50611bd78b828c01611a55565b999c989b509699959896976060870135966080013595509350505050565b8183528181602085013750600060208284010152600060207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116840101905092915050565b73ffffffffffffffffffffffffffffffffffffffff8716815285602082015260a060408201526000611c7460a083018688611bf5565b60608301949094525060800152949350505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b600060208284031215611cca57600080fd5b6107348261187b565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe1843603018112611d0857600080fd5b83018035915067ffffffffffffffff821115611d2357600080fd5b6020019150368190038213156118e657600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff821415611d9957611d99611d38565b5060010190565b60008383855260208086019550808560051b8301018460005b87811015611e63577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe085840301895281357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe1883603018112611e1a57600080fd5b8701803567ffffffffffffffff811115611e3357600080fd5b803603891315611e4257600080fd5b611e4f8582888501611bf5565b9a86019a9450505090830190600101611db9565b5090979650505050505050565b60a0808252810188905260008960c08301825b8b811015611ebe5773ffffffffffffffffffffffffffffffffffffffff611ea98461187b565b16825260209283019290910190600101611e83565b5083810360208501528881527f07ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff891115611ef757600080fd5b8860051b9150818a602083013781810191505060208101600081526020848303016040850152611f2881888a611da0565b6060850196909652505050608001529695505050505050565b60005b83811015611f5c578181015183820152602001611f44565b83811115611f6b576000848401525b50505050565b7f416363657373436f6e74726f6c3a206163636f756e7420000000000000000000815260008351611fa9816017850160208801611f41565b7f206973206d697373696e6720726f6c65200000000000000000000000000000006017918401918201528351611fe6816028840160208801611f41565b01602801949350505050565b6020815260008251806020840152612011816040850160208701611f41565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169190910160400192915050565b6000821982111561205657612056611d38565b500190565b8183823760009101908152919050565b73ffffffffffffffffffffffffffffffffffffffff851681528360208201526060604082015260006120a1606083018486611bf5565b9695505050505050565b6000817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff04831182151516156120e3576120e3611d38565b500290565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b60008161212657612126611d38565b507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff019056fea2646970667358221220275d18460294045f0333b41e202294299c8fd1be4f8fe0cff25fa496bcf503a664736f6c634300080b00335f58e3a2316349923ce3780f8d587db2d72378aed66a8261c916544fa6846ca5b09aa5aeb3702cfd50b6b62bc4532604938f21248a27a1d5ca736082b6819cc1d8aa0f3194971a2a116679f7c2090f6939c8d4e01a2a8d7e41d55e5351469e63", + "deployedBytecode": "0x60806040526004361061018f5760003560e01c806364d62353116100d6578063b1c5f4271161007f578063d547741f11610059578063d547741f146104e3578063e38335e514610503578063f27a0c921461051657600080fd5b8063b1c5f42714610476578063c4d252f514610496578063d45c4435146104b657600080fd5b80638f61f4f5116100b05780638f61f4f5146103dc57806391d1485414610410578063a217fddf1461046157600080fd5b806364d623531461037c5780638065657f1461039c5780638f2a0bb0146103bc57600080fd5b8063248a9ca31161013857806331d507501161011257806331d507501461031c57806336568abe1461033c578063584b153e1461035c57600080fd5b8063248a9ca31461029b5780632ab0f529146102cb5780632f2ff15d146102fc57600080fd5b80630d3cf6fc116101695780630d3cf6fc14610234578063134008d31461026857806313bc9f201461027b57600080fd5b806301d5062a1461019b57806301ffc9a7146101bd57806307bd0265146101f257600080fd5b3661019657005b600080fd5b3480156101a757600080fd5b506101bb6101b63660046118ed565b61052b565b005b3480156101c957600080fd5b506101dd6101d8366004611962565b6105c1565b60405190151581526020015b60405180910390f35b3480156101fe57600080fd5b506102267fd8aa0f3194971a2a116679f7c2090f6939c8d4e01a2a8d7e41d55e5351469e6381565b6040519081526020016101e9565b34801561024057600080fd5b506102267f5f58e3a2316349923ce3780f8d587db2d72378aed66a8261c916544fa6846ca581565b6101bb6102763660046119a4565b61065a565b34801561028757600080fd5b506101dd610296366004611a10565b610715565b3480156102a757600080fd5b506102266102b6366004611a10565b60009081526020819052604090206001015490565b3480156102d757600080fd5b506101dd6102e6366004611a10565b6000908152600160208190526040909120541490565b34801561030857600080fd5b506101bb610317366004611a29565b61073b565b34801561032857600080fd5b506101dd610337366004611a10565b610766565b34801561034857600080fd5b506101bb610357366004611a29565b61077f565b34801561036857600080fd5b506101dd610377366004611a10565b610837565b34801561038857600080fd5b506101bb610397366004611a10565b61084d565b3480156103a857600080fd5b506102266103b73660046119a4565b61091d565b3480156103c857600080fd5b506101bb6103d7366004611a9a565b61095c565b3480156103e857600080fd5b506102267fb09aa5aeb3702cfd50b6b62bc4532604938f21248a27a1d5ca736082b6819cc181565b34801561041c57600080fd5b506101dd61042b366004611a29565b60009182526020828152604080842073ffffffffffffffffffffffffffffffffffffffff93909316845291905290205460ff1690565b34801561046d57600080fd5b50610226600081565b34801561048257600080fd5b50610226610491366004611b4c565b610b8f565b3480156104a257600080fd5b506101bb6104b1366004611a10565b610bd4565b3480156104c257600080fd5b506102266104d1366004611a10565b60009081526001602052604090205490565b3480156104ef57600080fd5b506101bb6104fe366004611a29565b610cd0565b6101bb610511366004611b4c565b610cf6565b34801561052257600080fd5b50600254610226565b7fb09aa5aeb3702cfd50b6b62bc4532604938f21248a27a1d5ca736082b6819cc16105568133610f4e565b600061056689898989898961091d565b9050610572818461101e565b6000817f4cf4410cc57040e44862ef0f45f3dd5a5e02db8eb8add648d4b0e236f1d07dca8b8b8b8b8b8a6040516105ae96959493929190611c3e565b60405180910390a3505050505050505050565b60007fffffffff0000000000000000000000000000000000000000000000000000000082167f7965db0b00000000000000000000000000000000000000000000000000000000148061065457507f01ffc9a7000000000000000000000000000000000000000000000000000000007fffffffff000000000000000000000000000000000000000000000000000000008316145b92915050565b600080527fdae2aa361dfd1ca020a396615627d436107c35eff9fe7738a3512819782d70696020527f5ba6852781629bcdcd4bdaa6de76d786f1c64b16acdac474e55bebc0ea157951547fd8aa0f3194971a2a116679f7c2090f6939c8d4e01a2a8d7e41d55e5351469e639060ff166106d7576106d78133610f4e565b60006106e788888888888861091d565b90506106f38185611166565b6107028160008a8a8a8a6112a3565b61070b816113e8565b5050505050505050565b6000818152600160205260408120546001811180156107345750428111155b9392505050565b6000828152602081905260409020600101546107578133610f4e565b6107618383611491565b505050565b60008181526001602052604081205481905b1192915050565b73ffffffffffffffffffffffffffffffffffffffff81163314610829576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602f60248201527f416363657373436f6e74726f6c3a2063616e206f6e6c792072656e6f756e636560448201527f20726f6c657320666f722073656c66000000000000000000000000000000000060648201526084015b60405180910390fd5b6108338282611581565b5050565b6000818152600160208190526040822054610778565b3330146108dc576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f54696d656c6f636b436f6e74726f6c6c65723a2063616c6c6572206d7573742060448201527f62652074696d656c6f636b0000000000000000000000000000000000000000006064820152608401610820565b60025460408051918252602082018390527f11c24f4ead16507c69ac467fbd5e4eed5fb5c699626d2cc6d66421df253886d5910160405180910390a1600255565b600086868686868660405160200161093a96959493929190611c3e565b6040516020818303038152906040528051906020012090509695505050505050565b7fb09aa5aeb3702cfd50b6b62bc4532604938f21248a27a1d5ca736082b6819cc16109878133610f4e565b888714610a16576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602360248201527f54696d656c6f636b436f6e74726f6c6c65723a206c656e677468206d69736d6160448201527f74636800000000000000000000000000000000000000000000000000000000006064820152608401610820565b888514610aa5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602360248201527f54696d656c6f636b436f6e74726f6c6c65723a206c656e677468206d69736d6160448201527f74636800000000000000000000000000000000000000000000000000000000006064820152608401610820565b6000610ab78b8b8b8b8b8b8b8b610b8f565b9050610ac3818461101e565b60005b8a811015610b815780827f4cf4410cc57040e44862ef0f45f3dd5a5e02db8eb8add648d4b0e236f1d07dca8e8e85818110610b0357610b03611c89565b9050602002016020810190610b189190611cb8565b8d8d86818110610b2a57610b2a611c89565b905060200201358c8c87818110610b4357610b43611c89565b9050602002810190610b559190611cd3565b8c8b604051610b6996959493929190611c3e565b60405180910390a3610b7a81611d67565b9050610ac6565b505050505050505050505050565b60008888888888888888604051602001610bb0989796959493929190611e70565b60405160208183030381529060405280519060200120905098975050505050505050565b7fb09aa5aeb3702cfd50b6b62bc4532604938f21248a27a1d5ca736082b6819cc1610bff8133610f4e565b610c0882610837565b610c94576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603160248201527f54696d656c6f636b436f6e74726f6c6c65723a206f7065726174696f6e20636160448201527f6e6e6f742062652063616e63656c6c65640000000000000000000000000000006064820152608401610820565b6000828152600160205260408082208290555183917fbaa1eb22f2a492ba1a5fea61b8df4d27c6c8b5f3971e63bb58fa14ff72eedb7091a25050565b600082815260208190526040902060010154610cec8133610f4e565b6107618383611581565b600080527fdae2aa361dfd1ca020a396615627d436107c35eff9fe7738a3512819782d70696020527f5ba6852781629bcdcd4bdaa6de76d786f1c64b16acdac474e55bebc0ea157951547fd8aa0f3194971a2a116679f7c2090f6939c8d4e01a2a8d7e41d55e5351469e639060ff16610d7357610d738133610f4e565b878614610e02576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602360248201527f54696d656c6f636b436f6e74726f6c6c65723a206c656e677468206d69736d6160448201527f74636800000000000000000000000000000000000000000000000000000000006064820152608401610820565b878414610e91576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602360248201527f54696d656c6f636b436f6e74726f6c6c65723a206c656e677468206d69736d6160448201527f74636800000000000000000000000000000000000000000000000000000000006064820152608401610820565b6000610ea38a8a8a8a8a8a8a8a610b8f565b9050610eaf8185611166565b60005b89811015610f3857610f2882828d8d85818110610ed157610ed1611c89565b9050602002016020810190610ee69190611cb8565b8c8c86818110610ef857610ef8611c89565b905060200201358b8b87818110610f1157610f11611c89565b9050602002810190610f239190611cd3565b6112a3565b610f3181611d67565b9050610eb2565b50610f42816113e8565b50505050505050505050565b60008281526020818152604080832073ffffffffffffffffffffffffffffffffffffffff8516845290915290205460ff1661083357610fa48173ffffffffffffffffffffffffffffffffffffffff166014611638565b610faf836020611638565b604051602001610fc0929190611f71565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152908290527f08c379a000000000000000000000000000000000000000000000000000000000825261082091600401611ff2565b61102782610766565b156110b4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602f60248201527f54696d656c6f636b436f6e74726f6c6c65723a206f7065726174696f6e20616c60448201527f7265616479207363686564756c656400000000000000000000000000000000006064820152608401610820565b600254811015611146576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f54696d656c6f636b436f6e74726f6c6c65723a20696e73756666696369656e7460448201527f2064656c617900000000000000000000000000000000000000000000000000006064820152608401610820565b6111508142612043565b6000928352600160205260409092209190915550565b61116f82610715565b6111fb576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f54696d656c6f636b436f6e74726f6c6c65723a206f7065726174696f6e20697360448201527f206e6f74207265616479000000000000000000000000000000000000000000006064820152608401610820565b8015806112175750600081815260016020819052604090912054145b610833576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f54696d656c6f636b436f6e74726f6c6c65723a206d697373696e67206465706560448201527f6e64656e637900000000000000000000000000000000000000000000000000006064820152608401610820565b60008473ffffffffffffffffffffffffffffffffffffffff168484846040516112cd92919061205b565b60006040518083038185875af1925050503d806000811461130a576040519150601f19603f3d011682016040523d82523d6000602084013e61130f565b606091505b50509050806113a0576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603360248201527f54696d656c6f636b436f6e74726f6c6c65723a20756e6465726c79696e67207460448201527f72616e73616374696f6e207265766572746564000000000000000000000000006064820152608401610820565b85877fc2617efa69bab66782fa219543714338489c4e9e178271560a91b82c3f612b58878787876040516113d7949392919061206b565b60405180910390a350505050505050565b6113f181610715565b61147d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f54696d656c6f636b436f6e74726f6c6c65723a206f7065726174696f6e20697360448201527f206e6f74207265616479000000000000000000000000000000000000000000006064820152608401610820565b600090815260016020819052604090912055565b60008281526020818152604080832073ffffffffffffffffffffffffffffffffffffffff8516845290915290205460ff166108335760008281526020818152604080832073ffffffffffffffffffffffffffffffffffffffff85168452909152902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790556115233390565b73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16837f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a45050565b60008281526020818152604080832073ffffffffffffffffffffffffffffffffffffffff8516845290915290205460ff16156108335760008281526020818152604080832073ffffffffffffffffffffffffffffffffffffffff8516808552925280832080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016905551339285917ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b9190a45050565b606060006116478360026120ab565b611652906002612043565b67ffffffffffffffff81111561166a5761166a6120e8565b6040519080825280601f01601f191660200182016040528015611694576020820181803683370190505b5090507f3000000000000000000000000000000000000000000000000000000000000000816000815181106116cb576116cb611c89565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a9053507f78000000000000000000000000000000000000000000000000000000000000008160018151811061172e5761172e611c89565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350600061176a8460026120ab565b611775906001612043565b90505b6001811115611812577f303132333435363738396162636465660000000000000000000000000000000085600f16601081106117b6576117b6611c89565b1a60f81b8282815181106117cc576117cc611c89565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a90535060049490941c9361180b81612117565b9050611778565b508315610734576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f537472696e67733a20686578206c656e67746820696e73756666696369656e746044820152606401610820565b803573ffffffffffffffffffffffffffffffffffffffff8116811461189f57600080fd5b919050565b60008083601f8401126118b657600080fd5b50813567ffffffffffffffff8111156118ce57600080fd5b6020830191508360208285010111156118e657600080fd5b9250929050565b600080600080600080600060c0888a03121561190857600080fd5b6119118861187b565b965060208801359550604088013567ffffffffffffffff81111561193457600080fd5b6119408a828b016118a4565b989b979a50986060810135976080820135975060a09091013595509350505050565b60006020828403121561197457600080fd5b81357fffffffff000000000000000000000000000000000000000000000000000000008116811461073457600080fd5b60008060008060008060a087890312156119bd57600080fd5b6119c68761187b565b955060208701359450604087013567ffffffffffffffff8111156119e957600080fd5b6119f589828a016118a4565b979a9699509760608101359660809091013595509350505050565b600060208284031215611a2257600080fd5b5035919050565b60008060408385031215611a3c57600080fd5b82359150611a4c6020840161187b565b90509250929050565b60008083601f840112611a6757600080fd5b50813567ffffffffffffffff811115611a7f57600080fd5b6020830191508360208260051b85010111156118e657600080fd5b600080600080600080600080600060c08a8c031215611ab857600080fd5b893567ffffffffffffffff80821115611ad057600080fd5b611adc8d838e01611a55565b909b50995060208c0135915080821115611af557600080fd5b611b018d838e01611a55565b909950975060408c0135915080821115611b1a57600080fd5b50611b278c828d01611a55565b9a9d999c50979a969997986060880135976080810135975060a0013595509350505050565b60008060008060008060008060a0898b031215611b6857600080fd5b883567ffffffffffffffff80821115611b8057600080fd5b611b8c8c838d01611a55565b909a50985060208b0135915080821115611ba557600080fd5b611bb18c838d01611a55565b909850965060408b0135915080821115611bca57600080fd5b50611bd78b828c01611a55565b999c989b509699959896976060870135966080013595509350505050565b8183528181602085013750600060208284010152600060207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116840101905092915050565b73ffffffffffffffffffffffffffffffffffffffff8716815285602082015260a060408201526000611c7460a083018688611bf5565b60608301949094525060800152949350505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b600060208284031215611cca57600080fd5b6107348261187b565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe1843603018112611d0857600080fd5b83018035915067ffffffffffffffff821115611d2357600080fd5b6020019150368190038213156118e657600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff821415611d9957611d99611d38565b5060010190565b60008383855260208086019550808560051b8301018460005b87811015611e63577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe085840301895281357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe1883603018112611e1a57600080fd5b8701803567ffffffffffffffff811115611e3357600080fd5b803603891315611e4257600080fd5b611e4f8582888501611bf5565b9a86019a9450505090830190600101611db9565b5090979650505050505050565b60a0808252810188905260008960c08301825b8b811015611ebe5773ffffffffffffffffffffffffffffffffffffffff611ea98461187b565b16825260209283019290910190600101611e83565b5083810360208501528881527f07ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff891115611ef757600080fd5b8860051b9150818a602083013781810191505060208101600081526020848303016040850152611f2881888a611da0565b6060850196909652505050608001529695505050505050565b60005b83811015611f5c578181015183820152602001611f44565b83811115611f6b576000848401525b50505050565b7f416363657373436f6e74726f6c3a206163636f756e7420000000000000000000815260008351611fa9816017850160208801611f41565b7f206973206d697373696e6720726f6c65200000000000000000000000000000006017918401918201528351611fe6816028840160208801611f41565b01602801949350505050565b6020815260008251806020840152612011816040850160208701611f41565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169190910160400192915050565b6000821982111561205657612056611d38565b500190565b8183823760009101908152919050565b73ffffffffffffffffffffffffffffffffffffffff851681528360208201526060604082015260006120a1606083018486611bf5565b9695505050505050565b6000817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff04831182151516156120e3576120e3611d38565b500290565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b60008161212657612126611d38565b507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff019056fea2646970667358221220275d18460294045f0333b41e202294299c8fd1be4f8fe0cff25fa496bcf503a664736f6c634300080b0033", + "devdoc": { + "details": "Contract module which acts as a timelocked controller. When set as the owner of an `Ownable` smart contract, it enforces a timelock on all `onlyOwner` maintenance operations. This gives time for users of the controlled contract to exit before a potentially dangerous maintenance operation is applied. By default, this contract is self administered, meaning administration tasks have to go through the timelock process. The proposer (resp executor) role is in charge of proposing (resp executing) operations. A common use case is to position this {TimelockController} as the owner of a smart contract, with a multisig or a DAO as the sole proposer. _Available since v3.3._", + "events": { + "CallExecuted(bytes32,uint256,address,uint256,bytes)": { + "details": "Emitted when a call is performed as part of operation `id`." + }, + "CallScheduled(bytes32,uint256,address,uint256,bytes,bytes32,uint256)": { + "details": "Emitted when a call is scheduled as part of operation `id`." + }, + "Cancelled(bytes32)": { + "details": "Emitted when operation `id` is cancelled." + }, + "MinDelayChange(uint256,uint256)": { + "details": "Emitted when the minimum delay for future operations is modified." + } + }, + "kind": "dev", + "methods": { + "cancel(bytes32)": { + "details": "Cancel an operation. Requirements: - the caller must have the 'proposer' role." + }, + "constructor": { + "details": "Initializes the contract with a given `minDelay`." + }, + "execute(address,uint256,bytes,bytes32,bytes32)": { + "details": "Execute an (ready) operation containing a single transaction. Emits a {CallExecuted} event. Requirements: - the caller must have the 'executor' role." + }, + "executeBatch(address[],uint256[],bytes[],bytes32,bytes32)": { + "details": "Execute an (ready) operation containing a batch of transactions. Emits one {CallExecuted} event per transaction in the batch. Requirements: - the caller must have the 'executor' role." + }, + "getMinDelay()": { + "details": "Returns the minimum delay for an operation to become valid. This value can be changed by executing an operation that calls `updateDelay`." + }, + "getRoleAdmin(bytes32)": { + "details": "Returns the admin role that controls `role`. See {grantRole} and {revokeRole}. To change a role's admin, use {_setRoleAdmin}." + }, + "getTimestamp(bytes32)": { + "details": "Returns the timestamp at with an operation becomes ready (0 for unset operations, 1 for done operations)." + }, + "grantRole(bytes32,address)": { + "details": "Grants `role` to `account`. If `account` had not been already granted `role`, emits a {RoleGranted} event. Requirements: - the caller must have ``role``'s admin role." + }, + "hasRole(bytes32,address)": { + "details": "Returns `true` if `account` has been granted `role`." + }, + "hashOperation(address,uint256,bytes,bytes32,bytes32)": { + "details": "Returns the identifier of an operation containing a single transaction." + }, + "hashOperationBatch(address[],uint256[],bytes[],bytes32,bytes32)": { + "details": "Returns the identifier of an operation containing a batch of transactions." + }, + "isOperation(bytes32)": { + "details": "Returns whether an id correspond to a registered operation. This includes both Pending, Ready and Done operations." + }, + "isOperationDone(bytes32)": { + "details": "Returns whether an operation is done or not." + }, + "isOperationPending(bytes32)": { + "details": "Returns whether an operation is pending or not." + }, + "isOperationReady(bytes32)": { + "details": "Returns whether an operation is ready or not." + }, + "renounceRole(bytes32,address)": { + "details": "Revokes `role` from the calling account. Roles are often managed via {grantRole} and {revokeRole}: this function's purpose is to provide a mechanism for accounts to lose their privileges if they are compromised (such as when a trusted device is misplaced). If the calling account had been revoked `role`, emits a {RoleRevoked} event. Requirements: - the caller must be `account`." + }, + "revokeRole(bytes32,address)": { + "details": "Revokes `role` from `account`. If `account` had been granted `role`, emits a {RoleRevoked} event. Requirements: - the caller must have ``role``'s admin role." + }, + "schedule(address,uint256,bytes,bytes32,bytes32,uint256)": { + "details": "Schedule an operation containing a single transaction. Emits a {CallScheduled} event. Requirements: - the caller must have the 'proposer' role." + }, + "scheduleBatch(address[],uint256[],bytes[],bytes32,bytes32,uint256)": { + "details": "Schedule an operation containing a batch of transactions. Emits one {CallScheduled} event per transaction in the batch. Requirements: - the caller must have the 'proposer' role." + }, + "supportsInterface(bytes4)": { + "details": "See {IERC165-supportsInterface}." + }, + "updateDelay(uint256)": { + "details": "Changes the minimum timelock duration for future operations. Emits a {MinDelayChange} event. Requirements: - the caller must be the timelock itself. This can only be achieved by scheduling and later executing an operation where the timelock is the target and the data is the ABI-encoded call to this function." + } + }, + "version": 1 + }, + "userdoc": { + "kind": "user", + "methods": {}, + "version": 1 + }, + "storageLayout": { + "storage": [ + { + "astId": 24, + "contract": "contracts/bridge/utils/TimelockController.sol:TimelockController", + "label": "_roles", + "offset": 0, + "slot": "0", + "type": "t_mapping(t_bytes32,t_struct(RoleData)19_storage)" + }, + { + "astId": 986, + "contract": "contracts/bridge/utils/TimelockController.sol:TimelockController", + "label": "_timestamps", + "offset": 0, + "slot": "1", + "type": "t_mapping(t_bytes32,t_uint256)" + }, + { + "astId": 988, + "contract": "contracts/bridge/utils/TimelockController.sol:TimelockController", + "label": "_minDelay", + "offset": 0, + "slot": "2", + "type": "t_uint256" + } + ], + "types": { + "t_address": { + "encoding": "inplace", + "label": "address", + "numberOfBytes": "20" + }, + "t_bool": { + "encoding": "inplace", + "label": "bool", + "numberOfBytes": "1" + }, + "t_bytes32": { + "encoding": "inplace", + "label": "bytes32", + "numberOfBytes": "32" + }, + "t_mapping(t_address,t_bool)": { + "encoding": "mapping", + "key": "t_address", + "label": "mapping(address => bool)", + "numberOfBytes": "32", + "value": "t_bool" + }, + "t_mapping(t_bytes32,t_struct(RoleData)19_storage)": { + "encoding": "mapping", + "key": "t_bytes32", + "label": "mapping(bytes32 => struct AccessControl.RoleData)", + "numberOfBytes": "32", + "value": "t_struct(RoleData)19_storage" + }, + "t_mapping(t_bytes32,t_uint256)": { + "encoding": "mapping", + "key": "t_bytes32", + "label": "mapping(bytes32 => uint256)", + "numberOfBytes": "32", + "value": "t_uint256" + }, + "t_struct(RoleData)19_storage": { + "encoding": "inplace", + "label": "struct AccessControl.RoleData", + "members": [ + { + "astId": 16, + "contract": "contracts/bridge/utils/TimelockController.sol:TimelockController", + "label": "members", + "offset": 0, + "slot": "0", + "type": "t_mapping(t_address,t_bool)" + }, + { + "astId": 18, + "contract": "contracts/bridge/utils/TimelockController.sol:TimelockController", + "label": "adminRole", + "offset": 0, + "slot": "1", + "type": "t_bytes32" + } + ], + "numberOfBytes": "64" + }, + "t_uint256": { + "encoding": "inplace", + "label": "uint256", + "numberOfBytes": "32" + } + } + } +} \ No newline at end of file diff --git a/deployments/dfk/USDC.json b/deployments/dfk/USDC.json new file mode 100644 index 000000000..44f89ffc9 --- /dev/null +++ b/deployments/dfk/USDC.json @@ -0,0 +1,668 @@ +{ + "address": "0x3AD9DFE640E1A9Cc1D9B0948620820D975c3803a", + "abi": [ + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "Approval", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "bytes32", + "name": "previousAdminRole", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "bytes32", + "name": "newAdminRole", + "type": "bytes32" + } + ], + "name": "RoleAdminChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "sender", + "type": "address" + } + ], + "name": "RoleGranted", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "sender", + "type": "address" + } + ], + "name": "RoleRevoked", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "Transfer", + "type": "event" + }, + { + "inputs": [], + "name": "DEFAULT_ADMIN_ROLE", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "DOMAIN_SEPARATOR", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "MINTER_ROLE", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "address", + "name": "spender", + "type": "address" + } + ], + "name": "allowance", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "approve", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "balanceOf", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "burn", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "burnFrom", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "decimals", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "subtractedValue", + "type": "uint256" + } + ], + "name": "decreaseAllowance", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + } + ], + "name": "getRoleAdmin", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "internalType": "uint256", + "name": "index", + "type": "uint256" + } + ], + "name": "getRoleMember", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + } + ], + "name": "getRoleMemberCount", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "grantRole", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "hasRole", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "addedValue", + "type": "uint256" + } + ], + "name": "increaseAllowance", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "name", + "type": "string" + }, + { + "internalType": "string", + "name": "symbol", + "type": "string" + }, + { + "internalType": "uint8", + "name": "decimals", + "type": "uint8" + }, + { + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "initialize", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "mint", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "name", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "nonces", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" + }, + { + "internalType": "uint8", + "name": "v", + "type": "uint8" + }, + { + "internalType": "bytes32", + "name": "r", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "s", + "type": "bytes32" + } + ], + "name": "permit", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "renounceRole", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "revokeRole", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "symbol", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "totalSupply", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "recipient", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "transfer", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "internalType": "address", + "name": "recipient", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "transferFrom", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + } + ] +} \ No newline at end of file diff --git a/deployments/dfk/UST.json b/deployments/dfk/UST.json new file mode 100644 index 000000000..d838b1b47 --- /dev/null +++ b/deployments/dfk/UST.json @@ -0,0 +1,668 @@ +{ + "address": "0x360d6DD540E3448371876662FBE7F1aCaf08c5Ab", + "abi": [ + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "Approval", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "bytes32", + "name": "previousAdminRole", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "bytes32", + "name": "newAdminRole", + "type": "bytes32" + } + ], + "name": "RoleAdminChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "sender", + "type": "address" + } + ], + "name": "RoleGranted", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "sender", + "type": "address" + } + ], + "name": "RoleRevoked", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "Transfer", + "type": "event" + }, + { + "inputs": [], + "name": "DEFAULT_ADMIN_ROLE", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "DOMAIN_SEPARATOR", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "MINTER_ROLE", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "address", + "name": "spender", + "type": "address" + } + ], + "name": "allowance", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "approve", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "balanceOf", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "burn", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "burnFrom", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "decimals", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "subtractedValue", + "type": "uint256" + } + ], + "name": "decreaseAllowance", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + } + ], + "name": "getRoleAdmin", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "internalType": "uint256", + "name": "index", + "type": "uint256" + } + ], + "name": "getRoleMember", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + } + ], + "name": "getRoleMemberCount", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "grantRole", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "hasRole", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "addedValue", + "type": "uint256" + } + ], + "name": "increaseAllowance", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "name", + "type": "string" + }, + { + "internalType": "string", + "name": "symbol", + "type": "string" + }, + { + "internalType": "uint8", + "name": "decimals", + "type": "uint8" + }, + { + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "initialize", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "mint", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "name", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "nonces", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" + }, + { + "internalType": "uint8", + "name": "v", + "type": "uint8" + }, + { + "internalType": "bytes32", + "name": "r", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "s", + "type": "bytes32" + } + ], + "name": "permit", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "renounceRole", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "revokeRole", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "symbol", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "totalSupply", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "recipient", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "transfer", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "internalType": "address", + "name": "recipient", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "transferFrom", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + } + ] +} \ No newline at end of file diff --git a/deployments/dfk/WJEWEL.json b/deployments/dfk/WJEWEL.json new file mode 100644 index 000000000..175d91cca --- /dev/null +++ b/deployments/dfk/WJEWEL.json @@ -0,0 +1,366 @@ +{ + "address": "0xCCb93dABD71c8Dad03Fc4CE5559dC3D89F67a260", + "abi": [ + { + "inputs": [ + { + "internalType": "string", + "name": "name_", + "type": "string" + }, + { + "internalType": "string", + "name": "symbol_", + "type": "string" + }, + { + "internalType": "uint8", + "name": "decimals_", + "type": "uint8" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "Approval", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "previousOwner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "OwnershipTransferred", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "Transfer", + "type": "event" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "address", + "name": "spender", + "type": "address" + } + ], + "name": "allowance", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "approve", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "balanceOf", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "decimals", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "subtractedValue", + "type": "uint256" + } + ], + "name": "decreaseAllowance", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "addedValue", + "type": "uint256" + } + ], + "name": "increaseAllowance", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "recipient", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "mint", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "name", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "renounceOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "symbol", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "totalSupply", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "recipient", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "transfer", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "internalType": "address", + "name": "recipient", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "transferFrom", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } + ] + } \ No newline at end of file diff --git a/deployments/dfk/nETH.json b/deployments/dfk/nETH.json new file mode 100644 index 000000000..36b9edadb --- /dev/null +++ b/deployments/dfk/nETH.json @@ -0,0 +1,1104 @@ +{ + "address": "0x9596A3C6a4B2597adCC5D6d69b281A7C49e3Fe6A", + "abi": [ + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "Approval", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "bytes32", + "name": "previousAdminRole", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "bytes32", + "name": "newAdminRole", + "type": "bytes32" + } + ], + "name": "RoleAdminChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "sender", + "type": "address" + } + ], + "name": "RoleGranted", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "sender", + "type": "address" + } + ], + "name": "RoleRevoked", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "Transfer", + "type": "event" + }, + { + "inputs": [], + "name": "DEFAULT_ADMIN_ROLE", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "DOMAIN_SEPARATOR", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "MINTER_ROLE", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "address", + "name": "spender", + "type": "address" + } + ], + "name": "allowance", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "approve", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "balanceOf", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "burn", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "burnFrom", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "decimals", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "subtractedValue", + "type": "uint256" + } + ], + "name": "decreaseAllowance", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + } + ], + "name": "getRoleAdmin", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "internalType": "uint256", + "name": "index", + "type": "uint256" + } + ], + "name": "getRoleMember", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + } + ], + "name": "getRoleMemberCount", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "grantRole", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "hasRole", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "addedValue", + "type": "uint256" + } + ], + "name": "increaseAllowance", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "name", + "type": "string" + }, + { + "internalType": "string", + "name": "symbol", + "type": "string" + }, + { + "internalType": "uint8", + "name": "decimals", + "type": "uint8" + }, + { + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "initialize", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "mint", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "name", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "nonces", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" + }, + { + "internalType": "uint8", + "name": "v", + "type": "uint8" + }, + { + "internalType": "bytes32", + "name": "r", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "s", + "type": "bytes32" + } + ], + "name": "permit", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "renounceRole", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "revokeRole", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "symbol", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "totalSupply", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "recipient", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "transfer", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "internalType": "address", + "name": "recipient", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "transferFrom", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + } + ], + "transactionHash": "0xe347a44f8b7ed1e82a2b8b0ca1a04a999dbfcf918b8f8bf240fbb855b8087ece", + "receipt": { + "to": null, + "from": "0x235AF07E770f474d24F5bf73074735892371b40D", + "contractAddress": "0x9596A3C6a4B2597adCC5D6d69b281A7C49e3Fe6A", + "transactionIndex": 0, + "gasUsed": "1935674", + "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "blockHash": "0xb1f159cba296ad46fb16174861c5033f433e57a81aef7450cad1c90464f1e935", + "transactionHash": "0xe347a44f8b7ed1e82a2b8b0ca1a04a999dbfcf918b8f8bf240fbb855b8087ece", + "logs": [], + "blockNumber": 36, + "cumulativeGasUsed": "1935674", + "status": 1, + "byzantium": true + }, + "args": [], + "solcInputHash": "d9ddc44152056b9c2865111aa614cbcf", + "metadata": "{\"compiler\":{\"version\":\"0.6.12+commit.27d51765\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"spender\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"Approval\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"previousAdminRole\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"newAdminRole\",\"type\":\"bytes32\"}],\"name\":\"RoleAdminChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"RoleGranted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"RoleRevoked\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"Transfer\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"DEFAULT_ADMIN_ROLE\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"DOMAIN_SEPARATOR\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"MINTER_ROLE\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"spender\",\"type\":\"address\"}],\"name\":\"allowance\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"spender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"approve\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"balanceOf\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"burn\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"burnFrom\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"decimals\",\"outputs\":[{\"internalType\":\"uint8\",\"name\":\"\",\"type\":\"uint8\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"spender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"subtractedValue\",\"type\":\"uint256\"}],\"name\":\"decreaseAllowance\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"}],\"name\":\"getRoleAdmin\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"internalType\":\"uint256\",\"name\":\"index\",\"type\":\"uint256\"}],\"name\":\"getRoleMember\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"}],\"name\":\"getRoleMemberCount\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"grantRole\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"hasRole\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"spender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"addedValue\",\"type\":\"uint256\"}],\"name\":\"increaseAllowance\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"string\",\"name\":\"name\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"symbol\",\"type\":\"string\"},{\"internalType\":\"uint8\",\"name\":\"decimals\",\"type\":\"uint8\"},{\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"}],\"name\":\"initialize\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"mint\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"name\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"}],\"name\":\"nonces\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"spender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"deadline\",\"type\":\"uint256\"},{\"internalType\":\"uint8\",\"name\":\"v\",\"type\":\"uint8\"},{\"internalType\":\"bytes32\",\"name\":\"r\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"s\",\"type\":\"bytes32\"}],\"name\":\"permit\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"renounceRole\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"revokeRole\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"symbol\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"totalSupply\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"recipient\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"transfer\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"recipient\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"transferFrom\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{\"DOMAIN_SEPARATOR()\":{\"details\":\"See {IERC20Permit-DOMAIN_SEPARATOR}.\"},\"allowance(address,address)\":{\"details\":\"See {IERC20-allowance}.\"},\"approve(address,uint256)\":{\"details\":\"See {IERC20-approve}. Requirements: - `spender` cannot be the zero address.\"},\"balanceOf(address)\":{\"details\":\"See {IERC20-balanceOf}.\"},\"burn(uint256)\":{\"details\":\"Destroys `amount` tokens from the caller. See {ERC20-_burn}.\"},\"burnFrom(address,uint256)\":{\"details\":\"Destroys `amount` tokens from `account`, deducting from the caller's allowance. See {ERC20-_burn} and {ERC20-allowance}. Requirements: - the caller must have allowance for ``accounts``'s tokens of at least `amount`.\"},\"decimals()\":{\"details\":\"Returns the number of decimals used to get its user representation. For example, if `decimals` equals `2`, a balance of `505` tokens should be displayed to a user as `5,05` (`505 / 10 ** 2`). Tokens usually opt for a value of 18, imitating the relationship between Ether and Wei. This is the value {ERC20} uses, unless {_setupDecimals} is called. NOTE: This information is only used for _display_ purposes: it in no way affects any of the arithmetic of the contract, including {IERC20-balanceOf} and {IERC20-transfer}.\"},\"decreaseAllowance(address,uint256)\":{\"details\":\"Atomically decreases the allowance granted to `spender` by the caller. This is an alternative to {approve} that can be used as a mitigation for problems described in {IERC20-approve}. Emits an {Approval} event indicating the updated allowance. Requirements: - `spender` cannot be the zero address. - `spender` must have allowance for the caller of at least `subtractedValue`.\"},\"getRoleAdmin(bytes32)\":{\"details\":\"Returns the admin role that controls `role`. See {grantRole} and {revokeRole}. To change a role's admin, use {_setRoleAdmin}.\"},\"getRoleMember(bytes32,uint256)\":{\"details\":\"Returns one of the accounts that have `role`. `index` must be a value between 0 and {getRoleMemberCount}, non-inclusive. Role bearers are not sorted in any particular way, and their ordering may change at any point. WARNING: When using {getRoleMember} and {getRoleMemberCount}, make sure you perform all queries on the same block. See the following https://forum.openzeppelin.com/t/iterating-over-elements-on-enumerableset-in-openzeppelin-contracts/2296[forum post] for more information.\"},\"getRoleMemberCount(bytes32)\":{\"details\":\"Returns the number of accounts that have `role`. Can be used together with {getRoleMember} to enumerate all bearers of a role.\"},\"grantRole(bytes32,address)\":{\"details\":\"Grants `role` to `account`. If `account` had not been already granted `role`, emits a {RoleGranted} event. Requirements: - the caller must have ``role``'s admin role.\"},\"hasRole(bytes32,address)\":{\"details\":\"Returns `true` if `account` has been granted `role`.\"},\"increaseAllowance(address,uint256)\":{\"details\":\"Atomically increases the allowance granted to `spender` by the caller. This is an alternative to {approve} that can be used as a mitigation for problems described in {IERC20-approve}. Emits an {Approval} event indicating the updated allowance. Requirements: - `spender` cannot be the zero address.\"},\"initialize(string,string,uint8,address)\":{\"params\":{\"decimals\":\"Token name\",\"name\":\"Token name\",\"owner\":\"admin address to be initialized with\",\"symbol\":\"Token symbol\"}},\"name()\":{\"details\":\"Returns the name of the token.\"},\"nonces(address)\":{\"details\":\"See {IERC20Permit-nonces}.\"},\"permit(address,address,uint256,uint256,uint8,bytes32,bytes32)\":{\"details\":\"See {IERC20Permit-permit}.\"},\"renounceRole(bytes32,address)\":{\"details\":\"Revokes `role` from the calling account. Roles are often managed via {grantRole} and {revokeRole}: this function's purpose is to provide a mechanism for accounts to lose their privileges if they are compromised (such as when a trusted device is misplaced). If the calling account had been granted `role`, emits a {RoleRevoked} event. Requirements: - the caller must be `account`.\"},\"revokeRole(bytes32,address)\":{\"details\":\"Revokes `role` from `account`. If `account` had been granted `role`, emits a {RoleRevoked} event. Requirements: - the caller must have ``role``'s admin role.\"},\"symbol()\":{\"details\":\"Returns the symbol of the token, usually a shorter version of the name.\"},\"totalSupply()\":{\"details\":\"See {IERC20-totalSupply}.\"},\"transfer(address,uint256)\":{\"details\":\"See {IERC20-transfer}. Requirements: - `recipient` cannot be the zero address. - the caller must have a balance of at least `amount`.\"},\"transferFrom(address,address,uint256)\":{\"details\":\"See {IERC20-transferFrom}. Emits an {Approval} event indicating the updated allowance. This is not required by the EIP. See the note at the beginning of {ERC20}. Requirements: - `sender` and `recipient` cannot be the zero address. - `sender` must have a balance of at least `amount`. - the caller must have allowance for ``sender``'s tokens of at least `amount`.\"}},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{\"initialize(string,string,uint8,address)\":{\"notice\":\"Initializes this ERC20 contract with the given parameters.\"}},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/bridge/SynapseERC20.sol\":\"SynapseERC20\"},\"evmVersion\":\"istanbul\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":10000},\"remappings\":[]},\"sources\":{\"@openzeppelin/contracts-upgradeable/access/AccessControlUpgradeable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity >=0.6.0 <0.8.0;\\n\\nimport \\\"../utils/EnumerableSetUpgradeable.sol\\\";\\nimport \\\"../utils/AddressUpgradeable.sol\\\";\\nimport \\\"../utils/ContextUpgradeable.sol\\\";\\nimport \\\"../proxy/Initializable.sol\\\";\\n\\n/**\\n * @dev Contract module that allows children to implement role-based access\\n * control mechanisms.\\n *\\n * Roles are referred to by their `bytes32` identifier. These should be exposed\\n * in the external API and be unique. The best way to achieve this is by\\n * using `public constant` hash digests:\\n *\\n * ```\\n * bytes32 public constant MY_ROLE = keccak256(\\\"MY_ROLE\\\");\\n * ```\\n *\\n * Roles can be used to represent a set of permissions. To restrict access to a\\n * function call, use {hasRole}:\\n *\\n * ```\\n * function foo() public {\\n * require(hasRole(MY_ROLE, msg.sender));\\n * ...\\n * }\\n * ```\\n *\\n * Roles can be granted and revoked dynamically via the {grantRole} and\\n * {revokeRole} functions. Each role has an associated admin role, and only\\n * accounts that have a role's admin role can call {grantRole} and {revokeRole}.\\n *\\n * By default, the admin role for all roles is `DEFAULT_ADMIN_ROLE`, which means\\n * that only accounts with this role will be able to grant or revoke other\\n * roles. More complex role relationships can be created by using\\n * {_setRoleAdmin}.\\n *\\n * WARNING: The `DEFAULT_ADMIN_ROLE` is also its own admin: it has permission to\\n * grant and revoke this role. Extra precautions should be taken to secure\\n * accounts that have been granted it.\\n */\\nabstract contract AccessControlUpgradeable is Initializable, ContextUpgradeable {\\n function __AccessControl_init() internal initializer {\\n __Context_init_unchained();\\n __AccessControl_init_unchained();\\n }\\n\\n function __AccessControl_init_unchained() internal initializer {\\n }\\n using EnumerableSetUpgradeable for EnumerableSetUpgradeable.AddressSet;\\n using AddressUpgradeable for address;\\n\\n struct RoleData {\\n EnumerableSetUpgradeable.AddressSet members;\\n bytes32 adminRole;\\n }\\n\\n mapping (bytes32 => RoleData) private _roles;\\n\\n bytes32 public constant DEFAULT_ADMIN_ROLE = 0x00;\\n\\n /**\\n * @dev Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole`\\n *\\n * `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite\\n * {RoleAdminChanged} not being emitted signaling this.\\n *\\n * _Available since v3.1._\\n */\\n event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole);\\n\\n /**\\n * @dev Emitted when `account` is granted `role`.\\n *\\n * `sender` is the account that originated the contract call, an admin role\\n * bearer except when using {_setupRole}.\\n */\\n event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender);\\n\\n /**\\n * @dev Emitted when `account` is revoked `role`.\\n *\\n * `sender` is the account that originated the contract call:\\n * - if using `revokeRole`, it is the admin role bearer\\n * - if using `renounceRole`, it is the role bearer (i.e. `account`)\\n */\\n event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender);\\n\\n /**\\n * @dev Returns `true` if `account` has been granted `role`.\\n */\\n function hasRole(bytes32 role, address account) public view returns (bool) {\\n return _roles[role].members.contains(account);\\n }\\n\\n /**\\n * @dev Returns the number of accounts that have `role`. Can be used\\n * together with {getRoleMember} to enumerate all bearers of a role.\\n */\\n function getRoleMemberCount(bytes32 role) public view returns (uint256) {\\n return _roles[role].members.length();\\n }\\n\\n /**\\n * @dev Returns one of the accounts that have `role`. `index` must be a\\n * value between 0 and {getRoleMemberCount}, non-inclusive.\\n *\\n * Role bearers are not sorted in any particular way, and their ordering may\\n * change at any point.\\n *\\n * WARNING: When using {getRoleMember} and {getRoleMemberCount}, make sure\\n * you perform all queries on the same block. See the following\\n * https://forum.openzeppelin.com/t/iterating-over-elements-on-enumerableset-in-openzeppelin-contracts/2296[forum post]\\n * for more information.\\n */\\n function getRoleMember(bytes32 role, uint256 index) public view returns (address) {\\n return _roles[role].members.at(index);\\n }\\n\\n /**\\n * @dev Returns the admin role that controls `role`. See {grantRole} and\\n * {revokeRole}.\\n *\\n * To change a role's admin, use {_setRoleAdmin}.\\n */\\n function getRoleAdmin(bytes32 role) public view returns (bytes32) {\\n return _roles[role].adminRole;\\n }\\n\\n /**\\n * @dev Grants `role` to `account`.\\n *\\n * If `account` had not been already granted `role`, emits a {RoleGranted}\\n * event.\\n *\\n * Requirements:\\n *\\n * - the caller must have ``role``'s admin role.\\n */\\n function grantRole(bytes32 role, address account) public virtual {\\n require(hasRole(_roles[role].adminRole, _msgSender()), \\\"AccessControl: sender must be an admin to grant\\\");\\n\\n _grantRole(role, account);\\n }\\n\\n /**\\n * @dev Revokes `role` from `account`.\\n *\\n * If `account` had been granted `role`, emits a {RoleRevoked} event.\\n *\\n * Requirements:\\n *\\n * - the caller must have ``role``'s admin role.\\n */\\n function revokeRole(bytes32 role, address account) public virtual {\\n require(hasRole(_roles[role].adminRole, _msgSender()), \\\"AccessControl: sender must be an admin to revoke\\\");\\n\\n _revokeRole(role, account);\\n }\\n\\n /**\\n * @dev Revokes `role` from the calling account.\\n *\\n * Roles are often managed via {grantRole} and {revokeRole}: this function's\\n * purpose is to provide a mechanism for accounts to lose their privileges\\n * if they are compromised (such as when a trusted device is misplaced).\\n *\\n * If the calling account had been granted `role`, emits a {RoleRevoked}\\n * event.\\n *\\n * Requirements:\\n *\\n * - the caller must be `account`.\\n */\\n function renounceRole(bytes32 role, address account) public virtual {\\n require(account == _msgSender(), \\\"AccessControl: can only renounce roles for self\\\");\\n\\n _revokeRole(role, account);\\n }\\n\\n /**\\n * @dev Grants `role` to `account`.\\n *\\n * If `account` had not been already granted `role`, emits a {RoleGranted}\\n * event. Note that unlike {grantRole}, this function doesn't perform any\\n * checks on the calling account.\\n *\\n * [WARNING]\\n * ====\\n * This function should only be called from the constructor when setting\\n * up the initial roles for the system.\\n *\\n * Using this function in any other way is effectively circumventing the admin\\n * system imposed by {AccessControl}.\\n * ====\\n */\\n function _setupRole(bytes32 role, address account) internal virtual {\\n _grantRole(role, account);\\n }\\n\\n /**\\n * @dev Sets `adminRole` as ``role``'s admin role.\\n *\\n * Emits a {RoleAdminChanged} event.\\n */\\n function _setRoleAdmin(bytes32 role, bytes32 adminRole) internal virtual {\\n emit RoleAdminChanged(role, _roles[role].adminRole, adminRole);\\n _roles[role].adminRole = adminRole;\\n }\\n\\n function _grantRole(bytes32 role, address account) private {\\n if (_roles[role].members.add(account)) {\\n emit RoleGranted(role, account, _msgSender());\\n }\\n }\\n\\n function _revokeRole(bytes32 role, address account) private {\\n if (_roles[role].members.remove(account)) {\\n emit RoleRevoked(role, account, _msgSender());\\n }\\n }\\n uint256[49] private __gap;\\n}\\n\",\"keccak256\":\"0xa3c77c9ea6b47301c7ab5bf3addc1d809d13a27a179c4629a1b55308e8633d14\",\"license\":\"MIT\"},\"@openzeppelin/contracts-upgradeable/cryptography/ECDSAUpgradeable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity >=0.6.0 <0.8.0;\\n\\n/**\\n * @dev Elliptic Curve Digital Signature Algorithm (ECDSA) operations.\\n *\\n * These functions can be used to verify that a message was signed by the holder\\n * of the private keys of a given address.\\n */\\nlibrary ECDSAUpgradeable {\\n /**\\n * @dev Returns the address that signed a hashed message (`hash`) with\\n * `signature`. This address can then be used for verification purposes.\\n *\\n * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:\\n * this function rejects them by requiring the `s` value to be in the lower\\n * half order, and the `v` value to be either 27 or 28.\\n *\\n * IMPORTANT: `hash` _must_ be the result of a hash operation for the\\n * verification to be secure: it is possible to craft signatures that\\n * recover to arbitrary addresses for non-hashed data. A safe way to ensure\\n * this is by receiving a hash of the original message (which may otherwise\\n * be too long), and then calling {toEthSignedMessageHash} on it.\\n */\\n function recover(bytes32 hash, bytes memory signature) internal pure returns (address) {\\n // Check the signature length\\n if (signature.length != 65) {\\n revert(\\\"ECDSA: invalid signature length\\\");\\n }\\n\\n // Divide the signature in r, s and v variables\\n bytes32 r;\\n bytes32 s;\\n uint8 v;\\n\\n // ecrecover takes the signature parameters, and the only way to get them\\n // currently is to use assembly.\\n // solhint-disable-next-line no-inline-assembly\\n assembly {\\n r := mload(add(signature, 0x20))\\n s := mload(add(signature, 0x40))\\n v := byte(0, mload(add(signature, 0x60)))\\n }\\n\\n return recover(hash, v, r, s);\\n }\\n\\n /**\\n * @dev Overload of {ECDSA-recover-bytes32-bytes-} that receives the `v`,\\n * `r` and `s` signature fields separately.\\n */\\n function recover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) internal pure returns (address) {\\n // EIP-2 still allows signature malleability for ecrecover(). Remove this possibility and make the signature\\n // unique. Appendix F in the Ethereum Yellow paper (https://ethereum.github.io/yellowpaper/paper.pdf), defines\\n // the valid range for s in (281): 0 < s < secp256k1n \\u00f7 2 + 1, and for v in (282): v \\u2208 {27, 28}. Most\\n // signatures from current libraries generate a unique signature with an s-value in the lower half order.\\n //\\n // If your library generates malleable signatures, such as s-values in the upper range, calculate a new s-value\\n // with 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 - s1 and flip v from 27 to 28 or\\n // vice versa. If your library also generates signatures with 0/1 for v instead 27/28, add 27 to v to accept\\n // these malleable signatures as well.\\n require(uint256(s) <= 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0, \\\"ECDSA: invalid signature 's' value\\\");\\n require(v == 27 || v == 28, \\\"ECDSA: invalid signature 'v' value\\\");\\n\\n // If the signature is valid (and not malleable), return the signer address\\n address signer = ecrecover(hash, v, r, s);\\n require(signer != address(0), \\\"ECDSA: invalid signature\\\");\\n\\n return signer;\\n }\\n\\n /**\\n * @dev Returns an Ethereum Signed Message, created from a `hash`. This\\n * replicates the behavior of the\\n * https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_sign[`eth_sign`]\\n * JSON-RPC method.\\n *\\n * See {recover}.\\n */\\n function toEthSignedMessageHash(bytes32 hash) internal pure returns (bytes32) {\\n // 32 is the length in bytes of hash,\\n // enforced by the type signature above\\n return keccak256(abi.encodePacked(\\\"\\\\x19Ethereum Signed Message:\\\\n32\\\", hash));\\n }\\n}\\n\",\"keccak256\":\"0xe348c45df01e0705c50ede5063d77111a996722ffb83f0a22979338a32b06887\",\"license\":\"MIT\"},\"@openzeppelin/contracts-upgradeable/drafts/EIP712Upgradeable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity >=0.6.0 <0.8.0;\\nimport \\\"../proxy/Initializable.sol\\\";\\n\\n/**\\n * @dev https://eips.ethereum.org/EIPS/eip-712[EIP 712] is a standard for hashing and signing of typed structured data.\\n *\\n * The encoding specified in the EIP is very generic, and such a generic implementation in Solidity is not feasible,\\n * thus this contract does not implement the encoding itself. Protocols need to implement the type-specific encoding\\n * they need in their contracts using a combination of `abi.encode` and `keccak256`.\\n *\\n * This contract implements the EIP 712 domain separator ({_domainSeparatorV4}) that is used as part of the encoding\\n * scheme, and the final step of the encoding to obtain the message digest that is then signed via ECDSA\\n * ({_hashTypedDataV4}).\\n *\\n * The implementation of the domain separator was designed to be as efficient as possible while still properly updating\\n * the chain id to protect against replay attacks on an eventual fork of the chain.\\n *\\n * NOTE: This contract implements the version of the encoding known as \\\"v4\\\", as implemented by the JSON RPC method\\n * https://docs.metamask.io/guide/signing-data.html[`eth_signTypedDataV4` in MetaMask].\\n *\\n * _Available since v3.4._\\n */\\nabstract contract EIP712Upgradeable is Initializable {\\n /* solhint-disable var-name-mixedcase */\\n bytes32 private _HASHED_NAME;\\n bytes32 private _HASHED_VERSION;\\n bytes32 private constant _TYPE_HASH = keccak256(\\\"EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)\\\");\\n /* solhint-enable var-name-mixedcase */\\n\\n /**\\n * @dev Initializes the domain separator and parameter caches.\\n *\\n * The meaning of `name` and `version` is specified in\\n * https://eips.ethereum.org/EIPS/eip-712#definition-of-domainseparator[EIP 712]:\\n *\\n * - `name`: the user readable name of the signing domain, i.e. the name of the DApp or the protocol.\\n * - `version`: the current major version of the signing domain.\\n *\\n * NOTE: These parameters cannot be changed except through a xref:learn::upgrading-smart-contracts.adoc[smart\\n * contract upgrade].\\n */\\n function __EIP712_init(string memory name, string memory version) internal initializer {\\n __EIP712_init_unchained(name, version);\\n }\\n\\n function __EIP712_init_unchained(string memory name, string memory version) internal initializer {\\n bytes32 hashedName = keccak256(bytes(name));\\n bytes32 hashedVersion = keccak256(bytes(version));\\n _HASHED_NAME = hashedName;\\n _HASHED_VERSION = hashedVersion;\\n }\\n\\n /**\\n * @dev Returns the domain separator for the current chain.\\n */\\n function _domainSeparatorV4() internal view returns (bytes32) {\\n return _buildDomainSeparator(_TYPE_HASH, _EIP712NameHash(), _EIP712VersionHash());\\n }\\n\\n function _buildDomainSeparator(bytes32 typeHash, bytes32 name, bytes32 version) private view returns (bytes32) {\\n return keccak256(\\n abi.encode(\\n typeHash,\\n name,\\n version,\\n _getChainId(),\\n address(this)\\n )\\n );\\n }\\n\\n /**\\n * @dev Given an already https://eips.ethereum.org/EIPS/eip-712#definition-of-hashstruct[hashed struct], this\\n * function returns the hash of the fully encoded EIP712 message for this domain.\\n *\\n * This hash can be used together with {ECDSA-recover} to obtain the signer of a message. For example:\\n *\\n * ```solidity\\n * bytes32 digest = _hashTypedDataV4(keccak256(abi.encode(\\n * keccak256(\\\"Mail(address to,string contents)\\\"),\\n * mailTo,\\n * keccak256(bytes(mailContents))\\n * )));\\n * address signer = ECDSA.recover(digest, signature);\\n * ```\\n */\\n function _hashTypedDataV4(bytes32 structHash) internal view virtual returns (bytes32) {\\n return keccak256(abi.encodePacked(\\\"\\\\x19\\\\x01\\\", _domainSeparatorV4(), structHash));\\n }\\n\\n function _getChainId() private view returns (uint256 chainId) {\\n this; // silence state mutability warning without generating bytecode - see https://github.com/ethereum/solidity/issues/2691\\n // solhint-disable-next-line no-inline-assembly\\n assembly {\\n chainId := chainid()\\n }\\n }\\n\\n /**\\n * @dev The hash of the name parameter for the EIP712 domain.\\n *\\n * NOTE: This function reads from storage by default, but can be redefined to return a constant value if gas costs\\n * are a concern.\\n */\\n function _EIP712NameHash() internal virtual view returns (bytes32) {\\n return _HASHED_NAME;\\n }\\n\\n /**\\n * @dev The hash of the version parameter for the EIP712 domain.\\n *\\n * NOTE: This function reads from storage by default, but can be redefined to return a constant value if gas costs\\n * are a concern.\\n */\\n function _EIP712VersionHash() internal virtual view returns (bytes32) {\\n return _HASHED_VERSION;\\n }\\n uint256[50] private __gap;\\n}\\n\",\"keccak256\":\"0x6cd0bc8c149150614ca3d4a3d3d21f844a0ab3032625f34fcfcf1c2c8b351638\",\"license\":\"MIT\"},\"@openzeppelin/contracts-upgradeable/drafts/ERC20PermitUpgradeable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity >=0.6.5 <0.8.0;\\n\\nimport \\\"../token/ERC20/ERC20Upgradeable.sol\\\";\\nimport \\\"./IERC20PermitUpgradeable.sol\\\";\\nimport \\\"../cryptography/ECDSAUpgradeable.sol\\\";\\nimport \\\"../utils/CountersUpgradeable.sol\\\";\\nimport \\\"./EIP712Upgradeable.sol\\\";\\nimport \\\"../proxy/Initializable.sol\\\";\\n\\n/**\\n * @dev Implementation of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in\\n * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612].\\n *\\n * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by\\n * presenting a message signed by the account. By not relying on `{IERC20-approve}`, the token holder account doesn't\\n * need to send a transaction, and thus is not required to hold Ether at all.\\n *\\n * _Available since v3.4._\\n */\\nabstract contract ERC20PermitUpgradeable is Initializable, ERC20Upgradeable, IERC20PermitUpgradeable, EIP712Upgradeable {\\n using CountersUpgradeable for CountersUpgradeable.Counter;\\n\\n mapping (address => CountersUpgradeable.Counter) private _nonces;\\n\\n // solhint-disable-next-line var-name-mixedcase\\n bytes32 private _PERMIT_TYPEHASH;\\n\\n /**\\n * @dev Initializes the {EIP712} domain separator using the `name` parameter, and setting `version` to `\\\"1\\\"`.\\n *\\n * It's a good idea to use the same `name` that is defined as the ERC20 token name.\\n */\\n function __ERC20Permit_init(string memory name) internal initializer {\\n __Context_init_unchained();\\n __EIP712_init_unchained(name, \\\"1\\\");\\n __ERC20Permit_init_unchained(name);\\n }\\n\\n function __ERC20Permit_init_unchained(string memory name) internal initializer {\\n _PERMIT_TYPEHASH = keccak256(\\\"Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)\\\");\\n }\\n\\n /**\\n * @dev See {IERC20Permit-permit}.\\n */\\n function permit(address owner, address spender, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s) public virtual override {\\n // solhint-disable-next-line not-rely-on-time\\n require(block.timestamp <= deadline, \\\"ERC20Permit: expired deadline\\\");\\n\\n bytes32 structHash = keccak256(\\n abi.encode(\\n _PERMIT_TYPEHASH,\\n owner,\\n spender,\\n value,\\n _nonces[owner].current(),\\n deadline\\n )\\n );\\n\\n bytes32 hash = _hashTypedDataV4(structHash);\\n\\n address signer = ECDSAUpgradeable.recover(hash, v, r, s);\\n require(signer == owner, \\\"ERC20Permit: invalid signature\\\");\\n\\n _nonces[owner].increment();\\n _approve(owner, spender, value);\\n }\\n\\n /**\\n * @dev See {IERC20Permit-nonces}.\\n */\\n function nonces(address owner) public view override returns (uint256) {\\n return _nonces[owner].current();\\n }\\n\\n /**\\n * @dev See {IERC20Permit-DOMAIN_SEPARATOR}.\\n */\\n // solhint-disable-next-line func-name-mixedcase\\n function DOMAIN_SEPARATOR() external view override returns (bytes32) {\\n return _domainSeparatorV4();\\n }\\n uint256[49] private __gap;\\n}\\n\",\"keccak256\":\"0xb30c40eb91411e29d23c8184b19fd37e6c2447f685631b798af2871ede483157\",\"license\":\"MIT\"},\"@openzeppelin/contracts-upgradeable/drafts/IERC20PermitUpgradeable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity >=0.6.0 <0.8.0;\\n\\n/**\\n * @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in\\n * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612].\\n *\\n * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by\\n * presenting a message signed by the account. By not relying on `{IERC20-approve}`, the token holder account doesn't\\n * need to send a transaction, and thus is not required to hold Ether at all.\\n */\\ninterface IERC20PermitUpgradeable {\\n /**\\n * @dev Sets `value` as the allowance of `spender` over `owner`'s tokens,\\n * given `owner`'s signed approval.\\n *\\n * IMPORTANT: The same issues {IERC20-approve} has related to transaction\\n * ordering also apply here.\\n *\\n * Emits an {Approval} event.\\n *\\n * Requirements:\\n *\\n * - `spender` cannot be the zero address.\\n * - `deadline` must be a timestamp in the future.\\n * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner`\\n * over the EIP712-formatted function arguments.\\n * - the signature must use ``owner``'s current nonce (see {nonces}).\\n *\\n * For more information on the signature format, see the\\n * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP\\n * section].\\n */\\n function permit(address owner, address spender, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s) external;\\n\\n /**\\n * @dev Returns the current nonce for `owner`. This value must be\\n * included whenever a signature is generated for {permit}.\\n *\\n * Every successful call to {permit} increases ``owner``'s nonce by one. This\\n * prevents a signature from being used multiple times.\\n */\\n function nonces(address owner) external view returns (uint256);\\n\\n /**\\n * @dev Returns the domain separator used in the encoding of the signature for `permit`, as defined by {EIP712}.\\n */\\n // solhint-disable-next-line func-name-mixedcase\\n function DOMAIN_SEPARATOR() external view returns (bytes32);\\n}\\n\",\"keccak256\":\"0x30c000f3a68d252b09a738c782e0fc9dbf168b81021a195de6102f8d095681ae\",\"license\":\"MIT\"},\"@openzeppelin/contracts-upgradeable/math/SafeMathUpgradeable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity >=0.6.0 <0.8.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 SafeMathUpgradeable {\\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\",\"keccak256\":\"0x0dd1e9b19801e3e7d900fbf4182d81e1afd23ad7be39504e33df6bbcba91d724\",\"license\":\"MIT\"},\"@openzeppelin/contracts-upgradeable/proxy/Initializable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\n// solhint-disable-next-line compiler-version\\npragma solidity >=0.4.24 <0.8.0;\\n\\nimport \\\"../utils/AddressUpgradeable.sol\\\";\\n\\n/**\\n * @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed\\n * behind a proxy. Since a proxied contract can't have a constructor, it's common to move constructor logic to an\\n * external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer\\n * function so it can only be called once. The {initializer} modifier provided by this contract will have this effect.\\n *\\n * TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as\\n * possible by providing the encoded function call as the `_data` argument to {UpgradeableProxy-constructor}.\\n *\\n * CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure\\n * that all initializers are idempotent. This is not verified automatically as constructors are by Solidity.\\n */\\nabstract contract Initializable {\\n\\n /**\\n * @dev Indicates that the contract has been initialized.\\n */\\n bool private _initialized;\\n\\n /**\\n * @dev Indicates that the contract is in the process of being initialized.\\n */\\n bool private _initializing;\\n\\n /**\\n * @dev Modifier to protect an initializer function from being invoked twice.\\n */\\n modifier initializer() {\\n require(_initializing || _isConstructor() || !_initialized, \\\"Initializable: contract is already initialized\\\");\\n\\n bool isTopLevelCall = !_initializing;\\n if (isTopLevelCall) {\\n _initializing = true;\\n _initialized = true;\\n }\\n\\n _;\\n\\n if (isTopLevelCall) {\\n _initializing = false;\\n }\\n }\\n\\n /// @dev Returns true if and only if the function is running in the constructor\\n function _isConstructor() private view returns (bool) {\\n return !AddressUpgradeable.isContract(address(this));\\n }\\n}\\n\",\"keccak256\":\"0xd8e4eb08dcc1d1860fb347ba5ffd595242b9a1b66d49a47f2b4cb51c3f35017e\",\"license\":\"MIT\"},\"@openzeppelin/contracts-upgradeable/token/ERC20/ERC20BurnableUpgradeable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity >=0.6.0 <0.8.0;\\n\\nimport \\\"../../utils/ContextUpgradeable.sol\\\";\\nimport \\\"./ERC20Upgradeable.sol\\\";\\nimport \\\"../../proxy/Initializable.sol\\\";\\n\\n/**\\n * @dev Extension of {ERC20} that allows token holders to destroy both their own\\n * tokens and those that they have an allowance for, in a way that can be\\n * recognized off-chain (via event analysis).\\n */\\nabstract contract ERC20BurnableUpgradeable is Initializable, ContextUpgradeable, ERC20Upgradeable {\\n function __ERC20Burnable_init() internal initializer {\\n __Context_init_unchained();\\n __ERC20Burnable_init_unchained();\\n }\\n\\n function __ERC20Burnable_init_unchained() internal initializer {\\n }\\n using SafeMathUpgradeable for uint256;\\n\\n /**\\n * @dev Destroys `amount` tokens from the caller.\\n *\\n * See {ERC20-_burn}.\\n */\\n function burn(uint256 amount) public virtual {\\n _burn(_msgSender(), amount);\\n }\\n\\n /**\\n * @dev Destroys `amount` tokens from `account`, deducting from the caller's\\n * allowance.\\n *\\n * See {ERC20-_burn} and {ERC20-allowance}.\\n *\\n * Requirements:\\n *\\n * - the caller must have allowance for ``accounts``'s tokens of at least\\n * `amount`.\\n */\\n function burnFrom(address account, uint256 amount) public virtual {\\n uint256 decreasedAllowance = allowance(account, _msgSender()).sub(amount, \\\"ERC20: burn amount exceeds allowance\\\");\\n\\n _approve(account, _msgSender(), decreasedAllowance);\\n _burn(account, amount);\\n }\\n uint256[50] private __gap;\\n}\\n\",\"keccak256\":\"0xd0359e87fe2618573f49a95e13d9dbc31521ad64526b135618abb2a2dc362fbe\",\"license\":\"MIT\"},\"@openzeppelin/contracts-upgradeable/token/ERC20/ERC20Upgradeable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity >=0.6.0 <0.8.0;\\n\\nimport \\\"../../utils/ContextUpgradeable.sol\\\";\\nimport \\\"./IERC20Upgradeable.sol\\\";\\nimport \\\"../../math/SafeMathUpgradeable.sol\\\";\\nimport \\\"../../proxy/Initializable.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 ERC20Upgradeable is Initializable, ContextUpgradeable, IERC20Upgradeable {\\n using SafeMathUpgradeable 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 function __ERC20_init(string memory name_, string memory symbol_) internal initializer {\\n __Context_init_unchained();\\n __ERC20_init_unchained(name_, symbol_);\\n }\\n\\n function __ERC20_init_unchained(string memory name_, string memory symbol_) internal initializer {\\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 uint256[44] private __gap;\\n}\\n\",\"keccak256\":\"0x506dd0718f9ace50588c13848167df5e04ae16abb56341afb10c31ff149bc79b\",\"license\":\"MIT\"},\"@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity >=0.6.0 <0.8.0;\\n\\n/**\\n * @dev Interface of the ERC20 standard as defined in the EIP.\\n */\\ninterface IERC20Upgradeable {\\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\",\"keccak256\":\"0xa1931c47a617014f858580db625aa0dcf343796f39acd4b5b51effc092a1f0a9\",\"license\":\"MIT\"},\"@openzeppelin/contracts-upgradeable/utils/AddressUpgradeable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity >=0.6.2 <0.8.0;\\n\\n/**\\n * @dev Collection of functions related to the address type\\n */\\nlibrary AddressUpgradeable {\\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 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\",\"keccak256\":\"0xfc5ea91fa9ceb1961023b2a6c978b902888c52b90847ac7813fe3b79524165f6\",\"license\":\"MIT\"},\"@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity >=0.6.0 <0.8.0;\\nimport \\\"../proxy/Initializable.sol\\\";\\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 ContextUpgradeable is Initializable {\\n function __Context_init() internal initializer {\\n __Context_init_unchained();\\n }\\n\\n function __Context_init_unchained() internal initializer {\\n }\\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 uint256[50] private __gap;\\n}\\n\",\"keccak256\":\"0xbbf8a21b9a66c48d45ff771b8563c6df19ba451d63dfb8380a865c1e1f29d1a0\",\"license\":\"MIT\"},\"@openzeppelin/contracts-upgradeable/utils/CountersUpgradeable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity >=0.6.0 <0.8.0;\\n\\nimport \\\"../math/SafeMathUpgradeable.sol\\\";\\n\\n/**\\n * @title Counters\\n * @author Matt Condon (@shrugs)\\n * @dev Provides counters that can only be incremented or decremented by one. This can be used e.g. to track the number\\n * of elements in a mapping, issuing ERC721 ids, or counting request ids.\\n *\\n * Include with `using Counters for Counters.Counter;`\\n * Since it is not possible to overflow a 256 bit integer with increments of one, `increment` can skip the {SafeMath}\\n * overflow check, thereby saving gas. This does assume however correct usage, in that the underlying `_value` is never\\n * directly accessed.\\n */\\nlibrary CountersUpgradeable {\\n using SafeMathUpgradeable for uint256;\\n\\n struct Counter {\\n // This variable should never be directly accessed by users of the library: interactions must be restricted to\\n // the library's function. As of Solidity v0.5.2, this cannot be enforced, though there is a proposal to add\\n // this feature: see https://github.com/ethereum/solidity/issues/4637\\n uint256 _value; // default: 0\\n }\\n\\n function current(Counter storage counter) internal view returns (uint256) {\\n return counter._value;\\n }\\n\\n function increment(Counter storage counter) internal {\\n // The {SafeMath} overflow check can be skipped here, see the comment at the top\\n counter._value += 1;\\n }\\n\\n function decrement(Counter storage counter) internal {\\n counter._value = counter._value.sub(1);\\n }\\n}\\n\",\"keccak256\":\"0xe0162cc9b4d619790be38ce4c184a1cd33d41698629ae6bcac00049f24f6cce8\",\"license\":\"MIT\"},\"@openzeppelin/contracts-upgradeable/utils/EnumerableSetUpgradeable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity >=0.6.0 <0.8.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 EnumerableSetUpgradeable {\\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\",\"keccak256\":\"0x20714cf126a1a984613579156d3cbc726db8025d8400e1db1d2bb714edaba335\",\"license\":\"MIT\"},\"contracts/bridge/SynapseERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.6.12;\\n\\nimport \\\"@openzeppelin/contracts-upgradeable/token/ERC20/ERC20Upgradeable.sol\\\";\\nimport \\\"@openzeppelin/contracts-upgradeable/token/ERC20/ERC20BurnableUpgradeable.sol\\\";\\nimport \\\"@openzeppelin/contracts-upgradeable/drafts/ERC20PermitUpgradeable.sol\\\";\\nimport \\\"@openzeppelin/contracts-upgradeable/access/AccessControlUpgradeable.sol\\\";\\nimport \\\"@openzeppelin/contracts-upgradeable/proxy/Initializable.sol\\\";\\n\\ncontract SynapseERC20 is\\n Initializable,\\n ContextUpgradeable,\\n AccessControlUpgradeable,\\n ERC20BurnableUpgradeable,\\n ERC20PermitUpgradeable\\n{\\n bytes32 public constant MINTER_ROLE = keccak256(\\\"MINTER_ROLE\\\");\\n\\n /**\\n * @notice Initializes this ERC20 contract with the given parameters.\\n * @param name Token name\\n * @param symbol Token symbol\\n * @param decimals Token name\\n * @param owner admin address to be initialized with\\n */\\n function initialize(\\n string memory name,\\n string memory symbol,\\n uint8 decimals,\\n address owner\\n ) external initializer {\\n __Context_init_unchained();\\n __AccessControl_init_unchained();\\n __ERC20_init_unchained(name, symbol);\\n __ERC20Burnable_init_unchained();\\n _setupDecimals(decimals);\\n __ERC20Permit_init(name);\\n _setupRole(DEFAULT_ADMIN_ROLE, owner);\\n }\\n\\n function mint(address to, uint256 amount) external {\\n require(hasRole(MINTER_ROLE, msg.sender), \\\"Not a minter\\\");\\n _mint(to, amount);\\n }\\n}\\n\",\"keccak256\":\"0x62201e7f62c9954664d7250cd5d6997729ff226d8eb246be911e3b59b3d976f7\",\"license\":\"MIT\"}},\"version\":1}", + "bytecode": "0x608060405234801561001057600080fd5b50612213806100206000396000f3fe608060405234801561001057600080fd5b50600436106101b95760003560e01c806379cc6790116100f9578063a9059cbb11610097578063d539139311610071578063d539139314610596578063d547741f1461059e578063dd62ed3e146105ca578063de7ea79d146105f8576101b9565b8063a9059cbb146104fc578063ca15c87314610528578063d505accf14610545576101b9565b806391d14854116100d357806391d148541461049457806395d89b41146104c0578063a217fddf146104c8578063a457c2d7146104d0576101b9565b806379cc6790146104035780637ecebe001461042f5780639010d07c14610455576101b9565b8063313ce567116101665780633950935111610140578063395093511461036857806340c10f191461039457806342966c68146103c057806370a08231146103dd576101b9565b8063313ce567146103165780633644e5151461033457806336568abe1461033c576101b9565b806323b872dd1161019757806323b872dd14610295578063248a9ca3146102cb5780632f2ff15d146102e8576101b9565b806306fdde03146101be578063095ea7b31461023b57806318160ddd1461027b575b600080fd5b6101c6610736565b6040805160208082528351818301528351919283929083019185019080838360005b838110156102005781810151838201526020016101e8565b50505050905090810190601f16801561022d5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b6102676004803603604081101561025157600080fd5b506001600160a01b0381351690602001356107ea565b604080519115158252519081900360200190f35b610283610808565b60408051918252519081900360200190f35b610267600480360360608110156102ab57600080fd5b506001600160a01b0381358116916020810135909116906040013561080e565b610283600480360360208110156102e157600080fd5b5035610895565b610314600480360360408110156102fe57600080fd5b50803590602001356001600160a01b03166108aa565b005b61031e610916565b6040805160ff9092168252519081900360200190f35b61028361091f565b6103146004803603604081101561035257600080fd5b50803590602001356001600160a01b031661092e565b6102676004803603604081101561037e57600080fd5b506001600160a01b03813516906020013561098f565b610314600480360360408110156103aa57600080fd5b506001600160a01b0381351690602001356109dd565b610314600480360360208110156103d657600080fd5b5035610a62565b610283600480360360208110156103f357600080fd5b50356001600160a01b0316610a76565b6103146004803603604081101561041957600080fd5b506001600160a01b038135169060200135610a91565b6102836004803603602081101561044557600080fd5b50356001600160a01b0316610aeb565b6104786004803603604081101561046b57600080fd5b5080359060200135610b0c565b604080516001600160a01b039092168252519081900360200190f35b610267600480360360408110156104aa57600080fd5b50803590602001356001600160a01b0316610b2b565b6101c6610b43565b610283610bc2565b610267600480360360408110156104e657600080fd5b506001600160a01b038135169060200135610bc7565b6102676004803603604081101561051257600080fd5b506001600160a01b038135169060200135610c2f565b6102836004803603602081101561053e57600080fd5b5035610c43565b610314600480360360e081101561055b57600080fd5b506001600160a01b03813581169160208101359091169060408101359060608101359060ff6080820135169060a08101359060c00135610c5a565b610283610dfd565b610314600480360360408110156105b457600080fd5b50803590602001356001600160a01b0316610e21565b610283600480360360408110156105e057600080fd5b506001600160a01b0381358116916020013516610e7a565b6103146004803603608081101561060e57600080fd5b81019060208101813564010000000081111561062957600080fd5b82018360208201111561063b57600080fd5b8035906020019184600183028401116401000000008311171561065d57600080fd5b91908080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525092959493602081019350359150506401000000008111156106b057600080fd5b8201836020820111156106c257600080fd5b803590602001918460018302840111640100000000831117156106e457600080fd5b91908080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509295505050813560ff16925050602001356001600160a01b0316610ea5565b60688054604080516020601f60027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6101006001881615020190951694909404938401819004810282018101909252828152606093909290918301828280156107e05780601f106107b5576101008083540402835291602001916107e0565b820191906000526020600020905b8154815290600101906020018083116107c357829003601f168201915b5050505050905090565b60006107fe6107f7610f8a565b8484610f8e565b5060015b92915050565b60675490565b600061081b84848461107a565b61088b84610827610f8a565b610886856040518060600160405280602881526020016120d4602891396001600160a01b038a16600090815260666020526040812090610865610f8a565b6001600160a01b0316815260208101919091526040016000205491906111d7565b610f8e565b5060019392505050565b60009081526033602052604090206002015490565b6000828152603360205260409020600201546108cd906108c8610f8a565b610b2b565b6109085760405162461bcd60e51b815260040180806020018281038252602f815260200180611f99602f913960400191505060405180910390fd5b610912828261126e565b5050565b606a5460ff1690565b60006109296112d7565b905090565b610936610f8a565b6001600160a01b0316816001600160a01b0316146109855760405162461bcd60e51b815260040180806020018281038252602f8152602001806121af602f913960400191505060405180910390fd5b6109128282611312565b60006107fe61099c610f8a565b8461088685606660006109ad610f8a565b6001600160a01b03908116825260208083019390935260409182016000908120918c16815292529020549061137b565b610a077f9f2df0fed2c77648de5860a4cc508cd0818c85b8b8a1ab4ceeef8d981c8956a633610b2b565b610a58576040805162461bcd60e51b815260206004820152600c60248201527f4e6f742061206d696e7465720000000000000000000000000000000000000000604482015290519081900360640190fd5b61091282826113d5565b610a73610a6d610f8a565b826114c7565b50565b6001600160a01b031660009081526065602052604090205490565b6000610ac8826040518060600160405280602481526020016120fc60249139610ac186610abc610f8a565b610e7a565b91906111d7565b9050610adc83610ad6610f8a565b83610f8e565b610ae683836114c7565b505050565b6001600160a01b038116600090815260fd60205260408120610802906115c3565b6000828152603360205260408120610b2490836115c7565b9392505050565b6000828152603360205260408120610b2490836115d3565b60698054604080516020601f60027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6101006001881615020190951694909404938401819004810282018101909252828152606093909290918301828280156107e05780601f106107b5576101008083540402835291602001916107e0565b600081565b60006107fe610bd4610f8a565b846108868560405180606001604052806025815260200161218a6025913960666000610bfe610f8a565b6001600160a01b03908116825260208083019390935260409182016000908120918d168152925290205491906111d7565b60006107fe610c3c610f8a565b848461107a565b6000818152603360205260408120610802906115e8565b83421115610caf576040805162461bcd60e51b815260206004820152601d60248201527f45524332305065726d69743a206578706972656420646561646c696e65000000604482015290519081900360640190fd5b600060fe54888888610ce460fd60008e6001600160a01b03166001600160a01b031681526020019081526020016000206115c3565b8960405160200180878152602001866001600160a01b03168152602001856001600160a01b0316815260200184815260200183815260200182815260200196505050505050506040516020818303038152906040528051906020012090506000610d4d826115f3565b90506000610d5d8287878761165a565b9050896001600160a01b0316816001600160a01b031614610dc5576040805162461bcd60e51b815260206004820152601e60248201527f45524332305065726d69743a20696e76616c6964207369676e61747572650000604482015290519081900360640190fd5b6001600160a01b038a16600090815260fd60205260409020610de6906117f6565b610df18a8a8a610f8e565b50505050505050505050565b7f9f2df0fed2c77648de5860a4cc508cd0818c85b8b8a1ab4ceeef8d981c8956a681565b600082815260336020526040902060020154610e3f906108c8610f8a565b6109855760405162461bcd60e51b81526004018080602001828103825260308152602001806120546030913960400191505060405180910390fd5b6001600160a01b03918216600090815260666020908152604080832093909416825291909152205490565b600054610100900460ff1680610ebe5750610ebe6117ff565b80610ecc575060005460ff16155b610f075760405162461bcd60e51b815260040180806020018281038252602e815260200180612084602e913960400191505060405180910390fd5b600054610100900460ff16158015610f32576000805460ff1961ff0019909116610100171660011790555b610f3a611810565b610f42611810565b610f4c85856118b1565b610f54611810565b610f5d83611989565b610f668561199f565b610f71600083610908565b8015610f83576000805461ff00191690555b5050505050565b3390565b6001600160a01b038316610fd35760405162461bcd60e51b81526004018080602001828103825260248152602001806121666024913960400191505060405180910390fd5b6001600160a01b0382166110185760405162461bcd60e51b8152600401808060200182810382526022815260200180611fea6022913960400191505060405180910390fd5b6001600160a01b03808416600081815260666020908152604080832094871680845294825291829020859055815185815291517f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b9259281900390910190a3505050565b6001600160a01b0383166110bf5760405162461bcd60e51b81526004018080602001828103825260258152602001806121416025913960400191505060405180910390fd5b6001600160a01b0382166111045760405162461bcd60e51b8152600401808060200182810382526023815260200180611f766023913960400191505060405180910390fd5b61110f838383610ae6565b61114c8160405180606001604052806026815260200161200c602691396001600160a01b03861660009081526065602052604090205491906111d7565b6001600160a01b03808516600090815260656020526040808220939093559084168152205461117b908261137b565b6001600160a01b0380841660008181526065602090815260409182902094909455805185815290519193928716927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef92918290030190a3505050565b600081848411156112665760405162461bcd60e51b81526004018080602001828103825283818151815260200191508051906020019080838360005b8381101561122b578181015183820152602001611213565b50505050905090810190601f1680156112585780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b505050900390565b60008281526033602052604090206112869082611a91565b1561091257611293610f8a565b6001600160a01b0316816001600160a01b0316837f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a45050565b60006109297f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f611305611aa6565b61130d611aac565b611ab2565b600082815260336020526040902061132a9082611b14565b1561091257611337610f8a565b6001600160a01b0316816001600160a01b0316837ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b60405160405180910390a45050565b600082820183811015610b24576040805162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b6001600160a01b038216611430576040805162461bcd60e51b815260206004820152601f60248201527f45524332303a206d696e7420746f20746865207a65726f206164647265737300604482015290519081900360640190fd5b61143c60008383610ae6565b606754611449908261137b565b6067556001600160a01b03821660009081526065602052604090205461146f908261137b565b6001600160a01b03831660008181526065602090815260408083209490945583518581529351929391927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9281900390910190a35050565b6001600160a01b03821661150c5760405162461bcd60e51b81526004018080602001828103825260218152602001806121206021913960400191505060405180910390fd5b61151882600083610ae6565b61155581604051806060016040528060228152602001611fc8602291396001600160a01b03851660009081526065602052604090205491906111d7565b6001600160a01b03831660009081526065602052604090205560675461157b9082611b29565b6067556040805182815290516000916001600160a01b038516917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9181900360200190a35050565b5490565b6000610b248383611b86565b6000610b24836001600160a01b038416611bea565b6000610802826115c3565b60006115fd6112d7565b8260405160200180807f190100000000000000000000000000000000000000000000000000000000000081525060020183815260200182815260200192505050604051602081830303815290604052805190602001209050919050565b60007f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a08211156116bb5760405162461bcd60e51b81526004018080602001828103825260228152602001806120326022913960400191505060405180910390fd5b8360ff16601b14806116d057508360ff16601c145b61170b5760405162461bcd60e51b81526004018080602001828103825260228152602001806120b26022913960400191505060405180910390fd5b600060018686868660405160008152602001604052604051808581526020018460ff1681526020018381526020018281526020019450505050506020604051602081039080840390855afa158015611767573d6000803e3d6000fd5b50506040517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe001519150506001600160a01b0381166117ed576040805162461bcd60e51b815260206004820152601860248201527f45434453413a20696e76616c6964207369676e61747572650000000000000000604482015290519081900360640190fd5b95945050505050565b80546001019055565b600061180a30611c02565b15905090565b600054610100900460ff168061182957506118296117ff565b80611837575060005460ff16155b6118725760405162461bcd60e51b815260040180806020018281038252602e815260200180612084602e913960400191505060405180910390fd5b600054610100900460ff1615801561189d576000805460ff1961ff0019909116610100171660011790555b8015610a73576000805461ff001916905550565b600054610100900460ff16806118ca57506118ca6117ff565b806118d8575060005460ff16155b6119135760405162461bcd60e51b815260040180806020018281038252602e815260200180612084602e913960400191505060405180910390fd5b600054610100900460ff1615801561193e576000805460ff1961ff0019909116610100171660011790555b8251611951906068906020860190611ec0565b508151611965906069906020850190611ec0565b50606a805460ff191660121790558015610ae6576000805461ff0019169055505050565b606a805460ff191660ff92909216919091179055565b600054610100900460ff16806119b857506119b86117ff565b806119c6575060005460ff16155b611a015760405162461bcd60e51b815260040180806020018281038252602e815260200180612084602e913960400191505060405180910390fd5b600054610100900460ff16158015611a2c576000805460ff1961ff0019909116610100171660011790555b611a34611810565b611a73826040518060400160405280600181526020017f3100000000000000000000000000000000000000000000000000000000000000815250611c08565b611a7c82611cc8565b8015610912576000805461ff00191690555050565b6000610b24836001600160a01b038416611d8e565b60c95490565b60ca5490565b6000838383611abf611dd8565b3060405160200180868152602001858152602001848152602001838152602001826001600160a01b03168152602001955050505050506040516020818303038152906040528051906020012090509392505050565b6000610b24836001600160a01b038416611ddc565b600082821115611b80576040805162461bcd60e51b815260206004820152601e60248201527f536166654d6174683a207375627472616374696f6e206f766572666c6f770000604482015290519081900360640190fd5b50900390565b81546000908210611bc85760405162461bcd60e51b8152600401808060200182810382526022815260200180611f546022913960400191505060405180910390fd5b826000018281548110611bd757fe5b9060005260206000200154905092915050565b60009081526001919091016020526040902054151590565b3b151590565b600054610100900460ff1680611c215750611c216117ff565b80611c2f575060005460ff16155b611c6a5760405162461bcd60e51b815260040180806020018281038252602e815260200180612084602e913960400191505060405180910390fd5b600054610100900460ff16158015611c95576000805460ff1961ff0019909116610100171660011790555b825160208085019190912083519184019190912060c99190915560ca558015610ae6576000805461ff0019169055505050565b600054610100900460ff1680611ce15750611ce16117ff565b80611cef575060005460ff16155b611d2a5760405162461bcd60e51b815260040180806020018281038252602e815260200180612084602e913960400191505060405180910390fd5b600054610100900460ff16158015611d55576000805460ff1961ff0019909116610100171660011790555b7f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c960fe558015610912576000805461ff00191690555050565b6000611d9a8383611bea565b611dd057508154600181810184556000848152602080822090930184905584548482528286019093526040902091909155610802565b506000610802565b4690565b60008181526001830160205260408120548015611eb65783547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8083019190810190600090879083908110611e2d57fe5b9060005260206000200154905080876000018481548110611e4a57fe5b600091825260208083209091019290925582815260018981019092526040902090840190558654879080611e7a57fe5b60019003818190600052602060002001600090559055866001016000878152602001908152602001600020600090556001945050505050610802565b6000915050610802565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f10611f0157805160ff1916838001178555611f2e565b82800160010185558215611f2e579182015b82811115611f2e578251825591602001919060010190611f13565b50611f3a929150611f3e565b5090565b5b80821115611f3a5760008155600101611f3f56fe456e756d657261626c655365743a20696e646578206f7574206f6620626f756e647345524332303a207472616e7366657220746f20746865207a65726f2061646472657373416363657373436f6e74726f6c3a2073656e646572206d75737420626520616e2061646d696e20746f206772616e7445524332303a206275726e20616d6f756e7420657863656564732062616c616e636545524332303a20617070726f766520746f20746865207a65726f206164647265737345524332303a207472616e7366657220616d6f756e7420657863656564732062616c616e636545434453413a20696e76616c6964207369676e6174757265202773272076616c7565416363657373436f6e74726f6c3a2073656e646572206d75737420626520616e2061646d696e20746f207265766f6b65496e697469616c697a61626c653a20636f6e747261637420697320616c726561647920696e697469616c697a656445434453413a20696e76616c6964207369676e6174757265202776272076616c756545524332303a207472616e7366657220616d6f756e74206578636565647320616c6c6f77616e636545524332303a206275726e20616d6f756e74206578636565647320616c6c6f77616e636545524332303a206275726e2066726f6d20746865207a65726f206164647265737345524332303a207472616e736665722066726f6d20746865207a65726f206164647265737345524332303a20617070726f76652066726f6d20746865207a65726f206164647265737345524332303a2064656372656173656420616c6c6f77616e63652062656c6f77207a65726f416363657373436f6e74726f6c3a2063616e206f6e6c792072656e6f756e636520726f6c657320666f722073656c66a2646970667358221220e7c3753b08173a11ca96acfac750f90800b1683e662b545723723a1385793bd164736f6c634300060c0033", + "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106101b95760003560e01c806379cc6790116100f9578063a9059cbb11610097578063d539139311610071578063d539139314610596578063d547741f1461059e578063dd62ed3e146105ca578063de7ea79d146105f8576101b9565b8063a9059cbb146104fc578063ca15c87314610528578063d505accf14610545576101b9565b806391d14854116100d357806391d148541461049457806395d89b41146104c0578063a217fddf146104c8578063a457c2d7146104d0576101b9565b806379cc6790146104035780637ecebe001461042f5780639010d07c14610455576101b9565b8063313ce567116101665780633950935111610140578063395093511461036857806340c10f191461039457806342966c68146103c057806370a08231146103dd576101b9565b8063313ce567146103165780633644e5151461033457806336568abe1461033c576101b9565b806323b872dd1161019757806323b872dd14610295578063248a9ca3146102cb5780632f2ff15d146102e8576101b9565b806306fdde03146101be578063095ea7b31461023b57806318160ddd1461027b575b600080fd5b6101c6610736565b6040805160208082528351818301528351919283929083019185019080838360005b838110156102005781810151838201526020016101e8565b50505050905090810190601f16801561022d5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b6102676004803603604081101561025157600080fd5b506001600160a01b0381351690602001356107ea565b604080519115158252519081900360200190f35b610283610808565b60408051918252519081900360200190f35b610267600480360360608110156102ab57600080fd5b506001600160a01b0381358116916020810135909116906040013561080e565b610283600480360360208110156102e157600080fd5b5035610895565b610314600480360360408110156102fe57600080fd5b50803590602001356001600160a01b03166108aa565b005b61031e610916565b6040805160ff9092168252519081900360200190f35b61028361091f565b6103146004803603604081101561035257600080fd5b50803590602001356001600160a01b031661092e565b6102676004803603604081101561037e57600080fd5b506001600160a01b03813516906020013561098f565b610314600480360360408110156103aa57600080fd5b506001600160a01b0381351690602001356109dd565b610314600480360360208110156103d657600080fd5b5035610a62565b610283600480360360208110156103f357600080fd5b50356001600160a01b0316610a76565b6103146004803603604081101561041957600080fd5b506001600160a01b038135169060200135610a91565b6102836004803603602081101561044557600080fd5b50356001600160a01b0316610aeb565b6104786004803603604081101561046b57600080fd5b5080359060200135610b0c565b604080516001600160a01b039092168252519081900360200190f35b610267600480360360408110156104aa57600080fd5b50803590602001356001600160a01b0316610b2b565b6101c6610b43565b610283610bc2565b610267600480360360408110156104e657600080fd5b506001600160a01b038135169060200135610bc7565b6102676004803603604081101561051257600080fd5b506001600160a01b038135169060200135610c2f565b6102836004803603602081101561053e57600080fd5b5035610c43565b610314600480360360e081101561055b57600080fd5b506001600160a01b03813581169160208101359091169060408101359060608101359060ff6080820135169060a08101359060c00135610c5a565b610283610dfd565b610314600480360360408110156105b457600080fd5b50803590602001356001600160a01b0316610e21565b610283600480360360408110156105e057600080fd5b506001600160a01b0381358116916020013516610e7a565b6103146004803603608081101561060e57600080fd5b81019060208101813564010000000081111561062957600080fd5b82018360208201111561063b57600080fd5b8035906020019184600183028401116401000000008311171561065d57600080fd5b91908080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525092959493602081019350359150506401000000008111156106b057600080fd5b8201836020820111156106c257600080fd5b803590602001918460018302840111640100000000831117156106e457600080fd5b91908080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509295505050813560ff16925050602001356001600160a01b0316610ea5565b60688054604080516020601f60027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6101006001881615020190951694909404938401819004810282018101909252828152606093909290918301828280156107e05780601f106107b5576101008083540402835291602001916107e0565b820191906000526020600020905b8154815290600101906020018083116107c357829003601f168201915b5050505050905090565b60006107fe6107f7610f8a565b8484610f8e565b5060015b92915050565b60675490565b600061081b84848461107a565b61088b84610827610f8a565b610886856040518060600160405280602881526020016120d4602891396001600160a01b038a16600090815260666020526040812090610865610f8a565b6001600160a01b0316815260208101919091526040016000205491906111d7565b610f8e565b5060019392505050565b60009081526033602052604090206002015490565b6000828152603360205260409020600201546108cd906108c8610f8a565b610b2b565b6109085760405162461bcd60e51b815260040180806020018281038252602f815260200180611f99602f913960400191505060405180910390fd5b610912828261126e565b5050565b606a5460ff1690565b60006109296112d7565b905090565b610936610f8a565b6001600160a01b0316816001600160a01b0316146109855760405162461bcd60e51b815260040180806020018281038252602f8152602001806121af602f913960400191505060405180910390fd5b6109128282611312565b60006107fe61099c610f8a565b8461088685606660006109ad610f8a565b6001600160a01b03908116825260208083019390935260409182016000908120918c16815292529020549061137b565b610a077f9f2df0fed2c77648de5860a4cc508cd0818c85b8b8a1ab4ceeef8d981c8956a633610b2b565b610a58576040805162461bcd60e51b815260206004820152600c60248201527f4e6f742061206d696e7465720000000000000000000000000000000000000000604482015290519081900360640190fd5b61091282826113d5565b610a73610a6d610f8a565b826114c7565b50565b6001600160a01b031660009081526065602052604090205490565b6000610ac8826040518060600160405280602481526020016120fc60249139610ac186610abc610f8a565b610e7a565b91906111d7565b9050610adc83610ad6610f8a565b83610f8e565b610ae683836114c7565b505050565b6001600160a01b038116600090815260fd60205260408120610802906115c3565b6000828152603360205260408120610b2490836115c7565b9392505050565b6000828152603360205260408120610b2490836115d3565b60698054604080516020601f60027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6101006001881615020190951694909404938401819004810282018101909252828152606093909290918301828280156107e05780601f106107b5576101008083540402835291602001916107e0565b600081565b60006107fe610bd4610f8a565b846108868560405180606001604052806025815260200161218a6025913960666000610bfe610f8a565b6001600160a01b03908116825260208083019390935260409182016000908120918d168152925290205491906111d7565b60006107fe610c3c610f8a565b848461107a565b6000818152603360205260408120610802906115e8565b83421115610caf576040805162461bcd60e51b815260206004820152601d60248201527f45524332305065726d69743a206578706972656420646561646c696e65000000604482015290519081900360640190fd5b600060fe54888888610ce460fd60008e6001600160a01b03166001600160a01b031681526020019081526020016000206115c3565b8960405160200180878152602001866001600160a01b03168152602001856001600160a01b0316815260200184815260200183815260200182815260200196505050505050506040516020818303038152906040528051906020012090506000610d4d826115f3565b90506000610d5d8287878761165a565b9050896001600160a01b0316816001600160a01b031614610dc5576040805162461bcd60e51b815260206004820152601e60248201527f45524332305065726d69743a20696e76616c6964207369676e61747572650000604482015290519081900360640190fd5b6001600160a01b038a16600090815260fd60205260409020610de6906117f6565b610df18a8a8a610f8e565b50505050505050505050565b7f9f2df0fed2c77648de5860a4cc508cd0818c85b8b8a1ab4ceeef8d981c8956a681565b600082815260336020526040902060020154610e3f906108c8610f8a565b6109855760405162461bcd60e51b81526004018080602001828103825260308152602001806120546030913960400191505060405180910390fd5b6001600160a01b03918216600090815260666020908152604080832093909416825291909152205490565b600054610100900460ff1680610ebe5750610ebe6117ff565b80610ecc575060005460ff16155b610f075760405162461bcd60e51b815260040180806020018281038252602e815260200180612084602e913960400191505060405180910390fd5b600054610100900460ff16158015610f32576000805460ff1961ff0019909116610100171660011790555b610f3a611810565b610f42611810565b610f4c85856118b1565b610f54611810565b610f5d83611989565b610f668561199f565b610f71600083610908565b8015610f83576000805461ff00191690555b5050505050565b3390565b6001600160a01b038316610fd35760405162461bcd60e51b81526004018080602001828103825260248152602001806121666024913960400191505060405180910390fd5b6001600160a01b0382166110185760405162461bcd60e51b8152600401808060200182810382526022815260200180611fea6022913960400191505060405180910390fd5b6001600160a01b03808416600081815260666020908152604080832094871680845294825291829020859055815185815291517f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b9259281900390910190a3505050565b6001600160a01b0383166110bf5760405162461bcd60e51b81526004018080602001828103825260258152602001806121416025913960400191505060405180910390fd5b6001600160a01b0382166111045760405162461bcd60e51b8152600401808060200182810382526023815260200180611f766023913960400191505060405180910390fd5b61110f838383610ae6565b61114c8160405180606001604052806026815260200161200c602691396001600160a01b03861660009081526065602052604090205491906111d7565b6001600160a01b03808516600090815260656020526040808220939093559084168152205461117b908261137b565b6001600160a01b0380841660008181526065602090815260409182902094909455805185815290519193928716927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef92918290030190a3505050565b600081848411156112665760405162461bcd60e51b81526004018080602001828103825283818151815260200191508051906020019080838360005b8381101561122b578181015183820152602001611213565b50505050905090810190601f1680156112585780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b505050900390565b60008281526033602052604090206112869082611a91565b1561091257611293610f8a565b6001600160a01b0316816001600160a01b0316837f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a45050565b60006109297f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f611305611aa6565b61130d611aac565b611ab2565b600082815260336020526040902061132a9082611b14565b1561091257611337610f8a565b6001600160a01b0316816001600160a01b0316837ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b60405160405180910390a45050565b600082820183811015610b24576040805162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b6001600160a01b038216611430576040805162461bcd60e51b815260206004820152601f60248201527f45524332303a206d696e7420746f20746865207a65726f206164647265737300604482015290519081900360640190fd5b61143c60008383610ae6565b606754611449908261137b565b6067556001600160a01b03821660009081526065602052604090205461146f908261137b565b6001600160a01b03831660008181526065602090815260408083209490945583518581529351929391927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9281900390910190a35050565b6001600160a01b03821661150c5760405162461bcd60e51b81526004018080602001828103825260218152602001806121206021913960400191505060405180910390fd5b61151882600083610ae6565b61155581604051806060016040528060228152602001611fc8602291396001600160a01b03851660009081526065602052604090205491906111d7565b6001600160a01b03831660009081526065602052604090205560675461157b9082611b29565b6067556040805182815290516000916001600160a01b038516917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9181900360200190a35050565b5490565b6000610b248383611b86565b6000610b24836001600160a01b038416611bea565b6000610802826115c3565b60006115fd6112d7565b8260405160200180807f190100000000000000000000000000000000000000000000000000000000000081525060020183815260200182815260200192505050604051602081830303815290604052805190602001209050919050565b60007f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a08211156116bb5760405162461bcd60e51b81526004018080602001828103825260228152602001806120326022913960400191505060405180910390fd5b8360ff16601b14806116d057508360ff16601c145b61170b5760405162461bcd60e51b81526004018080602001828103825260228152602001806120b26022913960400191505060405180910390fd5b600060018686868660405160008152602001604052604051808581526020018460ff1681526020018381526020018281526020019450505050506020604051602081039080840390855afa158015611767573d6000803e3d6000fd5b50506040517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe001519150506001600160a01b0381166117ed576040805162461bcd60e51b815260206004820152601860248201527f45434453413a20696e76616c6964207369676e61747572650000000000000000604482015290519081900360640190fd5b95945050505050565b80546001019055565b600061180a30611c02565b15905090565b600054610100900460ff168061182957506118296117ff565b80611837575060005460ff16155b6118725760405162461bcd60e51b815260040180806020018281038252602e815260200180612084602e913960400191505060405180910390fd5b600054610100900460ff1615801561189d576000805460ff1961ff0019909116610100171660011790555b8015610a73576000805461ff001916905550565b600054610100900460ff16806118ca57506118ca6117ff565b806118d8575060005460ff16155b6119135760405162461bcd60e51b815260040180806020018281038252602e815260200180612084602e913960400191505060405180910390fd5b600054610100900460ff1615801561193e576000805460ff1961ff0019909116610100171660011790555b8251611951906068906020860190611ec0565b508151611965906069906020850190611ec0565b50606a805460ff191660121790558015610ae6576000805461ff0019169055505050565b606a805460ff191660ff92909216919091179055565b600054610100900460ff16806119b857506119b86117ff565b806119c6575060005460ff16155b611a015760405162461bcd60e51b815260040180806020018281038252602e815260200180612084602e913960400191505060405180910390fd5b600054610100900460ff16158015611a2c576000805460ff1961ff0019909116610100171660011790555b611a34611810565b611a73826040518060400160405280600181526020017f3100000000000000000000000000000000000000000000000000000000000000815250611c08565b611a7c82611cc8565b8015610912576000805461ff00191690555050565b6000610b24836001600160a01b038416611d8e565b60c95490565b60ca5490565b6000838383611abf611dd8565b3060405160200180868152602001858152602001848152602001838152602001826001600160a01b03168152602001955050505050506040516020818303038152906040528051906020012090509392505050565b6000610b24836001600160a01b038416611ddc565b600082821115611b80576040805162461bcd60e51b815260206004820152601e60248201527f536166654d6174683a207375627472616374696f6e206f766572666c6f770000604482015290519081900360640190fd5b50900390565b81546000908210611bc85760405162461bcd60e51b8152600401808060200182810382526022815260200180611f546022913960400191505060405180910390fd5b826000018281548110611bd757fe5b9060005260206000200154905092915050565b60009081526001919091016020526040902054151590565b3b151590565b600054610100900460ff1680611c215750611c216117ff565b80611c2f575060005460ff16155b611c6a5760405162461bcd60e51b815260040180806020018281038252602e815260200180612084602e913960400191505060405180910390fd5b600054610100900460ff16158015611c95576000805460ff1961ff0019909116610100171660011790555b825160208085019190912083519184019190912060c99190915560ca558015610ae6576000805461ff0019169055505050565b600054610100900460ff1680611ce15750611ce16117ff565b80611cef575060005460ff16155b611d2a5760405162461bcd60e51b815260040180806020018281038252602e815260200180612084602e913960400191505060405180910390fd5b600054610100900460ff16158015611d55576000805460ff1961ff0019909116610100171660011790555b7f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c960fe558015610912576000805461ff00191690555050565b6000611d9a8383611bea565b611dd057508154600181810184556000848152602080822090930184905584548482528286019093526040902091909155610802565b506000610802565b4690565b60008181526001830160205260408120548015611eb65783547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8083019190810190600090879083908110611e2d57fe5b9060005260206000200154905080876000018481548110611e4a57fe5b600091825260208083209091019290925582815260018981019092526040902090840190558654879080611e7a57fe5b60019003818190600052602060002001600090559055866001016000878152602001908152602001600020600090556001945050505050610802565b6000915050610802565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f10611f0157805160ff1916838001178555611f2e565b82800160010185558215611f2e579182015b82811115611f2e578251825591602001919060010190611f13565b50611f3a929150611f3e565b5090565b5b80821115611f3a5760008155600101611f3f56fe456e756d657261626c655365743a20696e646578206f7574206f6620626f756e647345524332303a207472616e7366657220746f20746865207a65726f2061646472657373416363657373436f6e74726f6c3a2073656e646572206d75737420626520616e2061646d696e20746f206772616e7445524332303a206275726e20616d6f756e7420657863656564732062616c616e636545524332303a20617070726f766520746f20746865207a65726f206164647265737345524332303a207472616e7366657220616d6f756e7420657863656564732062616c616e636545434453413a20696e76616c6964207369676e6174757265202773272076616c7565416363657373436f6e74726f6c3a2073656e646572206d75737420626520616e2061646d696e20746f207265766f6b65496e697469616c697a61626c653a20636f6e747261637420697320616c726561647920696e697469616c697a656445434453413a20696e76616c6964207369676e6174757265202776272076616c756545524332303a207472616e7366657220616d6f756e74206578636565647320616c6c6f77616e636545524332303a206275726e20616d6f756e74206578636565647320616c6c6f77616e636545524332303a206275726e2066726f6d20746865207a65726f206164647265737345524332303a207472616e736665722066726f6d20746865207a65726f206164647265737345524332303a20617070726f76652066726f6d20746865207a65726f206164647265737345524332303a2064656372656173656420616c6c6f77616e63652062656c6f77207a65726f416363657373436f6e74726f6c3a2063616e206f6e6c792072656e6f756e636520726f6c657320666f722073656c66a2646970667358221220e7c3753b08173a11ca96acfac750f90800b1683e662b545723723a1385793bd164736f6c634300060c0033", + "devdoc": { + "kind": "dev", + "methods": { + "DOMAIN_SEPARATOR()": { + "details": "See {IERC20Permit-DOMAIN_SEPARATOR}." + }, + "allowance(address,address)": { + "details": "See {IERC20-allowance}." + }, + "approve(address,uint256)": { + "details": "See {IERC20-approve}. Requirements: - `spender` cannot be the zero address." + }, + "balanceOf(address)": { + "details": "See {IERC20-balanceOf}." + }, + "burn(uint256)": { + "details": "Destroys `amount` tokens from the caller. See {ERC20-_burn}." + }, + "burnFrom(address,uint256)": { + "details": "Destroys `amount` tokens from `account`, deducting from the caller's allowance. See {ERC20-_burn} and {ERC20-allowance}. Requirements: - the caller must have allowance for ``accounts``'s tokens of at least `amount`." + }, + "decimals()": { + "details": "Returns the number of decimals used to get its user representation. For example, if `decimals` equals `2`, a balance of `505` tokens should be displayed to a user as `5,05` (`505 / 10 ** 2`). Tokens usually opt for a value of 18, imitating the relationship between Ether and Wei. This is the value {ERC20} uses, unless {_setupDecimals} is called. NOTE: This information is only used for _display_ purposes: it in no way affects any of the arithmetic of the contract, including {IERC20-balanceOf} and {IERC20-transfer}." + }, + "decreaseAllowance(address,uint256)": { + "details": "Atomically decreases the allowance granted to `spender` by the caller. This is an alternative to {approve} that can be used as a mitigation for problems described in {IERC20-approve}. Emits an {Approval} event indicating the updated allowance. Requirements: - `spender` cannot be the zero address. - `spender` must have allowance for the caller of at least `subtractedValue`." + }, + "getRoleAdmin(bytes32)": { + "details": "Returns the admin role that controls `role`. See {grantRole} and {revokeRole}. To change a role's admin, use {_setRoleAdmin}." + }, + "getRoleMember(bytes32,uint256)": { + "details": "Returns one of the accounts that have `role`. `index` must be a value between 0 and {getRoleMemberCount}, non-inclusive. Role bearers are not sorted in any particular way, and their ordering may change at any point. WARNING: When using {getRoleMember} and {getRoleMemberCount}, make sure you perform all queries on the same block. See the following https://forum.openzeppelin.com/t/iterating-over-elements-on-enumerableset-in-openzeppelin-contracts/2296[forum post] for more information." + }, + "getRoleMemberCount(bytes32)": { + "details": "Returns the number of accounts that have `role`. Can be used together with {getRoleMember} to enumerate all bearers of a role." + }, + "grantRole(bytes32,address)": { + "details": "Grants `role` to `account`. If `account` had not been already granted `role`, emits a {RoleGranted} event. Requirements: - the caller must have ``role``'s admin role." + }, + "hasRole(bytes32,address)": { + "details": "Returns `true` if `account` has been granted `role`." + }, + "increaseAllowance(address,uint256)": { + "details": "Atomically increases the allowance granted to `spender` by the caller. This is an alternative to {approve} that can be used as a mitigation for problems described in {IERC20-approve}. Emits an {Approval} event indicating the updated allowance. Requirements: - `spender` cannot be the zero address." + }, + "initialize(string,string,uint8,address)": { + "params": { + "decimals": "Token name", + "name": "Token name", + "owner": "admin address to be initialized with", + "symbol": "Token symbol" + } + }, + "name()": { + "details": "Returns the name of the token." + }, + "nonces(address)": { + "details": "See {IERC20Permit-nonces}." + }, + "permit(address,address,uint256,uint256,uint8,bytes32,bytes32)": { + "details": "See {IERC20Permit-permit}." + }, + "renounceRole(bytes32,address)": { + "details": "Revokes `role` from the calling account. Roles are often managed via {grantRole} and {revokeRole}: this function's purpose is to provide a mechanism for accounts to lose their privileges if they are compromised (such as when a trusted device is misplaced). If the calling account had been granted `role`, emits a {RoleRevoked} event. Requirements: - the caller must be `account`." + }, + "revokeRole(bytes32,address)": { + "details": "Revokes `role` from `account`. If `account` had been granted `role`, emits a {RoleRevoked} event. Requirements: - the caller must have ``role``'s admin role." + }, + "symbol()": { + "details": "Returns the symbol of the token, usually a shorter version of the name." + }, + "totalSupply()": { + "details": "See {IERC20-totalSupply}." + }, + "transfer(address,uint256)": { + "details": "See {IERC20-transfer}. Requirements: - `recipient` cannot be the zero address. - the caller must have a balance of at least `amount`." + }, + "transferFrom(address,address,uint256)": { + "details": "See {IERC20-transferFrom}. Emits an {Approval} event indicating the updated allowance. This is not required by the EIP. See the note at the beginning of {ERC20}. Requirements: - `sender` and `recipient` cannot be the zero address. - `sender` must have a balance of at least `amount`. - the caller must have allowance for ``sender``'s tokens of at least `amount`." + } + }, + "version": 1 + }, + "userdoc": { + "kind": "user", + "methods": { + "initialize(string,string,uint8,address)": { + "notice": "Initializes this ERC20 contract with the given parameters." + } + }, + "version": 1 + }, + "storageLayout": { + "storage": [ + { + "astId": 1286, + "contract": "contracts/bridge/SynapseERC20.sol:SynapseERC20", + "label": "_initialized", + "offset": 0, + "slot": "0", + "type": "t_bool" + }, + { + "astId": 1289, + "contract": "contracts/bridge/SynapseERC20.sol:SynapseERC20", + "label": "_initializing", + "offset": 1, + "slot": "0", + "type": "t_bool" + }, + { + "astId": 2325, + "contract": "contracts/bridge/SynapseERC20.sol:SynapseERC20", + "label": "__gap", + "offset": 0, + "slot": "1", + "type": "t_array(t_uint256)50_storage" + }, + { + "astId": 43, + "contract": "contracts/bridge/SynapseERC20.sol:SynapseERC20", + "label": "_roles", + "offset": 0, + "slot": "51", + "type": "t_mapping(t_bytes32,t_struct(RoleData)39_storage)" + }, + { + "astId": 306, + "contract": "contracts/bridge/SynapseERC20.sol:SynapseERC20", + "label": "__gap", + "offset": 0, + "slot": "52", + "type": "t_array(t_uint256)49_storage" + }, + { + "astId": 1449, + "contract": "contracts/bridge/SynapseERC20.sol:SynapseERC20", + "label": "_balances", + "offset": 0, + "slot": "101", + "type": "t_mapping(t_address,t_uint256)" + }, + { + "astId": 1455, + "contract": "contracts/bridge/SynapseERC20.sol:SynapseERC20", + "label": "_allowances", + "offset": 0, + "slot": "102", + "type": "t_mapping(t_address,t_mapping(t_address,t_uint256))" + }, + { + "astId": 1457, + "contract": "contracts/bridge/SynapseERC20.sol:SynapseERC20", + "label": "_totalSupply", + "offset": 0, + "slot": "103", + "type": "t_uint256" + }, + { + "astId": 1459, + "contract": "contracts/bridge/SynapseERC20.sol:SynapseERC20", + "label": "_name", + "offset": 0, + "slot": "104", + "type": "t_string_storage" + }, + { + "astId": 1461, + "contract": "contracts/bridge/SynapseERC20.sol:SynapseERC20", + "label": "_symbol", + "offset": 0, + "slot": "105", + "type": "t_string_storage" + }, + { + "astId": 1463, + "contract": "contracts/bridge/SynapseERC20.sol:SynapseERC20", + "label": "_decimals", + "offset": 0, + "slot": "106", + "type": "t_uint8" + }, + { + "astId": 1958, + "contract": "contracts/bridge/SynapseERC20.sol:SynapseERC20", + "label": "__gap", + "offset": 0, + "slot": "107", + "type": "t_array(t_uint256)44_storage" + }, + { + "astId": 1428, + "contract": "contracts/bridge/SynapseERC20.sol:SynapseERC20", + "label": "__gap", + "offset": 0, + "slot": "151", + "type": "t_array(t_uint256)50_storage" + }, + { + "astId": 562, + "contract": "contracts/bridge/SynapseERC20.sol:SynapseERC20", + "label": "_HASHED_NAME", + "offset": 0, + "slot": "201", + "type": "t_bytes32" + }, + { + "astId": 564, + "contract": "contracts/bridge/SynapseERC20.sol:SynapseERC20", + "label": "_HASHED_VERSION", + "offset": 0, + "slot": "202", + "type": "t_bytes32" + }, + { + "astId": 713, + "contract": "contracts/bridge/SynapseERC20.sol:SynapseERC20", + "label": "__gap", + "offset": 0, + "slot": "203", + "type": "t_array(t_uint256)50_storage" + }, + { + "astId": 738, + "contract": "contracts/bridge/SynapseERC20.sol:SynapseERC20", + "label": "_nonces", + "offset": 0, + "slot": "253", + "type": "t_mapping(t_address,t_struct(Counter)2336_storage)" + }, + { + "astId": 740, + "contract": "contracts/bridge/SynapseERC20.sol:SynapseERC20", + "label": "_PERMIT_TYPEHASH", + "offset": 0, + "slot": "254", + "type": "t_bytes32" + }, + { + "astId": 887, + "contract": "contracts/bridge/SynapseERC20.sol:SynapseERC20", + "label": "__gap", + "offset": 0, + "slot": "255", + "type": "t_array(t_uint256)49_storage" + } + ], + "types": { + "t_address": { + "encoding": "inplace", + "label": "address", + "numberOfBytes": "20" + }, + "t_array(t_bytes32)dyn_storage": { + "base": "t_bytes32", + "encoding": "dynamic_array", + "label": "bytes32[]", + "numberOfBytes": "32" + }, + "t_array(t_uint256)44_storage": { + "base": "t_uint256", + "encoding": "inplace", + "label": "uint256[44]", + "numberOfBytes": "1408" + }, + "t_array(t_uint256)49_storage": { + "base": "t_uint256", + "encoding": "inplace", + "label": "uint256[49]", + "numberOfBytes": "1568" + }, + "t_array(t_uint256)50_storage": { + "base": "t_uint256", + "encoding": "inplace", + "label": "uint256[50]", + "numberOfBytes": "1600" + }, + "t_bool": { + "encoding": "inplace", + "label": "bool", + "numberOfBytes": "1" + }, + "t_bytes32": { + "encoding": "inplace", + "label": "bytes32", + "numberOfBytes": "32" + }, + "t_mapping(t_address,t_mapping(t_address,t_uint256))": { + "encoding": "mapping", + "key": "t_address", + "label": "mapping(address => mapping(address => uint256))", + "numberOfBytes": "32", + "value": "t_mapping(t_address,t_uint256)" + }, + "t_mapping(t_address,t_struct(Counter)2336_storage)": { + "encoding": "mapping", + "key": "t_address", + "label": "mapping(address => struct CountersUpgradeable.Counter)", + "numberOfBytes": "32", + "value": "t_struct(Counter)2336_storage" + }, + "t_mapping(t_address,t_uint256)": { + "encoding": "mapping", + "key": "t_address", + "label": "mapping(address => uint256)", + "numberOfBytes": "32", + "value": "t_uint256" + }, + "t_mapping(t_bytes32,t_struct(RoleData)39_storage)": { + "encoding": "mapping", + "key": "t_bytes32", + "label": "mapping(bytes32 => struct AccessControlUpgradeable.RoleData)", + "numberOfBytes": "32", + "value": "t_struct(RoleData)39_storage" + }, + "t_mapping(t_bytes32,t_uint256)": { + "encoding": "mapping", + "key": "t_bytes32", + "label": "mapping(bytes32 => uint256)", + "numberOfBytes": "32", + "value": "t_uint256" + }, + "t_string_storage": { + "encoding": "bytes", + "label": "string", + "numberOfBytes": "32" + }, + "t_struct(AddressSet)2652_storage": { + "encoding": "inplace", + "label": "struct EnumerableSetUpgradeable.AddressSet", + "members": [ + { + "astId": 2651, + "contract": "contracts/bridge/SynapseERC20.sol:SynapseERC20", + "label": "_inner", + "offset": 0, + "slot": "0", + "type": "t_struct(Set)2387_storage" + } + ], + "numberOfBytes": "64" + }, + "t_struct(Counter)2336_storage": { + "encoding": "inplace", + "label": "struct CountersUpgradeable.Counter", + "members": [ + { + "astId": 2335, + "contract": "contracts/bridge/SynapseERC20.sol:SynapseERC20", + "label": "_value", + "offset": 0, + "slot": "0", + "type": "t_uint256" + } + ], + "numberOfBytes": "32" + }, + "t_struct(RoleData)39_storage": { + "encoding": "inplace", + "label": "struct AccessControlUpgradeable.RoleData", + "members": [ + { + "astId": 36, + "contract": "contracts/bridge/SynapseERC20.sol:SynapseERC20", + "label": "members", + "offset": 0, + "slot": "0", + "type": "t_struct(AddressSet)2652_storage" + }, + { + "astId": 38, + "contract": "contracts/bridge/SynapseERC20.sol:SynapseERC20", + "label": "adminRole", + "offset": 0, + "slot": "2", + "type": "t_bytes32" + } + ], + "numberOfBytes": "96" + }, + "t_struct(Set)2387_storage": { + "encoding": "inplace", + "label": "struct EnumerableSetUpgradeable.Set", + "members": [ + { + "astId": 2382, + "contract": "contracts/bridge/SynapseERC20.sol:SynapseERC20", + "label": "_values", + "offset": 0, + "slot": "0", + "type": "t_array(t_bytes32)dyn_storage" + }, + { + "astId": 2386, + "contract": "contracts/bridge/SynapseERC20.sol:SynapseERC20", + "label": "_indexes", + "offset": 0, + "slot": "1", + "type": "t_mapping(t_bytes32,t_uint256)" + } + ], + "numberOfBytes": "64" + }, + "t_uint256": { + "encoding": "inplace", + "label": "uint256", + "numberOfBytes": "32" + }, + "t_uint8": { + "encoding": "inplace", + "label": "uint8", + "numberOfBytes": "1" + } + } + } +} \ No newline at end of file diff --git a/deployments/dfk/nUSD.json b/deployments/dfk/nUSD.json new file mode 100644 index 000000000..a7f69de1e --- /dev/null +++ b/deployments/dfk/nUSD.json @@ -0,0 +1,668 @@ +{ + "address": "0x52285D426120aB91F378b3dF4A15a036a62200aE", + "abi": [ + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "Approval", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "bytes32", + "name": "previousAdminRole", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "bytes32", + "name": "newAdminRole", + "type": "bytes32" + } + ], + "name": "RoleAdminChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "sender", + "type": "address" + } + ], + "name": "RoleGranted", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "sender", + "type": "address" + } + ], + "name": "RoleRevoked", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "Transfer", + "type": "event" + }, + { + "inputs": [], + "name": "DEFAULT_ADMIN_ROLE", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "DOMAIN_SEPARATOR", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "MINTER_ROLE", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "address", + "name": "spender", + "type": "address" + } + ], + "name": "allowance", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "approve", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "balanceOf", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "burn", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "burnFrom", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "decimals", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "subtractedValue", + "type": "uint256" + } + ], + "name": "decreaseAllowance", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + } + ], + "name": "getRoleAdmin", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "internalType": "uint256", + "name": "index", + "type": "uint256" + } + ], + "name": "getRoleMember", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + } + ], + "name": "getRoleMemberCount", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "grantRole", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "hasRole", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "addedValue", + "type": "uint256" + } + ], + "name": "increaseAllowance", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "name", + "type": "string" + }, + { + "internalType": "string", + "name": "symbol", + "type": "string" + }, + { + "internalType": "uint8", + "name": "decimals", + "type": "uint8" + }, + { + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "initialize", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "mint", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "name", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "nonces", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" + }, + { + "internalType": "uint8", + "name": "v", + "type": "uint8" + }, + { + "internalType": "bytes32", + "name": "r", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "s", + "type": "bytes32" + } + ], + "name": "permit", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "renounceRole", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "revokeRole", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "symbol", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "totalSupply", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "recipient", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "transfer", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "internalType": "address", + "name": "recipient", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "transferFrom", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + } + ] +} \ No newline at end of file diff --git a/deployments/dfk/solcInputs/1635d55d57a0a2552952c0d22586ed23.json b/deployments/dfk/solcInputs/1635d55d57a0a2552952c0d22586ed23.json new file mode 100644 index 000000000..20732985c --- /dev/null +++ b/deployments/dfk/solcInputs/1635d55d57a0a2552952c0d22586ed23.json @@ -0,0 +1,56 @@ +{ + "language": "Solidity", + "sources": { + "solc_0.7/openzeppelin/access/Ownable.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.7.0;\n\nimport \"../GSN/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 */\ncontract 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 (address initialOwner) {\n _owner = initialOwner;\n emit OwnershipTransferred(address(0), initialOwner);\n }\n\n /**\n * @dev Returns the address of the current owner.\n */\n function owner() public view 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" + }, + "solc_0.7/openzeppelin/GSN/Context.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.7.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" + }, + "solc_0.7/openzeppelin/proxy/ProxyAdmin.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.7.0;\n\nimport \"../access/Ownable.sol\";\nimport \"./TransparentUpgradeableProxy.sol\";\n\n/**\n * @dev This is an auxiliary contract meant to be assigned as the admin of a {TransparentUpgradeableProxy}. For an\n * explanation of why you would want to use this see the documentation for {TransparentUpgradeableProxy}.\n */\ncontract ProxyAdmin is Ownable {\n\n constructor(address owner) Ownable(owner) {}\n\n /**\n * @dev Returns the current implementation of `proxy`.\n *\n * Requirements:\n *\n * - This contract must be the admin of `proxy`.\n */\n function getProxyImplementation(TransparentUpgradeableProxy proxy) public view returns (address) {\n // We need to manually run the static call since the getter cannot be flagged as view\n // bytes4(keccak256(\"implementation()\")) == 0x5c60da1b\n (bool success, bytes memory returndata) = address(proxy).staticcall(hex\"5c60da1b\");\n require(success);\n return abi.decode(returndata, (address));\n }\n\n /**\n * @dev Returns the current admin of `proxy`.\n *\n * Requirements:\n *\n * - This contract must be the admin of `proxy`.\n */\n function getProxyAdmin(TransparentUpgradeableProxy proxy) public view returns (address) {\n // We need to manually run the static call since the getter cannot be flagged as view\n // bytes4(keccak256(\"admin()\")) == 0xf851a440\n (bool success, bytes memory returndata) = address(proxy).staticcall(hex\"f851a440\");\n require(success);\n return abi.decode(returndata, (address));\n }\n\n /**\n * @dev Changes the admin of `proxy` to `newAdmin`.\n *\n * Requirements:\n *\n * - This contract must be the current admin of `proxy`.\n */\n function changeProxyAdmin(TransparentUpgradeableProxy proxy, address newAdmin) public onlyOwner {\n proxy.changeAdmin(newAdmin);\n }\n\n /**\n * @dev Upgrades `proxy` to `implementation`. See {TransparentUpgradeableProxy-upgradeTo}.\n *\n * Requirements:\n *\n * - This contract must be the admin of `proxy`.\n */\n function upgrade(TransparentUpgradeableProxy proxy, address implementation) public onlyOwner {\n proxy.upgradeTo(implementation);\n }\n\n /**\n * @dev Upgrades `proxy` to `implementation` and calls a function on the new implementation. See\n * {TransparentUpgradeableProxy-upgradeToAndCall}.\n *\n * Requirements:\n *\n * - This contract must be the admin of `proxy`.\n */\n function upgradeAndCall(TransparentUpgradeableProxy proxy, address implementation, bytes memory data) public payable onlyOwner {\n proxy.upgradeToAndCall{value: msg.value}(implementation, data);\n }\n}\n" + }, + "solc_0.7/openzeppelin/proxy/TransparentUpgradeableProxy.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.7.0;\n\nimport \"./UpgradeableProxy.sol\";\n\n/**\n * @dev This contract implements a proxy that is upgradeable by an admin.\n * \n * To avoid https://medium.com/nomic-labs-blog/malicious-backdoors-in-ethereum-proxies-62629adf3357[proxy selector\n * clashing], which can potentially be used in an attack, this contract uses the\n * https://blog.openzeppelin.com/the-transparent-proxy-pattern/[transparent proxy pattern]. This pattern implies two\n * things that go hand in hand:\n * \n * 1. If any account other than the admin calls the proxy, the call will be forwarded to the implementation, even if\n * that call matches one of the admin functions exposed by the proxy itself.\n * 2. If the admin calls the proxy, it can access the admin functions, but its calls will never be forwarded to the\n * implementation. If the admin tries to call a function on the implementation it will fail with an error that says\n * \"admin cannot fallback to proxy target\".\n * \n * These properties mean that the admin account can only be used for admin actions like upgrading the proxy or changing\n * the admin, so it's best if it's a dedicated account that is not used for anything else. This will avoid headaches due\n * to sudden errors when trying to call a function from the proxy implementation.\n * \n * Our recommendation is for the dedicated account to be an instance of the {ProxyAdmin} contract. If set up this way,\n * you should think of the `ProxyAdmin` instance as the real administrative inerface of your proxy.\n */\ncontract TransparentUpgradeableProxy is UpgradeableProxy {\n /**\n * @dev Initializes an upgradeable proxy managed by `_admin`, backed by the implementation at `_logic`, and\n * optionally initialized with `_data` as explained in {UpgradeableProxy-constructor}.\n */\n constructor(address initialLogic, address initialAdmin, bytes memory _data) payable UpgradeableProxy(initialLogic, _data) {\n assert(_ADMIN_SLOT == bytes32(uint256(keccak256(\"eip1967.proxy.admin\")) - 1));\n _setAdmin(initialAdmin);\n }\n\n /**\n * @dev Emitted when the admin account has changed.\n */\n event AdminChanged(address previousAdmin, address newAdmin);\n\n /**\n * @dev Storage slot with the admin of the contract.\n * This is the keccak-256 hash of \"eip1967.proxy.admin\" subtracted by 1, and is\n * validated in the constructor.\n */\n bytes32 private constant _ADMIN_SLOT = 0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103;\n\n /**\n * @dev Modifier used internally that will delegate the call to the implementation unless the sender is the admin.\n */\n modifier ifAdmin() {\n if (msg.sender == _admin()) {\n _;\n } else {\n _fallback();\n }\n }\n\n /**\n * @dev Returns the current admin.\n * \n * NOTE: Only the admin can call this function. See {ProxyAdmin-getProxyAdmin}.\n * \n * TIP: To get this value clients can read directly from the storage slot shown below (specified by EIP1967) using the\n * https://eth.wiki/json-rpc/API#eth_getstorageat[`eth_getStorageAt`] RPC call.\n * `0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103`\n */\n function admin() external ifAdmin returns (address) {\n return _admin();\n }\n\n /**\n * @dev Returns the current implementation.\n * \n * NOTE: Only the admin can call this function. See {ProxyAdmin-getProxyImplementation}.\n * \n * TIP: To get this value clients can read directly from the storage slot shown below (specified by EIP1967) using the\n * https://eth.wiki/json-rpc/API#eth_getstorageat[`eth_getStorageAt`] RPC call.\n * `0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc`\n */\n function implementation() external ifAdmin returns (address) {\n return _implementation();\n }\n\n /**\n * @dev Changes the admin of the proxy.\n * \n * Emits an {AdminChanged} event.\n * \n * NOTE: Only the admin can call this function. See {ProxyAdmin-changeProxyAdmin}.\n */\n function changeAdmin(address newAdmin) external ifAdmin {\n require(newAdmin != address(0), \"TransparentUpgradeableProxy: new admin is the zero address\");\n emit AdminChanged(_admin(), newAdmin);\n _setAdmin(newAdmin);\n }\n\n /**\n * @dev Upgrade the implementation of the proxy.\n * \n * NOTE: Only the admin can call this function. See {ProxyAdmin-upgrade}.\n */\n function upgradeTo(address newImplementation) external ifAdmin {\n _upgradeTo(newImplementation);\n }\n\n /**\n * @dev Upgrade the implementation of the proxy, and then call a function from the new implementation as specified\n * by `data`, which should be an encoded function call. This is useful to initialize new storage variables in the\n * proxied contract.\n * \n * NOTE: Only the admin can call this function. See {ProxyAdmin-upgradeAndCall}.\n */\n function upgradeToAndCall(address newImplementation, bytes calldata data) external payable ifAdmin {\n _upgradeTo(newImplementation);\n // solhint-disable-next-line avoid-low-level-calls\n (bool success,) = newImplementation.delegatecall(data);\n require(success);\n }\n\n /**\n * @dev Returns the current admin.\n */\n function _admin() internal view returns (address adm) {\n bytes32 slot = _ADMIN_SLOT;\n // solhint-disable-next-line no-inline-assembly\n assembly {\n adm := sload(slot)\n }\n }\n\n /**\n * @dev Stores a new address in the EIP1967 admin slot.\n */\n function _setAdmin(address newAdmin) private {\n bytes32 slot = _ADMIN_SLOT;\n\n // solhint-disable-next-line no-inline-assembly\n assembly {\n sstore(slot, newAdmin)\n }\n }\n\n /**\n * @dev Makes sure the admin cannot access the fallback function. See {Proxy-_beforeFallback}.\n */\n function _beforeFallback() internal override virtual {\n require(msg.sender != _admin(), \"TransparentUpgradeableProxy: admin cannot fallback to proxy target\");\n super._beforeFallback();\n }\n}\n" + }, + "solc_0.7/openzeppelin/proxy/UpgradeableProxy.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.7.0;\n\nimport \"./Proxy.sol\";\nimport \"../utils/Address.sol\";\n\n/**\n * @dev This contract implements an upgradeable proxy. It is upgradeable because calls are delegated to an\n * implementation address that can be changed. This address is stored in storage in the location specified by\n * https://eips.ethereum.org/EIPS/eip-1967[EIP1967], so that it doesn't conflict with the storage layout of the\n * implementation behind the proxy.\n * \n * Upgradeability is only provided internally through {_upgradeTo}. For an externally upgradeable proxy see\n * {TransparentUpgradeableProxy}.\n */\ncontract UpgradeableProxy is Proxy {\n /**\n * @dev Initializes the upgradeable proxy with an initial implementation specified by `_logic`.\n * \n * If `_data` is nonempty, it's used as data in a delegate call to `_logic`. This will typically be an encoded\n * function call, and allows initializating the storage of the proxy like a Solidity constructor.\n */\n constructor(address _logic, bytes memory _data) payable {\n assert(_IMPLEMENTATION_SLOT == bytes32(uint256(keccak256(\"eip1967.proxy.implementation\")) - 1));\n _setImplementation(_logic);\n if(_data.length > 0) {\n // solhint-disable-next-line avoid-low-level-calls\n (bool success,) = _logic.delegatecall(_data);\n require(success);\n }\n }\n\n /**\n * @dev Emitted when the implementation is upgraded.\n */\n event Upgraded(address indexed implementation);\n\n /**\n * @dev Storage slot with the address of the current implementation.\n * This is the keccak-256 hash of \"eip1967.proxy.implementation\" subtracted by 1, and is\n * validated in the constructor.\n */\n bytes32 private constant _IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc;\n\n /**\n * @dev Returns the current implementation address.\n */\n function _implementation() internal override view returns (address impl) {\n bytes32 slot = _IMPLEMENTATION_SLOT;\n // solhint-disable-next-line no-inline-assembly\n assembly {\n impl := sload(slot)\n }\n }\n\n /**\n * @dev Upgrades the proxy to a new implementation.\n * \n * Emits an {Upgraded} event.\n */\n function _upgradeTo(address newImplementation) internal {\n _setImplementation(newImplementation);\n emit Upgraded(newImplementation);\n }\n\n /**\n * @dev Stores a new address in the EIP1967 implementation slot.\n */\n function _setImplementation(address newImplementation) private {\n require(Address.isContract(newImplementation), \"UpgradeableProxy: new implementation is not a contract\");\n\n bytes32 slot = _IMPLEMENTATION_SLOT;\n\n // solhint-disable-next-line no-inline-assembly\n assembly {\n sstore(slot, newImplementation)\n }\n }\n}\n" + }, + "solc_0.7/openzeppelin/proxy/Proxy.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.7.0;\n\n/**\n * @dev This abstract contract provides a fallback function that delegates all calls to another contract using the EVM\n * instruction `delegatecall`. We refer to the second contract as the _implementation_ behind the proxy, and it has to\n * be specified by overriding the virtual {_implementation} function.\n * \n * Additionally, delegation to the implementation can be triggered manually through the {_fallback} function, or to a\n * different contract through the {_delegate} function.\n * \n * The success and return data of the delegated call will be returned back to the caller of the proxy.\n */\nabstract contract Proxy {\n /**\n * @dev Delegates the current call to `implementation`.\n * \n * This function does not return to its internall call site, it will return directly to the external caller.\n */\n function _delegate(address implementation) internal {\n // solhint-disable-next-line no-inline-assembly\n assembly {\n // Copy msg.data. We take full control of memory in this inline assembly\n // block because it will not return to Solidity code. We overwrite the\n // Solidity scratch pad at memory position 0.\n calldatacopy(0, 0, calldatasize())\n\n // Call the implementation.\n // out and outsize are 0 because we don't know the size yet.\n let result := delegatecall(gas(), implementation, 0, calldatasize(), 0, 0)\n\n // Copy the returned data.\n returndatacopy(0, 0, returndatasize())\n\n switch result\n // delegatecall returns 0 on error.\n case 0 { revert(0, returndatasize()) }\n default { return(0, returndatasize()) }\n }\n }\n\n /**\n * @dev This is a virtual function that should be overriden so it returns the address to which the fallback function\n * and {_fallback} should delegate.\n */\n function _implementation() internal virtual view returns (address);\n\n /**\n * @dev Delegates the current call to the address returned by `_implementation()`.\n * \n * This function does not return to its internall call site, it will return directly to the external caller.\n */\n function _fallback() internal {\n _beforeFallback();\n _delegate(_implementation());\n }\n\n /**\n * @dev Fallback function that delegates calls to the address returned by `_implementation()`. Will run if no other\n * function in the contract matches the call data.\n */\n fallback () payable external {\n _fallback();\n }\n\n /**\n * @dev Fallback function that delegates calls to the address returned by `_implementation()`. Will run if call data\n * is empty.\n */\n receive () payable external {\n _fallback();\n }\n\n /**\n * @dev Hook that is called before falling back to the implementation. Can happen as part of a manual `_fallback`\n * call, or as part of the Solidity `fallback` or `receive` functions.\n * \n * If overriden should call `super._beforeFallback()`.\n */\n function _beforeFallback() internal virtual {\n }\n}\n" + }, + "solc_0.7/openzeppelin/utils/Address.sol": { + "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 // According to EIP-1052, 0x0 is the value returned for not-yet created accounts\n // and 0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470 is returned\n // for accounts without code, i.e. `keccak256('')`\n bytes32 codehash;\n bytes32 accountHash = 0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470;\n // solhint-disable-next-line no-inline-assembly\n assembly { codehash := extcodehash(account) }\n return (codehash != accountHash && codehash != 0x0);\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 return _functionCallWithValue(target, data, value, errorMessage);\n }\n\n function _functionCallWithValue(address target, bytes memory data, uint256 weiValue, string memory errorMessage) private returns (bytes memory) {\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: weiValue }(data);\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" + }, + "solc_0.7/proxy/OptimizedTransparentUpgradeableProxy.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.7.0;\n\nimport \"../openzeppelin/proxy/UpgradeableProxy.sol\";\n\n/**\n * @dev This contract implements a proxy that is upgradeable by an admin.\n *\n * To avoid https://medium.com/nomic-labs-blog/malicious-backdoors-in-ethereum-proxies-62629adf3357[proxy selector\n * clashing], which can potentially be used in an attack, this contract uses the\n * https://blog.openzeppelin.com/the-transparent-proxy-pattern/[transparent proxy pattern]. This pattern implies two\n * things that go hand in hand:\n *\n * 1. If any account other than the admin calls the proxy, the call will be forwarded to the implementation, even if\n * that call matches one of the admin functions exposed by the proxy itself.\n * 2. If the admin calls the proxy, it can access the admin functions, but its calls will never be forwarded to the\n * implementation. If the admin tries to call a function on the implementation it will fail with an error that says\n * \"admin cannot fallback to proxy target\".\n *\n * These properties mean that the admin account can only be used for admin actions like upgrading the proxy or changing\n * the admin, so it's best if it's a dedicated account that is not used for anything else. This will avoid headaches due\n * to sudden errors when trying to call a function from the proxy implementation.\n *\n * Our recommendation is for the dedicated account to be an instance of the {ProxyAdmin} contract. If set up this way,\n * you should think of the `ProxyAdmin` instance as the real administrative inerface of your proxy.\n */\ncontract OptimizedTransparentUpgradeableProxy is UpgradeableProxy {\n address internal immutable _ADMIN;\n\n /**\n * @dev Initializes an upgradeable proxy managed by `_admin`, backed by the implementation at `_logic`, and\n * optionally initialized with `_data` as explained in {UpgradeableProxy-constructor}.\n */\n constructor(\n address initialLogic,\n address initialAdmin,\n bytes memory _data\n ) payable UpgradeableProxy(initialLogic, _data) {\n assert(_ADMIN_SLOT == bytes32(uint256(keccak256(\"eip1967.proxy.admin\")) - 1));\n bytes32 slot = _ADMIN_SLOT;\n\n _ADMIN = initialAdmin;\n\n // still store it to work with EIP-1967\n // solhint-disable-next-line no-inline-assembly\n assembly {\n sstore(slot, initialAdmin)\n }\n }\n\n /**\n * @dev Storage slot with the admin of the contract.\n * This is the keccak-256 hash of \"eip1967.proxy.admin\" subtracted by 1, and is\n * validated in the constructor.\n */\n bytes32 private constant _ADMIN_SLOT = 0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103;\n\n /**\n * @dev Modifier used internally that will delegate the call to the implementation unless the sender is the admin.\n */\n modifier ifAdmin() {\n if (msg.sender == _admin()) {\n _;\n } else {\n _fallback();\n }\n }\n\n /**\n * @dev Returns the current admin.\n *\n * NOTE: Only the admin can call this function. See {ProxyAdmin-getProxyAdmin}.\n *\n * TIP: To get this value clients can read directly from the storage slot shown below (specified by EIP1967) using the\n * https://eth.wiki/json-rpc/API#eth_getstorageat[`eth_getStorageAt`] RPC call.\n * `0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103`\n */\n function admin() external ifAdmin returns (address) {\n return _admin();\n }\n\n /**\n * @dev Returns the current implementation.\n *\n * NOTE: Only the admin can call this function. See {ProxyAdmin-getProxyImplementation}.\n *\n * TIP: To get this value clients can read directly from the storage slot shown below (specified by EIP1967) using the\n * https://eth.wiki/json-rpc/API#eth_getstorageat[`eth_getStorageAt`] RPC call.\n * `0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc`\n */\n function implementation() external ifAdmin returns (address) {\n return _implementation();\n }\n\n /**\n * @dev Upgrade the implementation of the proxy.\n *\n * NOTE: Only the admin can call this function. See {ProxyAdmin-upgrade}.\n */\n function upgradeTo(address newImplementation) external ifAdmin {\n _upgradeTo(newImplementation);\n }\n\n /**\n * @dev Upgrade the implementation of the proxy, and then call a function from the new implementation as specified\n * by `data`, which should be an encoded function call. This is useful to initialize new storage variables in the\n * proxied contract.\n *\n * NOTE: Only the admin can call this function. See {ProxyAdmin-upgradeAndCall}.\n */\n function upgradeToAndCall(address newImplementation, bytes calldata data) external payable ifAdmin {\n _upgradeTo(newImplementation);\n // solhint-disable-next-line avoid-low-level-calls\n (bool success, ) = newImplementation.delegatecall(data);\n require(success);\n }\n\n /**\n * @dev Returns the current admin.\n */\n function _admin() internal view returns (address adm) {\n return _ADMIN;\n }\n\n /**\n * @dev Makes sure the admin cannot access the fallback function. See {Proxy-_beforeFallback}.\n */\n function _beforeFallback() internal virtual override {\n require(msg.sender != _admin(), \"TransparentUpgradeableProxy: admin cannot fallback to proxy target\");\n super._beforeFallback();\n }\n}\n" + } + }, + "settings": { + "optimizer": { + "enabled": true, + "runs": 999999 + }, + "outputSelection": { + "*": { + "*": [ + "abi", + "evm.bytecode", + "evm.deployedBytecode", + "evm.methodIdentifiers", + "metadata", + "devdoc", + "userdoc", + "storageLayout", + "evm.gasEstimates" + ], + "": [ + "ast" + ] + } + }, + "metadata": { + "useLiteralContent": true + } + } +} \ No newline at end of file diff --git a/deployments/dfk/solcInputs/4081879ecbcad532ab272d265ceb1761.json b/deployments/dfk/solcInputs/4081879ecbcad532ab272d265ceb1761.json new file mode 100644 index 000000000..7442c38b4 --- /dev/null +++ b/deployments/dfk/solcInputs/4081879ecbcad532ab272d265ceb1761.json @@ -0,0 +1,56 @@ +{ + "language": "Solidity", + "sources": { + "contracts/bridge/utils/TimelockController.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.0;\n\nimport '@openzeppelin/contracts-4.3.1/access/AccessControl.sol';\nimport '@openzeppelin/contracts-4.3.1/utils/math/SafeMath.sol';\n\n/**\n * @dev Contract module which acts as a timelocked controller. When set as the\n * owner of an `Ownable` smart contract, it enforces a timelock on all\n * `onlyOwner` maintenance operations. This gives time for users of the\n * controlled contract to exit before a potentially dangerous maintenance\n * operation is applied.\n *\n * By default, this contract is self administered, meaning administration tasks\n * have to go through the timelock process. The proposer (resp executor) role\n * is in charge of proposing (resp executing) operations. A common use case is\n * to position this {TimelockController} as the owner of a smart contract, with\n * a multisig or a DAO as the sole proposer.\n *\n * _Available since v3.3._\n */\ncontract TimelockController is AccessControl {\n bytes32 public constant TIMELOCK_ADMIN_ROLE = keccak256(\"TIMELOCK_ADMIN_ROLE\");\n bytes32 public constant PROPOSER_ROLE = keccak256(\"PROPOSER_ROLE\");\n bytes32 public constant EXECUTOR_ROLE = keccak256(\"EXECUTOR_ROLE\");\n uint256 internal constant _DONE_TIMESTAMP = uint256(1);\n\n mapping(bytes32 => uint256) private _timestamps;\n uint256 private _minDelay;\n\n /**\n * @dev Emitted when a call is scheduled as part of operation `id`.\n */\n event CallScheduled(\n bytes32 indexed id,\n uint256 indexed index,\n address target,\n uint256 value,\n bytes data,\n bytes32 predecessor,\n uint256 delay\n );\n\n /**\n * @dev Emitted when a call is performed as part of operation `id`.\n */\n event CallExecuted(bytes32 indexed id, uint256 indexed index, address target, uint256 value, bytes data);\n\n /**\n * @dev Emitted when operation `id` is cancelled.\n */\n event Cancelled(bytes32 indexed id);\n\n /**\n * @dev Emitted when the minimum delay for future operations is modified.\n */\n event MinDelayChange(uint256 oldDuration, uint256 newDuration);\n\n /**\n * @dev Initializes the contract with a given `minDelay`.\n */\n constructor(\n uint256 minDelay,\n address[] memory proposers,\n address[] memory executors\n ) {\n _setRoleAdmin(TIMELOCK_ADMIN_ROLE, TIMELOCK_ADMIN_ROLE);\n _setRoleAdmin(PROPOSER_ROLE, TIMELOCK_ADMIN_ROLE);\n _setRoleAdmin(EXECUTOR_ROLE, TIMELOCK_ADMIN_ROLE);\n\n // deployer + self administration\n _setupRole(TIMELOCK_ADMIN_ROLE, _msgSender());\n _setupRole(TIMELOCK_ADMIN_ROLE, address(this));\n\n // register proposers\n for (uint256 i = 0; i < proposers.length; ++i) {\n _setupRole(PROPOSER_ROLE, proposers[i]);\n }\n\n // register executors\n for (uint256 i = 0; i < executors.length; ++i) {\n _setupRole(EXECUTOR_ROLE, executors[i]);\n }\n\n _minDelay = minDelay;\n emit MinDelayChange(0, minDelay);\n }\n\n /**\n * @dev Modifier to make a function callable only by a certain role. In\n * addition to checking the sender's role, `address(0)` 's role is also\n * considered. Granting a role to `address(0)` is equivalent to enabling\n * this role for everyone.\n */\n modifier onlyRoleOrOpenRole(bytes32 role) {\n if (!hasRole(role, address(0))) {\n _checkRole(role, _msgSender());\n }\n _;\n }\n\n /**\n * @dev Contract might receive/hold ETH as part of the maintenance process.\n */\n receive() external payable {}\n\n /**\n * @dev Returns whether an id correspond to a registered operation. This\n * includes both Pending, Ready and Done operations.\n */\n function isOperation(bytes32 id) public view virtual returns (bool pending) {\n return getTimestamp(id) > 0;\n }\n\n /**\n * @dev Returns whether an operation is pending or not.\n */\n function isOperationPending(bytes32 id) public view virtual returns (bool pending) {\n return getTimestamp(id) > _DONE_TIMESTAMP;\n }\n\n /**\n * @dev Returns whether an operation is ready or not.\n */\n function isOperationReady(bytes32 id) public view virtual returns (bool ready) {\n uint256 timestamp = getTimestamp(id);\n return timestamp > _DONE_TIMESTAMP && timestamp <= block.timestamp;\n }\n\n /**\n * @dev Returns whether an operation is done or not.\n */\n function isOperationDone(bytes32 id) public view virtual returns (bool done) {\n return getTimestamp(id) == _DONE_TIMESTAMP;\n }\n\n /**\n * @dev Returns the timestamp at with an operation becomes ready (0 for\n * unset operations, 1 for done operations).\n */\n function getTimestamp(bytes32 id) public view virtual returns (uint256 timestamp) {\n return _timestamps[id];\n }\n\n /**\n * @dev Returns the minimum delay for an operation to become valid.\n *\n * This value can be changed by executing an operation that calls `updateDelay`.\n */\n function getMinDelay() public view virtual returns (uint256 duration) {\n return _minDelay;\n }\n\n /**\n * @dev Returns the identifier of an operation containing a single\n * transaction.\n */\n function hashOperation(\n address target,\n uint256 value,\n bytes calldata data,\n bytes32 predecessor,\n bytes32 salt\n ) public pure virtual returns (bytes32 hash) {\n return keccak256(abi.encode(target, value, data, predecessor, salt));\n }\n\n /**\n * @dev Returns the identifier of an operation containing a batch of\n * transactions.\n */\n function hashOperationBatch(\n address[] calldata targets,\n uint256[] calldata values,\n bytes[] calldata datas,\n bytes32 predecessor,\n bytes32 salt\n ) public pure virtual returns (bytes32 hash) {\n return keccak256(abi.encode(targets, values, datas, predecessor, salt));\n }\n\n /**\n * @dev Schedule an operation containing a single transaction.\n *\n * Emits a {CallScheduled} event.\n *\n * Requirements:\n *\n * - the caller must have the 'proposer' role.\n */\n function schedule(\n address target,\n uint256 value,\n bytes calldata data,\n bytes32 predecessor,\n bytes32 salt,\n uint256 delay\n ) public virtual onlyRole(PROPOSER_ROLE) {\n bytes32 id = hashOperation(target, value, data, predecessor, salt);\n _schedule(id, delay);\n emit CallScheduled(id, 0, target, value, data, predecessor, delay);\n }\n\n /**\n * @dev Schedule an operation containing a batch of transactions.\n *\n * Emits one {CallScheduled} event per transaction in the batch.\n *\n * Requirements:\n *\n * - the caller must have the 'proposer' role.\n */\n function scheduleBatch(\n address[] calldata targets,\n uint256[] calldata values,\n bytes[] calldata datas,\n bytes32 predecessor,\n bytes32 salt,\n uint256 delay\n ) public virtual onlyRole(PROPOSER_ROLE) {\n require(targets.length == values.length, \"TimelockController: length mismatch\");\n require(targets.length == datas.length, \"TimelockController: length mismatch\");\n\n bytes32 id = hashOperationBatch(targets, values, datas, predecessor, salt);\n _schedule(id, delay);\n for (uint256 i = 0; i < targets.length; ++i) {\n emit CallScheduled(id, i, targets[i], values[i], datas[i], predecessor, delay);\n }\n }\n\n /**\n * @dev Schedule an operation that is to becomes valid after a given delay.\n */\n function _schedule(bytes32 id, uint256 delay) private {\n require(!isOperation(id), \"TimelockController: operation already scheduled\");\n require(delay >= getMinDelay(), \"TimelockController: insufficient delay\");\n _timestamps[id] = block.timestamp + delay;\n }\n\n /**\n * @dev Cancel an operation.\n *\n * Requirements:\n *\n * - the caller must have the 'proposer' role.\n */\n function cancel(bytes32 id) public virtual onlyRole(PROPOSER_ROLE) {\n require(isOperationPending(id), \"TimelockController: operation cannot be cancelled\");\n delete _timestamps[id];\n\n emit Cancelled(id);\n }\n\n /**\n * @dev Execute an (ready) operation containing a single transaction.\n *\n * Emits a {CallExecuted} event.\n *\n * Requirements:\n *\n * - the caller must have the 'executor' role.\n */\n function execute(\n address target,\n uint256 value,\n bytes calldata data,\n bytes32 predecessor,\n bytes32 salt\n ) public payable virtual onlyRoleOrOpenRole(EXECUTOR_ROLE) {\n bytes32 id = hashOperation(target, value, data, predecessor, salt);\n _beforeCall(id, predecessor);\n _call(id, 0, target, value, data);\n _afterCall(id);\n }\n\n /**\n * @dev Execute an (ready) operation containing a batch of transactions.\n *\n * Emits one {CallExecuted} event per transaction in the batch.\n *\n * Requirements:\n *\n * - the caller must have the 'executor' role.\n */\n function executeBatch(\n address[] calldata targets,\n uint256[] calldata values,\n bytes[] calldata datas,\n bytes32 predecessor,\n bytes32 salt\n ) public payable virtual onlyRoleOrOpenRole(EXECUTOR_ROLE) {\n require(targets.length == values.length, \"TimelockController: length mismatch\");\n require(targets.length == datas.length, \"TimelockController: length mismatch\");\n\n bytes32 id = hashOperationBatch(targets, values, datas, predecessor, salt);\n _beforeCall(id, predecessor);\n for (uint256 i = 0; i < targets.length; ++i) {\n _call(id, i, targets[i], values[i], datas[i]);\n }\n _afterCall(id);\n }\n\n /**\n * @dev Checks before execution of an operation's calls.\n */\n function _beforeCall(bytes32 id, bytes32 predecessor) private view {\n require(isOperationReady(id), \"TimelockController: operation is not ready\");\n require(predecessor == bytes32(0) || isOperationDone(predecessor), \"TimelockController: missing dependency\");\n }\n\n /**\n * @dev Checks after execution of an operation's calls.\n */\n function _afterCall(bytes32 id) private {\n require(isOperationReady(id), \"TimelockController: operation is not ready\");\n _timestamps[id] = _DONE_TIMESTAMP;\n }\n\n /**\n * @dev Execute an operation's call.\n *\n * Emits a {CallExecuted} event.\n */\n function _call(\n bytes32 id,\n uint256 index,\n address target,\n uint256 value,\n bytes calldata data\n ) private {\n (bool success, ) = target.call{value: value}(data);\n require(success, \"TimelockController: underlying transaction reverted\");\n\n emit CallExecuted(id, index, target, value, data);\n }\n\n /**\n * @dev Changes the minimum timelock duration for future operations.\n *\n * Emits a {MinDelayChange} event.\n *\n * Requirements:\n *\n * - the caller must be the timelock itself. This can only be achieved by scheduling and later executing\n * an operation where the timelock is the target and the data is the ABI-encoded call to this function.\n */\n function updateDelay(uint256 newDelay) external virtual {\n require(msg.sender == address(this), \"TimelockController: caller must be timelock\");\n emit MinDelayChange(_minDelay, newDelay);\n _minDelay = newDelay;\n }\n}" + }, + "@openzeppelin/contracts-4.3.1/access/AccessControl.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (access/AccessControl.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./IAccessControl.sol\";\nimport \"../utils/Context.sol\";\nimport \"../utils/Strings.sol\";\nimport \"../utils/introspection/ERC165.sol\";\n\n/**\n * @dev Contract module that allows children to implement role-based access\n * control mechanisms. This is a lightweight version that doesn't allow enumerating role\n * members except through off-chain means by accessing the contract event logs. Some\n * applications may benefit from on-chain enumerability, for those cases see\n * {AccessControlEnumerable}.\n *\n * Roles are referred to by their `bytes32` identifier. These should be exposed\n * in the external API and be unique. The best way to achieve this is by\n * using `public constant` hash digests:\n *\n * ```\n * bytes32 public constant MY_ROLE = keccak256(\"MY_ROLE\");\n * ```\n *\n * Roles can be used to represent a set of permissions. To restrict access to a\n * function call, use {hasRole}:\n *\n * ```\n * function foo() public {\n * require(hasRole(MY_ROLE, msg.sender));\n * ...\n * }\n * ```\n *\n * Roles can be granted and revoked dynamically via the {grantRole} and\n * {revokeRole} functions. Each role has an associated admin role, and only\n * accounts that have a role's admin role can call {grantRole} and {revokeRole}.\n *\n * By default, the admin role for all roles is `DEFAULT_ADMIN_ROLE`, which means\n * that only accounts with this role will be able to grant or revoke other\n * roles. More complex role relationships can be created by using\n * {_setRoleAdmin}.\n *\n * WARNING: The `DEFAULT_ADMIN_ROLE` is also its own admin: it has permission to\n * grant and revoke this role. Extra precautions should be taken to secure\n * accounts that have been granted it.\n */\nabstract contract AccessControl is Context, IAccessControl, ERC165 {\n struct RoleData {\n mapping(address => bool) members;\n bytes32 adminRole;\n }\n\n mapping(bytes32 => RoleData) private _roles;\n\n bytes32 public constant DEFAULT_ADMIN_ROLE = 0x00;\n\n /**\n * @dev Modifier that checks that an account has a specific role. Reverts\n * with a standardized message including the required role.\n *\n * The format of the revert reason is given by the following regular expression:\n *\n * /^AccessControl: account (0x[0-9a-f]{40}) is missing role (0x[0-9a-f]{64})$/\n *\n * _Available since v4.1._\n */\n modifier onlyRole(bytes32 role) {\n _checkRole(role, _msgSender());\n _;\n }\n\n /**\n * @dev See {IERC165-supportsInterface}.\n */\n function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n return interfaceId == type(IAccessControl).interfaceId || super.supportsInterface(interfaceId);\n }\n\n /**\n * @dev Returns `true` if `account` has been granted `role`.\n */\n function hasRole(bytes32 role, address account) public view override returns (bool) {\n return _roles[role].members[account];\n }\n\n /**\n * @dev Revert with a standard message if `account` is missing `role`.\n *\n * The format of the revert reason is given by the following regular expression:\n *\n * /^AccessControl: account (0x[0-9a-f]{40}) is missing role (0x[0-9a-f]{64})$/\n */\n function _checkRole(bytes32 role, address account) internal view {\n if (!hasRole(role, account)) {\n revert(\n string(\n abi.encodePacked(\n \"AccessControl: account \",\n Strings.toHexString(uint160(account), 20),\n \" is missing role \",\n Strings.toHexString(uint256(role), 32)\n )\n )\n );\n }\n }\n\n /**\n * @dev Returns the admin role that controls `role`. See {grantRole} and\n * {revokeRole}.\n *\n * To change a role's admin, use {_setRoleAdmin}.\n */\n function getRoleAdmin(bytes32 role) public view override returns (bytes32) {\n return _roles[role].adminRole;\n }\n\n /**\n * @dev Grants `role` to `account`.\n *\n * If `account` had not been already granted `role`, emits a {RoleGranted}\n * event.\n *\n * Requirements:\n *\n * - the caller must have ``role``'s admin role.\n */\n function grantRole(bytes32 role, address account) public virtual override onlyRole(getRoleAdmin(role)) {\n _grantRole(role, account);\n }\n\n /**\n * @dev Revokes `role` from `account`.\n *\n * If `account` had been granted `role`, emits a {RoleRevoked} event.\n *\n * Requirements:\n *\n * - the caller must have ``role``'s admin role.\n */\n function revokeRole(bytes32 role, address account) public virtual override onlyRole(getRoleAdmin(role)) {\n _revokeRole(role, account);\n }\n\n /**\n * @dev Revokes `role` from the calling account.\n *\n * Roles are often managed via {grantRole} and {revokeRole}: this function's\n * purpose is to provide a mechanism for accounts to lose their privileges\n * if they are compromised (such as when a trusted device is misplaced).\n *\n * If the calling account had been revoked `role`, emits a {RoleRevoked}\n * event.\n *\n * Requirements:\n *\n * - the caller must be `account`.\n */\n function renounceRole(bytes32 role, address account) public virtual override {\n require(account == _msgSender(), \"AccessControl: can only renounce roles for self\");\n\n _revokeRole(role, account);\n }\n\n /**\n * @dev Grants `role` to `account`.\n *\n * If `account` had not been already granted `role`, emits a {RoleGranted}\n * event. Note that unlike {grantRole}, this function doesn't perform any\n * checks on the calling account.\n *\n * [WARNING]\n * ====\n * This function should only be called from the constructor when setting\n * up the initial roles for the system.\n *\n * Using this function in any other way is effectively circumventing the admin\n * system imposed by {AccessControl}.\n * ====\n *\n * NOTE: This function is deprecated in favor of {_grantRole}.\n */\n function _setupRole(bytes32 role, address account) internal virtual {\n _grantRole(role, account);\n }\n\n /**\n * @dev Sets `adminRole` as ``role``'s admin role.\n *\n * Emits a {RoleAdminChanged} event.\n */\n function _setRoleAdmin(bytes32 role, bytes32 adminRole) internal virtual {\n bytes32 previousAdminRole = getRoleAdmin(role);\n _roles[role].adminRole = adminRole;\n emit RoleAdminChanged(role, previousAdminRole, adminRole);\n }\n\n /**\n * @dev Grants `role` to `account`.\n *\n * Internal function without access restriction.\n */\n function _grantRole(bytes32 role, address account) internal virtual {\n if (!hasRole(role, account)) {\n _roles[role].members[account] = true;\n emit RoleGranted(role, account, _msgSender());\n }\n }\n\n /**\n * @dev Revokes `role` from `account`.\n *\n * Internal function without access restriction.\n */\n function _revokeRole(bytes32 role, address account) internal virtual {\n if (hasRole(role, account)) {\n _roles[role].members[account] = false;\n emit RoleRevoked(role, account, _msgSender());\n }\n }\n}\n" + }, + "@openzeppelin/contracts-4.3.1/utils/math/SafeMath.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/math/SafeMath.sol)\n\npragma solidity ^0.8.0;\n\n// CAUTION\n// This version of SafeMath should only be used with Solidity 0.8 or later,\n// because it relies on the compiler's built in overflow checks.\n\n/**\n * @dev Wrappers over Solidity's arithmetic operations.\n *\n * NOTE: `SafeMath` is generally not needed starting with Solidity 0.8, since the compiler\n * now has built in overflow checking.\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 unchecked {\n uint256 c = a + b;\n if (c < a) return (false, 0);\n return (true, c);\n }\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 unchecked {\n if (b > a) return (false, 0);\n return (true, a - b);\n }\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 unchecked {\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 /**\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 unchecked {\n if (b == 0) return (false, 0);\n return (true, a / b);\n }\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 unchecked {\n if (b == 0) return (false, 0);\n return (true, a % b);\n }\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 return a + b;\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 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 return a * b;\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.\n *\n * Requirements:\n *\n * - The divisor cannot be zero.\n */\n function div(uint256 a, uint256 b) internal pure returns (uint256) {\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 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(\n uint256 a,\n uint256 b,\n string memory errorMessage\n ) internal pure returns (uint256) {\n unchecked {\n require(b <= a, errorMessage);\n return a - b;\n }\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 * 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(\n uint256 a,\n uint256 b,\n string memory errorMessage\n ) internal pure returns (uint256) {\n unchecked {\n require(b > 0, errorMessage);\n return a / b;\n }\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(\n uint256 a,\n uint256 b,\n string memory errorMessage\n ) internal pure returns (uint256) {\n unchecked {\n require(b > 0, errorMessage);\n return a % b;\n }\n }\n}\n" + }, + "@openzeppelin/contracts-4.3.1/access/IAccessControl.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (access/IAccessControl.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev External interface of AccessControl declared to support ERC165 detection.\n */\ninterface IAccessControl {\n /**\n * @dev Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole`\n *\n * `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite\n * {RoleAdminChanged} not being emitted signaling this.\n *\n * _Available since v3.1._\n */\n event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole);\n\n /**\n * @dev Emitted when `account` is granted `role`.\n *\n * `sender` is the account that originated the contract call, an admin role\n * bearer except when using {AccessControl-_setupRole}.\n */\n event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender);\n\n /**\n * @dev Emitted when `account` is revoked `role`.\n *\n * `sender` is the account that originated the contract call:\n * - if using `revokeRole`, it is the admin role bearer\n * - if using `renounceRole`, it is the role bearer (i.e. `account`)\n */\n event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender);\n\n /**\n * @dev Returns `true` if `account` has been granted `role`.\n */\n function hasRole(bytes32 role, address account) external view returns (bool);\n\n /**\n * @dev Returns the admin role that controls `role`. See {grantRole} and\n * {revokeRole}.\n *\n * To change a role's admin, use {AccessControl-_setRoleAdmin}.\n */\n function getRoleAdmin(bytes32 role) external view returns (bytes32);\n\n /**\n * @dev Grants `role` to `account`.\n *\n * If `account` had not been already granted `role`, emits a {RoleGranted}\n * event.\n *\n * Requirements:\n *\n * - the caller must have ``role``'s admin role.\n */\n function grantRole(bytes32 role, address account) external;\n\n /**\n * @dev Revokes `role` from `account`.\n *\n * If `account` had been granted `role`, emits a {RoleRevoked} event.\n *\n * Requirements:\n *\n * - the caller must have ``role``'s admin role.\n */\n function revokeRole(bytes32 role, address account) external;\n\n /**\n * @dev Revokes `role` from the calling account.\n *\n * Roles are often managed via {grantRole} and {revokeRole}: this function's\n * purpose is to provide a mechanism for accounts to lose their privileges\n * if they are compromised (such as when a trusted device is misplaced).\n *\n * If the calling account had been granted `role`, emits a {RoleRevoked}\n * event.\n *\n * Requirements:\n *\n * - the caller must be `account`.\n */\n function renounceRole(bytes32 role, address account) external;\n}\n" + }, + "@openzeppelin/contracts-4.3.1/utils/Context.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)\n\npragma solidity ^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 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) {\n return msg.sender;\n }\n\n function _msgData() internal view virtual returns (bytes calldata) {\n return msg.data;\n }\n}\n" + }, + "@openzeppelin/contracts-4.3.1/utils/Strings.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/Strings.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev String operations.\n */\nlibrary Strings {\n bytes16 private constant _HEX_SYMBOLS = \"0123456789abcdef\";\n\n /**\n * @dev Converts a `uint256` to its ASCII `string` decimal representation.\n */\n function toString(uint256 value) internal pure returns (string memory) {\n // Inspired by OraclizeAPI's implementation - MIT licence\n // https://github.com/oraclize/ethereum-api/blob/b42146b063c7d6ee1358846c198246239e9360e8/oraclizeAPI_0.4.25.sol\n\n if (value == 0) {\n return \"0\";\n }\n uint256 temp = value;\n uint256 digits;\n while (temp != 0) {\n digits++;\n temp /= 10;\n }\n bytes memory buffer = new bytes(digits);\n while (value != 0) {\n digits -= 1;\n buffer[digits] = bytes1(uint8(48 + uint256(value % 10)));\n value /= 10;\n }\n return string(buffer);\n }\n\n /**\n * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation.\n */\n function toHexString(uint256 value) internal pure returns (string memory) {\n if (value == 0) {\n return \"0x00\";\n }\n uint256 temp = value;\n uint256 length = 0;\n while (temp != 0) {\n length++;\n temp >>= 8;\n }\n return toHexString(value, length);\n }\n\n /**\n * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length.\n */\n function toHexString(uint256 value, uint256 length) internal pure returns (string memory) {\n bytes memory buffer = new bytes(2 * length + 2);\n buffer[0] = \"0\";\n buffer[1] = \"x\";\n for (uint256 i = 2 * length + 1; i > 1; --i) {\n buffer[i] = _HEX_SYMBOLS[value & 0xf];\n value >>= 4;\n }\n require(value == 0, \"Strings: hex length insufficient\");\n return string(buffer);\n }\n}\n" + }, + "@openzeppelin/contracts-4.3.1/utils/introspection/ERC165.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/introspection/ERC165.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./IERC165.sol\";\n\n/**\n * @dev Implementation of the {IERC165} interface.\n *\n * Contracts that want to implement ERC165 should inherit from this contract and override {supportsInterface} to check\n * for the additional interface id that will be supported. For example:\n *\n * ```solidity\n * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n * return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);\n * }\n * ```\n *\n * Alternatively, {ERC165Storage} provides an easier to use but more expensive implementation.\n */\nabstract contract ERC165 is IERC165 {\n /**\n * @dev See {IERC165-supportsInterface}.\n */\n function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n return interfaceId == type(IERC165).interfaceId;\n }\n}\n" + }, + "@openzeppelin/contracts-4.3.1/utils/introspection/IERC165.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Interface of the ERC165 standard, as defined in the\n * https://eips.ethereum.org/EIPS/eip-165[EIP].\n *\n * Implementers can declare support of contract interfaces, which can then be\n * queried by others ({ERC165Checker}).\n *\n * For an implementation, see {ERC165}.\n */\ninterface IERC165 {\n /**\n * @dev Returns true if this contract implements the interface defined by\n * `interfaceId`. See the corresponding\n * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]\n * to learn more about how these ids are created.\n *\n * This function call must use less than 30 000 gas.\n */\n function supportsInterface(bytes4 interfaceId) external view returns (bool);\n}\n" + } + }, + "settings": { + "optimizer": { + "enabled": true, + "runs": 5000000 + }, + "outputSelection": { + "*": { + "*": [ + "abi", + "evm.bytecode", + "evm.deployedBytecode", + "evm.methodIdentifiers", + "metadata", + "devdoc", + "userdoc", + "storageLayout", + "evm.gasEstimates" + ], + "": [ + "ast" + ] + } + }, + "metadata": { + "useLiteralContent": true + } + } +} \ No newline at end of file diff --git a/deployments/dfk/solcInputs/67709d0e6d2903fa456800932c6c2db8.json b/deployments/dfk/solcInputs/67709d0e6d2903fa456800932c6c2db8.json new file mode 100644 index 000000000..ea82cf499 --- /dev/null +++ b/deployments/dfk/solcInputs/67709d0e6d2903fa456800932c6c2db8.json @@ -0,0 +1,35 @@ +{ + "language": "Solidity", + "sources": { + "contracts/amm/helper/Multicall2.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.5.0;\npragma experimental ABIEncoderV2;\n\n/// @title Multicall2 - Aggregate results from multiple read-only function calls\n/// @author Michael Elliot \n/// @author Joshua Levine \n/// @author Nick Johnson \n\ncontract Multicall2 {\n struct Call {\n address target;\n bytes callData;\n }\n struct Result {\n bool success;\n bytes returnData;\n }\n\n function aggregate(Call[] memory calls)\n public\n returns (uint256 blockNumber, bytes[] memory returnData)\n {\n blockNumber = block.number;\n returnData = new bytes[](calls.length);\n for (uint256 i = 0; i < calls.length; i++) {\n (bool success, bytes memory ret) =\n calls[i].target.call(calls[i].callData);\n require(success, \"Multicall aggregate: call failed\");\n returnData[i] = ret;\n }\n }\n\n function blockAndAggregate(Call[] memory calls)\n public\n returns (\n uint256 blockNumber,\n bytes32 blockHash,\n Result[] memory returnData\n )\n {\n (blockNumber, blockHash, returnData) = tryBlockAndAggregate(\n true,\n calls\n );\n }\n\n function getBlockHash(uint256 blockNumber)\n public\n view\n returns (bytes32 blockHash)\n {\n blockHash = blockhash(blockNumber);\n }\n\n function getBlockNumber() public view returns (uint256 blockNumber) {\n blockNumber = block.number;\n }\n\n function getCurrentBlockCoinbase() public view returns (address coinbase) {\n coinbase = block.coinbase;\n }\n\n function getCurrentBlockDifficulty()\n public\n view\n returns (uint256 difficulty)\n {\n difficulty = block.difficulty;\n }\n\n function getCurrentBlockGasLimit() public view returns (uint256 gaslimit) {\n gaslimit = block.gaslimit;\n }\n\n function getCurrentBlockTimestamp()\n public\n view\n returns (uint256 timestamp)\n {\n timestamp = block.timestamp;\n }\n\n function getEthBalance(address addr) public view returns (uint256 balance) {\n balance = addr.balance;\n }\n\n function getLastBlockHash() public view returns (bytes32 blockHash) {\n blockHash = blockhash(block.number - 1);\n }\n\n function tryAggregate(bool requireSuccess, Call[] memory calls)\n public\n returns (Result[] memory returnData)\n {\n returnData = new Result[](calls.length);\n for (uint256 i = 0; i < calls.length; i++) {\n (bool success, bytes memory ret) =\n calls[i].target.call(calls[i].callData);\n\n if (requireSuccess) {\n require(success, \"Multicall2 aggregate: call failed\");\n }\n\n returnData[i] = Result(success, ret);\n }\n }\n\n function tryBlockAndAggregate(bool requireSuccess, Call[] memory calls)\n public\n returns (\n uint256 blockNumber,\n bytes32 blockHash,\n Result[] memory returnData\n )\n {\n blockNumber = block.number;\n blockHash = blockhash(block.number);\n returnData = tryAggregate(requireSuccess, calls);\n }\n}\n" + } + }, + "settings": { + "optimizer": { + "enabled": true, + "runs": 5000000 + }, + "outputSelection": { + "*": { + "*": [ + "abi", + "evm.bytecode", + "evm.deployedBytecode", + "evm.methodIdentifiers", + "metadata", + "devdoc", + "userdoc", + "storageLayout", + "evm.gasEstimates" + ], + "": [ + "ast" + ] + } + }, + "metadata": { + "useLiteralContent": true + } + } +} \ No newline at end of file diff --git a/deployments/dfk/solcInputs/76b4e8a3d6fd1a3364758c7f6c169cd0.json b/deployments/dfk/solcInputs/76b4e8a3d6fd1a3364758c7f6c169cd0.json new file mode 100644 index 000000000..ab855541c --- /dev/null +++ b/deployments/dfk/solcInputs/76b4e8a3d6fd1a3364758c7f6c169cd0.json @@ -0,0 +1,67 @@ +{ + "language": "Solidity", + "sources": { + "contracts/bridge/interfaces/IMasterChef.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.6.12;\npragma experimental ABIEncoderV2;\nimport \"@boringcrypto/boring-solidity/contracts/libraries/BoringERC20.sol\";\n\ninterface IMasterChef {\n using BoringERC20 for IERC20;\n struct UserInfo {\n uint256 amount; // How many LP tokens the user has provided.\n uint256 rewardDebt; // Reward debt. See explanation below.\n }\n\n struct PoolInfo {\n IERC20 lpToken; // Address of LP token contract.\n uint256 allocPoint; // How many allocation points assigned to this pool. SYNAPSE to distribute per block.\n uint256 lastRewardBlock; // Last block number that SYNAPSE distribution occurs.\n uint256 accSynapsePerShare; // Accumulated SYNAPSE per share, times 1e12. See below.\n }\n\n function poolInfo(uint256 pid) external view returns (IMasterChef.PoolInfo memory);\n function totalAllocPoint() external view returns (uint256);\n function deposit(uint256 _pid, uint256 _amount) external;\n}" + }, + "@boringcrypto/boring-solidity/contracts/libraries/BoringERC20.sol": { + "content": "// SPDX-License-Identifier: UNLICENSED\r\npragma solidity 0.6.12;\r\n\r\nimport \"../interfaces/IERC20.sol\";\r\n\r\nlibrary BoringERC20 {\r\n function safeSymbol(IERC20 token) internal view returns(string memory) {\r\n (bool success, bytes memory data) = address(token).staticcall(abi.encodeWithSelector(0x95d89b41));\r\n return success && data.length > 0 ? abi.decode(data, (string)) : \"???\";\r\n }\r\n\r\n function safeName(IERC20 token) internal view returns(string memory) {\r\n (bool success, bytes memory data) = address(token).staticcall(abi.encodeWithSelector(0x06fdde03));\r\n return success && data.length > 0 ? abi.decode(data, (string)) : \"???\";\r\n }\r\n\r\n function safeDecimals(IERC20 token) internal view returns (uint8) {\r\n (bool success, bytes memory data) = address(token).staticcall(abi.encodeWithSelector(0x313ce567));\r\n return success && data.length == 32 ? abi.decode(data, (uint8)) : 18;\r\n }\r\n\r\n function safeTransfer(IERC20 token, address to, uint256 amount) internal {\r\n (bool success, bytes memory data) = address(token).call(abi.encodeWithSelector(0xa9059cbb, to, amount));\r\n require(success && (data.length == 0 || abi.decode(data, (bool))), \"BoringERC20: Transfer failed\");\r\n }\r\n\r\n function safeTransferFrom(IERC20 token, address from, address to, uint256 amount) internal {\r\n (bool success, bytes memory data) = address(token).call(abi.encodeWithSelector(0x23b872dd, from, to, amount));\r\n require(success && (data.length == 0 || abi.decode(data, (bool))), \"BoringERC20: TransferFrom failed\");\r\n }\r\n}" + }, + "@boringcrypto/boring-solidity/contracts/interfaces/IERC20.sol": { + "content": "// SPDX-License-Identifier: MIT\r\npragma solidity 0.6.12;\r\n\r\ninterface IERC20 {\r\n function totalSupply() external view returns (uint256);\r\n function balanceOf(address account) external view returns (uint256);\r\n function allowance(address owner, address spender) external view returns (uint256);\r\n function approve(address spender, uint256 amount) external returns (bool);\r\n event Transfer(address indexed from, address indexed to, uint256 value);\r\n event Approval(address indexed owner, address indexed spender, uint256 value);\r\n\r\n // EIP 2612\r\n function permit(address owner, address spender, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s) external;\r\n}" + }, + "contracts/bridge/MiniChefV2.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.6.12;\npragma experimental ABIEncoderV2;\n\nimport \"@boringcrypto/boring-solidity/contracts/libraries/BoringMath.sol\";\nimport \"@boringcrypto/boring-solidity/contracts/BoringBatchable.sol\";\nimport \"@boringcrypto/boring-solidity/contracts/BoringOwnable.sol\";\nimport \"./libraries/SignedSafeMath.sol\";\nimport \"./interfaces/IRewarder.sol\";\nimport \"./interfaces/IMasterChef.sol\";\n\n/// @notice The (older) MasterChef contract gives out a constant number of SYNAPSE tokens per block.\n/// It is the only address with minting rights for SYNAPSE.\n/// The idea for this MasterChef V2 (MCV2) contract is therefore to be the owner of a dummy token\n/// that is deposited into the MasterChef V1 (MCV1) contract.\n/// The allocation point for this pool on MCV1 is the total allocation point for all pools that receive double incentives.\ncontract MiniChefV2 is BoringOwnable, BoringBatchable {\n using BoringMath for uint256;\n using BoringMath128 for uint128;\n using BoringERC20 for IERC20;\n using SignedSafeMath for int256;\n\n /// @notice Info of each MCV2 user.\n /// `amount` LP token amount the user has provided.\n /// `rewardDebt` The amount of SYNAPSE entitled to the user.\n struct UserInfo {\n uint256 amount;\n int256 rewardDebt;\n }\n\n /// @notice Info of each MCV2 pool.\n /// `allocPoint` The amount of allocation points assigned to the pool.\n /// Also known as the amount of SYNAPSE to distribute per block.\n struct PoolInfo {\n uint128 accSynapsePerShare;\n uint64 lastRewardTime;\n uint64 allocPoint;\n }\n\n /// @notice Address of SYNAPSE contract.\n IERC20 public immutable SYNAPSE;\n\n /// @notice Info of each MCV2 pool.\n PoolInfo[] public poolInfo;\n /// @notice Address of the LP token for each MCV2 pool.\n IERC20[] public lpToken;\n /// @notice Address of each `IRewarder` contract in MCV2.\n IRewarder[] public rewarder;\n\n /// @notice Info of each user that stakes LP tokens.\n mapping(uint256 => mapping(address => UserInfo)) public userInfo;\n /// @dev Total allocation points. Must be the sum of all allocation points in all pools.\n uint256 public totalAllocPoint;\n\n uint256 public synapsePerSecond;\n uint256 private constant ACC_SYNAPSE_PRECISION = 1e12;\n\n event Deposit(\n address indexed user,\n uint256 indexed pid,\n uint256 amount,\n address indexed to\n );\n event Withdraw(\n address indexed user,\n uint256 indexed pid,\n uint256 amount,\n address indexed to\n );\n event EmergencyWithdraw(\n address indexed user,\n uint256 indexed pid,\n uint256 amount,\n address indexed to\n );\n event Harvest(address indexed user, uint256 indexed pid, uint256 amount);\n event LogPoolAddition(\n uint256 indexed pid,\n uint256 allocPoint,\n IERC20 indexed lpToken,\n IRewarder indexed rewarder\n );\n event LogSetPool(\n uint256 indexed pid,\n uint256 allocPoint,\n IRewarder indexed rewarder,\n bool overwrite\n );\n event LogUpdatePool(\n uint256 indexed pid,\n uint64 lastRewardTime,\n uint256 lpSupply,\n uint256 accSynapsePerShare\n );\n event LogSynapsePerSecond(uint256 synapsePerSecond);\n\n /// @param _synapse The SYNAPSE token contract address.\n constructor(IERC20 _synapse) public {\n SYNAPSE = _synapse;\n }\n\n /// @notice Returns the number of MCV2 pools.\n function poolLength() public view returns (uint256 pools) {\n pools = poolInfo.length;\n }\n\n /// @notice Add a new LP to the pool. Can only be called by the owner.\n /// DO NOT add the same LP token more than once. Rewards will be messed up if you do.\n /// @param allocPoint AP of the new pool.\n /// @param _lpToken Address of the LP ERC-20 token.\n /// @param _rewarder Address of the rewarder delegate.\n function add(\n uint256 allocPoint,\n IERC20 _lpToken,\n IRewarder _rewarder\n ) public onlyOwner {\n totalAllocPoint = totalAllocPoint.add(allocPoint);\n lpToken.push(_lpToken);\n rewarder.push(_rewarder);\n\n poolInfo.push(\n PoolInfo({\n allocPoint: allocPoint.to64(),\n lastRewardTime: block.timestamp.to64(),\n accSynapsePerShare: 0\n })\n );\n emit LogPoolAddition(\n lpToken.length.sub(1),\n allocPoint,\n _lpToken,\n _rewarder\n );\n }\n\n /// @notice Update the given pool's SYNAPSE allocation point and `IRewarder` contract. Can only be called by the owner.\n /// @param _pid The index of the pool. See `poolInfo`.\n /// @param _allocPoint New AP of the pool.\n /// @param _rewarder Address of the rewarder delegate.\n /// @param overwrite True if _rewarder should be `set`. Otherwise `_rewarder` is ignored.\n function set(\n uint256 _pid,\n uint256 _allocPoint,\n IRewarder _rewarder,\n bool overwrite\n ) public onlyOwner {\n totalAllocPoint = totalAllocPoint.sub(poolInfo[_pid].allocPoint).add(\n _allocPoint\n );\n poolInfo[_pid].allocPoint = _allocPoint.to64();\n if (overwrite) {\n rewarder[_pid] = _rewarder;\n }\n emit LogSetPool(\n _pid,\n _allocPoint,\n overwrite ? _rewarder : rewarder[_pid],\n overwrite\n );\n }\n\n /// @notice Sets the synapse per second to be distributed. Can only be called by the owner.\n /// @param _synapsePerSecond The amount of Synapse to be distributed per second.\n function setSynapsePerSecond(uint256 _synapsePerSecond) public onlyOwner {\n synapsePerSecond = _synapsePerSecond;\n emit LogSynapsePerSecond(_synapsePerSecond);\n }\n\n /// @notice View function to see pending SYNAPSE on frontend.\n /// @param _pid The index of the pool. See `poolInfo`.\n /// @param _user Address of user.\n /// @return pending SYNAPSE reward for a given user.\n function pendingSynapse(uint256 _pid, address _user)\n external\n view\n returns (uint256 pending)\n {\n PoolInfo memory pool = poolInfo[_pid];\n UserInfo storage user = userInfo[_pid][_user];\n uint256 accSynapsePerShare = pool.accSynapsePerShare;\n uint256 lpSupply = lpToken[_pid].balanceOf(address(this));\n if (block.timestamp > pool.lastRewardTime && lpSupply != 0) {\n uint256 time = block.timestamp.sub(pool.lastRewardTime);\n uint256 synapseReward = time.mul(synapsePerSecond).mul(\n pool.allocPoint\n ) / totalAllocPoint;\n accSynapsePerShare = accSynapsePerShare.add(\n synapseReward.mul(ACC_SYNAPSE_PRECISION) / lpSupply\n );\n }\n pending = int256(\n user.amount.mul(accSynapsePerShare) / ACC_SYNAPSE_PRECISION\n ).sub(user.rewardDebt)\n .toUInt256();\n }\n\n /// @notice Update reward variables for all pools. Be careful of gas spending!\n /// @param pids Pool IDs of all to be updated. Make sure to update all active pools.\n function massUpdatePools(uint256[] calldata pids) external {\n uint256 len = pids.length;\n for (uint256 i = 0; i < len; ++i) {\n updatePool(pids[i]);\n }\n }\n\n /// @notice Update reward variables of the given pool.\n /// @param pid The index of the pool. See `poolInfo`.\n /// @return pool Returns the pool that was updated.\n function updatePool(uint256 pid) public returns (PoolInfo memory pool) {\n pool = poolInfo[pid];\n if (block.timestamp > pool.lastRewardTime) {\n uint256 lpSupply = lpToken[pid].balanceOf(address(this));\n if (lpSupply > 0) {\n uint256 time = block.timestamp.sub(pool.lastRewardTime);\n uint256 synapseReward = time.mul(synapsePerSecond).mul(\n pool.allocPoint\n ) / totalAllocPoint;\n pool.accSynapsePerShare = pool.accSynapsePerShare.add(\n (synapseReward.mul(ACC_SYNAPSE_PRECISION) / lpSupply)\n .to128()\n );\n }\n pool.lastRewardTime = block.timestamp.to64();\n poolInfo[pid] = pool;\n emit LogUpdatePool(\n pid,\n pool.lastRewardTime,\n lpSupply,\n pool.accSynapsePerShare\n );\n }\n }\n\n /// @notice Deposit LP tokens to MCV2 for SYNAPSE allocation.\n /// @param pid The index of the pool. See `poolInfo`.\n /// @param amount LP token amount to deposit.\n /// @param to The receiver of `amount` deposit benefit.\n function deposit(\n uint256 pid,\n uint256 amount,\n address to\n ) public {\n PoolInfo memory pool = updatePool(pid);\n UserInfo storage user = userInfo[pid][to];\n\n // Effects\n user.amount = user.amount.add(amount);\n user.rewardDebt = user.rewardDebt.add(\n int256(amount.mul(pool.accSynapsePerShare) / ACC_SYNAPSE_PRECISION)\n );\n\n // Interactions\n IRewarder _rewarder = rewarder[pid];\n if (address(_rewarder) != address(0)) {\n _rewarder.onSynapseReward(pid, to, to, 0, user.amount);\n }\n\n lpToken[pid].safeTransferFrom(msg.sender, address(this), amount);\n\n emit Deposit(msg.sender, pid, amount, to);\n }\n\n /// @notice Withdraw LP tokens from MCV2.\n /// @param pid The index of the pool. See `poolInfo`.\n /// @param amount LP token amount to withdraw.\n /// @param to Receiver of the LP tokens.\n function withdraw(\n uint256 pid,\n uint256 amount,\n address to\n ) public {\n PoolInfo memory pool = updatePool(pid);\n UserInfo storage user = userInfo[pid][msg.sender];\n\n // Effects\n user.rewardDebt = user.rewardDebt.sub(\n int256(amount.mul(pool.accSynapsePerShare) / ACC_SYNAPSE_PRECISION)\n );\n user.amount = user.amount.sub(amount);\n\n // Interactions\n IRewarder _rewarder = rewarder[pid];\n if (address(_rewarder) != address(0)) {\n _rewarder.onSynapseReward(pid, msg.sender, to, 0, user.amount);\n }\n\n lpToken[pid].safeTransfer(to, amount);\n\n emit Withdraw(msg.sender, pid, amount, to);\n }\n\n /// @notice Harvest proceeds for transaction sender to `to`.\n /// @param pid The index of the pool. See `poolInfo`.\n /// @param to Receiver of SYNAPSE rewards.\n function harvest(uint256 pid, address to) public {\n PoolInfo memory pool = updatePool(pid);\n UserInfo storage user = userInfo[pid][msg.sender];\n int256 accumulatedSynapse = int256(\n user.amount.mul(pool.accSynapsePerShare) / ACC_SYNAPSE_PRECISION\n );\n uint256 _pendingSynapse = accumulatedSynapse\n .sub(user.rewardDebt)\n .toUInt256();\n\n // Effects\n user.rewardDebt = accumulatedSynapse;\n\n // Interactions\n if (_pendingSynapse != 0) {\n SYNAPSE.safeTransfer(to, _pendingSynapse);\n }\n\n IRewarder _rewarder = rewarder[pid];\n if (address(_rewarder) != address(0)) {\n _rewarder.onSynapseReward(\n pid,\n msg.sender,\n to,\n _pendingSynapse,\n user.amount\n );\n }\n\n emit Harvest(msg.sender, pid, _pendingSynapse);\n }\n\n /// @notice Withdraw LP tokens from MCV2 and harvest proceeds for transaction sender to `to`.\n /// @param pid The index of the pool. See `poolInfo`.\n /// @param amount LP token amount to withdraw.\n /// @param to Receiver of the LP tokens and SYNAPSE rewards.\n function withdrawAndHarvest(\n uint256 pid,\n uint256 amount,\n address to\n ) public {\n PoolInfo memory pool = updatePool(pid);\n UserInfo storage user = userInfo[pid][msg.sender];\n int256 accumulatedSynapse = int256(\n user.amount.mul(pool.accSynapsePerShare) / ACC_SYNAPSE_PRECISION\n );\n uint256 _pendingSynapse = accumulatedSynapse\n .sub(user.rewardDebt)\n .toUInt256();\n\n // Effects\n user.rewardDebt = accumulatedSynapse.sub(\n int256(amount.mul(pool.accSynapsePerShare) / ACC_SYNAPSE_PRECISION)\n );\n user.amount = user.amount.sub(amount);\n\n // Interactions\n SYNAPSE.safeTransfer(to, _pendingSynapse);\n\n IRewarder _rewarder = rewarder[pid];\n if (address(_rewarder) != address(0)) {\n _rewarder.onSynapseReward(\n pid,\n msg.sender,\n to,\n _pendingSynapse,\n user.amount\n );\n }\n\n lpToken[pid].safeTransfer(to, amount);\n\n emit Withdraw(msg.sender, pid, amount, to);\n emit Harvest(msg.sender, pid, _pendingSynapse);\n }\n\n /// @notice Withdraw without caring about rewards. EMERGENCY ONLY.\n /// @param pid The index of the pool. See `poolInfo`.\n /// @param to Receiver of the LP tokens.\n function emergencyWithdraw(uint256 pid, address to) public {\n UserInfo storage user = userInfo[pid][msg.sender];\n uint256 amount = user.amount;\n user.amount = 0;\n user.rewardDebt = 0;\n\n IRewarder _rewarder = rewarder[pid];\n if (address(_rewarder) != address(0)) {\n _rewarder.onSynapseReward(pid, msg.sender, to, 0, 0);\n }\n\n // Note: transfer can fail or succeed if `amount` is zero.\n lpToken[pid].safeTransfer(to, amount);\n emit EmergencyWithdraw(msg.sender, pid, amount, to);\n }\n}\n" + }, + "@boringcrypto/boring-solidity/contracts/libraries/BoringMath.sol": { + "content": "// SPDX-License-Identifier: MIT\r\npragma solidity 0.6.12;\r\n// a library for performing overflow-safe math, updated with awesomeness from of DappHub (https://github.com/dapphub/ds-math)\r\nlibrary BoringMath {\r\n function add(uint256 a, uint256 b) internal pure returns (uint256 c) {require((c = a + b) >= b, \"BoringMath: Add Overflow\");}\r\n function sub(uint256 a, uint256 b) internal pure returns (uint256 c) {require((c = a - b) <= a, \"BoringMath: Underflow\");}\r\n function mul(uint256 a, uint256 b) internal pure returns (uint256 c) {require(b == 0 || (c = a * b)/b == a, \"BoringMath: Mul Overflow\");}\r\n function to128(uint256 a) internal pure returns (uint128 c) {\r\n require(a <= uint128(-1), \"BoringMath: uint128 Overflow\");\r\n c = uint128(a);\r\n }\r\n function to64(uint256 a) internal pure returns (uint64 c) {\r\n require(a <= uint64(-1), \"BoringMath: uint64 Overflow\");\r\n c = uint64(a);\r\n }\r\n function to32(uint256 a) internal pure returns (uint32 c) {\r\n require(a <= uint32(-1), \"BoringMath: uint32 Overflow\");\r\n c = uint32(a);\r\n }\r\n}\r\n\r\nlibrary BoringMath128 {\r\n function add(uint128 a, uint128 b) internal pure returns (uint128 c) {require((c = a + b) >= b, \"BoringMath: Add Overflow\");}\r\n function sub(uint128 a, uint128 b) internal pure returns (uint128 c) {require((c = a - b) <= a, \"BoringMath: Underflow\");}\r\n}\r\n\r\nlibrary BoringMath64 {\r\n function add(uint64 a, uint64 b) internal pure returns (uint64 c) {require((c = a + b) >= b, \"BoringMath: Add Overflow\");}\r\n function sub(uint64 a, uint64 b) internal pure returns (uint64 c) {require((c = a - b) <= a, \"BoringMath: Underflow\");}\r\n}\r\n\r\nlibrary BoringMath32 {\r\n function add(uint32 a, uint32 b) internal pure returns (uint32 c) {require((c = a + b) >= b, \"BoringMath: Add Overflow\");}\r\n function sub(uint32 a, uint32 b) internal pure returns (uint32 c) {require((c = a - b) <= a, \"BoringMath: Underflow\");}\r\n}" + }, + "@boringcrypto/boring-solidity/contracts/BoringBatchable.sol": { + "content": "// SPDX-License-Identifier: UNLICENSED\r\n// Audit on 5-Jan-2021 by Keno and BoringCrypto\r\n\r\n// P1 - P3: OK\r\npragma solidity 0.6.12;\r\npragma experimental ABIEncoderV2;\r\n// solhint-disable avoid-low-level-calls\r\n\r\nimport \"./libraries/BoringERC20.sol\";\r\n\r\n// T1 - T4: OK\r\ncontract BaseBoringBatchable {\r\n function _getRevertMsg(bytes memory _returnData) internal pure returns (string memory) {\r\n // If the _res length is less than 68, then the transaction failed silently (without a revert message)\r\n if (_returnData.length < 68) return \"Transaction reverted silently\";\r\n\r\n assembly {\r\n // Slice the sighash.\r\n _returnData := add(_returnData, 0x04)\r\n }\r\n return abi.decode(_returnData, (string)); // All that remains is the revert string\r\n } \r\n \r\n // F3 - F9: OK\r\n // F1: External is ok here because this is the batch function, adding it to a batch makes no sense\r\n // F2: Calls in the batch may be payable, delegatecall operates in the same context, so each call in the batch has access to msg.value\r\n // C1 - C21: OK\r\n // C3: The length of the loop is fully under user control, so can't be exploited\r\n // C7: Delegatecall is only used on the same contract, so it's safe\r\n function batch(bytes[] calldata calls, bool revertOnFail) external payable returns(bool[] memory successes, bytes[] memory results) {\r\n // Interactions\r\n successes = new bool[](calls.length);\r\n results = new bytes[](calls.length);\r\n for (uint256 i = 0; i < calls.length; i++) {\r\n (bool success, bytes memory result) = address(this).delegatecall(calls[i]);\r\n require(success || !revertOnFail, _getRevertMsg(result));\r\n successes[i] = success;\r\n results[i] = result;\r\n }\r\n }\r\n}\r\n\r\n// T1 - T4: OK\r\ncontract BoringBatchable is BaseBoringBatchable {\r\n // F1 - F9: OK\r\n // F6: Parameters can be used front-run the permit and the user's permit will fail (due to nonce or other revert)\r\n // if part of a batch this could be used to grief once as the second call would not need the permit\r\n // C1 - C21: OK\r\n function permitToken(IERC20 token, address from, address to, uint256 amount, uint256 deadline, uint8 v, bytes32 r, bytes32 s) public {\r\n // Interactions\r\n // X1 - X5\r\n token.permit(from, to, amount, deadline, v, r, s);\r\n }\r\n}" + }, + "@boringcrypto/boring-solidity/contracts/BoringOwnable.sol": { + "content": "// SPDX-License-Identifier: MIT\r\n// Audit on 5-Jan-2021 by Keno and BoringCrypto\r\n\r\n// P1 - P3: OK\r\npragma solidity 0.6.12;\r\n\r\n// Source: https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/access/Ownable.sol + Claimable.sol\r\n// Edited by BoringCrypto\r\n\r\n// T1 - T4: OK\r\ncontract BoringOwnableData {\r\n // V1 - V5: OK\r\n address public owner;\r\n // V1 - V5: OK\r\n address public pendingOwner;\r\n}\r\n\r\n// T1 - T4: OK\r\ncontract BoringOwnable is BoringOwnableData {\r\n // E1: OK\r\n event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\r\n\r\n constructor () public {\r\n owner = msg.sender;\r\n emit OwnershipTransferred(address(0), msg.sender);\r\n }\r\n\r\n // F1 - F9: OK\r\n // C1 - C21: OK\r\n function transferOwnership(address newOwner, bool direct, bool renounce) public onlyOwner {\r\n if (direct) {\r\n // Checks\r\n require(newOwner != address(0) || renounce, \"Ownable: zero address\");\r\n\r\n // Effects\r\n emit OwnershipTransferred(owner, newOwner);\r\n owner = newOwner;\r\n pendingOwner = address(0);\r\n } else {\r\n // Effects\r\n pendingOwner = newOwner;\r\n }\r\n }\r\n\r\n // F1 - F9: OK\r\n // C1 - C21: OK\r\n function claimOwnership() public {\r\n address _pendingOwner = pendingOwner;\r\n \r\n // Checks\r\n require(msg.sender == _pendingOwner, \"Ownable: caller != pending owner\");\r\n\r\n // Effects\r\n emit OwnershipTransferred(owner, _pendingOwner);\r\n owner = _pendingOwner;\r\n pendingOwner = address(0);\r\n }\r\n\r\n // M1 - M5: OK\r\n // C1 - C21: OK\r\n modifier onlyOwner() {\r\n require(msg.sender == owner, \"Ownable: caller is not the owner\");\r\n _;\r\n }\r\n}" + }, + "contracts/bridge/libraries/SignedSafeMath.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.6.12;\n\nlibrary SignedSafeMath {\n int256 constant private _INT256_MIN = -2**255;\n\n /**\n * @dev Returns the multiplication of two signed integers, reverting on\n * overflow.\n *\n * Counterpart to Solidity's `*` operator.\n *\n * Requirements:\n *\n * - Multiplication cannot overflow.\n */\n function mul(int256 a, int256 b) internal pure returns (int256) {\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) {\n return 0;\n }\n\n require(!(a == -1 && b == _INT256_MIN), \"SignedSafeMath: multiplication overflow\");\n\n int256 c = a * b;\n require(c / a == b, \"SignedSafeMath: multiplication overflow\");\n\n return c;\n }\n\n /**\n * @dev Returns the integer division of two signed integers. Reverts 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(int256 a, int256 b) internal pure returns (int256) {\n require(b != 0, \"SignedSafeMath: division by zero\");\n require(!(b == -1 && a == _INT256_MIN), \"SignedSafeMath: division overflow\");\n\n int256 c = a / b;\n\n return c;\n }\n\n /**\n * @dev Returns the subtraction of two signed integers, reverting on\n * overflow.\n *\n * Counterpart to Solidity's `-` operator.\n *\n * Requirements:\n *\n * - Subtraction cannot overflow.\n */\n function sub(int256 a, int256 b) internal pure returns (int256) {\n int256 c = a - b;\n require((b >= 0 && c <= a) || (b < 0 && c > a), \"SignedSafeMath: subtraction overflow\");\n\n return c;\n }\n\n /**\n * @dev Returns the addition of two signed integers, reverting on\n * overflow.\n *\n * Counterpart to Solidity's `+` operator.\n *\n * Requirements:\n *\n * - Addition cannot overflow.\n */\n function add(int256 a, int256 b) internal pure returns (int256) {\n int256 c = a + b;\n require((b >= 0 && c >= a) || (b < 0 && c < a), \"SignedSafeMath: addition overflow\");\n\n return c;\n }\n\n function toUInt256(int256 a) internal pure returns (uint256) {\n require(a >= 0, \"Integer < 0\");\n return uint256(a);\n }\n}" + }, + "contracts/bridge/interfaces/IRewarder.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.6.12;\nimport \"@boringcrypto/boring-solidity/contracts/libraries/BoringERC20.sol\";\ninterface IRewarder {\n using BoringERC20 for IERC20;\n function onSynapseReward(uint256 pid, address user, address recipient, uint256 synapseAmount, uint256 newLpAmount) external;\n function pendingTokens(uint256 pid, address user, uint256 synapseAmount) external view returns (IERC20[] memory, uint256[] memory);\n}" + }, + "contracts/bridge/mocks/RewarderMock.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.6.12;\nimport \"../interfaces/IRewarder.sol\";\nimport \"@boringcrypto/boring-solidity/contracts/libraries/BoringERC20.sol\";\nimport \"@boringcrypto/boring-solidity/contracts/libraries/BoringMath.sol\";\n\n\ncontract RewarderMock is IRewarder {\n using BoringMath for uint256;\n using BoringERC20 for IERC20;\n uint256 private immutable rewardMultiplier;\n IERC20 private immutable rewardToken;\n uint256 private constant REWARD_TOKEN_DIVISOR = 1e18;\n address private immutable MASTERCHEF_V2;\n\n constructor (uint256 _rewardMultiplier, IERC20 _rewardToken, address _MASTERCHEF_V2) public {\n rewardMultiplier = _rewardMultiplier;\n rewardToken = _rewardToken;\n MASTERCHEF_V2 = _MASTERCHEF_V2;\n }\n\n function onSynapseReward (uint256, address user, address to, uint256 synapseAmount, uint256) onlyMCV2 override external {\n uint256 pendingReward = synapseAmount.mul(rewardMultiplier) / REWARD_TOKEN_DIVISOR;\n uint256 rewardBal = rewardToken.balanceOf(address(this));\n if (pendingReward > rewardBal) {\n rewardToken.safeTransfer(to, rewardBal);\n } else {\n rewardToken.safeTransfer(to, pendingReward);\n }\n }\n \n function pendingTokens(uint256 pid, address user, uint256 synapseAmount) override external view returns (IERC20[] memory rewardTokens, uint256[] memory rewardAmounts) {\n IERC20[] memory _rewardTokens = new IERC20[](1);\n _rewardTokens[0] = (rewardToken);\n uint256[] memory _rewardAmounts = new uint256[](1);\n _rewardAmounts[0] = synapseAmount.mul(rewardMultiplier) / REWARD_TOKEN_DIVISOR;\n return (_rewardTokens, _rewardAmounts);\n }\n\n modifier onlyMCV2 {\n require(\n msg.sender == MASTERCHEF_V2,\n \"Only MCV2 can call this function.\"\n );\n _;\n }\n \n}" + }, + "contracts/bridge/mocks/RewarderBrockenMock.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.6.12;\nimport \"../interfaces/IRewarder.sol\";\n\n\ncontract RewarderBrokenMock is IRewarder {\n\n function onSynapseReward (uint256, address, address, uint256, uint256) override external {\n revert();\n }\n\n function pendingTokens(uint256 pid, address user, uint256 synapseAmount) override external view returns (IERC20[] memory rewardTokens, uint256[] memory rewardAmounts){\n revert();\n }\n \n}" + } + }, + "settings": { + "optimizer": { + "enabled": true, + "runs": 10000 + }, + "outputSelection": { + "*": { + "*": [ + "abi", + "evm.bytecode", + "evm.deployedBytecode", + "evm.methodIdentifiers", + "metadata", + "devdoc", + "userdoc", + "storageLayout", + "evm.gasEstimates", + "devdoc", + "userdoc" + ], + "": [ + "ast" + ] + } + }, + "metadata": { + "useLiteralContent": true + } + } +} \ No newline at end of file diff --git a/deployments/dfk/solcInputs/95380060a7ec73498bb886cdc300b807.json b/deployments/dfk/solcInputs/95380060a7ec73498bb886cdc300b807.json new file mode 100644 index 000000000..7c24888f9 --- /dev/null +++ b/deployments/dfk/solcInputs/95380060a7ec73498bb886cdc300b807.json @@ -0,0 +1,304 @@ +{ + "language": "Solidity", + "sources": { + "contracts/amm/AaveSwap.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.6.12;\n\nimport \"./Swap.sol\";\n\n/**\n * @title AaveSwap - A StableSwap implementation in solidity, integrated with Aave.\n * @notice This contract is responsible for custody of closely pegged assets (eg. group of stablecoins)\n * and automatic market making system. Users become an LP (Liquidity Provider) by depositing their tokens\n * in desired ratios for an exchange of the pool token that represents their share of the pool.\n * Users can burn pool tokens and withdraw their share of token(s).\n *\n * Each time a swap between the pooled tokens happens, a set fee incurs which effectively gets\n * distributed to the LPs.\n *\n * In case of emergencies, admin can pause additional deposits, swaps, or single-asset withdraws - which\n * stops the ratio of the tokens in the pool from changing.\n * Users can always withdraw their tokens via multi-asset withdraws.\n *\n * @dev Most of the logic is stored as a library `SwapUtils` for the sake of reducing contract's\n * deployment size.\n */\n\ncontract AaveSwap is Swap {\n address internal AAVE_REWARDS;\n address internal AAVE_LENDING_POOL;\n address internal REWARD_TOKEN;\n address internal REWARD_RECEIVER;\n address[] internal AAVE_ASSETS;\n\n /**\n * @notice Initializes this Swap contract with the given parameters.\n * This will also clone a LPToken contract that represents users'\n * LP positions. The owner of LPToken will be this contract - which means\n * only this contract is allowed to mint/burn tokens.\n *\n * @param _pooledTokens an array of ERC20s this pool will accept\n * @param decimals the decimals to use for each pooled token,\n * eg 8 for WBTC. Cannot be larger than POOL_PRECISION_DECIMALS\n * @param lpTokenName the long-form name of the token to be deployed\n * @param lpTokenSymbol the short symbol for the token to be deployed\n * @param _a the amplification coefficient * n * (n - 1). See the\n * StableSwap paper for details\n * @param _fee default swap fee to be initialized with\n * @param _adminFee default adminFee to be initialized with\n * @param lpTokenTargetAddress the address of an existing LPToken contract to use as a target\n */\n function initialize(\n IERC20[] memory _pooledTokens,\n uint8[] memory decimals,\n string memory lpTokenName,\n string memory lpTokenSymbol,\n uint256 _a,\n uint256 _fee,\n uint256 _adminFee,\n address lpTokenTargetAddress\n ) public virtual override initializer {\n Swap.initialize(\n _pooledTokens,\n decimals,\n lpTokenName,\n lpTokenSymbol,\n _a,\n _fee,\n _adminFee,\n lpTokenTargetAddress\n );\n AAVE_REWARDS = 0x01D83Fe6A10D2f2B7AF17034343746188272cAc9;\n AAVE_LENDING_POOL = 0x4F01AeD16D97E3aB5ab2B501154DC9bb0F1A5A2C;\n REWARD_TOKEN = 0xB31f66AA3C1e785363F0875A1B74E27b85FD66c7;\n AAVE_ASSETS = [0x53f7c5869a859F0AeC3D334ee8B4Cf01E3492f21];\n REWARD_RECEIVER = msg.sender;\n }\n\n function setRewardReceiver(address _reward_receiver) external onlyOwner {\n REWARD_RECEIVER = _reward_receiver;\n }\n\n function claimAaveRewards() external {\n AAVE_REWARDS.call(\n abi.encodeWithSignature(\n \"claimRewards(address[],uint256,address)\",\n AAVE_ASSETS,\n type(uint256).max,\n REWARD_RECEIVER\n )\n );\n }\n}\n" + }, + "contracts/amm/Swap.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.6.12;\n\nimport \"@openzeppelin/contracts/math/SafeMath.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/SafeERC20.sol\";\nimport \"@openzeppelin/contracts/proxy/Clones.sol\";\nimport \"@openzeppelin/contracts-upgradeable/utils/ReentrancyGuardUpgradeable.sol\";\nimport \"./OwnerPausableUpgradeable.sol\";\nimport \"./SwapUtils.sol\";\nimport \"./AmplificationUtils.sol\";\n\n/**\n * @title Swap - A StableSwap implementation in solidity.\n * @notice This contract is responsible for custody of closely pegged assets (eg. group of stablecoins)\n * and automatic market making system. Users become an LP (Liquidity Provider) by depositing their tokens\n * in desired ratios for an exchange of the pool token that represents their share of the pool.\n * Users can burn pool tokens and withdraw their share of token(s).\n *\n * Each time a swap between the pooled tokens happens, a set fee incurs which effectively gets\n * distributed to the LPs.\n *\n * In case of emergencies, admin can pause additional deposits, swaps, or single-asset withdraws - which\n * stops the ratio of the tokens in the pool from changing.\n * Users can always withdraw their tokens via multi-asset withdraws.\n *\n * @dev Most of the logic is stored as a library `SwapUtils` for the sake of reducing contract's\n * deployment size.\n */\ncontract Swap is OwnerPausableUpgradeable, ReentrancyGuardUpgradeable {\n using SafeERC20 for IERC20;\n using SafeMath for uint256;\n using SwapUtils for SwapUtils.Swap;\n using AmplificationUtils for SwapUtils.Swap;\n\n // Struct storing data responsible for automatic market maker functionalities. In order to\n // access this data, this contract uses SwapUtils library. For more details, see SwapUtils.sol\n SwapUtils.Swap public swapStorage;\n\n // Maps token address to an index in the pool. Used to prevent duplicate tokens in the pool.\n // getTokenIndex function also relies on this mapping to retrieve token index.\n mapping(address => uint8) private tokenIndexes;\n\n /*** EVENTS ***/\n\n // events replicated from SwapUtils to make the ABI easier for dumb\n // clients\n event TokenSwap(\n address indexed buyer,\n uint256 tokensSold,\n uint256 tokensBought,\n uint128 soldId,\n uint128 boughtId\n );\n event AddLiquidity(\n address indexed provider,\n uint256[] tokenAmounts,\n uint256[] fees,\n uint256 invariant,\n uint256 lpTokenSupply\n );\n event RemoveLiquidity(\n address indexed provider,\n uint256[] tokenAmounts,\n uint256 lpTokenSupply\n );\n event RemoveLiquidityOne(\n address indexed provider,\n uint256 lpTokenAmount,\n uint256 lpTokenSupply,\n uint256 boughtId,\n uint256 tokensBought\n );\n event RemoveLiquidityImbalance(\n address indexed provider,\n uint256[] tokenAmounts,\n uint256[] fees,\n uint256 invariant,\n uint256 lpTokenSupply\n );\n event NewAdminFee(uint256 newAdminFee);\n event NewSwapFee(uint256 newSwapFee);\n event RampA(\n uint256 oldA,\n uint256 newA,\n uint256 initialTime,\n uint256 futureTime\n );\n event StopRampA(uint256 currentA, uint256 time);\n\n /**\n * @notice Initializes this Swap contract with the given parameters.\n * This will also clone a LPToken contract that represents users'\n * LP positions. The owner of LPToken will be this contract - which means\n * only this contract is allowed to mint/burn tokens.\n *\n * @param _pooledTokens an array of ERC20s this pool will accept\n * @param decimals the decimals to use for each pooled token,\n * eg 8 for WBTC. Cannot be larger than POOL_PRECISION_DECIMALS\n * @param lpTokenName the long-form name of the token to be deployed\n * @param lpTokenSymbol the short symbol for the token to be deployed\n * @param _a the amplification coefficient * n * (n - 1). See the\n * StableSwap paper for details\n * @param _fee default swap fee to be initialized with\n * @param _adminFee default adminFee to be initialized with\n * @param lpTokenTargetAddress the address of an existing LPToken contract to use as a target\n */\n function initialize(\n IERC20[] memory _pooledTokens,\n uint8[] memory decimals,\n string memory lpTokenName,\n string memory lpTokenSymbol,\n uint256 _a,\n uint256 _fee,\n uint256 _adminFee,\n address lpTokenTargetAddress\n ) public virtual initializer {\n __OwnerPausable_init();\n __ReentrancyGuard_init();\n // Check _pooledTokens and precisions parameter\n require(_pooledTokens.length > 1, \"_pooledTokens.length <= 1\");\n require(_pooledTokens.length <= 32, \"_pooledTokens.length > 32\");\n require(\n _pooledTokens.length == decimals.length,\n \"_pooledTokens decimals mismatch\"\n );\n\n uint256[] memory precisionMultipliers = new uint256[](decimals.length);\n\n for (uint8 i = 0; i < _pooledTokens.length; i++) {\n if (i > 0) {\n // Check if index is already used. Check if 0th element is a duplicate.\n require(\n tokenIndexes[address(_pooledTokens[i])] == 0 &&\n _pooledTokens[0] != _pooledTokens[i],\n \"Duplicate tokens\"\n );\n }\n require(\n address(_pooledTokens[i]) != address(0),\n \"The 0 address isn't an ERC-20\"\n );\n require(\n decimals[i] <= SwapUtils.POOL_PRECISION_DECIMALS,\n \"Token decimals exceeds max\"\n );\n precisionMultipliers[i] =\n 10 **\n uint256(SwapUtils.POOL_PRECISION_DECIMALS).sub(\n uint256(decimals[i])\n );\n tokenIndexes[address(_pooledTokens[i])] = i;\n }\n\n // Check _a, _fee, _adminFee parameters\n require(_a < AmplificationUtils.MAX_A, \"_a exceeds maximum\");\n require(_fee < SwapUtils.MAX_SWAP_FEE, \"_fee exceeds maximum\");\n require(\n _adminFee < SwapUtils.MAX_ADMIN_FEE,\n \"_adminFee exceeds maximum\"\n );\n\n // Clone and initialize a LPToken contract\n LPToken lpToken = LPToken(Clones.clone(lpTokenTargetAddress));\n require(\n lpToken.initialize(lpTokenName, lpTokenSymbol),\n \"could not init lpToken clone\"\n );\n\n // Initialize swapStorage struct\n swapStorage.lpToken = lpToken;\n swapStorage.pooledTokens = _pooledTokens;\n swapStorage.tokenPrecisionMultipliers = precisionMultipliers;\n swapStorage.balances = new uint256[](_pooledTokens.length);\n swapStorage.initialA = _a.mul(AmplificationUtils.A_PRECISION);\n swapStorage.futureA = _a.mul(AmplificationUtils.A_PRECISION);\n // swapStorage.initialATime = 0;\n // swapStorage.futureATime = 0;\n swapStorage.swapFee = _fee;\n swapStorage.adminFee = _adminFee;\n }\n\n /*** MODIFIERS ***/\n\n /**\n * @notice Modifier to check deadline against current timestamp\n * @param deadline latest timestamp to accept this transaction\n */\n modifier deadlineCheck(uint256 deadline) {\n require(block.timestamp <= deadline, \"Deadline not met\");\n _;\n }\n\n /*** VIEW FUNCTIONS ***/\n\n /**\n * @notice Return A, the amplification coefficient * n * (n - 1)\n * @dev See the StableSwap paper for details\n * @return A parameter\n */\n function getA() external view virtual returns (uint256) {\n return swapStorage.getA();\n }\n\n /**\n * @notice Return A in its raw precision form\n * @dev See the StableSwap paper for details\n * @return A parameter in its raw precision form\n */\n function getAPrecise() external view virtual returns (uint256) {\n return swapStorage.getAPrecise();\n }\n\n /**\n * @notice Return address of the pooled token at given index. Reverts if tokenIndex is out of range.\n * @param index the index of the token\n * @return address of the token at given index\n */\n function getToken(uint8 index) public view virtual returns (IERC20) {\n require(index < swapStorage.pooledTokens.length, \"Out of range\");\n return swapStorage.pooledTokens[index];\n }\n\n /**\n * @notice Return the index of the given token address. Reverts if no matching\n * token is found.\n * @param tokenAddress address of the token\n * @return the index of the given token address\n */\n function getTokenIndex(address tokenAddress)\n public\n view\n virtual\n returns (uint8)\n {\n uint8 index = tokenIndexes[tokenAddress];\n require(\n address(getToken(index)) == tokenAddress,\n \"Token does not exist\"\n );\n return index;\n }\n\n /**\n * @notice Return current balance of the pooled token at given index\n * @param index the index of the token\n * @return current balance of the pooled token at given index with token's native precision\n */\n function getTokenBalance(uint8 index)\n external\n view\n virtual\n returns (uint256)\n {\n require(index < swapStorage.pooledTokens.length, \"Index out of range\");\n return swapStorage.balances[index];\n }\n\n /**\n * @notice Get the virtual price, to help calculate profit\n * @return the virtual price, scaled to the POOL_PRECISION_DECIMALS\n */\n function getVirtualPrice() external view virtual returns (uint256) {\n return swapStorage.getVirtualPrice();\n }\n\n /**\n * @notice Calculate amount of tokens you receive on swap\n * @param tokenIndexFrom the token the user wants to sell\n * @param tokenIndexTo the token the user wants to buy\n * @param dx the amount of tokens the user wants to sell. If the token charges\n * a fee on transfers, use the amount that gets transferred after the fee.\n * @return amount of tokens the user will receive\n */\n function calculateSwap(\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx\n ) external view virtual returns (uint256) {\n return swapStorage.calculateSwap(tokenIndexFrom, tokenIndexTo, dx);\n }\n\n /**\n * @notice A simple method to calculate prices from deposits or\n * withdrawals, excluding fees but including slippage. This is\n * helpful as an input into the various \"min\" parameters on calls\n * to fight front-running\n *\n * @dev This shouldn't be used outside frontends for user estimates.\n *\n * @param amounts an array of token amounts to deposit or withdrawal,\n * corresponding to pooledTokens. The amount should be in each\n * pooled token's native precision. If a token charges a fee on transfers,\n * use the amount that gets transferred after the fee.\n * @param deposit whether this is a deposit or a withdrawal\n * @return token amount the user will receive\n */\n function calculateTokenAmount(uint256[] calldata amounts, bool deposit)\n external\n view\n virtual\n returns (uint256)\n {\n return swapStorage.calculateTokenAmount(amounts, deposit);\n }\n\n /**\n * @notice A simple method to calculate amount of each underlying\n * tokens that is returned upon burning given amount of LP tokens\n * @param amount the amount of LP tokens that would be burned on withdrawal\n * @return array of token balances that the user will receive\n */\n function calculateRemoveLiquidity(uint256 amount)\n external\n view\n virtual\n returns (uint256[] memory)\n {\n return swapStorage.calculateRemoveLiquidity(amount);\n }\n\n /**\n * @notice Calculate the amount of underlying token available to withdraw\n * when withdrawing via only single token\n * @param tokenAmount the amount of LP token to burn\n * @param tokenIndex index of which token will be withdrawn\n * @return availableTokenAmount calculated amount of underlying token\n * available to withdraw\n */\n function calculateRemoveLiquidityOneToken(\n uint256 tokenAmount,\n uint8 tokenIndex\n ) external view virtual returns (uint256 availableTokenAmount) {\n return swapStorage.calculateWithdrawOneToken(tokenAmount, tokenIndex);\n }\n\n /**\n * @notice This function reads the accumulated amount of admin fees of the token with given index\n * @param index Index of the pooled token\n * @return admin's token balance in the token's precision\n */\n function getAdminBalance(uint256 index)\n external\n view\n virtual\n returns (uint256)\n {\n return swapStorage.getAdminBalance(index);\n }\n\n /*** STATE MODIFYING FUNCTIONS ***/\n\n /**\n * @notice Swap two tokens using this pool\n * @param tokenIndexFrom the token the user wants to swap from\n * @param tokenIndexTo the token the user wants to swap to\n * @param dx the amount of tokens the user wants to swap from\n * @param minDy the min amount the user would like to receive, or revert.\n * @param deadline latest timestamp to accept this transaction\n */\n function swap(\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx,\n uint256 minDy,\n uint256 deadline\n )\n external\n virtual\n nonReentrant\n whenNotPaused\n deadlineCheck(deadline)\n returns (uint256)\n {\n return swapStorage.swap(tokenIndexFrom, tokenIndexTo, dx, minDy);\n }\n\n /**\n * @notice Add liquidity to the pool with the given amounts of tokens\n * @param amounts the amounts of each token to add, in their native precision\n * @param minToMint the minimum LP tokens adding this amount of liquidity\n * should mint, otherwise revert. Handy for front-running mitigation\n * @param deadline latest timestamp to accept this transaction\n * @return amount of LP token user minted and received\n */\n function addLiquidity(\n uint256[] calldata amounts,\n uint256 minToMint,\n uint256 deadline\n )\n external\n virtual\n nonReentrant\n whenNotPaused\n deadlineCheck(deadline)\n returns (uint256)\n {\n return swapStorage.addLiquidity(amounts, minToMint);\n }\n\n /**\n * @notice Burn LP tokens to remove liquidity from the pool. Withdraw fee that decays linearly\n * over period of 4 weeks since last deposit will apply.\n * @dev Liquidity can always be removed, even when the pool is paused.\n * @param amount the amount of LP tokens to burn\n * @param minAmounts the minimum amounts of each token in the pool\n * acceptable for this burn. Useful as a front-running mitigation\n * @param deadline latest timestamp to accept this transaction\n * @return amounts of tokens user received\n */\n function removeLiquidity(\n uint256 amount,\n uint256[] calldata minAmounts,\n uint256 deadline\n )\n external\n virtual\n nonReentrant\n deadlineCheck(deadline)\n returns (uint256[] memory)\n {\n return swapStorage.removeLiquidity(amount, minAmounts);\n }\n\n /**\n * @notice Remove liquidity from the pool all in one token. Withdraw fee that decays linearly\n * over period of 4 weeks since last deposit will apply.\n * @param tokenAmount the amount of the token you want to receive\n * @param tokenIndex the index of the token you want to receive\n * @param minAmount the minimum amount to withdraw, otherwise revert\n * @param deadline latest timestamp to accept this transaction\n * @return amount of chosen token user received\n */\n function removeLiquidityOneToken(\n uint256 tokenAmount,\n uint8 tokenIndex,\n uint256 minAmount,\n uint256 deadline\n )\n external\n virtual\n nonReentrant\n whenNotPaused\n deadlineCheck(deadline)\n returns (uint256)\n {\n return\n swapStorage.removeLiquidityOneToken(\n tokenAmount,\n tokenIndex,\n minAmount\n );\n }\n\n /**\n * @notice Remove liquidity from the pool, weighted differently than the\n * pool's current balances. Withdraw fee that decays linearly\n * over period of 4 weeks since last deposit will apply.\n * @param amounts how much of each token to withdraw\n * @param maxBurnAmount the max LP token provider is willing to pay to\n * remove liquidity. Useful as a front-running mitigation.\n * @param deadline latest timestamp to accept this transaction\n * @return amount of LP tokens burned\n */\n function removeLiquidityImbalance(\n uint256[] calldata amounts,\n uint256 maxBurnAmount,\n uint256 deadline\n )\n external\n virtual\n nonReentrant\n whenNotPaused\n deadlineCheck(deadline)\n returns (uint256)\n {\n return swapStorage.removeLiquidityImbalance(amounts, maxBurnAmount);\n }\n\n /*** ADMIN FUNCTIONS ***/\n\n /**\n * @notice Withdraw all admin fees to the contract owner\n */\n function withdrawAdminFees() external onlyOwner {\n swapStorage.withdrawAdminFees(owner());\n }\n\n /**\n * @notice Update the admin fee. Admin fee takes portion of the swap fee.\n * @param newAdminFee new admin fee to be applied on future transactions\n */\n function setAdminFee(uint256 newAdminFee) external onlyOwner {\n swapStorage.setAdminFee(newAdminFee);\n }\n\n /**\n * @notice Update the swap fee to be applied on swaps\n * @param newSwapFee new swap fee to be applied on future transactions\n */\n function setSwapFee(uint256 newSwapFee) external onlyOwner {\n swapStorage.setSwapFee(newSwapFee);\n }\n\n /**\n * @notice Start ramping up or down A parameter towards given futureA and futureTime\n * Checks if the change is too rapid, and commits the new A value only when it falls under\n * the limit range.\n * @param futureA the new A to ramp towards\n * @param futureTime timestamp when the new A should be reached\n */\n function rampA(uint256 futureA, uint256 futureTime) external onlyOwner {\n swapStorage.rampA(futureA, futureTime);\n }\n\n /**\n * @notice Stop ramping A immediately. Reverts if ramp A is already stopped.\n */\n function stopRampA() external onlyOwner {\n swapStorage.stopRampA();\n }\n}\n" + }, + "@openzeppelin/contracts/math/SafeMath.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <0.8.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" + }, + "@openzeppelin/contracts/token/ERC20/SafeERC20.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <0.8.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" + }, + "@openzeppelin/contracts/proxy/Clones.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <0.8.0;\n\n/**\n * @dev https://eips.ethereum.org/EIPS/eip-1167[EIP 1167] is a standard for\n * deploying minimal proxy contracts, also known as \"clones\".\n *\n * > To simply and cheaply clone contract functionality in an immutable way, this standard specifies\n * > a minimal bytecode implementation that delegates all calls to a known, fixed address.\n *\n * The library includes functions to deploy a proxy using either `create` (traditional deployment) or `create2`\n * (salted deterministic deployment). It also includes functions to predict the addresses of clones deployed using the\n * deterministic method.\n *\n * _Available since v3.4._\n */\nlibrary Clones {\n /**\n * @dev Deploys and returns the address of a clone that mimics the behaviour of `master`.\n *\n * This function uses the create opcode, which should never revert.\n */\n function clone(address master) internal returns (address instance) {\n // solhint-disable-next-line no-inline-assembly\n assembly {\n let ptr := mload(0x40)\n mstore(ptr, 0x3d602d80600a3d3981f3363d3d373d3d3d363d73000000000000000000000000)\n mstore(add(ptr, 0x14), shl(0x60, master))\n mstore(add(ptr, 0x28), 0x5af43d82803e903d91602b57fd5bf30000000000000000000000000000000000)\n instance := create(0, ptr, 0x37)\n }\n require(instance != address(0), \"ERC1167: create failed\");\n }\n\n /**\n * @dev Deploys and returns the address of a clone that mimics the behaviour of `master`.\n *\n * This function uses the create2 opcode and a `salt` to deterministically deploy\n * the clone. Using the same `master` and `salt` multiple time will revert, since\n * the clones cannot be deployed twice at the same address.\n */\n function cloneDeterministic(address master, bytes32 salt) internal returns (address instance) {\n // solhint-disable-next-line no-inline-assembly\n assembly {\n let ptr := mload(0x40)\n mstore(ptr, 0x3d602d80600a3d3981f3363d3d373d3d3d363d73000000000000000000000000)\n mstore(add(ptr, 0x14), shl(0x60, master))\n mstore(add(ptr, 0x28), 0x5af43d82803e903d91602b57fd5bf30000000000000000000000000000000000)\n instance := create2(0, ptr, 0x37, salt)\n }\n require(instance != address(0), \"ERC1167: create2 failed\");\n }\n\n /**\n * @dev Computes the address of a clone deployed using {Clones-cloneDeterministic}.\n */\n function predictDeterministicAddress(address master, bytes32 salt, address deployer) internal pure returns (address predicted) {\n // solhint-disable-next-line no-inline-assembly\n assembly {\n let ptr := mload(0x40)\n mstore(ptr, 0x3d602d80600a3d3981f3363d3d373d3d3d363d73000000000000000000000000)\n mstore(add(ptr, 0x14), shl(0x60, master))\n mstore(add(ptr, 0x28), 0x5af43d82803e903d91602b57fd5bf3ff00000000000000000000000000000000)\n mstore(add(ptr, 0x38), shl(0x60, deployer))\n mstore(add(ptr, 0x4c), salt)\n mstore(add(ptr, 0x6c), keccak256(ptr, 0x37))\n predicted := keccak256(add(ptr, 0x37), 0x55)\n }\n }\n\n /**\n * @dev Computes the address of a clone deployed using {Clones-cloneDeterministic}.\n */\n function predictDeterministicAddress(address master, bytes32 salt) internal view returns (address predicted) {\n return predictDeterministicAddress(master, salt, address(this));\n }\n}\n" + }, + "@openzeppelin/contracts-upgradeable/utils/ReentrancyGuardUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <0.8.0;\nimport \"../proxy/Initializable.sol\";\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 ReentrancyGuardUpgradeable is Initializable {\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 function __ReentrancyGuard_init() internal initializer {\n __ReentrancyGuard_init_unchained();\n }\n\n function __ReentrancyGuard_init_unchained() internal initializer {\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 uint256[49] private __gap;\n}\n" + }, + "contracts/amm/OwnerPausableUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.6.12;\n\nimport \"@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol\";\nimport \"@openzeppelin/contracts-upgradeable/utils/PausableUpgradeable.sol\";\n\n/**\n * @title OwnerPausable\n * @notice An ownable contract allows the owner to pause and unpause the\n * contract without a delay.\n * @dev Only methods using the provided modifiers will be paused.\n */\nabstract contract OwnerPausableUpgradeable is\n OwnableUpgradeable,\n PausableUpgradeable\n{\n function __OwnerPausable_init() internal initializer {\n __Context_init_unchained();\n __Ownable_init_unchained();\n __Pausable_init_unchained();\n }\n\n /**\n * @notice Pause the contract. Revert if already paused.\n */\n function pause() external onlyOwner {\n PausableUpgradeable._pause();\n }\n\n /**\n * @notice Unpause the contract. Revert if already unpaused.\n */\n function unpause() external onlyOwner {\n PausableUpgradeable._unpause();\n }\n}\n" + }, + "contracts/amm/SwapUtils.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.6.12;\n\nimport \"@openzeppelin/contracts/math/SafeMath.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/SafeERC20.sol\";\nimport \"./AmplificationUtils.sol\";\nimport \"./LPToken.sol\";\nimport \"./MathUtils.sol\";\n\n/**\n * @title SwapUtils library\n * @notice A library to be used within Swap.sol. Contains functions responsible for custody and AMM functionalities.\n * @dev Contracts relying on this library must initialize SwapUtils.Swap struct then use this library\n * for SwapUtils.Swap struct. Note that this library contains both functions called by users and admins.\n * Admin functions should be protected within contracts using this library.\n */\nlibrary SwapUtils {\n using SafeERC20 for IERC20;\n using SafeMath for uint256;\n using MathUtils for uint256;\n\n /*** EVENTS ***/\n\n event TokenSwap(\n address indexed buyer,\n uint256 tokensSold,\n uint256 tokensBought,\n uint128 soldId,\n uint128 boughtId\n );\n event AddLiquidity(\n address indexed provider,\n uint256[] tokenAmounts,\n uint256[] fees,\n uint256 invariant,\n uint256 lpTokenSupply\n );\n event RemoveLiquidity(\n address indexed provider,\n uint256[] tokenAmounts,\n uint256 lpTokenSupply\n );\n event RemoveLiquidityOne(\n address indexed provider,\n uint256 lpTokenAmount,\n uint256 lpTokenSupply,\n uint256 boughtId,\n uint256 tokensBought\n );\n event RemoveLiquidityImbalance(\n address indexed provider,\n uint256[] tokenAmounts,\n uint256[] fees,\n uint256 invariant,\n uint256 lpTokenSupply\n );\n event NewAdminFee(uint256 newAdminFee);\n event NewSwapFee(uint256 newSwapFee);\n\n struct Swap {\n // variables around the ramp management of A,\n // the amplification coefficient * n * (n - 1)\n // see https://www.curve.fi/stableswap-paper.pdf for details\n uint256 initialA;\n uint256 futureA;\n uint256 initialATime;\n uint256 futureATime;\n // fee calculation\n uint256 swapFee;\n uint256 adminFee;\n LPToken lpToken;\n // contract references for all tokens being pooled\n IERC20[] pooledTokens;\n // multipliers for each pooled token's precision to get to POOL_PRECISION_DECIMALS\n // for example, TBTC has 18 decimals, so the multiplier should be 1. WBTC\n // has 8, so the multiplier should be 10 ** 18 / 10 ** 8 => 10 ** 10\n uint256[] tokenPrecisionMultipliers;\n // the pool balance of each token, in the token's precision\n // the contract's actual token balance might differ\n uint256[] balances;\n }\n\n // Struct storing variables used in calculations in the\n // calculateWithdrawOneTokenDY function to avoid stack too deep errors\n struct CalculateWithdrawOneTokenDYInfo {\n uint256 d0;\n uint256 d1;\n uint256 newY;\n uint256 feePerToken;\n uint256 preciseA;\n }\n\n // Struct storing variables used in calculations in the\n // {add,remove}Liquidity functions to avoid stack too deep errors\n struct ManageLiquidityInfo {\n uint256 d0;\n uint256 d1;\n uint256 d2;\n uint256 preciseA;\n LPToken lpToken;\n uint256 totalSupply;\n uint256[] balances;\n uint256[] multipliers;\n }\n\n // the precision all pools tokens will be converted to\n uint8 public constant POOL_PRECISION_DECIMALS = 18;\n\n // the denominator used to calculate admin and LP fees. For example, an\n // LP fee might be something like tradeAmount.mul(fee).div(FEE_DENOMINATOR)\n uint256 private constant FEE_DENOMINATOR = 10**10;\n\n // Max swap fee is 1% or 100bps of each swap\n uint256 public constant MAX_SWAP_FEE = 10**8;\n\n // Max adminFee is 100% of the swapFee\n // adminFee does not add additional fee on top of swapFee\n // Instead it takes a certain % of the swapFee. Therefore it has no impact on the\n // users but only on the earnings of LPs\n uint256 public constant MAX_ADMIN_FEE = 10**10;\n\n // Constant value used as max loop limit\n uint256 private constant MAX_LOOP_LIMIT = 256;\n\n /*** VIEW & PURE FUNCTIONS ***/\n\n function _getAPrecise(Swap storage self) internal view returns (uint256) {\n return AmplificationUtils._getAPrecise(self);\n }\n\n /**\n * @notice Calculate the dy, the amount of selected token that user receives and\n * the fee of withdrawing in one token\n * @param tokenAmount the amount to withdraw in the pool's precision\n * @param tokenIndex which token will be withdrawn\n * @param self Swap struct to read from\n * @return the amount of token user will receive\n */\n function calculateWithdrawOneToken(\n Swap storage self,\n uint256 tokenAmount,\n uint8 tokenIndex\n ) external view returns (uint256) {\n (uint256 availableTokenAmount, ) = _calculateWithdrawOneToken(\n self,\n tokenAmount,\n tokenIndex,\n self.lpToken.totalSupply()\n );\n return availableTokenAmount;\n }\n\n function _calculateWithdrawOneToken(\n Swap storage self,\n uint256 tokenAmount,\n uint8 tokenIndex,\n uint256 totalSupply\n ) internal view returns (uint256, uint256) {\n uint256 dy;\n uint256 newY;\n uint256 currentY;\n\n (dy, newY, currentY) = calculateWithdrawOneTokenDY(\n self,\n tokenIndex,\n tokenAmount,\n totalSupply\n );\n\n // dy_0 (without fees)\n // dy, dy_0 - dy\n\n uint256 dySwapFee = currentY\n .sub(newY)\n .div(self.tokenPrecisionMultipliers[tokenIndex])\n .sub(dy);\n\n return (dy, dySwapFee);\n }\n\n /**\n * @notice Calculate the dy of withdrawing in one token\n * @param self Swap struct to read from\n * @param tokenIndex which token will be withdrawn\n * @param tokenAmount the amount to withdraw in the pools precision\n * @return the d and the new y after withdrawing one token\n */\n function calculateWithdrawOneTokenDY(\n Swap storage self,\n uint8 tokenIndex,\n uint256 tokenAmount,\n uint256 totalSupply\n )\n internal\n view\n returns (\n uint256,\n uint256,\n uint256\n )\n {\n // Get the current D, then solve the stableswap invariant\n // y_i for D - tokenAmount\n uint256[] memory xp = _xp(self);\n\n require(tokenIndex < xp.length, \"Token index out of range\");\n\n\n CalculateWithdrawOneTokenDYInfo memory v\n = CalculateWithdrawOneTokenDYInfo(0, 0, 0, 0, 0);\n v.preciseA = _getAPrecise(self);\n v.d0 = getD(xp, v.preciseA);\n v.d1 = v.d0.sub(tokenAmount.mul(v.d0).div(totalSupply));\n\n require(tokenAmount <= xp[tokenIndex], \"Withdraw exceeds available\");\n\n v.newY = getYD(v.preciseA, tokenIndex, xp, v.d1);\n\n uint256[] memory xpReduced = new uint256[](xp.length);\n\n v.feePerToken = _feePerToken(self.swapFee, xp.length);\n for (uint256 i = 0; i < xp.length; i++) {\n uint256 xpi = xp[i];\n // if i == tokenIndex, dxExpected = xp[i] * d1 / d0 - newY\n // else dxExpected = xp[i] - (xp[i] * d1 / d0)\n // xpReduced[i] -= dxExpected * fee / FEE_DENOMINATOR\n xpReduced[i] = xpi.sub(\n (\n (i == tokenIndex)\n ? xpi.mul(v.d1).div(v.d0).sub(v.newY)\n : xpi.sub(xpi.mul(v.d1).div(v.d0))\n )\n .mul(v.feePerToken)\n .div(FEE_DENOMINATOR)\n );\n }\n\n uint256 dy = xpReduced[tokenIndex].sub(\n getYD(v.preciseA, tokenIndex, xpReduced, v.d1)\n );\n dy = dy.sub(1).div(self.tokenPrecisionMultipliers[tokenIndex]);\n\n return (dy, v.newY, xp[tokenIndex]);\n }\n\n /**\n * @notice Calculate the price of a token in the pool with given\n * precision-adjusted balances and a particular D.\n *\n * @dev This is accomplished via solving the invariant iteratively.\n * See the StableSwap paper and Curve.fi implementation for further details.\n *\n * x_1**2 + x1 * (sum' - (A*n**n - 1) * D / (A * n**n)) = D ** (n + 1) / (n ** (2 * n) * prod' * A)\n * x_1**2 + b*x_1 = c\n * x_1 = (x_1**2 + c) / (2*x_1 + b)\n *\n * @param a the amplification coefficient * n * (n - 1). See the StableSwap paper for details.\n * @param tokenIndex Index of token we are calculating for.\n * @param xp a precision-adjusted set of pool balances. Array should be\n * the same cardinality as the pool.\n * @param d the stableswap invariant\n * @return the price of the token, in the same precision as in xp\n */\n function getYD(\n uint256 a,\n uint8 tokenIndex,\n uint256[] memory xp,\n uint256 d\n ) internal pure returns (uint256) {\n uint256 numTokens = xp.length;\n require(tokenIndex < numTokens, \"Token not found\");\n\n uint256 c = d;\n uint256 s;\n uint256 nA = a.mul(numTokens);\n\n for (uint256 i = 0; i < numTokens; i++) {\n if (i != tokenIndex) {\n s = s.add(xp[i]);\n c = c.mul(d).div(xp[i].mul(numTokens));\n // If we were to protect the division loss we would have to keep the denominator separate\n // and divide at the end. However this leads to overflow with large numTokens or/and D.\n // c = c * D * D * D * ... overflow!\n }\n }\n c = c.mul(d).mul(AmplificationUtils.A_PRECISION).div(nA.mul(numTokens));\n\n uint256 b = s.add(d.mul(AmplificationUtils.A_PRECISION).div(nA));\n uint256 yPrev;\n uint256 y = d;\n for (uint256 i = 0; i < MAX_LOOP_LIMIT; i++) {\n yPrev = y;\n y = y.mul(y).add(c).div(y.mul(2).add(b).sub(d));\n if (y.within1(yPrev)) {\n return y;\n }\n }\n revert(\"Approximation did not converge\");\n }\n\n /**\n * @notice Get D, the StableSwap invariant, based on a set of balances and a particular A.\n * @param xp a precision-adjusted set of pool balances. Array should be the same cardinality\n * as the pool.\n * @param a the amplification coefficient * n * (n - 1) in A_PRECISION.\n * See the StableSwap paper for details\n * @return the invariant, at the precision of the pool\n */\n function getD(uint256[] memory xp, uint256 a)\n internal\n pure\n returns (uint256)\n {\n uint256 numTokens = xp.length;\n uint256 s;\n for (uint256 i = 0; i < numTokens; i++) {\n s = s.add(xp[i]);\n }\n if (s == 0) {\n return 0;\n }\n\n uint256 prevD;\n uint256 d = s;\n uint256 nA = a.mul(numTokens);\n\n for (uint256 i = 0; i < MAX_LOOP_LIMIT; i++) {\n uint256 dP = d;\n for (uint256 j = 0; j < numTokens; j++) {\n dP = dP.mul(d).div(xp[j].mul(numTokens));\n // If we were to protect the division loss we would have to keep the denominator separate\n // and divide at the end. However this leads to overflow with large numTokens or/and D.\n // dP = dP * D * D * D * ... overflow!\n }\n prevD = d;\n d = nA\n .mul(s)\n .div(AmplificationUtils.A_PRECISION)\n .add(dP.mul(numTokens))\n .mul(d)\n .div(\n nA\n .sub(AmplificationUtils.A_PRECISION)\n .mul(d)\n .div(AmplificationUtils.A_PRECISION)\n .add(numTokens.add(1).mul(dP))\n );\n if (d.within1(prevD)) {\n return d;\n }\n }\n\n // Convergence should occur in 4 loops or less. If this is reached, there may be something wrong\n // with the pool. If this were to occur repeatedly, LPs should withdraw via `removeLiquidity()`\n // function which does not rely on D.\n revert(\"D does not converge\");\n }\n\n /**\n * @notice Given a set of balances and precision multipliers, return the\n * precision-adjusted balances.\n *\n * @param balances an array of token balances, in their native precisions.\n * These should generally correspond with pooled tokens.\n *\n * @param precisionMultipliers an array of multipliers, corresponding to\n * the amounts in the balances array. When multiplied together they\n * should yield amounts at the pool's precision.\n *\n * @return an array of amounts \"scaled\" to the pool's precision\n */\n function _xp(\n uint256[] memory balances,\n uint256[] memory precisionMultipliers\n ) internal pure returns (uint256[] memory) {\n uint256 numTokens = balances.length;\n require(\n numTokens == precisionMultipliers.length,\n \"Balances must match multipliers\"\n );\n uint256[] memory xp = new uint256[](numTokens);\n for (uint256 i = 0; i < numTokens; i++) {\n xp[i] = balances[i].mul(precisionMultipliers[i]);\n }\n return xp;\n }\n\n /**\n * @notice Return the precision-adjusted balances of all tokens in the pool\n * @param self Swap struct to read from\n * @return the pool balances \"scaled\" to the pool's precision, allowing\n * them to be more easily compared.\n */\n function _xp(Swap storage self) internal view returns (uint256[] memory) {\n return _xp(self.balances, self.tokenPrecisionMultipliers);\n }\n\n /**\n * @notice Get the virtual price, to help calculate profit\n * @param self Swap struct to read from\n * @return the virtual price, scaled to precision of POOL_PRECISION_DECIMALS\n */\n function getVirtualPrice(Swap storage self)\n external\n view\n returns (uint256)\n {\n uint256 d = getD(_xp(self), _getAPrecise(self));\n LPToken lpToken = self.lpToken;\n uint256 supply = lpToken.totalSupply();\n if (supply > 0) {\n return d.mul(10**uint256(POOL_PRECISION_DECIMALS)).div(supply);\n }\n return 0;\n }\n\n /**\n * @notice Calculate the new balances of the tokens given the indexes of the token\n * that is swapped from (FROM) and the token that is swapped to (TO).\n * This function is used as a helper function to calculate how much TO token\n * the user should receive on swap.\n *\n * @param preciseA precise form of amplification coefficient\n * @param tokenIndexFrom index of FROM token\n * @param tokenIndexTo index of TO token\n * @param x the new total amount of FROM token\n * @param xp balances of the tokens in the pool\n * @return the amount of TO token that should remain in the pool\n */\n function getY(\n uint256 preciseA,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 x,\n uint256[] memory xp\n ) internal pure returns (uint256) {\n uint256 numTokens = xp.length;\n require(\n tokenIndexFrom != tokenIndexTo,\n \"Can't compare token to itself\"\n );\n require(\n tokenIndexFrom < numTokens && tokenIndexTo < numTokens,\n \"Tokens must be in pool\"\n );\n\n uint256 d = getD(xp, preciseA);\n uint256 c = d;\n uint256 s;\n uint256 nA = numTokens.mul(preciseA);\n\n uint256 _x;\n for (uint256 i = 0; i < numTokens; i++) {\n if (i == tokenIndexFrom) {\n _x = x;\n } else if (i != tokenIndexTo) {\n _x = xp[i];\n } else {\n continue;\n }\n s = s.add(_x);\n c = c.mul(d).div(_x.mul(numTokens));\n // If we were to protect the division loss we would have to keep the denominator separate\n // and divide at the end. However this leads to overflow with large numTokens or/and D.\n // c = c * D * D * D * ... overflow!\n }\n c = c.mul(d).mul(AmplificationUtils.A_PRECISION).div(nA.mul(numTokens));\n uint256 b = s.add(d.mul(AmplificationUtils.A_PRECISION).div(nA));\n uint256 yPrev;\n uint256 y = d;\n\n // iterative approximation\n for (uint256 i = 0; i < MAX_LOOP_LIMIT; i++) {\n yPrev = y;\n y = y.mul(y).add(c).div(y.mul(2).add(b).sub(d));\n if (y.within1(yPrev)) {\n return y;\n }\n }\n revert(\"Approximation did not converge\");\n }\n\n /**\n * @notice Externally calculates a swap between two tokens.\n * @param self Swap struct to read from\n * @param tokenIndexFrom the token to sell\n * @param tokenIndexTo the token to buy\n * @param dx the number of tokens to sell. If the token charges a fee on transfers,\n * use the amount that gets transferred after the fee.\n * @return dy the number of tokens the user will get\n */\n function calculateSwap(\n Swap storage self,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx\n ) external view returns (uint256 dy) {\n (dy, ) = _calculateSwap(\n self,\n tokenIndexFrom,\n tokenIndexTo,\n dx,\n self.balances\n );\n }\n\n /**\n * @notice Internally calculates a swap between two tokens.\n *\n * @dev The caller is expected to transfer the actual amounts (dx and dy)\n * using the token contracts.\n *\n * @param self Swap struct to read from\n * @param tokenIndexFrom the token to sell\n * @param tokenIndexTo the token to buy\n * @param dx the number of tokens to sell. If the token charges a fee on transfers,\n * use the amount that gets transferred after the fee.\n * @return dy the number of tokens the user will get\n * @return dyFee the associated fee\n */\n function _calculateSwap(\n Swap storage self,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx,\n uint256[] memory balances\n ) internal view returns (uint256 dy, uint256 dyFee) {\n uint256[] memory multipliers = self.tokenPrecisionMultipliers;\n uint256[] memory xp = _xp(balances, multipliers);\n require(\n tokenIndexFrom < xp.length && tokenIndexTo < xp.length,\n \"Token index out of range\"\n );\n uint256 x = dx.mul(multipliers[tokenIndexFrom]).add(xp[tokenIndexFrom]);\n uint256 y = getY(\n _getAPrecise(self),\n tokenIndexFrom,\n tokenIndexTo,\n x,\n xp\n );\n dy = xp[tokenIndexTo].sub(y).sub(1);\n dyFee = dy.mul(self.swapFee).div(FEE_DENOMINATOR);\n dy = dy.sub(dyFee).div(multipliers[tokenIndexTo]);\n }\n\n /**\n * @notice A simple method to calculate amount of each underlying\n * tokens that is returned upon burning given amount of\n * LP tokens\n *\n * @param amount the amount of LP tokens that would to be burned on\n * withdrawal\n * @return array of amounts of tokens user will receive\n */\n function calculateRemoveLiquidity(Swap storage self, uint256 amount)\n external\n view\n returns (uint256[] memory)\n {\n return\n _calculateRemoveLiquidity(\n self.balances,\n amount,\n self.lpToken.totalSupply()\n );\n }\n\n function _calculateRemoveLiquidity(\n uint256[] memory balances,\n uint256 amount,\n uint256 totalSupply\n ) internal pure returns (uint256[] memory) {\n require(amount <= totalSupply, \"Cannot exceed total supply\");\n\n uint256[] memory amounts = new uint256[](balances.length);\n\n for (uint256 i = 0; i < balances.length; i++) {\n amounts[i] = balances[i].mul(amount).div(totalSupply);\n }\n return amounts;\n }\n\n /**\n * @notice A simple method to calculate prices from deposits or\n * withdrawals, excluding fees but including slippage. This is\n * helpful as an input into the various \"min\" parameters on calls\n * to fight front-running\n *\n * @dev This shouldn't be used outside frontends for user estimates.\n *\n * @param self Swap struct to read from\n * @param amounts an array of token amounts to deposit or withdrawal,\n * corresponding to pooledTokens. The amount should be in each\n * pooled token's native precision. If a token charges a fee on transfers,\n * use the amount that gets transferred after the fee.\n * @param deposit whether this is a deposit or a withdrawal\n * @return if deposit was true, total amount of lp token that will be minted and if\n * deposit was false, total amount of lp token that will be burned\n */\n function calculateTokenAmount(\n Swap storage self,\n uint256[] calldata amounts,\n bool deposit\n ) external view returns (uint256) {\n uint256 a = _getAPrecise(self);\n uint256[] memory balances = self.balances;\n uint256[] memory multipliers = self.tokenPrecisionMultipliers;\n\n uint256 d0 = getD(_xp(balances, multipliers), a);\n for (uint256 i = 0; i < balances.length; i++) {\n if (deposit) {\n balances[i] = balances[i].add(amounts[i]);\n } else {\n balances[i] = balances[i].sub(\n amounts[i],\n \"Cannot withdraw more than available\"\n );\n }\n }\n uint256 d1 = getD(_xp(balances, multipliers), a);\n uint256 totalSupply = self.lpToken.totalSupply();\n\n if (deposit) {\n return d1.sub(d0).mul(totalSupply).div(d0);\n } else {\n return d0.sub(d1).mul(totalSupply).div(d0);\n }\n }\n\n /**\n * @notice return accumulated amount of admin fees of the token with given index\n * @param self Swap struct to read from\n * @param index Index of the pooled token\n * @return admin balance in the token's precision\n */\n function getAdminBalance(Swap storage self, uint256 index)\n external\n view\n returns (uint256)\n {\n require(index < self.pooledTokens.length, \"Token index out of range\");\n return\n self.pooledTokens[index].balanceOf(address(this)).sub(\n self.balances[index]\n );\n }\n\n /**\n * @notice internal helper function to calculate fee per token multiplier used in\n * swap fee calculations\n * @param swapFee swap fee for the tokens\n * @param numTokens number of tokens pooled\n */\n function _feePerToken(uint256 swapFee, uint256 numTokens)\n internal\n pure\n returns (uint256)\n {\n return swapFee.mul(numTokens).div(numTokens.sub(1).mul(4));\n }\n\n /*** STATE MODIFYING FUNCTIONS ***/\n\n /**\n * @notice swap two tokens in the pool\n * @param self Swap struct to read from and write to\n * @param tokenIndexFrom the token the user wants to sell\n * @param tokenIndexTo the token the user wants to buy\n * @param dx the amount of tokens the user wants to sell\n * @param minDy the min amount the user would like to receive, or revert.\n * @return amount of token user received on swap\n */\n function swap(\n Swap storage self,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx,\n uint256 minDy\n ) external returns (uint256) {\n {\n IERC20 tokenFrom = self.pooledTokens[tokenIndexFrom];\n require(\n dx <= tokenFrom.balanceOf(msg.sender),\n \"Cannot swap more than you own\"\n );\n // Transfer tokens first to see if a fee was charged on transfer\n uint256 beforeBalance = tokenFrom.balanceOf(address(this));\n tokenFrom.safeTransferFrom(msg.sender, address(this), dx);\n\n // Use the actual transferred amount for AMM math\n dx = tokenFrom.balanceOf(address(this)).sub(beforeBalance);\n }\n\n uint256 dy;\n uint256 dyFee;\n uint256[] memory balances = self.balances;\n (dy, dyFee) = _calculateSwap(\n self,\n tokenIndexFrom,\n tokenIndexTo,\n dx,\n balances\n );\n require(dy >= minDy, \"Swap didn't result in min tokens\");\n\n uint256 dyAdminFee = dyFee.mul(self.adminFee).div(FEE_DENOMINATOR).div(\n self.tokenPrecisionMultipliers[tokenIndexTo]\n );\n\n self.balances[tokenIndexFrom] = balances[tokenIndexFrom].add(dx);\n self.balances[tokenIndexTo] = balances[tokenIndexTo].sub(dy).sub(\n dyAdminFee\n );\n\n self.pooledTokens[tokenIndexTo].safeTransfer(msg.sender, dy);\n\n emit TokenSwap(msg.sender, dx, dy, tokenIndexFrom, tokenIndexTo);\n\n return dy;\n }\n\n /**\n * @notice Add liquidity to the pool\n * @param self Swap struct to read from and write to\n * @param amounts the amounts of each token to add, in their native precision\n * @param minToMint the minimum LP tokens adding this amount of liquidity\n * should mint, otherwise revert. Handy for front-running mitigation\n * allowed addresses. If the pool is not in the guarded launch phase, this parameter will be ignored.\n * @return amount of LP token user received\n */\n function addLiquidity(\n Swap storage self,\n uint256[] memory amounts,\n uint256 minToMint\n ) external returns (uint256) {\n IERC20[] memory pooledTokens = self.pooledTokens;\n require(\n amounts.length == pooledTokens.length,\n \"Amounts must match pooled tokens\"\n );\n\n // current state\n ManageLiquidityInfo memory v = ManageLiquidityInfo(\n 0,\n 0,\n 0,\n _getAPrecise(self),\n self.lpToken,\n 0,\n self.balances,\n self.tokenPrecisionMultipliers\n );\n v.totalSupply = v.lpToken.totalSupply();\n\n if (v.totalSupply != 0) {\n v.d0 = getD(_xp(v.balances, v.multipliers), v.preciseA);\n }\n\n uint256[] memory newBalances = new uint256[](pooledTokens.length);\n\n for (uint256 i = 0; i < pooledTokens.length; i++) {\n require(\n v.totalSupply != 0 || amounts[i] > 0,\n \"Must supply all tokens in pool\"\n );\n\n // Transfer tokens first to see if a fee was charged on transfer\n if (amounts[i] != 0) {\n uint256 beforeBalance = pooledTokens[i].balanceOf(\n address(this)\n );\n pooledTokens[i].safeTransferFrom(\n msg.sender,\n address(this),\n amounts[i]\n );\n\n // Update the amounts[] with actual transfer amount\n amounts[i] = pooledTokens[i].balanceOf(address(this)).sub(\n beforeBalance\n );\n }\n\n newBalances[i] = v.balances[i].add(amounts[i]);\n }\n\n // invariant after change\n v.d1 = getD(_xp(newBalances, v.multipliers), v.preciseA);\n require(v.d1 > v.d0, \"D should increase\");\n\n // updated to reflect fees and calculate the user's LP tokens\n v.d2 = v.d1;\n uint256[] memory fees = new uint256[](pooledTokens.length);\n\n if (v.totalSupply != 0) {\n uint256 feePerToken = _feePerToken(\n self.swapFee,\n pooledTokens.length\n );\n for (uint256 i = 0; i < pooledTokens.length; i++) {\n uint256 idealBalance = v.d1.mul(v.balances[i]).div(v.d0);\n fees[i] = feePerToken\n .mul(idealBalance.difference(newBalances[i]))\n .div(FEE_DENOMINATOR);\n self.balances[i] = newBalances[i].sub(\n fees[i].mul(self.adminFee).div(FEE_DENOMINATOR)\n );\n newBalances[i] = newBalances[i].sub(fees[i]);\n }\n v.d2 = getD(_xp(newBalances, v.multipliers), v.preciseA);\n } else {\n // the initial depositor doesn't pay fees\n self.balances = newBalances;\n }\n\n uint256 toMint;\n if (v.totalSupply == 0) {\n toMint = v.d1;\n } else {\n toMint = v.d2.sub(v.d0).mul(v.totalSupply).div(v.d0);\n }\n\n require(toMint >= minToMint, \"Couldn't mint min requested\");\n\n // mint the user's LP tokens\n v.lpToken.mint(msg.sender, toMint);\n\n emit AddLiquidity(\n msg.sender,\n amounts,\n fees,\n v.d1,\n v.totalSupply.add(toMint)\n );\n\n return toMint;\n }\n\n /**\n * @notice Burn LP tokens to remove liquidity from the pool.\n * @dev Liquidity can always be removed, even when the pool is paused.\n * @param self Swap struct to read from and write to\n * @param amount the amount of LP tokens to burn\n * @param minAmounts the minimum amounts of each token in the pool\n * acceptable for this burn. Useful as a front-running mitigation\n * @return amounts of tokens the user received\n */\n function removeLiquidity(\n Swap storage self,\n uint256 amount,\n uint256[] calldata minAmounts\n ) external returns (uint256[] memory) {\n LPToken lpToken = self.lpToken;\n IERC20[] memory pooledTokens = self.pooledTokens;\n require(amount <= lpToken.balanceOf(msg.sender), \">LP.balanceOf\");\n require(\n minAmounts.length == pooledTokens.length,\n \"minAmounts must match poolTokens\"\n );\n\n uint256[] memory balances = self.balances;\n uint256 totalSupply = lpToken.totalSupply();\n\n uint256[] memory amounts = _calculateRemoveLiquidity(\n balances,\n amount,\n totalSupply\n );\n\n for (uint256 i = 0; i < amounts.length; i++) {\n require(amounts[i] >= minAmounts[i], \"amounts[i] < minAmounts[i]\");\n self.balances[i] = balances[i].sub(amounts[i]);\n pooledTokens[i].safeTransfer(msg.sender, amounts[i]);\n }\n\n lpToken.burnFrom(msg.sender, amount);\n\n emit RemoveLiquidity(msg.sender, amounts, totalSupply.sub(amount));\n\n return amounts;\n }\n\n /**\n * @notice Remove liquidity from the pool all in one token.\n * @param self Swap struct to read from and write to\n * @param tokenAmount the amount of the lp tokens to burn\n * @param tokenIndex the index of the token you want to receive\n * @param minAmount the minimum amount to withdraw, otherwise revert\n * @return amount chosen token that user received\n */\n function removeLiquidityOneToken(\n Swap storage self,\n uint256 tokenAmount,\n uint8 tokenIndex,\n uint256 minAmount\n ) external returns (uint256) {\n LPToken lpToken = self.lpToken;\n IERC20[] memory pooledTokens = self.pooledTokens;\n\n require(tokenAmount <= lpToken.balanceOf(msg.sender), \">LP.balanceOf\");\n require(tokenIndex < pooledTokens.length, \"Token not found\");\n\n uint256 totalSupply = lpToken.totalSupply();\n\n (uint256 dy, uint256 dyFee) = _calculateWithdrawOneToken(\n self,\n tokenAmount,\n tokenIndex,\n totalSupply\n );\n\n require(dy >= minAmount, \"dy < minAmount\");\n\n self.balances[tokenIndex] = self.balances[tokenIndex].sub(\n dy.add(dyFee.mul(self.adminFee).div(FEE_DENOMINATOR))\n );\n lpToken.burnFrom(msg.sender, tokenAmount);\n pooledTokens[tokenIndex].safeTransfer(msg.sender, dy);\n\n emit RemoveLiquidityOne(\n msg.sender,\n tokenAmount,\n totalSupply,\n tokenIndex,\n dy\n );\n\n return dy;\n }\n\n /**\n * @notice Remove liquidity from the pool, weighted differently than the\n * pool's current balances.\n *\n * @param self Swap struct to read from and write to\n * @param amounts how much of each token to withdraw\n * @param maxBurnAmount the max LP token provider is willing to pay to\n * remove liquidity. Useful as a front-running mitigation.\n * @return actual amount of LP tokens burned in the withdrawal\n */\n function removeLiquidityImbalance(\n Swap storage self,\n uint256[] memory amounts,\n uint256 maxBurnAmount\n ) public returns (uint256) {\n ManageLiquidityInfo memory v = ManageLiquidityInfo(\n 0,\n 0,\n 0,\n _getAPrecise(self),\n self.lpToken,\n 0,\n self.balances,\n self.tokenPrecisionMultipliers\n );\n v.totalSupply = v.lpToken.totalSupply();\n\n IERC20[] memory pooledTokens = self.pooledTokens;\n\n require(\n amounts.length == pooledTokens.length,\n \"Amounts should match pool tokens\"\n );\n\n require(\n maxBurnAmount <= v.lpToken.balanceOf(msg.sender) &&\n maxBurnAmount != 0,\n \">LP.balanceOf\"\n );\n\n uint256 feePerToken = _feePerToken(self.swapFee, pooledTokens.length);\n uint256[] memory fees = new uint256[](pooledTokens.length);\n {\n uint256[] memory balances1 = new uint256[](pooledTokens.length);\n v.d0 = getD(_xp(v.balances, v.multipliers), v.preciseA);\n for (uint256 i = 0; i < pooledTokens.length; i++) {\n balances1[i] = v.balances[i].sub(\n amounts[i],\n \"Cannot withdraw more than available\"\n );\n }\n v.d1 = getD(_xp(balances1, v.multipliers), v.preciseA);\n\n for (uint256 i = 0; i < pooledTokens.length; i++) {\n uint256 idealBalance = v.d1.mul(v.balances[i]).div(v.d0);\n uint256 difference = idealBalance.difference(balances1[i]);\n fees[i] = feePerToken.mul(difference).div(FEE_DENOMINATOR);\n self.balances[i] = balances1[i].sub(\n fees[i].mul(self.adminFee).div(FEE_DENOMINATOR)\n );\n balances1[i] = balances1[i].sub(fees[i]);\n }\n\n v.d2 = getD(_xp(balances1, v.multipliers), v.preciseA);\n }\n uint256 tokenAmount = v.d0.sub(v.d2).mul(v.totalSupply).div(v.d0);\n require(tokenAmount != 0, \"Burnt amount cannot be zero\");\n tokenAmount = tokenAmount.add(1);\n\n require(tokenAmount <= maxBurnAmount, \"tokenAmount > maxBurnAmount\");\n\n v.lpToken.burnFrom(msg.sender, tokenAmount);\n\n for (uint256 i = 0; i < pooledTokens.length; i++) {\n pooledTokens[i].safeTransfer(msg.sender, amounts[i]);\n }\n\n emit RemoveLiquidityImbalance(\n msg.sender,\n amounts,\n fees,\n v.d1,\n v.totalSupply.sub(tokenAmount)\n );\n\n return tokenAmount;\n }\n\n /**\n * @notice withdraw all admin fees to a given address\n * @param self Swap struct to withdraw fees from\n * @param to Address to send the fees to\n */\n function withdrawAdminFees(Swap storage self, address to) external {\n IERC20[] memory pooledTokens = self.pooledTokens;\n for (uint256 i = 0; i < pooledTokens.length; i++) {\n IERC20 token = pooledTokens[i];\n uint256 balance = token.balanceOf(address(this)).sub(\n self.balances[i]\n );\n if (balance != 0) {\n token.safeTransfer(to, balance);\n }\n }\n }\n\n /**\n * @notice Sets the admin fee\n * @dev adminFee cannot be higher than 100% of the swap fee\n * @param self Swap struct to update\n * @param newAdminFee new admin fee to be applied on future transactions\n */\n function setAdminFee(Swap storage self, uint256 newAdminFee) external {\n require(newAdminFee <= MAX_ADMIN_FEE, \"Fee is too high\");\n self.adminFee = newAdminFee;\n\n emit NewAdminFee(newAdminFee);\n }\n\n /**\n * @notice update the swap fee\n * @dev fee cannot be higher than 1% of each swap\n * @param self Swap struct to update\n * @param newSwapFee new swap fee to be applied on future transactions\n */\n function setSwapFee(Swap storage self, uint256 newSwapFee) external {\n require(newSwapFee <= MAX_SWAP_FEE, \"Fee is too high\");\n self.swapFee = newSwapFee;\n\n emit NewSwapFee(newSwapFee);\n }\n}\n" + }, + "contracts/amm/AmplificationUtils.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.6.12;\n\nimport \"@openzeppelin/contracts/token/ERC20/SafeERC20.sol\";\nimport \"./SwapUtils.sol\";\n\n/**\n * @title AmplificationUtils library\n * @notice A library to calculate and ramp the A parameter of a given `SwapUtils.Swap` struct.\n * This library assumes the struct is fully validated.\n */\nlibrary AmplificationUtils {\n using SafeMath for uint256;\n\n event RampA(\n uint256 oldA,\n uint256 newA,\n uint256 initialTime,\n uint256 futureTime\n );\n event StopRampA(uint256 currentA, uint256 time);\n\n // Constant values used in ramping A calculations\n uint256 public constant A_PRECISION = 100;\n uint256 public constant MAX_A = 10**6;\n uint256 private constant MAX_A_CHANGE = 2;\n uint256 private constant MIN_RAMP_TIME = 7 days;\n\n /**\n * @notice Return A, the amplification coefficient * n * (n - 1)\n * @dev See the StableSwap paper for details\n * @param self Swap struct to read from\n * @return A parameter\n */\n function getA(SwapUtils.Swap storage self) external view returns (uint256) {\n return _getAPrecise(self).div(A_PRECISION);\n }\n\n /**\n * @notice Return A in its raw precision\n * @dev See the StableSwap paper for details\n * @param self Swap struct to read from\n * @return A parameter in its raw precision form\n */\n function getAPrecise(SwapUtils.Swap storage self)\n external\n view\n returns (uint256)\n {\n return _getAPrecise(self);\n }\n\n /**\n * @notice Return A in its raw precision\n * @dev See the StableSwap paper for details\n * @param self Swap struct to read from\n * @return A parameter in its raw precision form\n */\n function _getAPrecise(SwapUtils.Swap storage self)\n internal\n view\n returns (uint256)\n {\n uint256 t1 = self.futureATime; // time when ramp is finished\n uint256 a1 = self.futureA; // final A value when ramp is finished\n\n if (block.timestamp < t1) {\n uint256 t0 = self.initialATime; // time when ramp is started\n uint256 a0 = self.initialA; // initial A value when ramp is started\n if (a1 > a0) {\n // a0 + (a1 - a0) * (block.timestamp - t0) / (t1 - t0)\n return\n a0.add(\n a1.sub(a0).mul(block.timestamp.sub(t0)).div(t1.sub(t0))\n );\n } else {\n // a0 - (a0 - a1) * (block.timestamp - t0) / (t1 - t0)\n return\n a0.sub(\n a0.sub(a1).mul(block.timestamp.sub(t0)).div(t1.sub(t0))\n );\n }\n } else {\n return a1;\n }\n }\n\n /**\n * @notice Start ramping up or down A parameter towards given futureA_ and futureTime_\n * Checks if the change is too rapid, and commits the new A value only when it falls under\n * the limit range.\n * @param self Swap struct to update\n * @param futureA_ the new A to ramp towards\n * @param futureTime_ timestamp when the new A should be reached\n */\n function rampA(\n SwapUtils.Swap storage self,\n uint256 futureA_,\n uint256 futureTime_\n ) external {\n require(\n block.timestamp >= self.initialATime.add(1 days),\n \"Wait 1 day before starting ramp\"\n );\n require(\n futureTime_ >= block.timestamp.add(MIN_RAMP_TIME),\n \"Insufficient ramp time\"\n );\n require(\n futureA_ > 0 && futureA_ < MAX_A,\n \"futureA_ must be > 0 and < MAX_A\"\n );\n\n uint256 initialAPrecise = _getAPrecise(self);\n uint256 futureAPrecise = futureA_.mul(A_PRECISION);\n\n if (futureAPrecise < initialAPrecise) {\n require(\n futureAPrecise.mul(MAX_A_CHANGE) >= initialAPrecise,\n \"futureA_ is too small\"\n );\n } else {\n require(\n futureAPrecise <= initialAPrecise.mul(MAX_A_CHANGE),\n \"futureA_ is too large\"\n );\n }\n\n self.initialA = initialAPrecise;\n self.futureA = futureAPrecise;\n self.initialATime = block.timestamp;\n self.futureATime = futureTime_;\n\n emit RampA(\n initialAPrecise,\n futureAPrecise,\n block.timestamp,\n futureTime_\n );\n }\n\n /**\n * @notice Stops ramping A immediately. Once this function is called, rampA()\n * cannot be called for another 24 hours\n * @param self Swap struct to update\n */\n function stopRampA(SwapUtils.Swap storage self) external {\n require(self.futureATime > block.timestamp, \"Ramp is already stopped\");\n\n uint256 currentA = _getAPrecise(self);\n self.initialA = currentA;\n self.futureA = currentA;\n self.initialATime = block.timestamp;\n self.futureATime = block.timestamp;\n\n emit StopRampA(currentA, block.timestamp);\n }\n}\n" + }, + "@openzeppelin/contracts/token/ERC20/IERC20.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <0.8.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" + }, + "@openzeppelin/contracts/utils/Address.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.2 <0.8.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" + }, + "@openzeppelin/contracts-upgradeable/proxy/Initializable.sol": { + "content": "// SPDX-License-Identifier: MIT\n\n// solhint-disable-next-line compiler-version\npragma solidity >=0.4.24 <0.8.0;\n\nimport \"../utils/AddressUpgradeable.sol\";\n\n/**\n * @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed\n * behind a proxy. Since a proxied contract can't have a constructor, it's common to move constructor logic to an\n * external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer\n * function so it can only be called once. The {initializer} modifier provided by this contract will have this effect.\n *\n * TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as\n * possible by providing the encoded function call as the `_data` argument to {UpgradeableProxy-constructor}.\n *\n * CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure\n * that all initializers are idempotent. This is not verified automatically as constructors are by Solidity.\n */\nabstract contract Initializable {\n\n /**\n * @dev Indicates that the contract has been initialized.\n */\n bool private _initialized;\n\n /**\n * @dev Indicates that the contract is in the process of being initialized.\n */\n bool private _initializing;\n\n /**\n * @dev Modifier to protect an initializer function from being invoked twice.\n */\n modifier initializer() {\n require(_initializing || _isConstructor() || !_initialized, \"Initializable: contract is already initialized\");\n\n bool isTopLevelCall = !_initializing;\n if (isTopLevelCall) {\n _initializing = true;\n _initialized = true;\n }\n\n _;\n\n if (isTopLevelCall) {\n _initializing = false;\n }\n }\n\n /// @dev Returns true if and only if the function is running in the constructor\n function _isConstructor() private view returns (bool) {\n return !AddressUpgradeable.isContract(address(this));\n }\n}\n" + }, + "@openzeppelin/contracts-upgradeable/utils/AddressUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.2 <0.8.0;\n\n/**\n * @dev Collection of functions related to the address type\n */\nlibrary AddressUpgradeable {\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 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" + }, + "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <0.8.0;\n\nimport \"../utils/ContextUpgradeable.sol\";\nimport \"../proxy/Initializable.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 OwnableUpgradeable is Initializable, ContextUpgradeable {\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 function __Ownable_init() internal initializer {\n __Context_init_unchained();\n __Ownable_init_unchained();\n }\n\n function __Ownable_init_unchained() internal initializer {\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 uint256[49] private __gap;\n}\n" + }, + "@openzeppelin/contracts-upgradeable/utils/PausableUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <0.8.0;\n\nimport \"./ContextUpgradeable.sol\";\nimport \"../proxy/Initializable.sol\";\n\n/**\n * @dev Contract module which allows children to implement an emergency stop\n * mechanism that can be triggered by an authorized account.\n *\n * This module is used through inheritance. It will make available the\n * modifiers `whenNotPaused` and `whenPaused`, which can be applied to\n * the functions of your contract. Note that they will not be pausable by\n * simply including this module, only once the modifiers are put in place.\n */\nabstract contract PausableUpgradeable is Initializable, ContextUpgradeable {\n /**\n * @dev Emitted when the pause is triggered by `account`.\n */\n event Paused(address account);\n\n /**\n * @dev Emitted when the pause is lifted by `account`.\n */\n event Unpaused(address account);\n\n bool private _paused;\n\n /**\n * @dev Initializes the contract in unpaused state.\n */\n function __Pausable_init() internal initializer {\n __Context_init_unchained();\n __Pausable_init_unchained();\n }\n\n function __Pausable_init_unchained() internal initializer {\n _paused = false;\n }\n\n /**\n * @dev Returns true if the contract is paused, and false otherwise.\n */\n function paused() public view virtual returns (bool) {\n return _paused;\n }\n\n /**\n * @dev Modifier to make a function callable only when the contract is not paused.\n *\n * Requirements:\n *\n * - The contract must not be paused.\n */\n modifier whenNotPaused() {\n require(!paused(), \"Pausable: paused\");\n _;\n }\n\n /**\n * @dev Modifier to make a function callable only when the contract is paused.\n *\n * Requirements:\n *\n * - The contract must be paused.\n */\n modifier whenPaused() {\n require(paused(), \"Pausable: not paused\");\n _;\n }\n\n /**\n * @dev Triggers stopped state.\n *\n * Requirements:\n *\n * - The contract must not be paused.\n */\n function _pause() internal virtual whenNotPaused {\n _paused = true;\n emit Paused(_msgSender());\n }\n\n /**\n * @dev Returns to normal state.\n *\n * Requirements:\n *\n * - The contract must be paused.\n */\n function _unpause() internal virtual whenPaused {\n _paused = false;\n emit Unpaused(_msgSender());\n }\n uint256[49] private __gap;\n}\n" + }, + "@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <0.8.0;\nimport \"../proxy/Initializable.sol\";\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 ContextUpgradeable is Initializable {\n function __Context_init() internal initializer {\n __Context_init_unchained();\n }\n\n function __Context_init_unchained() internal initializer {\n }\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 uint256[50] private __gap;\n}\n" + }, + "contracts/amm/LPToken.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.6.12;\n\nimport \"@openzeppelin/contracts-upgradeable/token/ERC20/ERC20BurnableUpgradeable.sol\";\nimport \"@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol\";\nimport \"./interfaces/ISwap.sol\";\n\n/**\n * @title Liquidity Provider Token\n * @notice This token is an ERC20 detailed token with added capability to be minted by the owner.\n * It is used to represent user's shares when providing liquidity to swap contracts.\n * @dev Only Swap contracts should initialize and own LPToken contracts.\n */\ncontract LPToken is ERC20BurnableUpgradeable, OwnableUpgradeable {\n using SafeMathUpgradeable for uint256;\n\n /**\n * @notice Initializes this LPToken contract with the given name and symbol\n * @dev The caller of this function will become the owner. A Swap contract should call this\n * in its initializer function.\n * @param name name of this token\n * @param symbol symbol of this token\n */\n function initialize(string memory name, string memory symbol)\n external\n initializer\n returns (bool)\n {\n __Context_init_unchained();\n __ERC20_init_unchained(name, symbol);\n __Ownable_init_unchained();\n return true;\n }\n\n /**\n * @notice Mints the given amount of LPToken to the recipient.\n * @dev only owner can call this mint function\n * @param recipient address of account to receive the tokens\n * @param amount amount of tokens to mint\n */\n function mint(address recipient, uint256 amount) external onlyOwner {\n require(amount != 0, \"LPToken: cannot mint 0\");\n _mint(recipient, amount);\n }\n\n /**\n * @dev Overrides ERC20._beforeTokenTransfer() which get called on every transfers including\n * minting and burning. * This assumes the owner is set to a Swap contract's address.\n */\n function _beforeTokenTransfer(\n address from,\n address to,\n uint256 amount\n ) internal virtual override(ERC20Upgradeable) {\n super._beforeTokenTransfer(from, to, amount);\n require(to != address(this), \"LPToken: cannot send to itself\");\n }\n}\n" + }, + "contracts/amm/MathUtils.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.6.12;\n\nimport \"@openzeppelin/contracts/math/SafeMath.sol\";\n\n/**\n * @title MathUtils library\n * @notice A library to be used in conjunction with SafeMath. Contains functions for calculating\n * differences between two uint256.\n */\nlibrary MathUtils {\n /**\n * @notice Compares a and b and returns true if the difference between a and b\n * is less than 1 or equal to each other.\n * @param a uint256 to compare with\n * @param b uint256 to compare with\n * @return True if the difference between a and b is less than 1 or equal,\n * otherwise return false\n */\n function within1(uint256 a, uint256 b) internal pure returns (bool) {\n return (difference(a, b) <= 1);\n }\n\n /**\n * @notice Calculates absolute difference between a and b\n * @param a uint256 to compare with\n * @param b uint256 to compare with\n * @return Difference between a and b\n */\n function difference(uint256 a, uint256 b) internal pure returns (uint256) {\n if (a > b) {\n return a - b;\n }\n return b - a;\n }\n}\n" + }, + "@openzeppelin/contracts-upgradeable/token/ERC20/ERC20BurnableUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <0.8.0;\n\nimport \"../../utils/ContextUpgradeable.sol\";\nimport \"./ERC20Upgradeable.sol\";\nimport \"../../proxy/Initializable.sol\";\n\n/**\n * @dev Extension of {ERC20} that allows token holders to destroy both their own\n * tokens and those that they have an allowance for, in a way that can be\n * recognized off-chain (via event analysis).\n */\nabstract contract ERC20BurnableUpgradeable is Initializable, ContextUpgradeable, ERC20Upgradeable {\n function __ERC20Burnable_init() internal initializer {\n __Context_init_unchained();\n __ERC20Burnable_init_unchained();\n }\n\n function __ERC20Burnable_init_unchained() internal initializer {\n }\n using SafeMathUpgradeable for uint256;\n\n /**\n * @dev Destroys `amount` tokens from the caller.\n *\n * See {ERC20-_burn}.\n */\n function burn(uint256 amount) public virtual {\n _burn(_msgSender(), amount);\n }\n\n /**\n * @dev Destroys `amount` tokens from `account`, deducting from the caller's\n * allowance.\n *\n * See {ERC20-_burn} and {ERC20-allowance}.\n *\n * Requirements:\n *\n * - the caller must have allowance for ``accounts``'s tokens of at least\n * `amount`.\n */\n function burnFrom(address account, uint256 amount) public virtual {\n uint256 decreasedAllowance = allowance(account, _msgSender()).sub(amount, \"ERC20: burn amount exceeds allowance\");\n\n _approve(account, _msgSender(), decreasedAllowance);\n _burn(account, amount);\n }\n uint256[50] private __gap;\n}\n" + }, + "contracts/amm/interfaces/ISwap.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.6.12;\n\nimport \"@openzeppelin/contracts/token/ERC20/ERC20.sol\";\n\ninterface ISwap {\n // pool data view functions\n function getA() external view returns (uint256);\n\n function getToken(uint8 index) external view returns (IERC20);\n\n function getTokenIndex(address tokenAddress) external view returns (uint8);\n\n function getTokenBalance(uint8 index) external view returns (uint256);\n\n function getVirtualPrice() external view returns (uint256);\n\n // min return calculation functions\n function calculateSwap(\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx\n ) external view returns (uint256);\n\n function calculateTokenAmount(uint256[] calldata amounts, bool deposit)\n external\n view\n returns (uint256);\n\n function calculateRemoveLiquidity(uint256 amount)\n external\n view\n returns (uint256[] memory);\n\n function calculateRemoveLiquidityOneToken(\n uint256 tokenAmount,\n uint8 tokenIndex\n ) external view returns (uint256 availableTokenAmount);\n\n // state modifying functions\n function initialize(\n IERC20[] memory pooledTokens,\n uint8[] memory decimals,\n string memory lpTokenName,\n string memory lpTokenSymbol,\n uint256 a,\n uint256 fee,\n uint256 adminFee,\n address lpTokenTargetAddress\n ) external;\n\n function swap(\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx,\n uint256 minDy,\n uint256 deadline\n ) external returns (uint256);\n\n function addLiquidity(\n uint256[] calldata amounts,\n uint256 minToMint,\n uint256 deadline\n ) external returns (uint256);\n\n function removeLiquidity(\n uint256 amount,\n uint256[] calldata minAmounts,\n uint256 deadline\n ) external returns (uint256[] memory);\n\n function removeLiquidityOneToken(\n uint256 tokenAmount,\n uint8 tokenIndex,\n uint256 minAmount,\n uint256 deadline\n ) external returns (uint256);\n\n function removeLiquidityImbalance(\n uint256[] calldata amounts,\n uint256 maxBurnAmount,\n uint256 deadline\n ) external returns (uint256);\n}\n" + }, + "@openzeppelin/contracts-upgradeable/token/ERC20/ERC20Upgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <0.8.0;\n\nimport \"../../utils/ContextUpgradeable.sol\";\nimport \"./IERC20Upgradeable.sol\";\nimport \"../../math/SafeMathUpgradeable.sol\";\nimport \"../../proxy/Initializable.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 ERC20Upgradeable is Initializable, ContextUpgradeable, IERC20Upgradeable {\n using SafeMathUpgradeable 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 function __ERC20_init(string memory name_, string memory symbol_) internal initializer {\n __Context_init_unchained();\n __ERC20_init_unchained(name_, symbol_);\n }\n\n function __ERC20_init_unchained(string memory name_, string memory symbol_) internal initializer {\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 uint256[44] private __gap;\n}\n" + }, + "@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <0.8.0;\n\n/**\n * @dev Interface of the ERC20 standard as defined in the EIP.\n */\ninterface IERC20Upgradeable {\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" + }, + "@openzeppelin/contracts-upgradeable/math/SafeMathUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <0.8.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 SafeMathUpgradeable {\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" + }, + "@openzeppelin/contracts/token/ERC20/ERC20.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <0.8.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_) public {\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" + }, + "@openzeppelin/contracts/utils/Context.sol": { + "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" + }, + "contracts/amm/SwapFlashLoan.sol": { + "content": "// SPDX-License-Identifier: MIT WITH AGPL-3.0-only\n\npragma solidity 0.6.12;\n\nimport \"./Swap.sol\";\nimport \"./interfaces/IFlashLoanReceiver.sol\";\n\n/**\n * @title Swap - A StableSwap implementation in solidity.\n * @notice This contract is responsible for custody of closely pegged assets (eg. group of stablecoins)\n * and automatic market making system. Users become an LP (Liquidity Provider) by depositing their tokens\n * in desired ratios for an exchange of the pool token that represents their share of the pool.\n * Users can burn pool tokens and withdraw their share of token(s).\n *\n * Each time a swap between the pooled tokens happens, a set fee incurs which effectively gets\n * distributed to the LPs.\n *\n * In case of emergencies, admin can pause additional deposits, swaps, or single-asset withdraws - which\n * stops the ratio of the tokens in the pool from changing.\n * Users can always withdraw their tokens via multi-asset withdraws.\n *\n * @dev Most of the logic is stored as a library `SwapUtils` for the sake of reducing contract's\n * deployment size.\n */\ncontract SwapFlashLoan is Swap {\n // Total fee that is charged on all flashloans in BPS. Borrowers must repay the amount plus the flash loan fee.\n // This fee is split between the protocol and the pool.\n uint256 public flashLoanFeeBPS;\n // Share of the flash loan fee that goes to the protocol in BPS. A portion of each flash loan fee is allocated\n // to the protocol rather than the pool.\n uint256 public protocolFeeShareBPS;\n // Max BPS for limiting flash loan fee settings.\n uint256 public constant MAX_BPS = 10000;\n\n /*** EVENTS ***/\n event FlashLoan(\n address indexed receiver,\n uint8 tokenIndex,\n uint256 amount,\n uint256 amountFee,\n uint256 protocolFee\n );\n\n /**\n * @notice Initializes this Swap contract with the given parameters.\n * This will also clone a LPToken contract that represents users'\n * LP positions. The owner of LPToken will be this contract - which means\n * only this contract is allowed to mint/burn tokens.\n *\n * @param _pooledTokens an array of ERC20s this pool will accept\n * @param decimals the decimals to use for each pooled token,\n * eg 8 for WBTC. Cannot be larger than POOL_PRECISION_DECIMALS\n * @param lpTokenName the long-form name of the token to be deployed\n * @param lpTokenSymbol the short symbol for the token to be deployed\n * @param _a the amplification coefficient * n * (n - 1). See the\n * StableSwap paper for details\n * @param _fee default swap fee to be initialized with\n * @param _adminFee default adminFee to be initialized with\n * @param lpTokenTargetAddress the address of an existing LPToken contract to use as a target\n */\n function initialize(\n IERC20[] memory _pooledTokens,\n uint8[] memory decimals,\n string memory lpTokenName,\n string memory lpTokenSymbol,\n uint256 _a,\n uint256 _fee,\n uint256 _adminFee,\n address lpTokenTargetAddress\n ) public virtual override initializer {\n Swap.initialize(\n _pooledTokens,\n decimals,\n lpTokenName,\n lpTokenSymbol,\n _a,\n _fee,\n _adminFee,\n lpTokenTargetAddress\n );\n flashLoanFeeBPS = 8; // 8 bps\n protocolFeeShareBPS = 0; // 0 bps\n }\n\n /*** STATE MODIFYING FUNCTIONS ***/\n\n /**\n * @notice Borrow the specified token from this pool for this transaction only. This function will call\n * `IFlashLoanReceiver(receiver).executeOperation` and the `receiver` must return the full amount of the token\n * and the associated fee by the end of the callback transaction. If the conditions are not met, this call\n * is reverted.\n * @param receiver the address of the receiver of the token. This address must implement the IFlashLoanReceiver\n * interface and the callback function `executeOperation`.\n * @param token the protocol fee in bps to be applied on the total flash loan fee\n * @param amount the total amount to borrow in this transaction\n * @param params optional data to pass along to the callback function\n */\n function flashLoan(\n address receiver,\n IERC20 token,\n uint256 amount,\n bytes memory params\n ) external nonReentrant {\n uint8 tokenIndex = getTokenIndex(address(token));\n uint256 availableLiquidityBefore = token.balanceOf(address(this));\n uint256 protocolBalanceBefore = availableLiquidityBefore.sub(\n swapStorage.balances[tokenIndex]\n );\n require(\n amount > 0 && availableLiquidityBefore >= amount,\n \"invalid amount\"\n );\n\n // Calculate the additional amount of tokens the pool should end up with\n uint256 amountFee = amount.mul(flashLoanFeeBPS).div(10000);\n // Calculate the portion of the fee that will go to the protocol\n uint256 protocolFee = amountFee.mul(protocolFeeShareBPS).div(10000);\n require(amountFee > 0, \"amount is small for a flashLoan\");\n\n // Transfer the requested amount of tokens\n token.safeTransfer(receiver, amount);\n\n // Execute callback function on receiver\n IFlashLoanReceiver(receiver).executeOperation(\n address(this),\n address(token),\n amount,\n amountFee,\n params\n );\n\n uint256 availableLiquidityAfter = token.balanceOf(address(this));\n require(\n availableLiquidityAfter >= availableLiquidityBefore.add(amountFee),\n \"flashLoan fee is not met\"\n );\n\n swapStorage.balances[tokenIndex] = availableLiquidityAfter\n .sub(protocolBalanceBefore)\n .sub(protocolFee);\n emit FlashLoan(receiver, tokenIndex, amount, amountFee, protocolFee);\n }\n\n /*** ADMIN FUNCTIONS ***/\n\n /**\n * @notice Updates the flash loan fee parameters. This function can only be called by the owner.\n * @param newFlashLoanFeeBPS the total fee in bps to be applied on future flash loans\n * @param newProtocolFeeShareBPS the protocol fee in bps to be applied on the total flash loan fee\n */\n function setFlashLoanFees(\n uint256 newFlashLoanFeeBPS,\n uint256 newProtocolFeeShareBPS\n ) external onlyOwner {\n require(\n newFlashLoanFeeBPS > 0 &&\n newFlashLoanFeeBPS <= MAX_BPS &&\n newProtocolFeeShareBPS <= MAX_BPS,\n \"fees are not in valid range\"\n );\n flashLoanFeeBPS = newFlashLoanFeeBPS;\n protocolFeeShareBPS = newProtocolFeeShareBPS;\n }\n}\n" + }, + "contracts/amm/interfaces/IFlashLoanReceiver.sol": { + "content": "// SPDX-License-Identifier: AGPL-3.0-only\n\npragma solidity 0.6.12;\n\n/**\n * @title IFlashLoanReceiver interface\n * @notice Interface for the Nerve fee IFlashLoanReceiver. Modified from Aave's IFlashLoanReceiver interface.\n * https://github.com/aave/aave-protocol/blob/4b4545fb583fd4f400507b10f3c3114f45b8a037/contracts/flashloan/interfaces/IFlashLoanReceiver.sol\n * @author Aave\n * @dev implement this interface to develop a flashloan-compatible flashLoanReceiver contract\n **/\ninterface IFlashLoanReceiver {\n function executeOperation(\n address pool,\n address token,\n uint256 amount,\n uint256 fee,\n bytes calldata params\n ) external;\n}\n" + }, + "contracts/amm/helper/FlashLoanBorrowerExample.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.6.12;\n\nimport \"@openzeppelin/contracts/math/SafeMath.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/SafeERC20.sol\";\nimport \"../interfaces/IFlashLoanReceiver.sol\";\nimport \"../interfaces/ISwapFlashLoan.sol\";\nimport \"hardhat/console.sol\";\n\ncontract FlashLoanBorrowerExample is IFlashLoanReceiver {\n using SafeMath for uint256;\n\n // Typical executeOperation function should do the 3 following actions\n // 1. Check if the flashLoan was successful\n // 2. Do actions with the borrowed tokens\n // 3. Repay the debt to the `pool`\n function executeOperation(\n address pool,\n address token,\n uint256 amount,\n uint256 fee,\n bytes calldata params\n ) external override {\n // 1. Check if the flashLoan was valid\n require(\n IERC20(token).balanceOf(address(this)) >= amount,\n \"flashloan is broken?\"\n );\n\n // 2. Do actions with the borrowed token\n bytes32 paramsHash = keccak256(params);\n if (paramsHash == keccak256(bytes(\"dontRepayDebt\"))) {\n return;\n } else if (paramsHash == keccak256(bytes(\"reentrancy_addLiquidity\"))) {\n ISwapFlashLoan(pool).addLiquidity(\n new uint256[](0),\n 0,\n block.timestamp\n );\n } else if (paramsHash == keccak256(bytes(\"reentrancy_swap\"))) {\n ISwapFlashLoan(pool).swap(1, 0, 1e6, 0, now);\n } else if (\n paramsHash == keccak256(bytes(\"reentrancy_removeLiquidity\"))\n ) {\n ISwapFlashLoan(pool).removeLiquidity(1e18, new uint256[](0), now);\n } else if (\n paramsHash == keccak256(bytes(\"reentrancy_removeLiquidityOneToken\"))\n ) {\n ISwapFlashLoan(pool).removeLiquidityOneToken(1e18, 0, 1e18, now);\n }\n\n // 3. Payback debt\n uint256 totalDebt = amount.add(fee);\n IERC20(token).transfer(pool, totalDebt);\n }\n\n function flashLoan(\n ISwapFlashLoan swap,\n IERC20 token,\n uint256 amount,\n bytes memory params\n ) external {\n swap.flashLoan(address(this), token, amount, params);\n }\n}\n" + }, + "contracts/amm/interfaces/ISwapFlashLoan.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.6.12;\n\nimport \"./ISwap.sol\";\n\ninterface ISwapFlashLoan is ISwap {\n function flashLoan(\n address receiver,\n IERC20 token,\n uint256 amount,\n bytes memory params\n ) external;\n}\n" + }, + "hardhat/console.sol": { + "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" + }, + "contracts/amm/helper/test/TestSwapReturnValues.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.6.12;\n\nimport \"../../interfaces/ISwap.sol\";\nimport \"hardhat/console.sol\";\n\ncontract TestSwapReturnValues {\n using SafeMath for uint256;\n\n ISwap public swap;\n IERC20 public lpToken;\n uint8 public n;\n\n uint256 public constant MAX_INT = 2**256 - 1;\n\n constructor(\n ISwap swapContract,\n IERC20 lpTokenContract,\n uint8 numOfTokens\n ) public {\n swap = swapContract;\n lpToken = lpTokenContract;\n n = numOfTokens;\n\n // Pre-approve tokens\n for (uint8 i; i < n; i++) {\n swap.getToken(i).approve(address(swap), MAX_INT);\n }\n lpToken.approve(address(swap), MAX_INT);\n }\n\n function test_swap(\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx,\n uint256 minDy\n ) public {\n uint256 balanceBefore =\n swap.getToken(tokenIndexTo).balanceOf(address(this));\n uint256 returnValue =\n swap.swap(tokenIndexFrom, tokenIndexTo, dx, minDy, block.timestamp);\n uint256 balanceAfter =\n swap.getToken(tokenIndexTo).balanceOf(address(this));\n\n console.log(\n \"swap: Expected %s, got %s\",\n balanceAfter.sub(balanceBefore),\n returnValue\n );\n\n require(\n returnValue == balanceAfter.sub(balanceBefore),\n \"swap()'s return value does not match received amount\"\n );\n }\n\n function test_addLiquidity(uint256[] calldata amounts, uint256 minToMint)\n public\n {\n uint256 balanceBefore = lpToken.balanceOf(address(this));\n uint256 returnValue = swap.addLiquidity(amounts, minToMint, MAX_INT);\n uint256 balanceAfter = lpToken.balanceOf(address(this));\n\n console.log(\n \"addLiquidity: Expected %s, got %s\",\n balanceAfter.sub(balanceBefore),\n returnValue\n );\n\n require(\n returnValue == balanceAfter.sub(balanceBefore),\n \"addLiquidity()'s return value does not match minted amount\"\n );\n }\n\n function test_removeLiquidity(uint256 amount, uint256[] memory minAmounts)\n public\n {\n uint256[] memory balanceBefore = new uint256[](n);\n uint256[] memory balanceAfter = new uint256[](n);\n\n for (uint8 i = 0; i < n; i++) {\n balanceBefore[i] = swap.getToken(i).balanceOf(address(this));\n }\n\n uint256[] memory returnValue =\n swap.removeLiquidity(amount, minAmounts, MAX_INT);\n\n for (uint8 i = 0; i < n; i++) {\n balanceAfter[i] = swap.getToken(i).balanceOf(address(this));\n console.log(\n \"removeLiquidity: Expected %s, got %s\",\n balanceAfter[i].sub(balanceBefore[i]),\n returnValue[i]\n );\n require(\n balanceAfter[i].sub(balanceBefore[i]) == returnValue[i],\n \"removeLiquidity()'s return value does not match received amounts of tokens\"\n );\n }\n }\n\n function test_removeLiquidityImbalance(\n uint256[] calldata amounts,\n uint256 maxBurnAmount\n ) public {\n uint256 balanceBefore = lpToken.balanceOf(address(this));\n uint256 returnValue =\n swap.removeLiquidityImbalance(amounts, maxBurnAmount, MAX_INT);\n uint256 balanceAfter = lpToken.balanceOf(address(this));\n\n console.log(\n \"removeLiquidityImbalance: Expected %s, got %s\",\n balanceBefore.sub(balanceAfter),\n returnValue\n );\n\n require(\n returnValue == balanceBefore.sub(balanceAfter),\n \"removeLiquidityImbalance()'s return value does not match burned lpToken amount\"\n );\n }\n\n function test_removeLiquidityOneToken(\n uint256 tokenAmount,\n uint8 tokenIndex,\n uint256 minAmount\n ) public {\n uint256 balanceBefore =\n swap.getToken(tokenIndex).balanceOf(address(this));\n uint256 returnValue =\n swap.removeLiquidityOneToken(\n tokenAmount,\n tokenIndex,\n minAmount,\n MAX_INT\n );\n uint256 balanceAfter =\n swap.getToken(tokenIndex).balanceOf(address(this));\n\n console.log(\n \"removeLiquidityOneToken: Expected %s, got %s\",\n balanceAfter.sub(balanceBefore),\n returnValue\n );\n\n require(\n returnValue == balanceAfter.sub(balanceBefore),\n \"removeLiquidityOneToken()'s return value does not match received token amount\"\n );\n }\n}\n" + }, + "contracts/amm/SwapDeployer.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.6.12;\n\nimport \"@openzeppelin/contracts/access/Ownable.sol\";\nimport \"@openzeppelin/contracts/proxy/Clones.sol\";\nimport \"./interfaces/ISwap.sol\";\n\ncontract SwapDeployer is Ownable {\n event NewSwapPool(\n address indexed deployer,\n address swapAddress,\n IERC20[] pooledTokens\n );\n\n constructor() public Ownable() {}\n\n function deploy(\n address swapAddress,\n IERC20[] memory _pooledTokens,\n uint8[] memory decimals,\n string memory lpTokenName,\n string memory lpTokenSymbol,\n uint256 _a,\n uint256 _fee,\n uint256 _adminFee,\n address lpTokenTargetAddress\n ) external returns (address) {\n address swapClone = Clones.clone(swapAddress);\n ISwap(swapClone).initialize(\n _pooledTokens,\n decimals,\n lpTokenName,\n lpTokenSymbol,\n _a,\n _fee,\n _adminFee,\n lpTokenTargetAddress\n );\n Ownable(swapClone).transferOwnership(owner());\n emit NewSwapPool(msg.sender, swapClone, _pooledTokens);\n return swapClone;\n }\n}\n" + }, + "@openzeppelin/contracts/access/Ownable.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <0.8.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 () internal {\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" + }, + "contracts/bridge/SynapseERC20Factory.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.6.12;\n\nimport \"@openzeppelin/contracts/access/Ownable.sol\";\nimport \"@openzeppelin/contracts/proxy/Clones.sol\";\nimport \"./interfaces/ISynapseERC20.sol\";\n\ncontract SynapseERC20Factory {\n constructor() public {}\n\n event SynapseERC20Created(address contractAddress);\n\n /**\n * @notice Deploys a new node\n * @param synapseERC20Address address of the synapseERC20Address contract to initialize with\n * @param name Token name\n * @param symbol Token symbol\n * @param decimals Token name\n * @param owner admin address to be initialized with\n * @return Address of the newest node management contract created\n **/\n function deploy(\n address synapseERC20Address,\n string memory name,\n string memory symbol,\n uint8 decimals,\n address owner\n ) external returns (address) {\n address synERC20Clone = Clones.clone(synapseERC20Address);\n ISynapseERC20(synERC20Clone).initialize(name, symbol, decimals, owner);\n\n emit SynapseERC20Created(synERC20Clone);\n\n return synERC20Clone;\n }\n}\n" + }, + "contracts/bridge/interfaces/ISynapseERC20.sol": { + "content": "// SPDX-License-Identifier: MIT\n\n\npragma solidity 0.6.12;\n\ninterface ISynapseERC20 { \n function initialize(\n string memory _name, string memory _symbol, uint8 _decimals, address owner) external;\n\n function mint(address to, uint256 amount) external;\n}\n\n" + }, + "contracts/bridge/wrappers/AvaxJewelMigration.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.6.12;\n\nimport '@openzeppelin/contracts/token/ERC20/ERC20.sol';\nimport \"@openzeppelin/contracts/token/ERC20/SafeERC20.sol\";\nimport \"@openzeppelin/contracts/access/Ownable.sol\";\n\nimport '../interfaces/ISynapseBridge.sol';\n\ninterface IERC20Mintable is IERC20 {\n function mint(address to, uint256 amount) external;\n}\n\ncontract AvaxJewelMigration is Ownable {\n using SafeERC20 for IERC20;\n using SafeERC20 for IERC20Mintable;\n\n\n ISynapseBridge constant synapseBridge = ISynapseBridge(0xC05e61d0E7a63D27546389B7aD62FdFf5A91aACE);\n // MULTICHAIN JEWEL \n IERC20 constant legacyToken = IERC20(0x4f60a160D8C2DDdaAfe16FCC57566dB84D674BD6);\n // SYNAPSE JEWEL\n IERC20 constant newToken = IERC20(0x997Ddaa07d716995DE90577C123Db411584E5E46);\n uint256 constant MAX_UINT256 = 2**256 - 1;\n\n constructor() public {\n newToken.safeApprove(address(synapseBridge), MAX_UINT256);\n }\n\n function migrate(uint256 amount) public {\n legacyToken.safeTransferFrom(msg.sender, address(this), amount);\n IERC20Mintable(address(newToken)).mint(msg.sender, amount);\n }\n\n function migrateAndBridge(uint256 amount, address to, uint256 chainId) external {\n migrate(amount);\n synapseBridge.redeem(to, chainId, newToken, amount);\n }\n\n function redeemLegacy() external onlyOwner {\n uint256 legacyBalance = legacyToken.balanceOf(address(this));\n legacyToken.safeTransfer(owner(), legacyBalance);\n }\n} " + }, + "contracts/bridge/interfaces/ISynapseBridge.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.6.12;\n\nimport '@openzeppelin/contracts/token/ERC20/SafeERC20.sol';\nimport '@openzeppelin/contracts/token/ERC20/ERC20Burnable.sol';\n\ninterface ISynapseBridge {\n using SafeERC20 for IERC20;\n\n function deposit(\n address to,\n uint256 chainId,\n IERC20 token,\n uint256 amount\n ) external;\n\n function depositAndSwap(\n address to,\n uint256 chainId,\n IERC20 token,\n uint256 amount,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 minDy,\n uint256 deadline\n ) external;\n\n function redeem(\n address to,\n uint256 chainId,\n IERC20 token,\n uint256 amount\n ) external;\n\n\n function redeemv2(\n bytes32 to,\n uint256 chainId,\n IERC20 token,\n uint256 amount\n ) external;\n\n\n function redeemAndSwap(\n address to,\n uint256 chainId,\n IERC20 token,\n uint256 amount,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 minDy,\n uint256 deadline\n ) external;\n\n function redeemAndRemove(\n address to,\n uint256 chainId,\n IERC20 token,\n uint256 amount,\n uint8 liqTokenIndex,\n uint256 liqMinAmount,\n uint256 liqDeadline\n ) external;\n}\n" + }, + "@openzeppelin/contracts/token/ERC20/ERC20Burnable.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <0.8.0;\n\nimport \"../../utils/Context.sol\";\nimport \"./ERC20.sol\";\n\n/**\n * @dev Extension of {ERC20} that allows token holders to destroy both their own\n * tokens and those that they have an allowance for, in a way that can be\n * recognized off-chain (via event analysis).\n */\nabstract contract ERC20Burnable is Context, ERC20 {\n using SafeMath for uint256;\n\n /**\n * @dev Destroys `amount` tokens from the caller.\n *\n * See {ERC20-_burn}.\n */\n function burn(uint256 amount) public virtual {\n _burn(_msgSender(), amount);\n }\n\n /**\n * @dev Destroys `amount` tokens from `account`, deducting from the caller's\n * allowance.\n *\n * See {ERC20-_burn} and {ERC20-allowance}.\n *\n * Requirements:\n *\n * - the caller must have allowance for ``accounts``'s tokens of at least\n * `amount`.\n */\n function burnFrom(address account, uint256 amount) public virtual {\n uint256 decreasedAllowance = allowance(account, _msgSender()).sub(amount, \"ERC20: burn amount exceeds allowance\");\n\n _approve(account, _msgSender(), decreasedAllowance);\n _burn(account, amount);\n }\n}\n" + }, + "contracts/bridge/wrappers/MoonriverBridgeZap.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.6.12;\n\nimport \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/SafeERC20.sol\";\nimport \"../interfaces/ISwap.sol\";\nimport \"../interfaces/ISynapseBridge.sol\";\nimport \"../interfaces/IWETH9.sol\";\n\ninterface IFrax {\n function exchangeCanonicalForOld(address bridge_token_address, uint256 token_amount) external returns (uint256);\n}\n\ncontract MoonriverBridgeZap {\n using SafeERC20 for IERC20;\n\n ISynapseBridge synapseBridge;\n address payable public immutable WETH_ADDRESS;\n IFrax private constant CANOLICAL_FRAX = IFrax(0x1A93B23281CC1CDE4C4741353F3064709A16197d);\n IERC20 private constant SYN_FRAX = IERC20(0xE96AC70907ffF3Efee79f502C985A7A21Bce407d);\n\n mapping(address => address) public swapMap;\n mapping(address => IERC20[]) public swapTokensMap;\n\n uint256 constant MAX_UINT256 = 2**256 - 1;\n\n constructor(\n address payable _wethAddress,\n address _swapOne,\n address tokenOne,\n address _swapTwo,\n address tokenTwo,\n ISynapseBridge _synapseBridge\n ) public {\n WETH_ADDRESS = _wethAddress;\n synapseBridge = _synapseBridge;\n swapMap[tokenOne] = _swapOne;\n swapMap[tokenTwo] = _swapTwo;\n IERC20(_wethAddress).safeIncreaseAllowance(address(_synapseBridge), MAX_UINT256);\n if (address(_swapOne) != address(0)) {\n {\n uint8 i;\n for (; i < 32; i++) {\n try ISwap(_swapOne).getToken(i) returns (\n IERC20 token\n ) {\n swapTokensMap[_swapOne].push(token);\n token.safeApprove(address(_swapOne), MAX_UINT256);\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n } catch {\n break;\n }\n }\n require(i > 1, \"swap must have at least 2 tokens\");\n }\n }\n if (address(_swapTwo) != address(0)) {\n {\n uint8 i;\n for (; i < 32; i++) {\n try ISwap(_swapTwo).getToken(i) returns (\n IERC20 token\n ) {\n swapTokensMap[_swapTwo].push(token);\n token.safeApprove(address(_swapTwo), MAX_UINT256);\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n } catch {\n break;\n }\n }\n require(i > 1, \"swap must have at least 2 tokens\");\n }\n }\n }\n\n /**\n * @notice Calculate amount of tokens you receive on swap\n * @param tokenIndexFrom the token the user wants to sell\n * @param tokenIndexTo the token the user wants to buy\n * @param dx the amount of tokens the user wants to sell. If the token charges\n * a fee on transfers, use the amount that gets transferred after the fee.\n * @return amount of tokens the user will receive\n */\n function calculateSwap(\n IERC20 token,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx\n ) external view virtual returns (uint256) {\n ISwap swap = ISwap(\n swapMap[address(token)]\n );\n return swap.calculateSwap(tokenIndexFrom, tokenIndexTo, dx);\n }\n\n function swapAndRedeem(\n address to,\n uint256 chainId,\n IERC20 token,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx,\n uint256 minDy,\n uint256 deadline\n ) external {\n ISwap swap = ISwap(swapMap[address(token)]);\n require(address(swap) != address(0), \"Swap is 0x00\");\n IERC20[] memory tokens = swapTokensMap[address(swap)];\n tokens[tokenIndexFrom].safeTransferFrom(\n msg.sender,\n address(this),\n dx\n );\n // swap\n\n uint256 swappedAmount = swap.swap(\n tokenIndexFrom,\n tokenIndexTo,\n dx,\n minDy,\n deadline\n );\n // deposit into bridge, gets nUSD\n if (\n token.allowance(address(this), address(synapseBridge)) <\n swappedAmount\n ) {\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n }\n synapseBridge.redeem(to, chainId, token, swappedAmount);\n }\n\n function swapAndRedeemAndSwap(\n address to,\n uint256 chainId,\n IERC20 token,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx,\n uint256 minDy,\n uint256 deadline,\n uint8 swapTokenIndexFrom,\n uint8 swapTokenIndexTo,\n uint256 swapMinDy,\n uint256 swapDeadline\n ) external {\n require(\n address(swapMap[address(token)]) != address(0),\n \"Swap is 0x00\"\n );\n IERC20[] memory tokens = swapTokensMap[\n swapMap[address(token)]\n ];\n tokens[tokenIndexFrom].safeTransferFrom(\n msg.sender,\n address(this),\n dx\n );\n // swap\n\n uint256 swappedAmount = ISwap(swapMap[address(token)]).swap(tokenIndexFrom, tokenIndexTo, dx, minDy, deadline);\n // deposit into bridge, gets nUSD\n if (\n token.allowance(address(this), address(synapseBridge)) <\n swappedAmount\n ) {\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n }\n synapseBridge.redeemAndSwap(\n to,\n chainId,\n token,\n swappedAmount,\n swapTokenIndexFrom,\n swapTokenIndexTo,\n swapMinDy,\n swapDeadline\n );\n }\n\n function swapAndRedeemAndRemove(\n address to,\n uint256 chainId,\n IERC20 token,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx,\n uint256 minDy,\n uint256 deadline,\n uint8 liqTokenIndex,\n uint256 liqMinAmount,\n uint256 liqDeadline\n ) external {\n ISwap swap = ISwap(swapMap[address(token)]);\n require(address(swap) != address(0), \"Swap is 0x00\");\n IERC20[] memory tokens = swapTokensMap[address(swap)];\n tokens[tokenIndexFrom].safeTransferFrom(\n msg.sender,\n address(this),\n dx\n );\n // swap\n\n uint256 swappedAmount = swap.swap(\n tokenIndexFrom,\n tokenIndexTo,\n dx,\n minDy,\n deadline\n );\n // deposit into bridge, gets nUSD\n if (\n token.allowance(address(this), address(synapseBridge)) <\n swappedAmount\n ) {\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n }\n synapseBridge.redeemAndRemove(\n to,\n chainId,\n token,\n swappedAmount,\n liqTokenIndex,\n liqMinAmount,\n liqDeadline\n );\n }\n\n /**\n * @notice wraps SynapseBridge redeem()\n * @param to address on other chain to redeem underlying assets to\n * @param chainId which underlying chain to bridge assets onto\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n **/\n function redeem(\n address to,\n uint256 chainId,\n IERC20 token,\n uint256 amount\n ) external {\n token.safeTransferFrom(msg.sender, address(this), amount);\n if (address(token) == address(CANOLICAL_FRAX)) {\n uint256 swappedAmount = CANOLICAL_FRAX.exchangeCanonicalForOld(address(SYN_FRAX), amount);\n if (SYN_FRAX.allowance(address(this), address(synapseBridge)) < amount) {\n SYN_FRAX.safeApprove(address(synapseBridge), MAX_UINT256);\n }\n synapseBridge.redeem(to, chainId, SYN_FRAX, swappedAmount);\n } else {\n if (token.allowance(address(this), address(synapseBridge)) < amount) {\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n }\n synapseBridge.redeem(to, chainId, token, amount);\n }\n }\n\n /**\n * @notice Wraps SynapseBridge redeemv2() function\n * @param to address on other chain to bridge assets to\n * @param chainId which chain to bridge assets onto\n * @param token ERC20 compatible token to redeem into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n **/\n function redeemv2(\n bytes32 to,\n uint256 chainId,\n IERC20 token,\n uint256 amount\n ) external {\n token.safeTransferFrom(msg.sender, address(this), amount);\n\n if (token.allowance(address(this), address(synapseBridge)) < amount) {\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n }\n synapseBridge.redeemv2(to, chainId, token, amount);\n }\n\n /**\n * @notice wraps SynapseBridge redeem()\n * @param to address on other chain to redeem underlying assets to\n * @param chainId which underlying chain to bridge assets onto\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n **/\n function deposit(\n address to,\n uint256 chainId,\n IERC20 token,\n uint256 amount\n ) external {\n token.safeTransferFrom(msg.sender, address(this), amount);\n if (token.allowance(address(this), address(synapseBridge)) < amount) {\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n }\n synapseBridge.deposit(to, chainId, token, amount);\n }\n\n /**\n * @notice Wraps SynapseBridge deposit() function to make it compatible w/ ETH -> WETH conversions\n * @param to address on other chain to bridge assets to\n * @param chainId which chain to bridge assets onto\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n **/\n function depositETH(\n address to,\n uint256 chainId,\n uint256 amount\n ) external payable {\n require(msg.value > 0 && msg.value == amount, 'INCORRECT MSG VALUE');\n IWETH9(WETH_ADDRESS).deposit{value: msg.value}();\n synapseBridge.deposit(to, chainId, IERC20(WETH_ADDRESS), amount);\n }\n\n\n\n function swapETHAndRedeem(\n address to,\n uint256 chainId,\n IERC20 token,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx,\n uint256 minDy,\n uint256 deadline\n ) external payable {\n require(WETH_ADDRESS != address(0), \"WETH 0\");\n require(msg.value > 0 && msg.value == dx, \"INCORRECT MSG VALUE\");\n ISwap swap = ISwap(swapMap[address(token)]);\n require(address(swap) != address(0), \"Swap is 0x00\");\n IWETH9(WETH_ADDRESS).deposit{value: msg.value}();\n\n // swap\n uint256 swappedAmount = swap.swap(\n tokenIndexFrom,\n tokenIndexTo,\n dx,\n minDy,\n deadline\n );\n synapseBridge.redeem(to, chainId, token, swappedAmount);\n }\n\n /**\n * @notice Wraps redeemAndSwap on SynapseBridge.sol\n * Relays to nodes that (typically) a wrapped synAsset ERC20 token has been burned and the underlying needs to be redeeemed on the native chain. This function indicates to the nodes that they should attempt to redeem the LP token for the underlying assets (E.g \"swap\" out of the LP token)\n * @param to address on other chain to redeem underlying assets to\n * @param chainId which underlying chain to bridge assets onto\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n * @param tokenIndexFrom the token the user wants to swap from\n * @param tokenIndexTo the token the user wants to swap to\n * @param minDy the min amount the user would like to receive, or revert to only minting the SynERC20 token crosschain.\n * @param deadline latest timestamp to accept this transaction\n **/\n function redeemAndSwap(\n address to,\n uint256 chainId,\n IERC20 token,\n uint256 amount,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 minDy,\n uint256 deadline\n ) external {\n token.safeTransferFrom(msg.sender, address(this), amount);\n if (token.allowance(address(this), address(synapseBridge)) < amount) {\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n }\n synapseBridge.redeemAndSwap(\n to,\n chainId,\n token,\n amount,\n tokenIndexFrom,\n tokenIndexTo,\n minDy,\n deadline\n );\n }\n\n /**\n * @notice Wraps redeemAndRemove on SynapseBridge\n * Relays to nodes that (typically) a wrapped synAsset ERC20 token has been burned and the underlying needs to be redeeemed on the native chain. This function indicates to the nodes that they should attempt to redeem the LP token for the underlying assets (E.g \"swap\" out of the LP token)\n * @param to address on other chain to redeem underlying assets to\n * @param chainId which underlying chain to bridge assets onto\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount of (typically) LP token to pass to the nodes to attempt to removeLiquidity() with to redeem for the underlying assets of the LP token\n * @param liqTokenIndex Specifies which of the underlying LP assets the nodes should attempt to redeem for\n * @param liqMinAmount Specifies the minimum amount of the underlying asset needed for the nodes to execute the redeem/swap\n * @param liqDeadline Specificies the deadline that the nodes are allowed to try to redeem/swap the LP token\n **/\n function redeemAndRemove(\n address to,\n uint256 chainId,\n IERC20 token,\n uint256 amount,\n uint8 liqTokenIndex,\n uint256 liqMinAmount,\n uint256 liqDeadline\n ) external {\n token.safeTransferFrom(msg.sender, address(this), amount);\n if (token.allowance(address(this), address(synapseBridge)) < amount) {\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n }\n synapseBridge.redeemAndRemove(\n to,\n chainId,\n token,\n amount,\n liqTokenIndex,\n liqMinAmount,\n liqDeadline\n );\n }\n}\n" + }, + "contracts/bridge/interfaces/ISwap.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.6.12;\n\nimport '@openzeppelin/contracts/token/ERC20/ERC20.sol';\n\ninterface ISwap {\n // pool data view functions\n function getA() external view returns (uint256);\n\n function getToken(uint8 index) external view returns (IERC20);\n\n function getTokenIndex(address tokenAddress) external view returns (uint8);\n\n function getTokenBalance(uint8 index) external view returns (uint256);\n\n function getVirtualPrice() external view returns (uint256);\n\n // min return calculation functions\n function calculateSwap(\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx\n ) external view returns (uint256);\n\n function calculateTokenAmount(uint256[] calldata amounts, bool deposit)\n external\n view\n returns (uint256);\n\n function calculateRemoveLiquidity(uint256 amount)\n external\n view\n returns (uint256[] memory);\n\n function calculateRemoveLiquidityOneToken(\n uint256 tokenAmount,\n uint8 tokenIndex\n ) external view returns (uint256 availableTokenAmount);\n\n // state modifying functions\n function initialize(\n IERC20[] memory pooledTokens,\n uint8[] memory decimals,\n string memory lpTokenName,\n string memory lpTokenSymbol,\n uint256 a,\n uint256 fee,\n uint256 adminFee,\n address lpTokenTargetAddress\n ) external;\n\n function swap(\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx,\n uint256 minDy,\n uint256 deadline\n ) external returns (uint256);\n\n function addLiquidity(\n uint256[] calldata amounts,\n uint256 minToMint,\n uint256 deadline\n ) external returns (uint256);\n\n function removeLiquidity(\n uint256 amount,\n uint256[] calldata minAmounts,\n uint256 deadline\n ) external returns (uint256[] memory);\n\n function removeLiquidityOneToken(\n uint256 tokenAmount,\n uint8 tokenIndex,\n uint256 minAmount,\n uint256 deadline\n ) external returns (uint256);\n\n function removeLiquidityImbalance(\n uint256[] calldata amounts,\n uint256 maxBurnAmount,\n uint256 deadline\n ) external returns (uint256);\n}\n" + }, + "contracts/bridge/interfaces/IWETH9.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.4.0;\n\ninterface IWETH9 {\n function name() external view returns (string memory);\n\n function symbol() external view returns (string memory);\n\n function decimals() external view returns (uint8);\n\n function balanceOf(address) external view returns (uint256);\n\n function allowance(address, address) external view returns (uint256);\n\n receive() external payable;\n\n function deposit() external payable;\n\n function withdraw(uint256 wad) external;\n\n function totalSupply() external view returns (uint256);\n\n function approve(address guy, uint256 wad) external returns (bool);\n\n function transfer(address dst, uint256 wad) external returns (bool);\n\n function transferFrom(\n address src,\n address dst,\n uint256 wad\n ) external returns (bool);\n}" + }, + "contracts/bridge/wrappers/L2BridgeZap.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.6.12;\n\nimport \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/SafeERC20.sol\";\nimport \"../interfaces/ISwap.sol\";\nimport \"../interfaces/ISynapseBridge.sol\";\nimport \"../interfaces/IWETH9.sol\";\n\ncontract L2BridgeZap {\n using SafeERC20 for IERC20;\n\n ISynapseBridge synapseBridge;\n address payable public immutable WETH_ADDRESS;\n\n mapping(address => address) public swapMap;\n mapping(address => IERC20[]) public swapTokensMap;\n\n uint256 constant MAX_UINT256 = 2**256 - 1;\n\n constructor(\n address payable _wethAddress,\n address _swapOne,\n address tokenOne,\n address _swapTwo,\n address tokenTwo,\n ISynapseBridge _synapseBridge\n ) public {\n WETH_ADDRESS = _wethAddress;\n synapseBridge = _synapseBridge;\n swapMap[tokenOne] = _swapOne;\n swapMap[tokenTwo] = _swapTwo;\n if (_wethAddress != address(0)) {\n IERC20(_wethAddress).safeIncreaseAllowance(address(_synapseBridge), MAX_UINT256);\n }\n if (address(_swapOne) != address(0)) {\n {\n uint8 i;\n for (; i < 32; i++) {\n try ISwap(_swapOne).getToken(i) returns (\n IERC20 token\n ) {\n swapTokensMap[_swapOne].push(token);\n token.safeApprove(address(_swapOne), MAX_UINT256);\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n } catch {\n break;\n }\n }\n require(i > 1, \"swap must have at least 2 tokens\");\n }\n }\n if (address(_swapTwo) != address(0)) {\n {\n uint8 i;\n for (; i < 32; i++) {\n try ISwap(_swapTwo).getToken(i) returns (\n IERC20 token\n ) {\n swapTokensMap[_swapTwo].push(token);\n token.safeApprove(address(_swapTwo), MAX_UINT256);\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n } catch {\n break;\n }\n }\n require(i > 1, \"swap must have at least 2 tokens\");\n }\n }\n }\n\n /**\n * @notice Calculate amount of tokens you receive on swap\n * @param tokenIndexFrom the token the user wants to sell\n * @param tokenIndexTo the token the user wants to buy\n * @param dx the amount of tokens the user wants to sell. If the token charges\n * a fee on transfers, use the amount that gets transferred after the fee.\n * @return amount of tokens the user will receive\n */\n function calculateSwap(\n IERC20 token,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx\n ) external view virtual returns (uint256) {\n ISwap swap = ISwap(\n swapMap[address(token)]\n );\n return swap.calculateSwap(tokenIndexFrom, tokenIndexTo, dx);\n }\n\n function swapAndRedeem(\n address to,\n uint256 chainId,\n IERC20 token,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx,\n uint256 minDy,\n uint256 deadline\n ) external {\n ISwap swap = ISwap(swapMap[address(token)]);\n require(address(swap) != address(0), \"Swap is 0x00\");\n IERC20[] memory tokens = swapTokensMap[address(swap)];\n tokens[tokenIndexFrom].safeTransferFrom(\n msg.sender,\n address(this),\n dx\n );\n // swap\n\n uint256 swappedAmount = swap.swap(\n tokenIndexFrom,\n tokenIndexTo,\n dx,\n minDy,\n deadline\n );\n // deposit into bridge, gets nUSD\n if (\n token.allowance(address(this), address(synapseBridge)) <\n swappedAmount\n ) {\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n }\n synapseBridge.redeem(to, chainId, token, swappedAmount);\n }\n\n function swapAndRedeemAndSwap(\n address to,\n uint256 chainId,\n IERC20 token,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx,\n uint256 minDy,\n uint256 deadline,\n uint8 swapTokenIndexFrom,\n uint8 swapTokenIndexTo,\n uint256 swapMinDy,\n uint256 swapDeadline\n ) external {\n require(\n address(swapMap[address(token)]) != address(0),\n \"Swap is 0x00\"\n );\n IERC20[] memory tokens = swapTokensMap[\n swapMap[address(token)]\n ];\n tokens[tokenIndexFrom].safeTransferFrom(\n msg.sender,\n address(this),\n dx\n );\n // swap\n\n uint256 swappedAmount = ISwap(swapMap[address(token)]).swap(tokenIndexFrom, tokenIndexTo, dx, minDy, deadline);\n // deposit into bridge, gets nUSD\n if (\n token.allowance(address(this), address(synapseBridge)) <\n swappedAmount\n ) {\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n }\n synapseBridge.redeemAndSwap(\n to,\n chainId,\n token,\n swappedAmount,\n swapTokenIndexFrom,\n swapTokenIndexTo,\n swapMinDy,\n swapDeadline\n );\n }\n\n function swapAndRedeemAndRemove(\n address to,\n uint256 chainId,\n IERC20 token,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx,\n uint256 minDy,\n uint256 deadline,\n uint8 liqTokenIndex,\n uint256 liqMinAmount,\n uint256 liqDeadline\n ) external {\n ISwap swap = ISwap(swapMap[address(token)]);\n require(address(swap) != address(0), \"Swap is 0x00\");\n IERC20[] memory tokens = swapTokensMap[address(swap)];\n tokens[tokenIndexFrom].safeTransferFrom(\n msg.sender,\n address(this),\n dx\n );\n // swap\n\n uint256 swappedAmount = swap.swap(\n tokenIndexFrom,\n tokenIndexTo,\n dx,\n minDy,\n deadline\n );\n // deposit into bridge, gets nUSD\n if (\n token.allowance(address(this), address(synapseBridge)) <\n swappedAmount\n ) {\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n }\n synapseBridge.redeemAndRemove(\n to,\n chainId,\n token,\n swappedAmount,\n liqTokenIndex,\n liqMinAmount,\n liqDeadline\n );\n }\n\n /**\n * @notice wraps SynapseBridge redeem()\n * @param to address on other chain to redeem underlying assets to\n * @param chainId which underlying chain to bridge assets onto\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n **/\n function redeem(\n address to,\n uint256 chainId,\n IERC20 token,\n uint256 amount\n ) external {\n token.safeTransferFrom(msg.sender, address(this), amount);\n if (token.allowance(address(this), address(synapseBridge)) < amount) {\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n }\n synapseBridge.redeem(to, chainId, token, amount);\n }\n\n /**\n * @notice wraps SynapseBridge redeem()\n * @param to address on other chain to redeem underlying assets to\n * @param chainId which underlying chain to bridge assets onto\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n **/\n function deposit(\n address to,\n uint256 chainId,\n IERC20 token,\n uint256 amount\n ) external {\n token.safeTransferFrom(msg.sender, address(this), amount);\n if (token.allowance(address(this), address(synapseBridge)) < amount) {\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n }\n synapseBridge.deposit(to, chainId, token, amount);\n }\n\n /**\n * @notice Wraps SynapseBridge deposit() function to make it compatible w/ ETH -> WETH conversions\n * @param to address on other chain to bridge assets to\n * @param chainId which chain to bridge assets onto\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n **/\n function depositETH(\n address to,\n uint256 chainId,\n uint256 amount\n ) external payable {\n require(msg.value > 0 && msg.value == amount, 'INCORRECT MSG VALUE');\n IWETH9(WETH_ADDRESS).deposit{value: msg.value}();\n synapseBridge.deposit(to, chainId, IERC20(WETH_ADDRESS), amount);\n }\n\n\n function swapETHAndRedeem(\n address to,\n uint256 chainId,\n IERC20 token,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx,\n uint256 minDy,\n uint256 deadline\n ) external payable {\n require(WETH_ADDRESS != address(0), \"WETH 0\");\n require(msg.value > 0 && msg.value == dx, \"INCORRECT MSG VALUE\");\n ISwap swap = ISwap(swapMap[address(token)]);\n require(address(swap) != address(0), \"Swap is 0x00\");\n IWETH9(WETH_ADDRESS).deposit{value: msg.value}();\n\n // swap\n uint256 swappedAmount = swap.swap(\n tokenIndexFrom,\n tokenIndexTo,\n dx,\n minDy,\n deadline\n );\n synapseBridge.redeem(to, chainId, token, swappedAmount);\n }\n\n\n function swapETHAndRedeemAndSwap(\n address to,\n uint256 chainId,\n IERC20 token,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx,\n uint256 minDy,\n uint256 deadline,\n uint8 swapTokenIndexFrom,\n uint8 swapTokenIndexTo,\n uint256 swapMinDy,\n uint256 swapDeadline\n ) external payable {\n require(WETH_ADDRESS != address(0), \"WETH 0\");\n require(msg.value > 0 && msg.value == dx, \"INCORRECT MSG VALUE\");\n ISwap swap = ISwap(swapMap[address(token)]);\n require(address(swap) != address(0), \"Swap is 0x00\");\n IWETH9(WETH_ADDRESS).deposit{value: msg.value}();\n\n // swap\n uint256 swappedAmount = swap.swap(\n tokenIndexFrom,\n tokenIndexTo,\n dx,\n minDy,\n deadline\n );\n synapseBridge.redeemAndSwap(to, chainId, token, swappedAmount,swapTokenIndexFrom,\n swapTokenIndexTo,\n swapMinDy,\n swapDeadline);\n }\n\n\n /**\n * @notice Wraps redeemAndSwap on SynapseBridge.sol\n * Relays to nodes that (typically) a wrapped synAsset ERC20 token has been burned and the underlying needs to be redeeemed on the native chain. This function indicates to the nodes that they should attempt to redeem the LP token for the underlying assets (E.g \"swap\" out of the LP token)\n * @param to address on other chain to redeem underlying assets to\n * @param chainId which underlying chain to bridge assets onto\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n * @param tokenIndexFrom the token the user wants to swap from\n * @param tokenIndexTo the token the user wants to swap to\n * @param minDy the min amount the user would like to receive, or revert to only minting the SynERC20 token crosschain.\n * @param deadline latest timestamp to accept this transaction\n **/\n function redeemAndSwap(\n address to,\n uint256 chainId,\n IERC20 token,\n uint256 amount,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 minDy,\n uint256 deadline\n ) external {\n token.safeTransferFrom(msg.sender, address(this), amount);\n if (token.allowance(address(this), address(synapseBridge)) < amount) {\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n }\n synapseBridge.redeemAndSwap(\n to,\n chainId,\n token,\n amount,\n tokenIndexFrom,\n tokenIndexTo,\n minDy,\n deadline\n );\n }\n\n /**\n * @notice Wraps redeemAndRemove on SynapseBridge\n * Relays to nodes that (typically) a wrapped synAsset ERC20 token has been burned and the underlying needs to be redeeemed on the native chain. This function indicates to the nodes that they should attempt to redeem the LP token for the underlying assets (E.g \"swap\" out of the LP token)\n * @param to address on other chain to redeem underlying assets to\n * @param chainId which underlying chain to bridge assets onto\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount of (typically) LP token to pass to the nodes to attempt to removeLiquidity() with to redeem for the underlying assets of the LP token\n * @param liqTokenIndex Specifies which of the underlying LP assets the nodes should attempt to redeem for\n * @param liqMinAmount Specifies the minimum amount of the underlying asset needed for the nodes to execute the redeem/swap\n * @param liqDeadline Specificies the deadline that the nodes are allowed to try to redeem/swap the LP token\n **/\n function redeemAndRemove(\n address to,\n uint256 chainId,\n IERC20 token,\n uint256 amount,\n uint8 liqTokenIndex,\n uint256 liqMinAmount,\n uint256 liqDeadline\n ) external {\n token.safeTransferFrom(msg.sender, address(this), amount);\n if (token.allowance(address(this), address(synapseBridge)) < amount) {\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n }\n synapseBridge.redeemAndRemove(\n to,\n chainId,\n token,\n amount,\n liqTokenIndex,\n liqMinAmount,\n liqDeadline\n );\n }\n\n /**\n * @notice Wraps SynapseBridge redeemv2() function\n * @param to address on other chain to bridge assets to\n * @param chainId which chain to bridge assets onto\n * @param token ERC20 compatible token to redeem into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n **/\n function redeemv2(\n bytes32 to,\n uint256 chainId,\n IERC20 token,\n uint256 amount\n ) external {\n token.safeTransferFrom(msg.sender, address(this), amount);\n\n if (token.allowance(address(this), address(synapseBridge)) < amount) {\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n }\n synapseBridge.redeemv2(to, chainId, token, amount);\n }\n}\n" + }, + "contracts/bridge/wrappers/L1BridgeZap.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.6.12;\n\nimport '@openzeppelin/contracts/token/ERC20/IERC20.sol';\nimport '@openzeppelin/contracts/token/ERC20/SafeERC20.sol';\nimport '../interfaces/ISwap.sol';\nimport '../interfaces/ISynapseBridge.sol';\nimport \"../interfaces/IWETH9.sol\";\n\n\n/**\n * @title L1BridgeZap\n * @notice This contract is responsible for handling user Zaps into the SynapseBridge contract, through the Synapse Swap contracts. It does so\n * It does so by combining the action of addLiquidity() to the base swap pool, and then calling either deposit() or depositAndSwap() on the bridge.\n * This is done in hopes of automating portions of the bridge user experience to users, while keeping the SynapseBridge contract logic small.\n *\n * @dev This contract should be deployed with a base Swap.sol address and a SynapseBridge.sol address, otherwise, it will not function.\n */\ncontract L1BridgeZap {\n using SafeERC20 for IERC20;\n\n uint256 constant MAX_UINT256 = 2**256 - 1;\n \n ISwap baseSwap;\n ISynapseBridge synapseBridge;\n IERC20[] public baseTokens;\n address payable public immutable WETH_ADDRESS;\n \n\n /**\n * @notice Constructs the contract, approves each token inside of baseSwap to be used by baseSwap (needed for addLiquidity())\n */\n constructor(address payable _wethAddress, ISwap _baseSwap, ISynapseBridge _synapseBridge) public {\n WETH_ADDRESS = _wethAddress;\n baseSwap = _baseSwap;\n synapseBridge = _synapseBridge;\n IERC20(_wethAddress).safeIncreaseAllowance(address(_synapseBridge), MAX_UINT256);\n {\n uint8 i;\n for (; i < 32; i++) {\n try _baseSwap.getToken(i) returns (IERC20 token) {\n baseTokens.push(token);\n token.safeIncreaseAllowance(address(_baseSwap), MAX_UINT256);\n } catch {\n break;\n }\n }\n require(i > 1, 'baseSwap must have at least 2 tokens');\n }\n }\n \n /**\n * @notice Wraps SynapseBridge deposit() function to make it compatible w/ ETH -> WETH conversions\n * @param to address on other chain to bridge assets to\n * @param chainId which chain to bridge assets onto\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n **/\n function depositETH(\n address to,\n uint256 chainId,\n uint256 amount\n ) external payable {\n require(msg.value > 0 && msg.value == amount, 'INCORRECT MSG VALUE');\n IWETH9(WETH_ADDRESS).deposit{value: msg.value}();\n synapseBridge.deposit(to, chainId, IERC20(WETH_ADDRESS), amount);\n }\n\n /**\n * @notice Wraps SynapseBridge depositAndSwap() function to make it compatible w/ ETH -> WETH conversions\n * @param to address on other chain to bridge assets to\n * @param chainId which chain to bridge assets onto\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n * @param tokenIndexFrom the token the user wants to swap from\n * @param tokenIndexTo the token the user wants to swap to\n * @param minDy the min amount the user would like to receive, or revert to only minting the SynERC20 token crosschain.\n * @param deadline latest timestamp to accept this transaction\n **/\n function depositETHAndSwap(\n address to,\n uint256 chainId,\n uint256 amount,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 minDy,\n uint256 deadline\n ) external payable {\n require(msg.value > 0 && msg.value == amount, 'INCORRECT MSG VALUE');\n IWETH9(WETH_ADDRESS).deposit{value: msg.value}();\n synapseBridge.depositAndSwap(to, chainId, IERC20(WETH_ADDRESS), amount, tokenIndexFrom, tokenIndexTo, minDy, deadline);\n }\n\n\n /**\n * @notice A simple method to calculate prices from deposits or\n * withdrawals, excluding fees but including slippage. This is\n * helpful as an input into the various \"min\" parameters on calls\n * to fight front-running\n *\n * @dev This shouldn't be used outside frontends for user estimates.\n *\n * @param amounts an array of token amounts to deposit or withdrawal,\n * corresponding to pooledTokens. The amount should be in each\n * pooled token's native precision.\n * @param deposit whether this is a deposit or a withdrawal\n * @return token amount the user will receive\n */\n function calculateTokenAmount(uint256[] calldata amounts, bool deposit)\n external\n view\n virtual\n returns (uint256)\n {\n return baseSwap.calculateTokenAmount(amounts, deposit);\n }\n\n /**\n * @notice Calculate the amount of underlying token available to withdraw\n * when withdrawing via only single token\n * @param tokenAmount the amount of LP token to burn\n * @param tokenIndex index of which token will be withdrawn\n * @return availableTokenAmount calculated amount of underlying token\n * available to withdraw\n */\n function calculateRemoveLiquidityOneToken(\n uint256 tokenAmount,\n uint8 tokenIndex\n ) external view virtual returns (uint256 availableTokenAmount) {\n return baseSwap.calculateRemoveLiquidityOneToken(tokenAmount, tokenIndex);\n }\n\n\n /**\n * @notice Combines adding liquidity to the given Swap, and calls deposit() on the bridge using that LP token\n * @param to address on other chain to bridge assets to\n * @param chainId which chain to bridge assets onto\n * @param token ERC20 compatible token to deposit into the bridge\n * @param liquidityAmounts the amounts of each token to add, in their native precision\n * @param minToMint the minimum LP tokens adding this amount of liquidity\n * should mint, otherwise revert. Handy for front-running mitigation\n * @param deadline latest timestamp to accept this transaction\n **/\n function zapAndDeposit(\n address to,\n uint256 chainId,\n IERC20 token,\n uint256[] calldata liquidityAmounts,\n uint256 minToMint,\n uint256 deadline\n ) external {\n // add liquidity\n for (uint256 i = 0; i < baseTokens.length; i++) {\n if (liquidityAmounts[i] != 0) {\n baseTokens[i].safeTransferFrom(\n msg.sender,\n address(this),\n liquidityAmounts[i]\n );\n }\n }\n\n uint256 liqAdded = baseSwap.addLiquidity(\n liquidityAmounts,\n minToMint,\n deadline\n );\n // deposit into bridge, gets nUSD\n if (token.allowance(address(this), address(synapseBridge)) < liqAdded) {\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n }\n synapseBridge.deposit(to, chainId, token, liqAdded);\n }\n\n /**\n * @notice Combines adding liquidity to the given Swap, and calls depositAndSwap() on the bridge using that LP token\n * @param to address on other chain to bridge assets to\n * @param chainId which chain to bridge assets onto\n * @param token ERC20 compatible token to deposit into the bridge\n * @param liquidityAmounts the amounts of each token to add, in their native precision\n * @param minToMint the minimum LP tokens adding this amount of liquidity\n * should mint, otherwise revert. Handy for front-running mitigation\n * @param liqDeadline latest timestamp to accept this transaction\n * @param tokenIndexFrom the token the user wants to swap from\n * @param tokenIndexTo the token the user wants to swap to\n * @param minDy the min amount the user would like to receive, or revert to only minting the SynERC20 token crosschain.\n * @param swapDeadline latest timestamp to accept this transaction\n **/\n function zapAndDepositAndSwap(\n address to,\n uint256 chainId,\n IERC20 token,\n uint256[] calldata liquidityAmounts,\n uint256 minToMint,\n uint256 liqDeadline,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 minDy,\n uint256 swapDeadline\n ) external {\n // add liquidity\n for (uint256 i = 0; i < baseTokens.length; i++) {\n if (liquidityAmounts[i] != 0) {\n baseTokens[i].safeTransferFrom(\n msg.sender,\n address(this),\n liquidityAmounts[i]\n );\n }\n }\n\n uint256 liqAdded = baseSwap.addLiquidity(\n liquidityAmounts,\n minToMint,\n liqDeadline\n );\n // deposit into bridge, bridge attemps to swap into desired asset\n if (token.allowance(address(this), address(synapseBridge)) < liqAdded) {\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n }\n synapseBridge.depositAndSwap(\n to,\n chainId,\n token,\n liqAdded,\n tokenIndexFrom,\n tokenIndexTo,\n minDy,\n swapDeadline\n );\n }\n\n /**\n * @notice Wraps SynapseBridge deposit() function\n * @param to address on other chain to bridge assets to\n * @param chainId which chain to bridge assets onto\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n **/\n function deposit(\n address to,\n uint256 chainId,\n IERC20 token,\n uint256 amount\n ) external {\n token.safeTransferFrom(msg.sender, address(this), amount);\n\n if (token.allowance(address(this), address(synapseBridge)) < amount) {\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n }\n synapseBridge.deposit(to, chainId, token, amount);\n }\n \n /**\n * @notice Wraps SynapseBridge depositAndSwap() function\n * @param to address on other chain to bridge assets to\n * @param chainId which chain to bridge assets onto\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n * @param tokenIndexFrom the token the user wants to swap from\n * @param tokenIndexTo the token the user wants to swap to\n * @param minDy the min amount the user would like to receive, or revert to only minting the SynERC20 token crosschain.\n * @param deadline latest timestamp to accept this transaction\n **/\n function depositAndSwap(\n address to,\n uint256 chainId,\n IERC20 token,\n uint256 amount,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 minDy,\n uint256 deadline\n ) external {\n token.safeTransferFrom(msg.sender, address(this), amount);\n \n if (token.allowance(address(this), address(synapseBridge)) < amount) {\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n }\n synapseBridge.depositAndSwap(to, chainId, token, amount, tokenIndexFrom, tokenIndexTo, minDy, deadline);\n }\n\n\n /**\n * @notice Wraps SynapseBridge redeem() function\n * @param to address on other chain to bridge assets to\n * @param chainId which chain to bridge assets onto\n * @param token ERC20 compatible token to redeem into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n **/\n function redeem(\n address to,\n uint256 chainId,\n IERC20 token,\n uint256 amount\n ) external {\n token.safeTransferFrom(msg.sender, address(this), amount);\n\n if (token.allowance(address(this), address(synapseBridge)) < amount) {\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n }\n synapseBridge.redeem(to, chainId, token, amount);\n }\n\n /**\n * @notice Wraps SynapseBridge redeemv2() function\n * @param to address on other chain to bridge assets to\n * @param chainId which chain to bridge assets onto\n * @param token ERC20 compatible token to redeem into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n **/\n function redeemv2(\n bytes32 to,\n uint256 chainId,\n IERC20 token,\n uint256 amount\n ) external {\n token.safeTransferFrom(msg.sender, address(this), amount);\n\n if (token.allowance(address(this), address(synapseBridge)) < amount) {\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n }\n synapseBridge.redeemv2(to, chainId, token, amount);\n }\n\n}\n" + }, + "contracts/bridge/wrappers/MigratorBridgeZap.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.6.12;\n\nimport '@openzeppelin/contracts/token/ERC20/IERC20.sol';\nimport '@openzeppelin/contracts/token/ERC20/SafeERC20.sol';\nimport '@openzeppelin/contracts/math/SafeMath.sol';\n\nimport '../interfaces/ISynapseBridge.sol';\nimport '../interfaces/IERC20Migrator.sol';\n\ncontract MigratorBridgeZap {\n using SafeERC20 for IERC20;\n using SafeMath for uint256;\n \n ISynapseBridge constant synapseBridge = ISynapseBridge(0xd123f70AE324d34A9E76b67a27bf77593bA8749f);\n IERC20Migrator constant erc20Migrator = IERC20Migrator(0xf0284FB86adA5E4D82555C529677eEA3B2C3E022); \n IERC20 constant legacyToken = IERC20(0x42F6f551ae042cBe50C739158b4f0CAC0Edb9096);\n IERC20 constant newToken = IERC20(0xa4080f1778e69467E905B8d6F72f6e441f9e9484);\n uint256 constant MAX_UINT256 = 2**256 - 1;\n\n constructor() public {\n legacyToken.safeApprove(address(erc20Migrator), MAX_UINT256);\n newToken.safeApprove(address(synapseBridge), MAX_UINT256);\n }\n\n function migrate(uint256 amount) external {\n legacyToken.safeTransferFrom(msg.sender, address(this), amount);\n erc20Migrator.migrate(amount);\n newToken.safeTransfer(msg.sender, amount.mul(5).div(2));\n }\n\n function migrateAndBridge(uint256 amount, address to, uint256 chainId) external {\n legacyToken.safeTransferFrom(msg.sender, address(this), amount);\n erc20Migrator.migrate(amount);\n synapseBridge.redeem(to, chainId, newToken, amount.mul(5).div(2));\n }\n}" + }, + "contracts/bridge/interfaces/IERC20Migrator.sol": { + "content": "// SPDX-License-Identifier: MIT\n\n\npragma solidity 0.6.12;\n\ninterface IERC20Migrator { \n function migrate(uint256 amount) external;\n}\n\n" + }, + "contracts/bridge/wrappers/JewelBridgeSwap.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.6.12;\n\nimport '@openzeppelin/contracts/token/ERC20/ERC20.sol';\nimport \"@openzeppelin/contracts/token/ERC20/SafeERC20.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/ERC20Burnable.sol\";\nimport \"@openzeppelin/contracts/math/SafeMath.sol\";\n\ninterface IERC20Mintable is IERC20 {\n function mint(address to, uint256 amount) external;\n}\n\ncontract JewelBridgeSwap {\n using SafeERC20 for IERC20;\n using SafeERC20 for IERC20Mintable;\n using SafeMath for uint256;\n\n // Maps token address to an index in the pool. Used to prevent duplicate tokens in the pool.\n // getTokenIndex function also relies on this mapping to retrieve token index.\n mapping(address => uint8) private tokenIndexes;\n IERC20[2] pooledTokens;\n \n constructor(IERC20 tokenA, IERC20 mintableTokenB) public {\n pooledTokens[0] = tokenA;\n pooledTokens[1] = mintableTokenB;\n tokenIndexes[address(tokenA)] = 0;\n tokenIndexes[address(mintableTokenB)] = 1;\n }\n\n /**\n * @notice Return address of the pooled token at given index. Reverts if tokenIndex is out of range.\n * @param index the index of the token\n * @return address of the token at given index\n */\n function getToken(uint8 index) public view returns (IERC20) {\n require(index < pooledTokens.length, \"Out of range\");\n return pooledTokens[index];\n }\n\n /**\n * @notice Return the index of the given token address. Reverts if no matching\n * token is found.\n * @param tokenAddress address of the token\n * @return the index of the given token address\n */\n function getTokenIndex(address tokenAddress)\n public\n view\n returns (uint8)\n {\n uint8 index = tokenIndexes[tokenAddress];\n require(\n address(getToken(index)) == tokenAddress,\n \"Token does not exist\"\n );\n return index;\n }\n\n /**\n * @notice Calculate amount of tokens you receive on swap\n * @param tokenIndexFrom the token the user wants to sell\n * @param tokenIndexTo the token the user wants to buy\n * @param dx the amount of tokens the user wants to swap. \n * @return amount of tokens the user will receive\n */\n function calculateSwap(\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx\n ) external view returns (uint256) {\n return dx;\n }\n\n /**\n * @notice Swap two tokens using this pool\n * @param tokenIndexFrom the token the user wants to swap from\n * @param tokenIndexTo the token the user wants to swap to\n * @param dx the amount of tokens the user wants to swap from\n * @param minDy the min amount the user would like to receive, or revert.\n * @param deadline latest timestamp to accept this transaction\n */\n function swap(\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx,\n uint256 minDy,\n uint256 deadline\n )\n external\n returns (uint256)\n {\n {\n IERC20 tokenFrom = pooledTokens[tokenIndexFrom];\n require(\n dx <= tokenFrom.balanceOf(msg.sender),\n \"Cannot swap more than you own\"\n );\n // Transfer tokens first to see if a fee was charged on transfer\n uint256 beforeBalance = tokenFrom.balanceOf(address(this));\n tokenFrom.safeTransferFrom(msg.sender, address(this), dx);\n\n // Use the actual transferred amount for AMM math\n dx = tokenFrom.balanceOf(address(this)).sub(beforeBalance);\n }\n\n // redeem JEWEL for synJEWEL\n if (tokenIndexFrom == 0 && tokenIndexTo == 1) {\n IERC20Mintable(address(pooledTokens[tokenIndexTo])).mint(msg.sender, dx);\n return dx;\n // redeem synJEWEL for JEWEL\n } else if (tokenIndexFrom == 1 && tokenIndexTo == 0) {\n ERC20Burnable(address(pooledTokens[tokenIndexFrom])).burn(dx);\n pooledTokens[tokenIndexTo].safeTransfer(msg.sender, dx);\n return dx;\n } else {\n revert(\"Unsupported indexes\");\n }\n }\n}" + }, + "contracts/bridge/testing/SynapseToken.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity >=0.6.0 <0.8.0;\n\n\nimport \"@openzeppelin/contracts/token/ERC20/ERC20.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/ERC20Burnable.sol\";\nimport \"@openzeppelin/contracts/access/AccessControl.sol\";\nimport \"@openzeppelin/contracts/drafts/ERC20Permit.sol\";\n\ncontract Synapse is ERC20, ERC20Burnable, AccessControl, ERC20Permit {\n bytes32 public constant MINTER_ROLE = keccak256(\"MINTER_ROLE\");\n\n constructor() public ERC20(\"Synapse\", \"SYN\") ERC20Permit(\"Synapse\") {\n _setupRole(DEFAULT_ADMIN_ROLE, msg.sender);\n _setupRole(MINTER_ROLE, msg.sender);\n }\n\n function mint(address to, uint256 amount) external {\n require(hasRole(MINTER_ROLE, msg.sender));\n _mint(to, amount);\n }\n}" + }, + "@openzeppelin/contracts/access/AccessControl.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <0.8.0;\n\nimport \"../utils/EnumerableSet.sol\";\nimport \"../utils/Address.sol\";\nimport \"../utils/Context.sol\";\n\n/**\n * @dev Contract module that allows children to implement role-based access\n * control mechanisms.\n *\n * Roles are referred to by their `bytes32` identifier. These should be exposed\n * in the external API and be unique. The best way to achieve this is by\n * using `public constant` hash digests:\n *\n * ```\n * bytes32 public constant MY_ROLE = keccak256(\"MY_ROLE\");\n * ```\n *\n * Roles can be used to represent a set of permissions. To restrict access to a\n * function call, use {hasRole}:\n *\n * ```\n * function foo() public {\n * require(hasRole(MY_ROLE, msg.sender));\n * ...\n * }\n * ```\n *\n * Roles can be granted and revoked dynamically via the {grantRole} and\n * {revokeRole} functions. Each role has an associated admin role, and only\n * accounts that have a role's admin role can call {grantRole} and {revokeRole}.\n *\n * By default, the admin role for all roles is `DEFAULT_ADMIN_ROLE`, which means\n * that only accounts with this role will be able to grant or revoke other\n * roles. More complex role relationships can be created by using\n * {_setRoleAdmin}.\n *\n * WARNING: The `DEFAULT_ADMIN_ROLE` is also its own admin: it has permission to\n * grant and revoke this role. Extra precautions should be taken to secure\n * accounts that have been granted it.\n */\nabstract contract AccessControl is Context {\n using EnumerableSet for EnumerableSet.AddressSet;\n using Address for address;\n\n struct RoleData {\n EnumerableSet.AddressSet members;\n bytes32 adminRole;\n }\n\n mapping (bytes32 => RoleData) private _roles;\n\n bytes32 public constant DEFAULT_ADMIN_ROLE = 0x00;\n\n /**\n * @dev Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole`\n *\n * `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite\n * {RoleAdminChanged} not being emitted signaling this.\n *\n * _Available since v3.1._\n */\n event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole);\n\n /**\n * @dev Emitted when `account` is granted `role`.\n *\n * `sender` is the account that originated the contract call, an admin role\n * bearer except when using {_setupRole}.\n */\n event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender);\n\n /**\n * @dev Emitted when `account` is revoked `role`.\n *\n * `sender` is the account that originated the contract call:\n * - if using `revokeRole`, it is the admin role bearer\n * - if using `renounceRole`, it is the role bearer (i.e. `account`)\n */\n event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender);\n\n /**\n * @dev Returns `true` if `account` has been granted `role`.\n */\n function hasRole(bytes32 role, address account) public view returns (bool) {\n return _roles[role].members.contains(account);\n }\n\n /**\n * @dev Returns the number of accounts that have `role`. Can be used\n * together with {getRoleMember} to enumerate all bearers of a role.\n */\n function getRoleMemberCount(bytes32 role) public view returns (uint256) {\n return _roles[role].members.length();\n }\n\n /**\n * @dev Returns one of the accounts that have `role`. `index` must be a\n * value between 0 and {getRoleMemberCount}, non-inclusive.\n *\n * Role bearers are not sorted in any particular way, and their ordering may\n * change at any point.\n *\n * WARNING: When using {getRoleMember} and {getRoleMemberCount}, make sure\n * you perform all queries on the same block. See the following\n * https://forum.openzeppelin.com/t/iterating-over-elements-on-enumerableset-in-openzeppelin-contracts/2296[forum post]\n * for more information.\n */\n function getRoleMember(bytes32 role, uint256 index) public view returns (address) {\n return _roles[role].members.at(index);\n }\n\n /**\n * @dev Returns the admin role that controls `role`. See {grantRole} and\n * {revokeRole}.\n *\n * To change a role's admin, use {_setRoleAdmin}.\n */\n function getRoleAdmin(bytes32 role) public view returns (bytes32) {\n return _roles[role].adminRole;\n }\n\n /**\n * @dev Grants `role` to `account`.\n *\n * If `account` had not been already granted `role`, emits a {RoleGranted}\n * event.\n *\n * Requirements:\n *\n * - the caller must have ``role``'s admin role.\n */\n function grantRole(bytes32 role, address account) public virtual {\n require(hasRole(_roles[role].adminRole, _msgSender()), \"AccessControl: sender must be an admin to grant\");\n\n _grantRole(role, account);\n }\n\n /**\n * @dev Revokes `role` from `account`.\n *\n * If `account` had been granted `role`, emits a {RoleRevoked} event.\n *\n * Requirements:\n *\n * - the caller must have ``role``'s admin role.\n */\n function revokeRole(bytes32 role, address account) public virtual {\n require(hasRole(_roles[role].adminRole, _msgSender()), \"AccessControl: sender must be an admin to revoke\");\n\n _revokeRole(role, account);\n }\n\n /**\n * @dev Revokes `role` from the calling account.\n *\n * Roles are often managed via {grantRole} and {revokeRole}: this function's\n * purpose is to provide a mechanism for accounts to lose their privileges\n * if they are compromised (such as when a trusted device is misplaced).\n *\n * If the calling account had been granted `role`, emits a {RoleRevoked}\n * event.\n *\n * Requirements:\n *\n * - the caller must be `account`.\n */\n function renounceRole(bytes32 role, address account) public virtual {\n require(account == _msgSender(), \"AccessControl: can only renounce roles for self\");\n\n _revokeRole(role, account);\n }\n\n /**\n * @dev Grants `role` to `account`.\n *\n * If `account` had not been already granted `role`, emits a {RoleGranted}\n * event. Note that unlike {grantRole}, this function doesn't perform any\n * checks on the calling account.\n *\n * [WARNING]\n * ====\n * This function should only be called from the constructor when setting\n * up the initial roles for the system.\n *\n * Using this function in any other way is effectively circumventing the admin\n * system imposed by {AccessControl}.\n * ====\n */\n function _setupRole(bytes32 role, address account) internal virtual {\n _grantRole(role, account);\n }\n\n /**\n * @dev Sets `adminRole` as ``role``'s admin role.\n *\n * Emits a {RoleAdminChanged} event.\n */\n function _setRoleAdmin(bytes32 role, bytes32 adminRole) internal virtual {\n emit RoleAdminChanged(role, _roles[role].adminRole, adminRole);\n _roles[role].adminRole = adminRole;\n }\n\n function _grantRole(bytes32 role, address account) private {\n if (_roles[role].members.add(account)) {\n emit RoleGranted(role, account, _msgSender());\n }\n }\n\n function _revokeRole(bytes32 role, address account) private {\n if (_roles[role].members.remove(account)) {\n emit RoleRevoked(role, account, _msgSender());\n }\n }\n}\n" + }, + "@openzeppelin/contracts/drafts/ERC20Permit.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.5 <0.8.0;\n\nimport \"../token/ERC20/ERC20.sol\";\nimport \"./IERC20Permit.sol\";\nimport \"../cryptography/ECDSA.sol\";\nimport \"../utils/Counters.sol\";\nimport \"./EIP712.sol\";\n\n/**\n * @dev Implementation of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in\n * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612].\n *\n * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by\n * presenting a message signed by the account. By not relying on `{IERC20-approve}`, the token holder account doesn't\n * need to send a transaction, and thus is not required to hold Ether at all.\n *\n * _Available since v3.4._\n */\nabstract contract ERC20Permit is ERC20, IERC20Permit, EIP712 {\n using Counters for Counters.Counter;\n\n mapping (address => Counters.Counter) private _nonces;\n\n // solhint-disable-next-line var-name-mixedcase\n bytes32 private immutable _PERMIT_TYPEHASH = keccak256(\"Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)\");\n\n /**\n * @dev Initializes the {EIP712} domain separator using the `name` parameter, and setting `version` to `\"1\"`.\n *\n * It's a good idea to use the same `name` that is defined as the ERC20 token name.\n */\n constructor(string memory name) internal EIP712(name, \"1\") {\n }\n\n /**\n * @dev See {IERC20Permit-permit}.\n */\n function permit(address owner, address spender, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s) public virtual override {\n // solhint-disable-next-line not-rely-on-time\n require(block.timestamp <= deadline, \"ERC20Permit: expired deadline\");\n\n bytes32 structHash = keccak256(\n abi.encode(\n _PERMIT_TYPEHASH,\n owner,\n spender,\n value,\n _nonces[owner].current(),\n deadline\n )\n );\n\n bytes32 hash = _hashTypedDataV4(structHash);\n\n address signer = ECDSA.recover(hash, v, r, s);\n require(signer == owner, \"ERC20Permit: invalid signature\");\n\n _nonces[owner].increment();\n _approve(owner, spender, value);\n }\n\n /**\n * @dev See {IERC20Permit-nonces}.\n */\n function nonces(address owner) public view override returns (uint256) {\n return _nonces[owner].current();\n }\n\n /**\n * @dev See {IERC20Permit-DOMAIN_SEPARATOR}.\n */\n // solhint-disable-next-line func-name-mixedcase\n function DOMAIN_SEPARATOR() external view override returns (bytes32) {\n return _domainSeparatorV4();\n }\n}\n" + }, + "@openzeppelin/contracts/utils/EnumerableSet.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <0.8.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" + }, + "@openzeppelin/contracts/drafts/IERC20Permit.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <0.8.0;\n\n/**\n * @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in\n * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612].\n *\n * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by\n * presenting a message signed by the account. By not relying on `{IERC20-approve}`, the token holder account doesn't\n * need to send a transaction, and thus is not required to hold Ether at all.\n */\ninterface IERC20Permit {\n /**\n * @dev Sets `value` as the allowance of `spender` over `owner`'s tokens,\n * given `owner`'s signed approval.\n *\n * IMPORTANT: The same issues {IERC20-approve} has related to transaction\n * ordering also apply here.\n *\n * Emits an {Approval} event.\n *\n * Requirements:\n *\n * - `spender` cannot be the zero address.\n * - `deadline` must be a timestamp in the future.\n * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner`\n * over the EIP712-formatted function arguments.\n * - the signature must use ``owner``'s current nonce (see {nonces}).\n *\n * For more information on the signature format, see the\n * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP\n * section].\n */\n function permit(address owner, address spender, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s) external;\n\n /**\n * @dev Returns the current nonce for `owner`. This value must be\n * included whenever a signature is generated for {permit}.\n *\n * Every successful call to {permit} increases ``owner``'s nonce by one. This\n * prevents a signature from being used multiple times.\n */\n function nonces(address owner) external view returns (uint256);\n\n /**\n * @dev Returns the domain separator used in the encoding of the signature for `permit`, as defined by {EIP712}.\n */\n // solhint-disable-next-line func-name-mixedcase\n function DOMAIN_SEPARATOR() external view returns (bytes32);\n}\n" + }, + "@openzeppelin/contracts/cryptography/ECDSA.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <0.8.0;\n\n/**\n * @dev Elliptic Curve Digital Signature Algorithm (ECDSA) operations.\n *\n * These functions can be used to verify that a message was signed by the holder\n * of the private keys of a given address.\n */\nlibrary ECDSA {\n /**\n * @dev Returns the address that signed a hashed message (`hash`) with\n * `signature`. This address can then be used for verification purposes.\n *\n * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:\n * this function rejects them by requiring the `s` value to be in the lower\n * half order, and the `v` value to be either 27 or 28.\n *\n * IMPORTANT: `hash` _must_ be the result of a hash operation for the\n * verification to be secure: it is possible to craft signatures that\n * recover to arbitrary addresses for non-hashed data. A safe way to ensure\n * this is by receiving a hash of the original message (which may otherwise\n * be too long), and then calling {toEthSignedMessageHash} on it.\n */\n function recover(bytes32 hash, bytes memory signature) internal pure returns (address) {\n // Check the signature length\n if (signature.length != 65) {\n revert(\"ECDSA: invalid signature length\");\n }\n\n // Divide the signature in r, s and v variables\n bytes32 r;\n bytes32 s;\n uint8 v;\n\n // ecrecover takes the signature parameters, and the only way to get them\n // currently is to use assembly.\n // solhint-disable-next-line no-inline-assembly\n assembly {\n r := mload(add(signature, 0x20))\n s := mload(add(signature, 0x40))\n v := byte(0, mload(add(signature, 0x60)))\n }\n\n return recover(hash, v, r, s);\n }\n\n /**\n * @dev Overload of {ECDSA-recover-bytes32-bytes-} that receives the `v`,\n * `r` and `s` signature fields separately.\n */\n function recover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) internal pure returns (address) {\n // EIP-2 still allows signature malleability for ecrecover(). Remove this possibility and make the signature\n // unique. Appendix F in the Ethereum Yellow paper (https://ethereum.github.io/yellowpaper/paper.pdf), defines\n // the valid range for s in (281): 0 < s < secp256k1n ÷ 2 + 1, and for v in (282): v ∈ {27, 28}. Most\n // signatures from current libraries generate a unique signature with an s-value in the lower half order.\n //\n // If your library generates malleable signatures, such as s-values in the upper range, calculate a new s-value\n // with 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 - s1 and flip v from 27 to 28 or\n // vice versa. If your library also generates signatures with 0/1 for v instead 27/28, add 27 to v to accept\n // these malleable signatures as well.\n require(uint256(s) <= 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0, \"ECDSA: invalid signature 's' value\");\n require(v == 27 || v == 28, \"ECDSA: invalid signature 'v' value\");\n\n // If the signature is valid (and not malleable), return the signer address\n address signer = ecrecover(hash, v, r, s);\n require(signer != address(0), \"ECDSA: invalid signature\");\n\n return signer;\n }\n\n /**\n * @dev Returns an Ethereum Signed Message, created from a `hash`. This\n * replicates the behavior of the\n * https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_sign[`eth_sign`]\n * JSON-RPC method.\n *\n * See {recover}.\n */\n function toEthSignedMessageHash(bytes32 hash) internal pure returns (bytes32) {\n // 32 is the length in bytes of hash,\n // enforced by the type signature above\n return keccak256(abi.encodePacked(\"\\x19Ethereum Signed Message:\\n32\", hash));\n }\n}\n" + }, + "@openzeppelin/contracts/utils/Counters.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <0.8.0;\n\nimport \"../math/SafeMath.sol\";\n\n/**\n * @title Counters\n * @author Matt Condon (@shrugs)\n * @dev Provides counters that can only be incremented or decremented by one. This can be used e.g. to track the number\n * of elements in a mapping, issuing ERC721 ids, or counting request ids.\n *\n * Include with `using Counters for Counters.Counter;`\n * Since it is not possible to overflow a 256 bit integer with increments of one, `increment` can skip the {SafeMath}\n * overflow check, thereby saving gas. This does assume however correct usage, in that the underlying `_value` is never\n * directly accessed.\n */\nlibrary Counters {\n using SafeMath for uint256;\n\n struct Counter {\n // This variable should never be directly accessed by users of the library: interactions must be restricted to\n // the library's function. As of Solidity v0.5.2, this cannot be enforced, though there is a proposal to add\n // this feature: see https://github.com/ethereum/solidity/issues/4637\n uint256 _value; // default: 0\n }\n\n function current(Counter storage counter) internal view returns (uint256) {\n return counter._value;\n }\n\n function increment(Counter storage counter) internal {\n // The {SafeMath} overflow check can be skipped here, see the comment at the top\n counter._value += 1;\n }\n\n function decrement(Counter storage counter) internal {\n counter._value = counter._value.sub(1);\n }\n}\n" + }, + "@openzeppelin/contracts/drafts/EIP712.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <0.8.0;\n\n/**\n * @dev https://eips.ethereum.org/EIPS/eip-712[EIP 712] is a standard for hashing and signing of typed structured data.\n *\n * The encoding specified in the EIP is very generic, and such a generic implementation in Solidity is not feasible,\n * thus this contract does not implement the encoding itself. Protocols need to implement the type-specific encoding\n * they need in their contracts using a combination of `abi.encode` and `keccak256`.\n *\n * This contract implements the EIP 712 domain separator ({_domainSeparatorV4}) that is used as part of the encoding\n * scheme, and the final step of the encoding to obtain the message digest that is then signed via ECDSA\n * ({_hashTypedDataV4}).\n *\n * The implementation of the domain separator was designed to be as efficient as possible while still properly updating\n * the chain id to protect against replay attacks on an eventual fork of the chain.\n *\n * NOTE: This contract implements the version of the encoding known as \"v4\", as implemented by the JSON RPC method\n * https://docs.metamask.io/guide/signing-data.html[`eth_signTypedDataV4` in MetaMask].\n *\n * _Available since v3.4._\n */\nabstract contract EIP712 {\n /* solhint-disable var-name-mixedcase */\n // Cache the domain separator as an immutable value, but also store the chain id that it corresponds to, in order to\n // invalidate the cached domain separator if the chain id changes.\n bytes32 private immutable _CACHED_DOMAIN_SEPARATOR;\n uint256 private immutable _CACHED_CHAIN_ID;\n\n bytes32 private immutable _HASHED_NAME;\n bytes32 private immutable _HASHED_VERSION;\n bytes32 private immutable _TYPE_HASH;\n /* solhint-enable var-name-mixedcase */\n\n /**\n * @dev Initializes the domain separator and parameter caches.\n *\n * The meaning of `name` and `version` is specified in\n * https://eips.ethereum.org/EIPS/eip-712#definition-of-domainseparator[EIP 712]:\n *\n * - `name`: the user readable name of the signing domain, i.e. the name of the DApp or the protocol.\n * - `version`: the current major version of the signing domain.\n *\n * NOTE: These parameters cannot be changed except through a xref:learn::upgrading-smart-contracts.adoc[smart\n * contract upgrade].\n */\n constructor(string memory name, string memory version) internal {\n bytes32 hashedName = keccak256(bytes(name));\n bytes32 hashedVersion = keccak256(bytes(version));\n bytes32 typeHash = keccak256(\"EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)\");\n _HASHED_NAME = hashedName;\n _HASHED_VERSION = hashedVersion;\n _CACHED_CHAIN_ID = _getChainId();\n _CACHED_DOMAIN_SEPARATOR = _buildDomainSeparator(typeHash, hashedName, hashedVersion);\n _TYPE_HASH = typeHash;\n }\n\n /**\n * @dev Returns the domain separator for the current chain.\n */\n function _domainSeparatorV4() internal view virtual returns (bytes32) {\n if (_getChainId() == _CACHED_CHAIN_ID) {\n return _CACHED_DOMAIN_SEPARATOR;\n } else {\n return _buildDomainSeparator(_TYPE_HASH, _HASHED_NAME, _HASHED_VERSION);\n }\n }\n\n function _buildDomainSeparator(bytes32 typeHash, bytes32 name, bytes32 version) private view returns (bytes32) {\n return keccak256(\n abi.encode(\n typeHash,\n name,\n version,\n _getChainId(),\n address(this)\n )\n );\n }\n\n /**\n * @dev Given an already https://eips.ethereum.org/EIPS/eip-712#definition-of-hashstruct[hashed struct], this\n * function returns the hash of the fully encoded EIP712 message for this domain.\n *\n * This hash can be used together with {ECDSA-recover} to obtain the signer of a message. For example:\n *\n * ```solidity\n * bytes32 digest = _hashTypedDataV4(keccak256(abi.encode(\n * keccak256(\"Mail(address to,string contents)\"),\n * mailTo,\n * keccak256(bytes(mailContents))\n * )));\n * address signer = ECDSA.recover(digest, signature);\n * ```\n */\n function _hashTypedDataV4(bytes32 structHash) internal view virtual returns (bytes32) {\n return keccak256(abi.encodePacked(\"\\x19\\x01\", _domainSeparatorV4(), structHash));\n }\n\n function _getChainId() private view returns (uint256 chainId) {\n this; // silence state mutability warning without generating bytecode - see https://github.com/ethereum/solidity/issues/2691\n // solhint-disable-next-line no-inline-assembly\n assembly {\n chainId := chainid()\n }\n }\n}\n" + }, + "contracts/bridge/mocks/ERC20Mock.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.6.12;\n\nimport \"@openzeppelin/contracts/token/ERC20/ERC20.sol\";\n\ncontract ERC20Mock is ERC20 {\n constructor(\n string memory name,\n string memory symbol,\n uint256 supply\n ) public ERC20(name, symbol) {\n _mint(msg.sender, supply);\n }\n\n function mint(address to, uint256 amount) external {\n _mint(to, amount);\n }\n}" + }, + "contracts/bridge/interfaces/IMetaSwapDeposit.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.6.12;\nimport '@openzeppelin/contracts/token/ERC20/ERC20.sol';\n\n/**\n * @title IMetaSwapDeposit interface\n * @notice Interface for the meta swap contract.\n * @dev implement this interface to develop a a factory-patterned ECDSA node management contract\n **/\ninterface IMetaSwapDeposit {\n // min return calculation functions\n function calculateSwap(\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx\n ) external view returns (uint256);\n\n function swap(\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx,\n uint256 minDy,\n uint256 deadline\n ) external returns (uint256);\n\n function getToken(uint256 index) external view returns (IERC20);\n}\n" + }, + "contracts/amm/interfaces/IMetaSwapDeposit.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.6.12;\n\nimport \"@openzeppelin/contracts/token/ERC20/ERC20.sol\";\nimport \"./ISwap.sol\";\nimport \"./IMetaSwap.sol\";\n\ninterface IMetaSwapDeposit {\n function initialize(\n ISwap baseSwap_,\n IMetaSwap metaSwap_,\n IERC20 metaLPToken_\n ) external;\n}\n" + }, + "contracts/amm/interfaces/IMetaSwap.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.6.12;\n\nimport \"@openzeppelin/contracts/token/ERC20/ERC20.sol\";\n\ninterface IMetaSwap {\n // pool data view functions\n function getA() external view returns (uint256);\n\n function getToken(uint8 index) external view returns (IERC20);\n\n function getTokenIndex(address tokenAddress) external view returns (uint8);\n\n function getTokenBalance(uint8 index) external view returns (uint256);\n\n function getVirtualPrice() external view returns (uint256);\n\n function isGuarded() external view returns (bool);\n\n // min return calculation functions\n function calculateSwap(\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx\n ) external view returns (uint256);\n\n function calculateSwapUnderlying(\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx\n ) external view returns (uint256);\n\n function calculateTokenAmount(uint256[] calldata amounts, bool deposit)\n external\n view\n returns (uint256);\n\n function calculateRemoveLiquidity(uint256 amount)\n external\n view\n returns (uint256[] memory);\n\n function calculateRemoveLiquidityOneToken(\n uint256 tokenAmount,\n uint8 tokenIndex\n ) external view returns (uint256 availableTokenAmount);\n\n // state modifying functions\n function initializeMetaSwap(\n IERC20[] memory pooledTokens,\n uint8[] memory decimals,\n string memory lpTokenName,\n string memory lpTokenSymbol,\n uint256 a,\n uint256 fee,\n uint256 adminFee,\n address lpTokenTargetAddress,\n address baseSwap\n ) external;\n\n function swap(\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx,\n uint256 minDy,\n uint256 deadline\n ) external returns (uint256);\n\n function swapUnderlying(\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx,\n uint256 minDy,\n uint256 deadline\n ) external returns (uint256);\n\n function addLiquidity(\n uint256[] calldata amounts,\n uint256 minToMint,\n uint256 deadline\n ) external returns (uint256);\n\n function removeLiquidity(\n uint256 amount,\n uint256[] calldata minAmounts,\n uint256 deadline\n ) external returns (uint256[] memory);\n\n function removeLiquidityOneToken(\n uint256 tokenAmount,\n uint8 tokenIndex,\n uint256 minAmount,\n uint256 deadline\n ) external returns (uint256);\n\n function removeLiquidityImbalance(\n uint256[] calldata amounts,\n uint256 maxBurnAmount,\n uint256 deadline\n ) external returns (uint256);\n\n function swapStorage()\n external\n view\n returns (\n uint256 initialA,\n uint256 futureA,\n uint256 initialATime,\n uint256 futureATime,\n uint256 swapFee,\n uint256 adminFee,\n address lpToken\n );\n}\n" + }, + "contracts/amm/helper/GenericERC20.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.6.12;\n\nimport \"@openzeppelin/contracts/token/ERC20/ERC20.sol\";\nimport \"@openzeppelin/contracts/access/Ownable.sol\";\n\n/**\n * @title Generic ERC20 token\n * @notice This contract simulates a generic ERC20 token that is mintable and burnable.\n */\ncontract GenericERC20 is ERC20, Ownable {\n /**\n * @notice Deploy this contract with given name, symbol, and decimals\n * @dev the caller of this constructor will become the owner of this contract\n * @param name_ name of this token\n * @param symbol_ symbol of this token\n * @param decimals_ number of decimals this token will be based on\n */\n constructor(\n string memory name_,\n string memory symbol_,\n uint8 decimals_\n ) public ERC20(name_, symbol_) {\n _setupDecimals(decimals_);\n }\n\n /**\n * @notice Mints given amount of tokens to recipient\n * @dev only owner can call this mint function\n * @param recipient address of account to receive the tokens\n * @param amount amount of tokens to mint\n */\n function mint(address recipient, uint256 amount) external onlyOwner {\n require(amount != 0, \"amount == 0\");\n _mint(recipient, amount);\n }\n}\n" + }, + "contracts/bridge/wrappers/HarmonyBridgeZap.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.6.12;\n\nimport \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/SafeERC20.sol\";\nimport \"../interfaces/ISwap.sol\";\nimport \"../interfaces/ISynapseBridge.sol\";\nimport \"../interfaces/IWETH9.sol\";\n\ninterface IFrax {\n function exchangeCanonicalForOld(address bridge_token_address, uint256 token_amount) external returns (uint256);\n}\n\ncontract HarmonyBridgeZap {\n using SafeERC20 for IERC20;\n\n ISynapseBridge synapseBridge;\n address payable public immutable WETH_ADDRESS;\n IFrax private constant CANOLICAL_FRAX = IFrax(0xFa7191D292d5633f702B0bd7E3E3BcCC0e633200);\n IERC20 private constant SYN_FRAX = IERC20(0x1852F70512298d56e9c8FDd905e02581E04ddb2a);\n\n mapping(address => address) public swapMap;\n mapping(address => IERC20[]) public swapTokensMap;\n\n uint256 constant MAX_UINT256 = 2**256 - 1;\n\n constructor(\n address payable _wethAddress,\n address _swapOne,\n address tokenOne,\n address _swapTwo,\n address tokenTwo,\n address _swapThree,\n address tokenThree,\n ISynapseBridge _synapseBridge\n ) public {\n WETH_ADDRESS = _wethAddress;\n synapseBridge = _synapseBridge;\n swapMap[tokenOne] = _swapOne;\n swapMap[tokenTwo] = _swapTwo;\n swapMap[tokenThree] = _swapThree;\n\n if (address(_swapOne) != address(0)) {\n {\n uint8 i;\n for (; i < 32; i++) {\n try ISwap(_swapOne).getToken(i) returns (\n IERC20 token\n ) {\n swapTokensMap[_swapOne].push(token);\n token.safeApprove(address(_swapOne), MAX_UINT256);\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n } catch {\n break;\n }\n }\n require(i > 1, \"swap must have at least 2 tokens\");\n }\n }\n if (address(_swapTwo) != address(0)) {\n {\n uint8 i;\n for (; i < 32; i++) {\n try ISwap(_swapTwo).getToken(i) returns (\n IERC20 token\n ) {\n swapTokensMap[_swapTwo].push(token);\n token.safeApprove(address(_swapTwo), MAX_UINT256);\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n } catch {\n break;\n }\n }\n require(i > 1, \"swap must have at least 2 tokens\");\n }\n }\n\n if (address(_swapThree) != address(0)) {\n {\n uint8 i;\n for (; i < 32; i++) {\n try ISwap(_swapThree).getToken(i) returns (\n IERC20 token\n ) {\n swapTokensMap[_swapThree].push(token);\n token.safeApprove(address(_swapThree), MAX_UINT256);\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n } catch {\n break;\n }\n }\n require(i > 1, \"swap must have at least 2 tokens\");\n }\n }\n }\n\n /**\n * @notice Calculate amount of tokens you receive on swap\n * @param tokenIndexFrom the token the user wants to sell\n * @param tokenIndexTo the token the user wants to buy\n * @param dx the amount of tokens the user wants to sell. If the token charges\n * a fee on transfers, use the amount that gets transferred after the fee.\n * @return amount of tokens the user will receive\n */\n function calculateSwap(\n IERC20 token,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx\n ) external view virtual returns (uint256) {\n ISwap swap = ISwap(\n swapMap[address(token)]\n );\n return swap.calculateSwap(tokenIndexFrom, tokenIndexTo, dx);\n }\n\n function swapAndRedeem(\n address to,\n uint256 chainId,\n IERC20 token,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx,\n uint256 minDy,\n uint256 deadline\n ) external {\n ISwap swap = ISwap(swapMap[address(token)]);\n require(address(swap) != address(0), \"Swap is 0x00\");\n IERC20[] memory tokens = swapTokensMap[address(swap)];\n tokens[tokenIndexFrom].safeTransferFrom(\n msg.sender,\n address(this),\n dx\n );\n // swap\n\n uint256 swappedAmount = swap.swap(\n tokenIndexFrom,\n tokenIndexTo,\n dx,\n minDy,\n deadline\n );\n // deposit into bridge, gets nUSD\n if (\n token.allowance(address(this), address(synapseBridge)) <\n swappedAmount\n ) {\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n }\n synapseBridge.redeem(to, chainId, token, swappedAmount);\n }\n\n function swapAndRedeemAndSwap(\n address to,\n uint256 chainId,\n IERC20 token,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx,\n uint256 minDy,\n uint256 deadline,\n uint8 swapTokenIndexFrom,\n uint8 swapTokenIndexTo,\n uint256 swapMinDy,\n uint256 swapDeadline\n ) external {\n require(\n address(swapMap[address(token)]) != address(0),\n \"Swap is 0x00\"\n );\n IERC20[] memory tokens = swapTokensMap[\n swapMap[address(token)]\n ];\n tokens[tokenIndexFrom].safeTransferFrom(\n msg.sender,\n address(this),\n dx\n );\n // swap\n\n uint256 swappedAmount = ISwap(swapMap[address(token)]).swap(tokenIndexFrom, tokenIndexTo, dx, minDy, deadline);\n // deposit into bridge, gets nUSD\n if (\n token.allowance(address(this), address(synapseBridge)) <\n swappedAmount\n ) {\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n }\n synapseBridge.redeemAndSwap(\n to,\n chainId,\n token,\n swappedAmount,\n swapTokenIndexFrom,\n swapTokenIndexTo,\n swapMinDy,\n swapDeadline\n );\n }\n\n function swapAndRedeemAndRemove(\n address to,\n uint256 chainId,\n IERC20 token,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx,\n uint256 minDy,\n uint256 deadline,\n uint8 liqTokenIndex,\n uint256 liqMinAmount,\n uint256 liqDeadline\n ) external {\n ISwap swap = ISwap(swapMap[address(token)]);\n require(address(swap) != address(0), \"Swap is 0x00\");\n IERC20[] memory tokens = swapTokensMap[address(swap)];\n tokens[tokenIndexFrom].safeTransferFrom(\n msg.sender,\n address(this),\n dx\n );\n // swap\n\n uint256 swappedAmount = swap.swap(\n tokenIndexFrom,\n tokenIndexTo,\n dx,\n minDy,\n deadline\n );\n // deposit into bridge, gets nUSD\n if (\n token.allowance(address(this), address(synapseBridge)) <\n swappedAmount\n ) {\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n }\n synapseBridge.redeemAndRemove(\n to,\n chainId,\n token,\n swappedAmount,\n liqTokenIndex,\n liqMinAmount,\n liqDeadline\n );\n }\n\n /**\n * @notice wraps SynapseBridge redeem()\n * @param to address on other chain to redeem underlying assets to\n * @param chainId which underlying chain to bridge assets onto\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n **/\n function redeem(\n address to,\n uint256 chainId,\n IERC20 token,\n uint256 amount\n ) external {\n token.safeTransferFrom(msg.sender, address(this), amount);\n if (address(token) == address(CANOLICAL_FRAX)) {\n uint256 swappedAmount = CANOLICAL_FRAX.exchangeCanonicalForOld(address(SYN_FRAX), amount);\n if (SYN_FRAX.allowance(address(this), address(synapseBridge)) < amount) {\n SYN_FRAX.safeApprove(address(synapseBridge), MAX_UINT256);\n }\n synapseBridge.redeem(to, chainId, SYN_FRAX, swappedAmount);\n } else {\n if (token.allowance(address(this), address(synapseBridge)) < amount) {\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n }\n synapseBridge.redeem(to, chainId, token, amount);\n }\n \n }\n\n /**\n * @notice Wraps SynapseBridge redeemv2() function\n * @param to address on other chain to bridge assets to\n * @param chainId which chain to bridge assets onto\n * @param token ERC20 compatible token to redeem into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n **/\n function redeemv2(\n bytes32 to,\n uint256 chainId,\n IERC20 token,\n uint256 amount\n ) external {\n token.safeTransferFrom(msg.sender, address(this), amount);\n\n if (token.allowance(address(this), address(synapseBridge)) < amount) {\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n }\n synapseBridge.redeemv2(to, chainId, token, amount);\n }\n\n /**\n * @notice wraps SynapseBridge redeem()\n * @param to address on other chain to redeem underlying assets to\n * @param chainId which underlying chain to bridge assets onto\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n **/\n function deposit(\n address to,\n uint256 chainId,\n IERC20 token,\n uint256 amount\n ) external {\n token.safeTransferFrom(msg.sender, address(this), amount);\n if (token.allowance(address(this), address(synapseBridge)) < amount) {\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n }\n synapseBridge.deposit(to, chainId, token, amount);\n }\n\n function swapETHAndRedeem(\n address to,\n uint256 chainId,\n IERC20 token,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx,\n uint256 minDy,\n uint256 deadline\n ) external payable {\n require(WETH_ADDRESS != address(0), \"WETH 0\");\n require(msg.value > 0 && msg.value == dx, \"INCORRECT MSG VALUE\");\n ISwap swap = ISwap(swapMap[address(token)]);\n require(address(swap) != address(0), \"Swap is 0x00\");\n IWETH9(WETH_ADDRESS).deposit{value: msg.value}();\n\n // swap\n uint256 swappedAmount = swap.swap(\n tokenIndexFrom,\n tokenIndexTo,\n dx,\n minDy,\n deadline\n );\n synapseBridge.redeem(to, chainId, token, swappedAmount);\n }\n\n /**\n * @notice Wraps redeemAndSwap on SynapseBridge.sol\n * Relays to nodes that (typically) a wrapped synAsset ERC20 token has been burned and the underlying needs to be redeeemed on the native chain. This function indicates to the nodes that they should attempt to redeem the LP token for the underlying assets (E.g \"swap\" out of the LP token)\n * @param to address on other chain to redeem underlying assets to\n * @param chainId which underlying chain to bridge assets onto\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n * @param tokenIndexFrom the token the user wants to swap from\n * @param tokenIndexTo the token the user wants to swap to\n * @param minDy the min amount the user would like to receive, or revert to only minting the SynERC20 token crosschain.\n * @param deadline latest timestamp to accept this transaction\n **/\n function redeemAndSwap(\n address to,\n uint256 chainId,\n IERC20 token,\n uint256 amount,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 minDy,\n uint256 deadline\n ) external {\n token.safeTransferFrom(msg.sender, address(this), amount);\n if (token.allowance(address(this), address(synapseBridge)) < amount) {\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n }\n synapseBridge.redeemAndSwap(\n to,\n chainId,\n token,\n amount,\n tokenIndexFrom,\n tokenIndexTo,\n minDy,\n deadline\n );\n }\n\n /**\n * @notice Wraps redeemAndRemove on SynapseBridge\n * Relays to nodes that (typically) a wrapped synAsset ERC20 token has been burned and the underlying needs to be redeeemed on the native chain. This function indicates to the nodes that they should attempt to redeem the LP token for the underlying assets (E.g \"swap\" out of the LP token)\n * @param to address on other chain to redeem underlying assets to\n * @param chainId which underlying chain to bridge assets onto\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount of (typically) LP token to pass to the nodes to attempt to removeLiquidity() with to redeem for the underlying assets of the LP token\n * @param liqTokenIndex Specifies which of the underlying LP assets the nodes should attempt to redeem for\n * @param liqMinAmount Specifies the minimum amount of the underlying asset needed for the nodes to execute the redeem/swap\n * @param liqDeadline Specificies the deadline that the nodes are allowed to try to redeem/swap the LP token\n **/\n function redeemAndRemove(\n address to,\n uint256 chainId,\n IERC20 token,\n uint256 amount,\n uint8 liqTokenIndex,\n uint256 liqMinAmount,\n uint256 liqDeadline\n ) external {\n token.safeTransferFrom(msg.sender, address(this), amount);\n if (token.allowance(address(this), address(synapseBridge)) < amount) {\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n }\n synapseBridge.redeemAndRemove(\n to,\n chainId,\n token,\n amount,\n liqTokenIndex,\n liqMinAmount,\n liqDeadline\n );\n }\n}\n" + }, + "contracts/bridge/wrappers/AvalancheBridgeZap.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.6.12;\n\nimport \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/SafeERC20.sol\";\nimport \"../interfaces/ISwap.sol\";\nimport \"../interfaces/ISynapseBridge.sol\";\nimport \"../interfaces/IWETH9.sol\";\n\ncontract AvalancheBridgeZap {\n using SafeERC20 for IERC20;\n\n ISynapseBridge synapseBridge;\n address payable public immutable WETH_ADDRESS;\n\n mapping(address => address) public swapMap;\n mapping(address => IERC20[]) public swapTokensMap;\n\n uint256 constant MAX_UINT256 = 2**256 - 1;\n\n constructor(\n address payable _wethAddress,\n address _swapOne,\n address tokenOne,\n address _swapTwo,\n address tokenTwo,\n ISynapseBridge _synapseBridge\n ) public {\n WETH_ADDRESS = _wethAddress;\n synapseBridge = _synapseBridge;\n swapMap[tokenOne] = _swapOne;\n swapMap[tokenTwo] = _swapTwo;\n if (_wethAddress != address(0)) {\n IERC20(_wethAddress).safeIncreaseAllowance(address(_synapseBridge), MAX_UINT256);\n }\n if (address(_swapOne) != address(0)) {\n {\n uint8 i;\n for (; i < 32; i++) {\n try ISwap(_swapOne).getToken(i) returns (\n IERC20 token\n ) {\n swapTokensMap[_swapOne].push(token);\n token.safeApprove(address(_swapOne), MAX_UINT256);\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n } catch {\n break;\n }\n }\n require(i > 1, \"swap must have at least 2 tokens\");\n }\n }\n if (address(_swapTwo) != address(0)) {\n {\n uint8 i;\n for (; i < 32; i++) {\n try ISwap(_swapTwo).getToken(i) returns (\n IERC20 token\n ) {\n swapTokensMap[_swapTwo].push(token);\n token.safeApprove(address(_swapTwo), MAX_UINT256);\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n } catch {\n break;\n }\n }\n require(i > 1, \"swap must have at least 2 tokens\");\n }\n }\n }\n\n /**\n * @notice Calculate amount of tokens you receive on swap\n * @param tokenIndexFrom the token the user wants to sell\n * @param tokenIndexTo the token the user wants to buy\n * @param dx the amount of tokens the user wants to sell. If the token charges\n * a fee on transfers, use the amount that gets transferred after the fee.\n * @return amount of tokens the user will receive\n */\n function calculateSwap(\n IERC20 token,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx\n ) external view virtual returns (uint256) {\n ISwap swap = ISwap(\n swapMap[address(token)]\n );\n return swap.calculateSwap(tokenIndexFrom, tokenIndexTo, dx);\n }\n\n function swapAndRedeem(\n address to,\n uint256 chainId,\n IERC20 token,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx,\n uint256 minDy,\n uint256 deadline\n ) external {\n ISwap swap = ISwap(swapMap[address(token)]);\n require(address(swap) != address(0), \"Swap is 0x00\");\n IERC20[] memory tokens = swapTokensMap[address(swap)];\n tokens[tokenIndexFrom].safeTransferFrom(\n msg.sender,\n address(this),\n dx\n );\n // swap\n\n uint256 swappedAmount = swap.swap(\n tokenIndexFrom,\n tokenIndexTo,\n dx,\n minDy,\n deadline\n );\n // deposit into bridge, gets nUSD\n if (\n token.allowance(address(this), address(synapseBridge)) <\n swappedAmount\n ) {\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n }\n synapseBridge.redeem(to, chainId, token, swappedAmount);\n }\n\n function swapAndRedeemAndSwap(\n address to,\n uint256 chainId,\n IERC20 token,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx,\n uint256 minDy,\n uint256 deadline,\n uint8 swapTokenIndexFrom,\n uint8 swapTokenIndexTo,\n uint256 swapMinDy,\n uint256 swapDeadline\n ) external {\n require(\n address(swapMap[address(token)]) != address(0),\n \"Swap is 0x00\"\n );\n IERC20[] memory tokens = swapTokensMap[\n swapMap[address(token)]\n ];\n tokens[tokenIndexFrom].safeTransferFrom(\n msg.sender,\n address(this),\n dx\n );\n // swap\n\n uint256 swappedAmount = ISwap(swapMap[address(token)]).swap(tokenIndexFrom, tokenIndexTo, dx, minDy, deadline);\n // deposit into bridge, gets nUSD\n if (\n token.allowance(address(this), address(synapseBridge)) <\n swappedAmount\n ) {\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n }\n synapseBridge.redeemAndSwap(\n to,\n chainId,\n token,\n swappedAmount,\n swapTokenIndexFrom,\n swapTokenIndexTo,\n swapMinDy,\n swapDeadline\n );\n }\n\n function swapAndRedeemAndRemove(\n address to,\n uint256 chainId,\n IERC20 token,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx,\n uint256 minDy,\n uint256 deadline,\n uint8 liqTokenIndex,\n uint256 liqMinAmount,\n uint256 liqDeadline\n ) external {\n ISwap swap = ISwap(swapMap[address(token)]);\n require(address(swap) != address(0), \"Swap is 0x00\");\n IERC20[] memory tokens = swapTokensMap[address(swap)];\n tokens[tokenIndexFrom].safeTransferFrom(\n msg.sender,\n address(this),\n dx\n );\n // swap\n\n uint256 swappedAmount = swap.swap(\n tokenIndexFrom,\n tokenIndexTo,\n dx,\n minDy,\n deadline\n );\n // deposit into bridge, gets nUSD\n if (\n token.allowance(address(this), address(synapseBridge)) <\n swappedAmount\n ) {\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n }\n synapseBridge.redeemAndRemove(\n to,\n chainId,\n token,\n swappedAmount,\n liqTokenIndex,\n liqMinAmount,\n liqDeadline\n );\n }\n\n /**\n * @notice wraps SynapseBridge redeem()\n * @param to address on other chain to redeem underlying assets to\n * @param chainId which underlying chain to bridge assets onto\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n **/\n function redeem(\n address to,\n uint256 chainId,\n IERC20 token,\n uint256 amount\n ) external {\n token.safeTransferFrom(msg.sender, address(this), amount);\n if (token.allowance(address(this), address(synapseBridge)) < amount) {\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n }\n synapseBridge.redeem(to, chainId, token, amount);\n }\n\n /**\n * @notice wraps SynapseBridge redeem()\n * @param to address on other chain to redeem underlying assets to\n * @param chainId which underlying chain to bridge assets onto\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n **/\n function deposit(\n address to,\n uint256 chainId,\n IERC20 token,\n uint256 amount\n ) external {\n token.safeTransferFrom(msg.sender, address(this), amount);\n if (token.allowance(address(this), address(synapseBridge)) < amount) {\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n }\n synapseBridge.deposit(to, chainId, token, amount);\n }\n\n /**\n * @notice Wraps SynapseBridge deposit() function to make it compatible w/ ETH -> WETH conversions\n * @param to address on other chain to bridge assets to\n * @param chainId which chain to bridge assets onto\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n **/\n function depositETH(\n address to,\n uint256 chainId,\n uint256 amount\n ) external payable {\n require(msg.value > 0 && msg.value == amount, 'INCORRECT MSG VALUE');\n IWETH9(WETH_ADDRESS).deposit{value: msg.value}();\n synapseBridge.deposit(to, chainId, IERC20(WETH_ADDRESS), amount);\n }\n\n\n function swapETHAndRedeem(\n address to,\n uint256 chainId,\n IERC20 token,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx,\n uint256 minDy,\n uint256 deadline\n ) external payable {\n require(WETH_ADDRESS != address(0), \"WETH 0\");\n require(msg.value > 0 && msg.value == dx, \"INCORRECT MSG VALUE\");\n ISwap swap = ISwap(swapMap[address(token)]);\n require(address(swap) != address(0), \"Swap is 0x00\");\n IWETH9(WETH_ADDRESS).deposit{value: msg.value}();\n\n // swap\n uint256 swappedAmount = swap.swap(\n tokenIndexFrom,\n tokenIndexTo,\n dx,\n minDy,\n deadline\n );\n synapseBridge.redeem(to, chainId, token, swappedAmount);\n }\n\n\n function swapETHAndRedeemAndSwap(\n address to,\n uint256 chainId,\n IERC20 token,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx,\n uint256 minDy,\n uint256 deadline,\n uint8 swapTokenIndexFrom,\n uint8 swapTokenIndexTo,\n uint256 swapMinDy,\n uint256 swapDeadline\n ) external payable {\n require(WETH_ADDRESS != address(0), \"WETH 0\");\n require(msg.value > 0 && msg.value == dx, \"INCORRECT MSG VALUE\");\n ISwap swap = ISwap(swapMap[address(token)]);\n require(address(swap) != address(0), \"Swap is 0x00\");\n IWETH9(WETH_ADDRESS).deposit{value: msg.value}();\n\n // swap\n uint256 swappedAmount = swap.swap(\n tokenIndexFrom,\n tokenIndexTo,\n dx,\n minDy,\n deadline\n );\n synapseBridge.redeemAndSwap(to, chainId, token, swappedAmount,swapTokenIndexFrom,\n swapTokenIndexTo,\n swapMinDy,\n swapDeadline);\n }\n\n\n /**\n * @notice Wraps redeemAndSwap on SynapseBridge.sol\n * Relays to nodes that (typically) a wrapped synAsset ERC20 token has been burned and the underlying needs to be redeeemed on the native chain. This function indicates to the nodes that they should attempt to redeem the LP token for the underlying assets (E.g \"swap\" out of the LP token)\n * @param to address on other chain to redeem underlying assets to\n * @param chainId which underlying chain to bridge assets onto\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n * @param tokenIndexFrom the token the user wants to swap from\n * @param tokenIndexTo the token the user wants to swap to\n * @param minDy the min amount the user would like to receive, or revert to only minting the SynERC20 token crosschain.\n * @param deadline latest timestamp to accept this transaction\n **/\n function redeemAndSwap(\n address to,\n uint256 chainId,\n IERC20 token,\n uint256 amount,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 minDy,\n uint256 deadline\n ) external {\n token.safeTransferFrom(msg.sender, address(this), amount);\n if (token.allowance(address(this), address(synapseBridge)) < amount) {\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n }\n synapseBridge.redeemAndSwap(\n to,\n chainId,\n token,\n amount,\n tokenIndexFrom,\n tokenIndexTo,\n minDy,\n deadline\n );\n }\n\n /**\n * @notice Wraps redeemAndRemove on SynapseBridge\n * Relays to nodes that (typically) a wrapped synAsset ERC20 token has been burned and the underlying needs to be redeeemed on the native chain. This function indicates to the nodes that they should attempt to redeem the LP token for the underlying assets (E.g \"swap\" out of the LP token)\n * @param to address on other chain to redeem underlying assets to\n * @param chainId which underlying chain to bridge assets onto\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount of (typically) LP token to pass to the nodes to attempt to removeLiquidity() with to redeem for the underlying assets of the LP token\n * @param liqTokenIndex Specifies which of the underlying LP assets the nodes should attempt to redeem for\n * @param liqMinAmount Specifies the minimum amount of the underlying asset needed for the nodes to execute the redeem/swap\n * @param liqDeadline Specificies the deadline that the nodes are allowed to try to redeem/swap the LP token\n **/\n function redeemAndRemove(\n address to,\n uint256 chainId,\n IERC20 token,\n uint256 amount,\n uint8 liqTokenIndex,\n uint256 liqMinAmount,\n uint256 liqDeadline\n ) external {\n token.safeTransferFrom(msg.sender, address(this), amount);\n if (token.allowance(address(this), address(synapseBridge)) < amount) {\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n }\n synapseBridge.redeemAndRemove(\n to,\n chainId,\n token,\n amount,\n liqTokenIndex,\n liqMinAmount,\n liqDeadline\n );\n }\n\n /**\n * @notice Wraps SynapseBridge redeemv2() function\n * @param to address on other chain to bridge assets to\n * @param chainId which chain to bridge assets onto\n * @param token ERC20 compatible token to redeem into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n **/\n function redeemv2(\n bytes32 to,\n uint256 chainId,\n IERC20 token,\n uint256 amount\n ) external {\n token.safeTransferFrom(msg.sender, address(this), amount);\n\n if (token.allowance(address(this), address(synapseBridge)) < amount) {\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n }\n synapseBridge.redeemv2(to, chainId, token, amount);\n }\n}\n" + }, + "contracts/bridge/SynapseBridge.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.6.12;\n\nimport \"@openzeppelin/contracts-upgradeable/proxy/Initializable.sol\";\nimport \"@openzeppelin/contracts-upgradeable/access/AccessControlUpgradeable.sol\";\nimport \"@openzeppelin/contracts-upgradeable/utils/ReentrancyGuardUpgradeable.sol\";\nimport \"@openzeppelin/contracts-upgradeable/utils/PausableUpgradeable.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/SafeERC20.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/ERC20Burnable.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport \"@openzeppelin/contracts/math/SafeMath.sol\";\n\nimport \"./interfaces/ISwap.sol\";\nimport \"./interfaces/IWETH9.sol\";\n\ninterface IERC20Mintable is IERC20 {\n function mint(address to, uint256 amount) external;\n}\n\ncontract SynapseBridge is\n Initializable,\n AccessControlUpgradeable,\n ReentrancyGuardUpgradeable,\n PausableUpgradeable\n{\n using SafeERC20 for IERC20;\n using SafeERC20 for IERC20Mintable;\n using SafeMath for uint256;\n\n bytes32 public constant NODEGROUP_ROLE = keccak256(\"NODEGROUP_ROLE\");\n bytes32 public constant GOVERNANCE_ROLE = keccak256(\"GOVERNANCE_ROLE\");\n\n mapping(address => uint256) private fees;\n\n uint256 public startBlockNumber;\n uint256 public constant bridgeVersion = 6;\n uint256 public chainGasAmount;\n address payable public WETH_ADDRESS;\n\n mapping(bytes32 => bool) private kappaMap;\n\n receive() external payable {}\n\n function initialize() external initializer {\n startBlockNumber = block.number;\n _setupRole(DEFAULT_ADMIN_ROLE, msg.sender);\n __AccessControl_init();\n }\n\n function setChainGasAmount(uint256 amount) external {\n require(hasRole(GOVERNANCE_ROLE, msg.sender), \"Not governance\");\n chainGasAmount = amount;\n }\n\n function setWethAddress(address payable _wethAddress) external {\n require(hasRole(DEFAULT_ADMIN_ROLE, msg.sender), \"Not admin\");\n WETH_ADDRESS = _wethAddress;\n }\n\n function addKappas(bytes32[] calldata kappas) external {\n require(hasRole(GOVERNANCE_ROLE, msg.sender), \"Not governance\");\n for (uint256 i = 0; i < kappas.length; ++i) {\n kappaMap[kappas[i]] = true;\n }\n }\n\n event TokenDeposit(\n address indexed to,\n uint256 chainId,\n IERC20 token,\n uint256 amount\n );\n event TokenRedeem(\n address indexed to,\n uint256 chainId,\n IERC20 token,\n uint256 amount\n );\n event TokenWithdraw(\n address indexed to,\n IERC20 token,\n uint256 amount,\n uint256 fee,\n bytes32 indexed kappa\n );\n event TokenMint(\n address indexed to,\n IERC20Mintable token,\n uint256 amount,\n uint256 fee,\n bytes32 indexed kappa\n );\n event TokenDepositAndSwap(\n address indexed to,\n uint256 chainId,\n IERC20 token,\n uint256 amount,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 minDy,\n uint256 deadline\n );\n event TokenMintAndSwap(\n address indexed to,\n IERC20Mintable token,\n uint256 amount,\n uint256 fee,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 minDy,\n uint256 deadline,\n bool swapSuccess,\n bytes32 indexed kappa\n );\n event TokenRedeemAndSwap(\n address indexed to,\n uint256 chainId,\n IERC20 token,\n uint256 amount,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 minDy,\n uint256 deadline\n );\n event TokenRedeemAndRemove(\n address indexed to,\n uint256 chainId,\n IERC20 token,\n uint256 amount,\n uint8 swapTokenIndex,\n uint256 swapMinAmount,\n uint256 swapDeadline\n );\n event TokenWithdrawAndRemove(\n address indexed to,\n IERC20 token,\n uint256 amount,\n uint256 fee,\n uint8 swapTokenIndex,\n uint256 swapMinAmount,\n uint256 swapDeadline,\n bool swapSuccess,\n bytes32 indexed kappa\n );\n\n // v2 events\n event TokenRedeemV2(\n bytes32 indexed to,\n uint256 chainId,\n IERC20 token,\n uint256 amount\n );\n\n // VIEW FUNCTIONS ***/\n function getFeeBalance(address tokenAddress)\n external\n view\n returns (uint256)\n {\n return fees[tokenAddress];\n }\n\n function kappaExists(bytes32 kappa) external view returns (bool) {\n return kappaMap[kappa];\n }\n\n // FEE FUNCTIONS ***/\n /**\n * * @notice withdraw specified ERC20 token fees to a given address\n * * @param token ERC20 token in which fees acccumulated to transfer\n * * @param to Address to send the fees to\n */\n function withdrawFees(IERC20 token, address to) external whenNotPaused {\n require(hasRole(GOVERNANCE_ROLE, msg.sender), \"Not governance\");\n require(to != address(0), \"Address is 0x000\");\n if (fees[address(token)] != 0) {\n token.safeTransfer(to, fees[address(token)]);\n fees[address(token)] = 0;\n }\n }\n\n // PAUSABLE FUNCTIONS ***/\n function pause() external {\n require(hasRole(GOVERNANCE_ROLE, msg.sender), \"Not governance\");\n _pause();\n }\n\n function unpause() external {\n require(hasRole(GOVERNANCE_ROLE, msg.sender), \"Not governance\");\n _unpause();\n }\n\n /**\n * @notice Relays to nodes to transfers an ERC20 token cross-chain\n * @param to address on other chain to bridge assets to\n * @param chainId which chain to bridge assets onto\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n **/\n function deposit(\n address to,\n uint256 chainId,\n IERC20 token,\n uint256 amount\n ) external nonReentrant whenNotPaused {\n emit TokenDeposit(to, chainId, token, amount);\n token.safeTransferFrom(msg.sender, address(this), amount);\n }\n\n /**\n * @notice Relays to nodes that (typically) a wrapped synAsset ERC20 token has been burned and the underlying needs to be redeeemed on the native chain\n * @param to address on other chain to redeem underlying assets to\n * @param chainId which underlying chain to bridge assets onto\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n **/\n function redeem(\n address to,\n uint256 chainId,\n ERC20Burnable token,\n uint256 amount\n ) external nonReentrant whenNotPaused {\n emit TokenRedeem(to, chainId, token, amount);\n token.burnFrom(msg.sender, amount);\n }\n\n /**\n * @notice Function to be called by the node group to withdraw the underlying assets from the contract\n * @param to address on chain to send underlying assets to\n * @param token ERC20 compatible token to withdraw from the bridge\n * @param amount Amount in native token decimals to withdraw\n * @param fee Amount in native token decimals to save to the contract as fees\n * @param kappa kappa\n **/\n function withdraw(\n address to,\n IERC20 token,\n uint256 amount,\n uint256 fee,\n bytes32 kappa\n ) external nonReentrant whenNotPaused {\n require(\n hasRole(NODEGROUP_ROLE, msg.sender),\n \"Caller is not a node group\"\n );\n require(amount > fee, \"Amount must be greater than fee\");\n require(!kappaMap[kappa], \"Kappa is already present\");\n kappaMap[kappa] = true;\n fees[address(token)] = fees[address(token)].add(fee);\n if (address(token) == WETH_ADDRESS && WETH_ADDRESS != address(0)) {\n IWETH9(WETH_ADDRESS).withdraw(amount.sub(fee));\n (bool success, ) = to.call{value: amount.sub(fee)}(\"\");\n require(success, \"ETH_TRANSFER_FAILED\");\n emit TokenWithdraw(to, token, amount, fee, kappa);\n } else {\n emit TokenWithdraw(to, token, amount, fee, kappa);\n token.safeTransfer(to, amount.sub(fee));\n }\n }\n\n /**\n * @notice Nodes call this function to mint a SynERC20 (or any asset that the bridge is given minter access to). This is called by the nodes after a TokenDeposit event is emitted.\n * @dev This means the SynapseBridge.sol contract must have minter access to the token attempting to be minted\n * @param to address on other chain to redeem underlying assets to\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain post-fees\n * @param fee Amount in native token decimals to save to the contract as fees\n * @param kappa kappa\n **/\n function mint(\n address payable to,\n IERC20Mintable token,\n uint256 amount,\n uint256 fee,\n bytes32 kappa\n ) external nonReentrant whenNotPaused {\n require(\n hasRole(NODEGROUP_ROLE, msg.sender),\n \"Caller is not a node group\"\n );\n require(amount > fee, \"Amount must be greater than fee\");\n require(!kappaMap[kappa], \"Kappa is already present\");\n kappaMap[kappa] = true;\n fees[address(token)] = fees[address(token)].add(fee);\n emit TokenMint(to, token, amount.sub(fee), fee, kappa);\n token.mint(address(this), amount);\n IERC20(token).safeTransfer(to, amount.sub(fee));\n if (chainGasAmount != 0 && address(this).balance > chainGasAmount) {\n to.call.value(chainGasAmount)(\"\");\n }\n }\n\n /**\n * @notice Relays to nodes to both transfer an ERC20 token cross-chain, and then have the nodes execute a swap through a liquidity pool on behalf of the user.\n * @param to address on other chain to bridge assets to\n * @param chainId which chain to bridge assets onto\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n * @param tokenIndexFrom the token the user wants to swap from\n * @param tokenIndexTo the token the user wants to swap to\n * @param minDy the min amount the user would like to receive, or revert to only minting the SynERC20 token crosschain.\n * @param deadline latest timestamp to accept this transaction\n **/\n function depositAndSwap(\n address to,\n uint256 chainId,\n IERC20 token,\n uint256 amount,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 minDy,\n uint256 deadline\n ) external nonReentrant whenNotPaused {\n emit TokenDepositAndSwap(\n to,\n chainId,\n token,\n amount,\n tokenIndexFrom,\n tokenIndexTo,\n minDy,\n deadline\n );\n token.safeTransferFrom(msg.sender, address(this), amount);\n }\n\n /**\n * @notice Relays to nodes that (typically) a wrapped synAsset ERC20 token has been burned and the underlying needs to be redeeemed on the native chain. This function indicates to the nodes that they should attempt to redeem the LP token for the underlying assets (E.g \"swap\" out of the LP token)\n * @param to address on other chain to redeem underlying assets to\n * @param chainId which underlying chain to bridge assets onto\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n * @param tokenIndexFrom the token the user wants to swap from\n * @param tokenIndexTo the token the user wants to swap to\n * @param minDy the min amount the user would like to receive, or revert to only minting the SynERC20 token crosschain.\n * @param deadline latest timestamp to accept this transaction\n **/\n function redeemAndSwap(\n address to,\n uint256 chainId,\n ERC20Burnable token,\n uint256 amount,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 minDy,\n uint256 deadline\n ) external nonReentrant whenNotPaused {\n emit TokenRedeemAndSwap(\n to,\n chainId,\n token,\n amount,\n tokenIndexFrom,\n tokenIndexTo,\n minDy,\n deadline\n );\n token.burnFrom(msg.sender, amount);\n }\n\n /**\n * @notice Relays to nodes that (typically) a wrapped synAsset ERC20 token has been burned and the underlying needs to be redeeemed on the native chain. This function indicates to the nodes that they should attempt to redeem the LP token for the underlying assets (E.g \"swap\" out of the LP token)\n * @param to address on other chain to redeem underlying assets to\n * @param chainId which underlying chain to bridge assets onto\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n * @param swapTokenIndex Specifies which of the underlying LP assets the nodes should attempt to redeem for\n * @param swapMinAmount Specifies the minimum amount of the underlying asset needed for the nodes to execute the redeem/swap\n * @param swapDeadline Specificies the deadline that the nodes are allowed to try to redeem/swap the LP token\n **/\n function redeemAndRemove(\n address to,\n uint256 chainId,\n ERC20Burnable token,\n uint256 amount,\n uint8 swapTokenIndex,\n uint256 swapMinAmount,\n uint256 swapDeadline\n ) external nonReentrant whenNotPaused {\n emit TokenRedeemAndRemove(\n to,\n chainId,\n token,\n amount,\n swapTokenIndex,\n swapMinAmount,\n swapDeadline\n );\n token.burnFrom(msg.sender, amount);\n }\n\n /**\n * @notice Nodes call this function to mint a SynERC20 (or any asset that the bridge is given minter access to), and then attempt to swap the SynERC20 into the desired destination asset. This is called by the nodes after a TokenDepositAndSwap event is emitted.\n * @dev This means the BridgeDeposit.sol contract must have minter access to the token attempting to be minted\n * @param to address on other chain to redeem underlying assets to\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain post-fees\n * @param fee Amount in native token decimals to save to the contract as fees\n * @param pool Destination chain's pool to use to swap SynERC20 -> Asset. The nodes determine this by using PoolConfig.sol.\n * @param tokenIndexFrom Index of the SynERC20 asset in the pool\n * @param tokenIndexTo Index of the desired final asset\n * @param minDy Minumum amount (in final asset decimals) that must be swapped for, otherwise the user will receive the SynERC20.\n * @param deadline Epoch time of the deadline that the swap is allowed to be executed.\n * @param kappa kappa\n **/\n function mintAndSwap(\n address payable to,\n IERC20Mintable token,\n uint256 amount,\n uint256 fee,\n ISwap pool,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 minDy,\n uint256 deadline,\n bytes32 kappa\n ) external nonReentrant whenNotPaused {\n require(\n hasRole(NODEGROUP_ROLE, msg.sender),\n \"Caller is not a node group\"\n );\n require(amount > fee, \"Amount must be greater than fee\");\n require(!kappaMap[kappa], \"Kappa is already present\");\n kappaMap[kappa] = true;\n fees[address(token)] = fees[address(token)].add(fee);\n // Transfer gas airdrop\n if (chainGasAmount != 0 && address(this).balance > chainGasAmount) {\n to.call.value(chainGasAmount)(\"\");\n }\n // first check to make sure more will be given than min amount required\n uint256 expectedOutput = ISwap(pool).calculateSwap(\n tokenIndexFrom,\n tokenIndexTo,\n amount.sub(fee)\n );\n\n if (expectedOutput >= minDy) {\n // proceed with swap\n token.mint(address(this), amount);\n token.safeIncreaseAllowance(address(pool), amount);\n try\n ISwap(pool).swap(\n tokenIndexFrom,\n tokenIndexTo,\n amount.sub(fee),\n minDy,\n deadline\n )\n returns (uint256 finalSwappedAmount) {\n // Swap succeeded, transfer swapped asset\n IERC20 swappedTokenTo = ISwap(pool).getToken(tokenIndexTo);\n if (\n address(swappedTokenTo) == WETH_ADDRESS &&\n WETH_ADDRESS != address(0)\n ) {\n IWETH9(WETH_ADDRESS).withdraw(finalSwappedAmount);\n (bool success, ) = to.call{value: finalSwappedAmount}(\"\");\n require(success, \"ETH_TRANSFER_FAILED\");\n emit TokenMintAndSwap(\n to,\n token,\n finalSwappedAmount,\n fee,\n tokenIndexFrom,\n tokenIndexTo,\n minDy,\n deadline,\n true,\n kappa\n );\n } else {\n swappedTokenTo.safeTransfer(to, finalSwappedAmount);\n emit TokenMintAndSwap(\n to,\n token,\n finalSwappedAmount,\n fee,\n tokenIndexFrom,\n tokenIndexTo,\n minDy,\n deadline,\n true,\n kappa\n );\n }\n } catch {\n IERC20(token).safeTransfer(to, amount.sub(fee));\n emit TokenMintAndSwap(\n to,\n token,\n amount.sub(fee),\n fee,\n tokenIndexFrom,\n tokenIndexTo,\n minDy,\n deadline,\n false,\n kappa\n );\n }\n } else {\n token.mint(address(this), amount);\n IERC20(token).safeTransfer(to, amount.sub(fee));\n emit TokenMintAndSwap(\n to,\n token,\n amount.sub(fee),\n fee,\n tokenIndexFrom,\n tokenIndexTo,\n minDy,\n deadline,\n false,\n kappa\n );\n }\n }\n\n /**\n * @notice Function to be called by the node group to withdraw the underlying assets from the contract\n * @param to address on chain to send underlying assets to\n * @param token ERC20 compatible token to withdraw from the bridge\n * @param amount Amount in native token decimals to withdraw\n * @param fee Amount in native token decimals to save to the contract as fees\n * @param pool Destination chain's pool to use to swap SynERC20 -> Asset. The nodes determine this by using PoolConfig.sol.\n * @param swapTokenIndex Specifies which of the underlying LP assets the nodes should attempt to redeem for\n * @param swapMinAmount Specifies the minimum amount of the underlying asset needed for the nodes to execute the redeem/swap\n * @param swapDeadline Specificies the deadline that the nodes are allowed to try to redeem/swap the LP token\n * @param kappa kappa\n **/\n function withdrawAndRemove(\n address to,\n IERC20 token,\n uint256 amount,\n uint256 fee,\n ISwap pool,\n uint8 swapTokenIndex,\n uint256 swapMinAmount,\n uint256 swapDeadline,\n bytes32 kappa\n ) external nonReentrant whenNotPaused {\n require(\n hasRole(NODEGROUP_ROLE, msg.sender),\n \"Caller is not a node group\"\n );\n require(amount > fee, \"Amount must be greater than fee\");\n require(!kappaMap[kappa], \"Kappa is already present\");\n kappaMap[kappa] = true;\n fees[address(token)] = fees[address(token)].add(fee);\n // first check to make sure more will be given than min amount required\n uint256 expectedOutput = ISwap(pool).calculateRemoveLiquidityOneToken(\n amount.sub(fee),\n swapTokenIndex\n );\n\n if (expectedOutput >= swapMinAmount) {\n token.safeIncreaseAllowance(address(pool), amount.sub(fee));\n try\n ISwap(pool).removeLiquidityOneToken(\n amount.sub(fee),\n swapTokenIndex,\n swapMinAmount,\n swapDeadline\n )\n returns (uint256 finalSwappedAmount) {\n // Swap succeeded, transfer swapped asset\n IERC20 swappedTokenTo = ISwap(pool).getToken(swapTokenIndex);\n swappedTokenTo.safeTransfer(to, finalSwappedAmount);\n emit TokenWithdrawAndRemove(\n to,\n token,\n finalSwappedAmount,\n fee,\n swapTokenIndex,\n swapMinAmount,\n swapDeadline,\n true,\n kappa\n );\n } catch {\n IERC20(token).safeTransfer(to, amount.sub(fee));\n emit TokenWithdrawAndRemove(\n to,\n token,\n amount.sub(fee),\n fee,\n swapTokenIndex,\n swapMinAmount,\n swapDeadline,\n false,\n kappa\n );\n }\n } else {\n token.safeTransfer(to, amount.sub(fee));\n emit TokenWithdrawAndRemove(\n to,\n token,\n amount.sub(fee),\n fee,\n swapTokenIndex,\n swapMinAmount,\n swapDeadline,\n false,\n kappa\n );\n }\n }\n\n // BRIDGE FUNCTIONS TO HANDLE DIFF ADDRESSES\n /**\n * @notice Relays to nodes that (typically) a wrapped synAsset ERC20 token has been burned and the underlying needs to be redeeemed on the native chain\n * @param to address on other chain to redeem underlying assets to\n * @param chainId which underlying chain to bridge assets onto\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n **/\n function redeemV2(\n bytes32 to,\n uint256 chainId,\n ERC20Burnable token,\n uint256 amount\n ) external nonReentrant whenNotPaused {\n emit TokenRedeemV2(to, chainId, token, amount);\n token.burnFrom(msg.sender, amount);\n }\n}\n" + }, + "@openzeppelin/contracts-upgradeable/access/AccessControlUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <0.8.0;\n\nimport \"../utils/EnumerableSetUpgradeable.sol\";\nimport \"../utils/AddressUpgradeable.sol\";\nimport \"../utils/ContextUpgradeable.sol\";\nimport \"../proxy/Initializable.sol\";\n\n/**\n * @dev Contract module that allows children to implement role-based access\n * control mechanisms.\n *\n * Roles are referred to by their `bytes32` identifier. These should be exposed\n * in the external API and be unique. The best way to achieve this is by\n * using `public constant` hash digests:\n *\n * ```\n * bytes32 public constant MY_ROLE = keccak256(\"MY_ROLE\");\n * ```\n *\n * Roles can be used to represent a set of permissions. To restrict access to a\n * function call, use {hasRole}:\n *\n * ```\n * function foo() public {\n * require(hasRole(MY_ROLE, msg.sender));\n * ...\n * }\n * ```\n *\n * Roles can be granted and revoked dynamically via the {grantRole} and\n * {revokeRole} functions. Each role has an associated admin role, and only\n * accounts that have a role's admin role can call {grantRole} and {revokeRole}.\n *\n * By default, the admin role for all roles is `DEFAULT_ADMIN_ROLE`, which means\n * that only accounts with this role will be able to grant or revoke other\n * roles. More complex role relationships can be created by using\n * {_setRoleAdmin}.\n *\n * WARNING: The `DEFAULT_ADMIN_ROLE` is also its own admin: it has permission to\n * grant and revoke this role. Extra precautions should be taken to secure\n * accounts that have been granted it.\n */\nabstract contract AccessControlUpgradeable is Initializable, ContextUpgradeable {\n function __AccessControl_init() internal initializer {\n __Context_init_unchained();\n __AccessControl_init_unchained();\n }\n\n function __AccessControl_init_unchained() internal initializer {\n }\n using EnumerableSetUpgradeable for EnumerableSetUpgradeable.AddressSet;\n using AddressUpgradeable for address;\n\n struct RoleData {\n EnumerableSetUpgradeable.AddressSet members;\n bytes32 adminRole;\n }\n\n mapping (bytes32 => RoleData) private _roles;\n\n bytes32 public constant DEFAULT_ADMIN_ROLE = 0x00;\n\n /**\n * @dev Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole`\n *\n * `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite\n * {RoleAdminChanged} not being emitted signaling this.\n *\n * _Available since v3.1._\n */\n event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole);\n\n /**\n * @dev Emitted when `account` is granted `role`.\n *\n * `sender` is the account that originated the contract call, an admin role\n * bearer except when using {_setupRole}.\n */\n event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender);\n\n /**\n * @dev Emitted when `account` is revoked `role`.\n *\n * `sender` is the account that originated the contract call:\n * - if using `revokeRole`, it is the admin role bearer\n * - if using `renounceRole`, it is the role bearer (i.e. `account`)\n */\n event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender);\n\n /**\n * @dev Returns `true` if `account` has been granted `role`.\n */\n function hasRole(bytes32 role, address account) public view returns (bool) {\n return _roles[role].members.contains(account);\n }\n\n /**\n * @dev Returns the number of accounts that have `role`. Can be used\n * together with {getRoleMember} to enumerate all bearers of a role.\n */\n function getRoleMemberCount(bytes32 role) public view returns (uint256) {\n return _roles[role].members.length();\n }\n\n /**\n * @dev Returns one of the accounts that have `role`. `index` must be a\n * value between 0 and {getRoleMemberCount}, non-inclusive.\n *\n * Role bearers are not sorted in any particular way, and their ordering may\n * change at any point.\n *\n * WARNING: When using {getRoleMember} and {getRoleMemberCount}, make sure\n * you perform all queries on the same block. See the following\n * https://forum.openzeppelin.com/t/iterating-over-elements-on-enumerableset-in-openzeppelin-contracts/2296[forum post]\n * for more information.\n */\n function getRoleMember(bytes32 role, uint256 index) public view returns (address) {\n return _roles[role].members.at(index);\n }\n\n /**\n * @dev Returns the admin role that controls `role`. See {grantRole} and\n * {revokeRole}.\n *\n * To change a role's admin, use {_setRoleAdmin}.\n */\n function getRoleAdmin(bytes32 role) public view returns (bytes32) {\n return _roles[role].adminRole;\n }\n\n /**\n * @dev Grants `role` to `account`.\n *\n * If `account` had not been already granted `role`, emits a {RoleGranted}\n * event.\n *\n * Requirements:\n *\n * - the caller must have ``role``'s admin role.\n */\n function grantRole(bytes32 role, address account) public virtual {\n require(hasRole(_roles[role].adminRole, _msgSender()), \"AccessControl: sender must be an admin to grant\");\n\n _grantRole(role, account);\n }\n\n /**\n * @dev Revokes `role` from `account`.\n *\n * If `account` had been granted `role`, emits a {RoleRevoked} event.\n *\n * Requirements:\n *\n * - the caller must have ``role``'s admin role.\n */\n function revokeRole(bytes32 role, address account) public virtual {\n require(hasRole(_roles[role].adminRole, _msgSender()), \"AccessControl: sender must be an admin to revoke\");\n\n _revokeRole(role, account);\n }\n\n /**\n * @dev Revokes `role` from the calling account.\n *\n * Roles are often managed via {grantRole} and {revokeRole}: this function's\n * purpose is to provide a mechanism for accounts to lose their privileges\n * if they are compromised (such as when a trusted device is misplaced).\n *\n * If the calling account had been granted `role`, emits a {RoleRevoked}\n * event.\n *\n * Requirements:\n *\n * - the caller must be `account`.\n */\n function renounceRole(bytes32 role, address account) public virtual {\n require(account == _msgSender(), \"AccessControl: can only renounce roles for self\");\n\n _revokeRole(role, account);\n }\n\n /**\n * @dev Grants `role` to `account`.\n *\n * If `account` had not been already granted `role`, emits a {RoleGranted}\n * event. Note that unlike {grantRole}, this function doesn't perform any\n * checks on the calling account.\n *\n * [WARNING]\n * ====\n * This function should only be called from the constructor when setting\n * up the initial roles for the system.\n *\n * Using this function in any other way is effectively circumventing the admin\n * system imposed by {AccessControl}.\n * ====\n */\n function _setupRole(bytes32 role, address account) internal virtual {\n _grantRole(role, account);\n }\n\n /**\n * @dev Sets `adminRole` as ``role``'s admin role.\n *\n * Emits a {RoleAdminChanged} event.\n */\n function _setRoleAdmin(bytes32 role, bytes32 adminRole) internal virtual {\n emit RoleAdminChanged(role, _roles[role].adminRole, adminRole);\n _roles[role].adminRole = adminRole;\n }\n\n function _grantRole(bytes32 role, address account) private {\n if (_roles[role].members.add(account)) {\n emit RoleGranted(role, account, _msgSender());\n }\n }\n\n function _revokeRole(bytes32 role, address account) private {\n if (_roles[role].members.remove(account)) {\n emit RoleRevoked(role, account, _msgSender());\n }\n }\n uint256[49] private __gap;\n}\n" + }, + "@openzeppelin/contracts-upgradeable/utils/EnumerableSetUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <0.8.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 EnumerableSetUpgradeable {\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" + }, + "contracts/bridge/MoonriverSynapseBridge.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.6.12;\n\nimport \"@openzeppelin/contracts-upgradeable/proxy/Initializable.sol\";\nimport \"@openzeppelin/contracts-upgradeable/access/AccessControlUpgradeable.sol\";\nimport \"@openzeppelin/contracts-upgradeable/utils/ReentrancyGuardUpgradeable.sol\";\nimport \"@openzeppelin/contracts-upgradeable/utils/PausableUpgradeable.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/SafeERC20.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/ERC20Burnable.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport \"@openzeppelin/contracts/math/SafeMath.sol\";\n\nimport \"./interfaces/ISwap.sol\";\nimport \"./interfaces/IWETH9.sol\";\n\ninterface IERC20Mintable is IERC20 {\n function mint(address to, uint256 amount) external;\n}\n\ninterface IFrax {\n function exchangeOldForCanonical(\n address bridge_token_address,\n uint256 token_amount\n ) external returns (uint256);\n}\n\ncontract MRSynapseBridge is\n Initializable,\n AccessControlUpgradeable,\n ReentrancyGuardUpgradeable,\n PausableUpgradeable\n{\n using SafeERC20 for IERC20;\n using SafeERC20 for IERC20Mintable;\n using SafeMath for uint256;\n\n bytes32 public constant NODEGROUP_ROLE = keccak256(\"NODEGROUP_ROLE\");\n bytes32 public constant GOVERNANCE_ROLE = keccak256(\"GOVERNANCE_ROLE\");\n\n mapping(address => uint256) private fees;\n\n uint256 public startBlockNumber;\n uint256 public constant bridgeVersion = 6;\n uint256 public chainGasAmount;\n address payable public WETH_ADDRESS;\n\n mapping(bytes32 => bool) private kappaMap;\n\n receive() external payable {}\n\n function initialize() external initializer {\n startBlockNumber = block.number;\n _setupRole(DEFAULT_ADMIN_ROLE, msg.sender);\n __AccessControl_init();\n }\n\n function setChainGasAmount(uint256 amount) external {\n require(hasRole(GOVERNANCE_ROLE, msg.sender), \"Not governance\");\n chainGasAmount = amount;\n }\n\n function setWethAddress(address payable _wethAddress) external {\n require(hasRole(DEFAULT_ADMIN_ROLE, msg.sender), \"Not admin\");\n WETH_ADDRESS = _wethAddress;\n }\n\n function addKappas(bytes32[] calldata kappas) external {\n require(hasRole(GOVERNANCE_ROLE, msg.sender), \"Not governance\");\n for (uint256 i = 0; i < kappas.length; ++i) {\n kappaMap[kappas[i]] = true;\n }\n }\n\n event TokenDeposit(\n address indexed to,\n uint256 chainId,\n IERC20 token,\n uint256 amount\n );\n event TokenRedeem(\n address indexed to,\n uint256 chainId,\n IERC20 token,\n uint256 amount\n );\n event TokenWithdraw(\n address indexed to,\n IERC20 token,\n uint256 amount,\n uint256 fee,\n bytes32 indexed kappa\n );\n event TokenMint(\n address indexed to,\n IERC20Mintable token,\n uint256 amount,\n uint256 fee,\n bytes32 indexed kappa\n );\n event TokenDepositAndSwap(\n address indexed to,\n uint256 chainId,\n IERC20 token,\n uint256 amount,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 minDy,\n uint256 deadline\n );\n event TokenMintAndSwap(\n address indexed to,\n IERC20Mintable token,\n uint256 amount,\n uint256 fee,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 minDy,\n uint256 deadline,\n bool swapSuccess,\n bytes32 indexed kappa\n );\n event TokenRedeemAndSwap(\n address indexed to,\n uint256 chainId,\n IERC20 token,\n uint256 amount,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 minDy,\n uint256 deadline\n );\n event TokenRedeemAndRemove(\n address indexed to,\n uint256 chainId,\n IERC20 token,\n uint256 amount,\n uint8 swapTokenIndex,\n uint256 swapMinAmount,\n uint256 swapDeadline\n );\n event TokenWithdrawAndRemove(\n address indexed to,\n IERC20 token,\n uint256 amount,\n uint256 fee,\n uint8 swapTokenIndex,\n uint256 swapMinAmount,\n uint256 swapDeadline,\n bool swapSuccess,\n bytes32 indexed kappa\n );\n\n // v2 events\n event TokenRedeemV2(\n bytes32 indexed to,\n uint256 chainId,\n IERC20 token,\n uint256 amount\n );\n\n // VIEW FUNCTIONS ***/\n function getFeeBalance(address tokenAddress)\n external\n view\n returns (uint256)\n {\n return fees[tokenAddress];\n }\n\n function kappaExists(bytes32 kappa) external view returns (bool) {\n return kappaMap[kappa];\n }\n\n // FEE FUNCTIONS ***/\n /**\n * * @notice withdraw specified ERC20 token fees to a given address\n * * @param token ERC20 token in which fees acccumulated to transfer\n * * @param to Address to send the fees to\n */\n function withdrawFees(IERC20 token, address to) external whenNotPaused {\n require(hasRole(GOVERNANCE_ROLE, msg.sender), \"Not governance\");\n require(to != address(0), \"Address is 0x000\");\n if (fees[address(token)] != 0) {\n token.safeTransfer(to, fees[address(token)]);\n fees[address(token)] = 0;\n }\n }\n\n // PAUSABLE FUNCTIONS ***/\n function pause() external {\n require(hasRole(GOVERNANCE_ROLE, msg.sender), \"Not governance\");\n _pause();\n }\n\n function unpause() external {\n require(hasRole(GOVERNANCE_ROLE, msg.sender), \"Not governance\");\n _unpause();\n }\n\n /**\n * @notice Relays to nodes to transfers an ERC20 token cross-chain\n * @param to address on other chain to bridge assets to\n * @param chainId which chain to bridge assets onto\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n **/\n function deposit(\n address to,\n uint256 chainId,\n IERC20 token,\n uint256 amount\n ) external nonReentrant whenNotPaused {\n emit TokenDeposit(to, chainId, token, amount);\n token.safeTransferFrom(msg.sender, address(this), amount);\n }\n\n /**\n * @notice Relays to nodes that (typically) a wrapped synAsset ERC20 token has been burned and the underlying needs to be redeeemed on the native chain\n * @param to address on other chain to redeem underlying assets to\n * @param chainId which underlying chain to bridge assets onto\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n **/\n function redeem(\n address to,\n uint256 chainId,\n ERC20Burnable token,\n uint256 amount\n ) external nonReentrant whenNotPaused {\n emit TokenRedeem(to, chainId, token, amount);\n token.burnFrom(msg.sender, amount);\n }\n\n /**\n * @notice Function to be called by the node group to withdraw the underlying assets from the contract\n * @param to address on chain to send underlying assets to\n * @param token ERC20 compatible token to withdraw from the bridge\n * @param amount Amount in native token decimals to withdraw\n * @param fee Amount in native token decimals to save to the contract as fees\n * @param kappa kappa\n **/\n function withdraw(\n address to,\n IERC20 token,\n uint256 amount,\n uint256 fee,\n bytes32 kappa\n ) external nonReentrant whenNotPaused {\n require(\n hasRole(NODEGROUP_ROLE, msg.sender),\n \"Caller is not a node group\"\n );\n require(amount > fee, \"Amount must be greater than fee\");\n require(!kappaMap[kappa], \"Kappa is already present\");\n kappaMap[kappa] = true;\n fees[address(token)] = fees[address(token)].add(fee);\n if (address(token) == WETH_ADDRESS && WETH_ADDRESS != address(0)) {\n IWETH9(WETH_ADDRESS).withdraw(amount.sub(fee));\n (bool success, ) = to.call{value: amount.sub(fee)}(\"\");\n require(success, \"ETH_TRANSFER_FAILED\");\n emit TokenWithdraw(to, token, amount, fee, kappa);\n } else {\n emit TokenWithdraw(to, token, amount, fee, kappa);\n token.safeTransfer(to, amount.sub(fee));\n }\n }\n\n /**\n * @notice Nodes call this function to mint a SynERC20 (or any asset that the bridge is given minter access to). This is called by the nodes after a TokenDeposit event is emitted.\n * @dev This means the SynapseBridge.sol contract must have minter access to the token attempting to be minted\n * @param to address on other chain to redeem underlying assets to\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain post-fees\n * @param fee Amount in native token decimals to save to the contract as fees\n * @param kappa kappa\n **/\n function mint(\n address payable to,\n IERC20Mintable token,\n uint256 amount,\n uint256 fee,\n bytes32 kappa\n ) external nonReentrant whenNotPaused {\n require(\n hasRole(NODEGROUP_ROLE, msg.sender),\n \"Caller is not a node group\"\n );\n require(amount > fee, \"Amount must be greater than fee\");\n require(!kappaMap[kappa], \"Kappa is already present\");\n kappaMap[kappa] = true;\n fees[address(token)] = fees[address(token)].add(fee);\n emit TokenMint(to, token, amount.sub(fee), fee, kappa);\n token.mint(address(this), amount);\n // checks if synFRAX\n if (address(token) == 0xE96AC70907ffF3Efee79f502C985A7A21Bce407d) {\n token.safeIncreaseAllowance(\n 0x1A93B23281CC1CDE4C4741353F3064709A16197d,\n amount.sub(fee)\n );\n try\n IFrax(0x1A93B23281CC1CDE4C4741353F3064709A16197d)\n .exchangeOldForCanonical(address(token), amount.sub(fee))\n returns (uint256 canolical_tokens_out) {\n IERC20(0x1A93B23281CC1CDE4C4741353F3064709A16197d).safeTransfer(\n to,\n canolical_tokens_out\n );\n } catch {\n IERC20(token).safeTransfer(to, amount.sub(fee));\n }\n } else {\n IERC20(token).safeTransfer(to, amount.sub(fee));\n }\n if (chainGasAmount != 0 && address(this).balance > chainGasAmount) {\n to.call.value(chainGasAmount)(\"\");\n }\n }\n\n /**\n * @notice Relays to nodes to both transfer an ERC20 token cross-chain, and then have the nodes execute a swap through a liquidity pool on behalf of the user.\n * @param to address on other chain to bridge assets to\n * @param chainId which chain to bridge assets onto\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n * @param tokenIndexFrom the token the user wants to swap from\n * @param tokenIndexTo the token the user wants to swap to\n * @param minDy the min amount the user would like to receive, or revert to only minting the SynERC20 token crosschain.\n * @param deadline latest timestamp to accept this transaction\n **/\n function depositAndSwap(\n address to,\n uint256 chainId,\n IERC20 token,\n uint256 amount,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 minDy,\n uint256 deadline\n ) external nonReentrant whenNotPaused {\n emit TokenDepositAndSwap(\n to,\n chainId,\n token,\n amount,\n tokenIndexFrom,\n tokenIndexTo,\n minDy,\n deadline\n );\n token.safeTransferFrom(msg.sender, address(this), amount);\n }\n\n /**\n * @notice Relays to nodes that (typically) a wrapped synAsset ERC20 token has been burned and the underlying needs to be redeeemed on the native chain. This function indicates to the nodes that they should attempt to redeem the LP token for the underlying assets (E.g \"swap\" out of the LP token)\n * @param to address on other chain to redeem underlying assets to\n * @param chainId which underlying chain to bridge assets onto\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n * @param tokenIndexFrom the token the user wants to swap from\n * @param tokenIndexTo the token the user wants to swap to\n * @param minDy the min amount the user would like to receive, or revert to only minting the SynERC20 token crosschain.\n * @param deadline latest timestamp to accept this transaction\n **/\n function redeemAndSwap(\n address to,\n uint256 chainId,\n ERC20Burnable token,\n uint256 amount,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 minDy,\n uint256 deadline\n ) external nonReentrant whenNotPaused {\n emit TokenRedeemAndSwap(\n to,\n chainId,\n token,\n amount,\n tokenIndexFrom,\n tokenIndexTo,\n minDy,\n deadline\n );\n token.burnFrom(msg.sender, amount);\n }\n\n /**\n * @notice Relays to nodes that (typically) a wrapped synAsset ERC20 token has been burned and the underlying needs to be redeeemed on the native chain. This function indicates to the nodes that they should attempt to redeem the LP token for the underlying assets (E.g \"swap\" out of the LP token)\n * @param to address on other chain to redeem underlying assets to\n * @param chainId which underlying chain to bridge assets onto\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n * @param swapTokenIndex Specifies which of the underlying LP assets the nodes should attempt to redeem for\n * @param swapMinAmount Specifies the minimum amount of the underlying asset needed for the nodes to execute the redeem/swap\n * @param swapDeadline Specificies the deadline that the nodes are allowed to try to redeem/swap the LP token\n **/\n function redeemAndRemove(\n address to,\n uint256 chainId,\n ERC20Burnable token,\n uint256 amount,\n uint8 swapTokenIndex,\n uint256 swapMinAmount,\n uint256 swapDeadline\n ) external nonReentrant whenNotPaused {\n emit TokenRedeemAndRemove(\n to,\n chainId,\n token,\n amount,\n swapTokenIndex,\n swapMinAmount,\n swapDeadline\n );\n token.burnFrom(msg.sender, amount);\n }\n\n /**\n * @notice Nodes call this function to mint a SynERC20 (or any asset that the bridge is given minter access to), and then attempt to swap the SynERC20 into the desired destination asset. This is called by the nodes after a TokenDepositAndSwap event is emitted.\n * @dev This means the BridgeDeposit.sol contract must have minter access to the token attempting to be minted\n * @param to address on other chain to redeem underlying assets to\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain post-fees\n * @param fee Amount in native token decimals to save to the contract as fees\n * @param pool Destination chain's pool to use to swap SynERC20 -> Asset. The nodes determine this by using PoolConfig.sol.\n * @param tokenIndexFrom Index of the SynERC20 asset in the pool\n * @param tokenIndexTo Index of the desired final asset\n * @param minDy Minumum amount (in final asset decimals) that must be swapped for, otherwise the user will receive the SynERC20.\n * @param deadline Epoch time of the deadline that the swap is allowed to be executed.\n * @param kappa kappa\n **/\n function mintAndSwap(\n address payable to,\n IERC20Mintable token,\n uint256 amount,\n uint256 fee,\n ISwap pool,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 minDy,\n uint256 deadline,\n bytes32 kappa\n ) external nonReentrant whenNotPaused {\n require(\n hasRole(NODEGROUP_ROLE, msg.sender),\n \"Caller is not a node group\"\n );\n require(amount > fee, \"Amount must be greater than fee\");\n require(!kappaMap[kappa], \"Kappa is already present\");\n kappaMap[kappa] = true;\n fees[address(token)] = fees[address(token)].add(fee);\n // Transfer gas airdrop\n if (chainGasAmount != 0 && address(this).balance > chainGasAmount) {\n to.call.value(chainGasAmount)(\"\");\n }\n // first check to make sure more will be given than min amount required\n uint256 expectedOutput = ISwap(pool).calculateSwap(\n tokenIndexFrom,\n tokenIndexTo,\n amount.sub(fee)\n );\n\n if (expectedOutput >= minDy) {\n // proceed with swap\n token.mint(address(this), amount);\n token.safeIncreaseAllowance(address(pool), amount);\n try\n ISwap(pool).swap(\n tokenIndexFrom,\n tokenIndexTo,\n amount.sub(fee),\n minDy,\n deadline\n )\n returns (uint256 finalSwappedAmount) {\n // Swap succeeded, transfer swapped asset\n IERC20 swappedTokenTo = ISwap(pool).getToken(tokenIndexTo);\n if (\n address(swappedTokenTo) == WETH_ADDRESS &&\n WETH_ADDRESS != address(0)\n ) {\n IWETH9(WETH_ADDRESS).withdraw(finalSwappedAmount);\n (bool success, ) = to.call{value: finalSwappedAmount}(\"\");\n require(success, \"ETH_TRANSFER_FAILED\");\n emit TokenMintAndSwap(\n to,\n token,\n finalSwappedAmount,\n fee,\n tokenIndexFrom,\n tokenIndexTo,\n minDy,\n deadline,\n true,\n kappa\n );\n } else {\n swappedTokenTo.safeTransfer(to, finalSwappedAmount);\n emit TokenMintAndSwap(\n to,\n token,\n finalSwappedAmount,\n fee,\n tokenIndexFrom,\n tokenIndexTo,\n minDy,\n deadline,\n true,\n kappa\n );\n }\n } catch {\n IERC20(token).safeTransfer(to, amount.sub(fee));\n emit TokenMintAndSwap(\n to,\n token,\n amount.sub(fee),\n fee,\n tokenIndexFrom,\n tokenIndexTo,\n minDy,\n deadline,\n false,\n kappa\n );\n }\n } else {\n token.mint(address(this), amount);\n IERC20(token).safeTransfer(to, amount.sub(fee));\n emit TokenMintAndSwap(\n to,\n token,\n amount.sub(fee),\n fee,\n tokenIndexFrom,\n tokenIndexTo,\n minDy,\n deadline,\n false,\n kappa\n );\n }\n }\n\n /**\n * @notice Function to be called by the node group to withdraw the underlying assets from the contract\n * @param to address on chain to send underlying assets to\n * @param token ERC20 compatible token to withdraw from the bridge\n * @param amount Amount in native token decimals to withdraw\n * @param fee Amount in native token decimals to save to the contract as fees\n * @param pool Destination chain's pool to use to swap SynERC20 -> Asset. The nodes determine this by using PoolConfig.sol.\n * @param swapTokenIndex Specifies which of the underlying LP assets the nodes should attempt to redeem for\n * @param swapMinAmount Specifies the minimum amount of the underlying asset needed for the nodes to execute the redeem/swap\n * @param swapDeadline Specificies the deadline that the nodes are allowed to try to redeem/swap the LP token\n * @param kappa kappa\n **/\n function withdrawAndRemove(\n address to,\n IERC20 token,\n uint256 amount,\n uint256 fee,\n ISwap pool,\n uint8 swapTokenIndex,\n uint256 swapMinAmount,\n uint256 swapDeadline,\n bytes32 kappa\n ) external nonReentrant whenNotPaused {\n require(\n hasRole(NODEGROUP_ROLE, msg.sender),\n \"Caller is not a node group\"\n );\n require(amount > fee, \"Amount must be greater than fee\");\n require(!kappaMap[kappa], \"Kappa is already present\");\n kappaMap[kappa] = true;\n fees[address(token)] = fees[address(token)].add(fee);\n // first check to make sure more will be given than min amount required\n uint256 expectedOutput = ISwap(pool).calculateRemoveLiquidityOneToken(\n amount.sub(fee),\n swapTokenIndex\n );\n\n if (expectedOutput >= swapMinAmount) {\n token.safeIncreaseAllowance(address(pool), amount.sub(fee));\n try\n ISwap(pool).removeLiquidityOneToken(\n amount.sub(fee),\n swapTokenIndex,\n swapMinAmount,\n swapDeadline\n )\n returns (uint256 finalSwappedAmount) {\n // Swap succeeded, transfer swapped asset\n IERC20 swappedTokenTo = ISwap(pool).getToken(swapTokenIndex);\n swappedTokenTo.safeTransfer(to, finalSwappedAmount);\n emit TokenWithdrawAndRemove(\n to,\n token,\n finalSwappedAmount,\n fee,\n swapTokenIndex,\n swapMinAmount,\n swapDeadline,\n true,\n kappa\n );\n } catch {\n IERC20(token).safeTransfer(to, amount.sub(fee));\n emit TokenWithdrawAndRemove(\n to,\n token,\n amount.sub(fee),\n fee,\n swapTokenIndex,\n swapMinAmount,\n swapDeadline,\n false,\n kappa\n );\n }\n } else {\n token.safeTransfer(to, amount.sub(fee));\n emit TokenWithdrawAndRemove(\n to,\n token,\n amount.sub(fee),\n fee,\n swapTokenIndex,\n swapMinAmount,\n swapDeadline,\n false,\n kappa\n );\n }\n }\n\n // BRIDGE FUNCTIONS TO HANDLE DIFF ADDRESSES\n /**\n * @notice Relays to nodes that (typically) a wrapped synAsset ERC20 token has been burned and the underlying needs to be redeeemed on the native chain\n * @param to address on other chain to redeem underlying assets to\n * @param chainId which underlying chain to bridge assets onto\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n **/\n function redeemV2(\n bytes32 to,\n uint256 chainId,\n ERC20Burnable token,\n uint256 amount\n ) external nonReentrant whenNotPaused {\n emit TokenRedeemV2(to, chainId, token, amount);\n token.burnFrom(msg.sender, amount);\n }\n}\n" + }, + "contracts/bridge/HarmonySynapseBridge.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.6.12;\n\nimport \"@openzeppelin/contracts-upgradeable/proxy/Initializable.sol\";\nimport \"@openzeppelin/contracts-upgradeable/access/AccessControlUpgradeable.sol\";\nimport \"@openzeppelin/contracts-upgradeable/utils/ReentrancyGuardUpgradeable.sol\";\nimport \"@openzeppelin/contracts-upgradeable/utils/PausableUpgradeable.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/SafeERC20.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/ERC20Burnable.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport \"@openzeppelin/contracts/math/SafeMath.sol\";\n\nimport \"./interfaces/ISwap.sol\";\nimport \"./interfaces/IWETH9.sol\";\n\ninterface IERC20Mintable is IERC20 {\n function mint(address to, uint256 amount) external;\n}\n\ninterface IFrax {\n function exchangeOldForCanonical(\n address bridge_token_address,\n uint256 token_amount\n ) external returns (uint256);\n}\n\ncontract HarmonySynapseBridge is\n Initializable,\n AccessControlUpgradeable,\n ReentrancyGuardUpgradeable,\n PausableUpgradeable\n{\n using SafeERC20 for IERC20;\n using SafeERC20 for IERC20Mintable;\n using SafeMath for uint256;\n\n bytes32 public constant NODEGROUP_ROLE = keccak256(\"NODEGROUP_ROLE\");\n bytes32 public constant GOVERNANCE_ROLE = keccak256(\"GOVERNANCE_ROLE\");\n\n mapping(address => uint256) private fees;\n\n uint256 public startBlockNumber;\n uint256 public constant bridgeVersion = 6;\n uint256 public chainGasAmount;\n address payable public WETH_ADDRESS;\n\n mapping(bytes32 => bool) private kappaMap;\n\n receive() external payable {}\n\n function initialize() external initializer {\n startBlockNumber = block.number;\n _setupRole(DEFAULT_ADMIN_ROLE, msg.sender);\n __AccessControl_init();\n }\n\n function setChainGasAmount(uint256 amount) external {\n require(hasRole(GOVERNANCE_ROLE, msg.sender), \"Not governance\");\n chainGasAmount = amount;\n }\n\n function setWethAddress(address payable _wethAddress) external {\n require(hasRole(DEFAULT_ADMIN_ROLE, msg.sender), \"Not admin\");\n WETH_ADDRESS = _wethAddress;\n }\n\n function addKappas(bytes32[] calldata kappas) external {\n require(hasRole(GOVERNANCE_ROLE, msg.sender), \"Not governance\");\n for (uint256 i = 0; i < kappas.length; ++i) {\n kappaMap[kappas[i]] = true;\n }\n }\n\n event TokenDeposit(\n address indexed to,\n uint256 chainId,\n IERC20 token,\n uint256 amount\n );\n event TokenRedeem(\n address indexed to,\n uint256 chainId,\n IERC20 token,\n uint256 amount\n );\n event TokenWithdraw(\n address indexed to,\n IERC20 token,\n uint256 amount,\n uint256 fee,\n bytes32 indexed kappa\n );\n event TokenMint(\n address indexed to,\n IERC20Mintable token,\n uint256 amount,\n uint256 fee,\n bytes32 indexed kappa\n );\n event TokenDepositAndSwap(\n address indexed to,\n uint256 chainId,\n IERC20 token,\n uint256 amount,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 minDy,\n uint256 deadline\n );\n event TokenMintAndSwap(\n address indexed to,\n IERC20Mintable token,\n uint256 amount,\n uint256 fee,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 minDy,\n uint256 deadline,\n bool swapSuccess,\n bytes32 indexed kappa\n );\n event TokenRedeemAndSwap(\n address indexed to,\n uint256 chainId,\n IERC20 token,\n uint256 amount,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 minDy,\n uint256 deadline\n );\n event TokenRedeemAndRemove(\n address indexed to,\n uint256 chainId,\n IERC20 token,\n uint256 amount,\n uint8 swapTokenIndex,\n uint256 swapMinAmount,\n uint256 swapDeadline\n );\n event TokenWithdrawAndRemove(\n address indexed to,\n IERC20 token,\n uint256 amount,\n uint256 fee,\n uint8 swapTokenIndex,\n uint256 swapMinAmount,\n uint256 swapDeadline,\n bool swapSuccess,\n bytes32 indexed kappa\n );\n\n // v2 events\n event TokenRedeemV2(\n bytes32 indexed to,\n uint256 chainId,\n IERC20 token,\n uint256 amount\n );\n\n // VIEW FUNCTIONS ***/\n function getFeeBalance(address tokenAddress)\n external\n view\n returns (uint256)\n {\n return fees[tokenAddress];\n }\n\n function kappaExists(bytes32 kappa) external view returns (bool) {\n return kappaMap[kappa];\n }\n\n // FEE FUNCTIONS ***/\n /**\n * * @notice withdraw specified ERC20 token fees to a given address\n * * @param token ERC20 token in which fees acccumulated to transfer\n * * @param to Address to send the fees to\n */\n function withdrawFees(IERC20 token, address to) external whenNotPaused {\n require(hasRole(GOVERNANCE_ROLE, msg.sender), \"Not governance\");\n require(to != address(0), \"Address is 0x000\");\n if (fees[address(token)] != 0) {\n token.safeTransfer(to, fees[address(token)]);\n fees[address(token)] = 0;\n }\n }\n\n // PAUSABLE FUNCTIONS ***/\n function pause() external {\n require(hasRole(GOVERNANCE_ROLE, msg.sender), \"Not governance\");\n _pause();\n }\n\n function unpause() external {\n require(hasRole(GOVERNANCE_ROLE, msg.sender), \"Not governance\");\n _unpause();\n }\n\n /**\n * @notice Relays to nodes to transfers an ERC20 token cross-chain\n * @param to address on other chain to bridge assets to\n * @param chainId which chain to bridge assets onto\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n **/\n function deposit(\n address to,\n uint256 chainId,\n IERC20 token,\n uint256 amount\n ) external nonReentrant whenNotPaused {\n emit TokenDeposit(to, chainId, token, amount);\n token.safeTransferFrom(msg.sender, address(this), amount);\n }\n\n /**\n * @notice Relays to nodes that (typically) a wrapped synAsset ERC20 token has been burned and the underlying needs to be redeeemed on the native chain\n * @param to address on other chain to redeem underlying assets to\n * @param chainId which underlying chain to bridge assets onto\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n **/\n function redeem(\n address to,\n uint256 chainId,\n ERC20Burnable token,\n uint256 amount\n ) external nonReentrant whenNotPaused {\n emit TokenRedeem(to, chainId, token, amount);\n token.burnFrom(msg.sender, amount);\n }\n\n /**\n * @notice Function to be called by the node group to withdraw the underlying assets from the contract\n * @param to address on chain to send underlying assets to\n * @param token ERC20 compatible token to withdraw from the bridge\n * @param amount Amount in native token decimals to withdraw\n * @param fee Amount in native token decimals to save to the contract as fees\n * @param kappa kappa\n **/\n function withdraw(\n address to,\n IERC20 token,\n uint256 amount,\n uint256 fee,\n bytes32 kappa\n ) external nonReentrant whenNotPaused {\n require(\n hasRole(NODEGROUP_ROLE, msg.sender),\n \"Caller is not a node group\"\n );\n require(amount > fee, \"Amount must be greater than fee\");\n require(!kappaMap[kappa], \"Kappa is already present\");\n kappaMap[kappa] = true;\n fees[address(token)] = fees[address(token)].add(fee);\n if (address(token) == WETH_ADDRESS && WETH_ADDRESS != address(0)) {\n IWETH9(WETH_ADDRESS).withdraw(amount.sub(fee));\n (bool success, ) = to.call{value: amount.sub(fee)}(\"\");\n require(success, \"ETH_TRANSFER_FAILED\");\n emit TokenWithdraw(to, token, amount, fee, kappa);\n } else {\n emit TokenWithdraw(to, token, amount, fee, kappa);\n token.safeTransfer(to, amount.sub(fee));\n }\n }\n\n /**\n * @notice Nodes call this function to mint a SynERC20 (or any asset that the bridge is given minter access to). This is called by the nodes after a TokenDeposit event is emitted.\n * @dev This means the SynapseBridge.sol contract must have minter access to the token attempting to be minted\n * @param to address on other chain to redeem underlying assets to\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain post-fees\n * @param fee Amount in native token decimals to save to the contract as fees\n * @param kappa kappa\n **/\n function mint(\n address payable to,\n IERC20Mintable token,\n uint256 amount,\n uint256 fee,\n bytes32 kappa\n ) external nonReentrant whenNotPaused {\n require(\n hasRole(NODEGROUP_ROLE, msg.sender),\n \"Caller is not a node group\"\n );\n require(amount > fee, \"Amount must be greater than fee\");\n require(!kappaMap[kappa], \"Kappa is already present\");\n kappaMap[kappa] = true;\n fees[address(token)] = fees[address(token)].add(fee);\n emit TokenMint(to, token, amount.sub(fee), fee, kappa);\n token.mint(address(this), amount);\n // checks if synFRAX\n if (address(token) == 0x1852F70512298d56e9c8FDd905e02581E04ddb2a) {\n if (\n token.allowance(\n address(this),\n 0xFa7191D292d5633f702B0bd7E3E3BcCC0e633200\n ) < amount.sub(fee)\n ) {\n token.safeApprove(\n address(0xFa7191D292d5633f702B0bd7E3E3BcCC0e633200),\n 0\n );\n token.safeApprove(\n address(0xFa7191D292d5633f702B0bd7E3E3BcCC0e633200),\n type(uint256).max\n );\n }\n try\n IFrax(0xFa7191D292d5633f702B0bd7E3E3BcCC0e633200)\n .exchangeOldForCanonical(address(token), amount.sub(fee))\n returns (uint256 canolical_tokens_out) {\n IERC20(0xFa7191D292d5633f702B0bd7E3E3BcCC0e633200).safeTransfer(\n to,\n canolical_tokens_out\n );\n } catch {\n IERC20(token).safeTransfer(to, amount.sub(fee));\n }\n } else {\n IERC20(token).safeTransfer(to, amount.sub(fee));\n }\n if (chainGasAmount != 0 && address(this).balance > chainGasAmount) {\n to.call.value(chainGasAmount)(\"\");\n }\n }\n\n /**\n * @notice Relays to nodes to both transfer an ERC20 token cross-chain, and then have the nodes execute a swap through a liquidity pool on behalf of the user.\n * @param to address on other chain to bridge assets to\n * @param chainId which chain to bridge assets onto\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n * @param tokenIndexFrom the token the user wants to swap from\n * @param tokenIndexTo the token the user wants to swap to\n * @param minDy the min amount the user would like to receive, or revert to only minting the SynERC20 token crosschain.\n * @param deadline latest timestamp to accept this transaction\n **/\n function depositAndSwap(\n address to,\n uint256 chainId,\n IERC20 token,\n uint256 amount,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 minDy,\n uint256 deadline\n ) external nonReentrant whenNotPaused {\n emit TokenDepositAndSwap(\n to,\n chainId,\n token,\n amount,\n tokenIndexFrom,\n tokenIndexTo,\n minDy,\n deadline\n );\n token.safeTransferFrom(msg.sender, address(this), amount);\n }\n\n /**\n * @notice Relays to nodes that (typically) a wrapped synAsset ERC20 token has been burned and the underlying needs to be redeeemed on the native chain. This function indicates to the nodes that they should attempt to redeem the LP token for the underlying assets (E.g \"swap\" out of the LP token)\n * @param to address on other chain to redeem underlying assets to\n * @param chainId which underlying chain to bridge assets onto\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n * @param tokenIndexFrom the token the user wants to swap from\n * @param tokenIndexTo the token the user wants to swap to\n * @param minDy the min amount the user would like to receive, or revert to only minting the SynERC20 token crosschain.\n * @param deadline latest timestamp to accept this transaction\n **/\n function redeemAndSwap(\n address to,\n uint256 chainId,\n ERC20Burnable token,\n uint256 amount,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 minDy,\n uint256 deadline\n ) external nonReentrant whenNotPaused {\n emit TokenRedeemAndSwap(\n to,\n chainId,\n token,\n amount,\n tokenIndexFrom,\n tokenIndexTo,\n minDy,\n deadline\n );\n token.burnFrom(msg.sender, amount);\n }\n\n /**\n * @notice Relays to nodes that (typically) a wrapped synAsset ERC20 token has been burned and the underlying needs to be redeeemed on the native chain. This function indicates to the nodes that they should attempt to redeem the LP token for the underlying assets (E.g \"swap\" out of the LP token)\n * @param to address on other chain to redeem underlying assets to\n * @param chainId which underlying chain to bridge assets onto\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n * @param swapTokenIndex Specifies which of the underlying LP assets the nodes should attempt to redeem for\n * @param swapMinAmount Specifies the minimum amount of the underlying asset needed for the nodes to execute the redeem/swap\n * @param swapDeadline Specificies the deadline that the nodes are allowed to try to redeem/swap the LP token\n **/\n function redeemAndRemove(\n address to,\n uint256 chainId,\n ERC20Burnable token,\n uint256 amount,\n uint8 swapTokenIndex,\n uint256 swapMinAmount,\n uint256 swapDeadline\n ) external nonReentrant whenNotPaused {\n emit TokenRedeemAndRemove(\n to,\n chainId,\n token,\n amount,\n swapTokenIndex,\n swapMinAmount,\n swapDeadline\n );\n token.burnFrom(msg.sender, amount);\n }\n\n /**\n * @notice Nodes call this function to mint a SynERC20 (or any asset that the bridge is given minter access to), and then attempt to swap the SynERC20 into the desired destination asset. This is called by the nodes after a TokenDepositAndSwap event is emitted.\n * @dev This means the BridgeDeposit.sol contract must have minter access to the token attempting to be minted\n * @param to address on other chain to redeem underlying assets to\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain post-fees\n * @param fee Amount in native token decimals to save to the contract as fees\n * @param pool Destination chain's pool to use to swap SynERC20 -> Asset. The nodes determine this by using PoolConfig.sol.\n * @param tokenIndexFrom Index of the SynERC20 asset in the pool\n * @param tokenIndexTo Index of the desired final asset\n * @param minDy Minumum amount (in final asset decimals) that must be swapped for, otherwise the user will receive the SynERC20.\n * @param deadline Epoch time of the deadline that the swap is allowed to be executed.\n * @param kappa kappa\n **/\n function mintAndSwap(\n address payable to,\n IERC20Mintable token,\n uint256 amount,\n uint256 fee,\n ISwap pool,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 minDy,\n uint256 deadline,\n bytes32 kappa\n ) external nonReentrant whenNotPaused {\n require(\n hasRole(NODEGROUP_ROLE, msg.sender),\n \"Caller is not a node group\"\n );\n require(amount > fee, \"Amount must be greater than fee\");\n require(!kappaMap[kappa], \"Kappa is already present\");\n kappaMap[kappa] = true;\n fees[address(token)] = fees[address(token)].add(fee);\n // Transfer gas airdrop\n if (chainGasAmount != 0 && address(this).balance > chainGasAmount) {\n to.call.value(chainGasAmount)(\"\");\n }\n // first check to make sure more will be given than min amount required\n uint256 expectedOutput = ISwap(pool).calculateSwap(\n tokenIndexFrom,\n tokenIndexTo,\n amount.sub(fee)\n );\n\n if (expectedOutput >= minDy) {\n // proceed with swap\n token.mint(address(this), amount);\n token.safeIncreaseAllowance(address(pool), amount);\n try\n ISwap(pool).swap(\n tokenIndexFrom,\n tokenIndexTo,\n amount.sub(fee),\n minDy,\n deadline\n )\n returns (uint256 finalSwappedAmount) {\n // Swap succeeded, transfer swapped asset\n IERC20 swappedTokenTo = ISwap(pool).getToken(tokenIndexTo);\n if (\n address(swappedTokenTo) == WETH_ADDRESS &&\n WETH_ADDRESS != address(0)\n ) {\n IWETH9(WETH_ADDRESS).withdraw(finalSwappedAmount);\n (bool success, ) = to.call{value: finalSwappedAmount}(\"\");\n require(success, \"ETH_TRANSFER_FAILED\");\n emit TokenMintAndSwap(\n to,\n token,\n finalSwappedAmount,\n fee,\n tokenIndexFrom,\n tokenIndexTo,\n minDy,\n deadline,\n true,\n kappa\n );\n } else {\n swappedTokenTo.safeTransfer(to, finalSwappedAmount);\n emit TokenMintAndSwap(\n to,\n token,\n finalSwappedAmount,\n fee,\n tokenIndexFrom,\n tokenIndexTo,\n minDy,\n deadline,\n true,\n kappa\n );\n }\n } catch {\n IERC20(token).safeTransfer(to, amount.sub(fee));\n emit TokenMintAndSwap(\n to,\n token,\n amount.sub(fee),\n fee,\n tokenIndexFrom,\n tokenIndexTo,\n minDy,\n deadline,\n false,\n kappa\n );\n }\n } else {\n token.mint(address(this), amount);\n IERC20(token).safeTransfer(to, amount.sub(fee));\n emit TokenMintAndSwap(\n to,\n token,\n amount.sub(fee),\n fee,\n tokenIndexFrom,\n tokenIndexTo,\n minDy,\n deadline,\n false,\n kappa\n );\n }\n }\n\n /**\n * @notice Function to be called by the node group to withdraw the underlying assets from the contract\n * @param to address on chain to send underlying assets to\n * @param token ERC20 compatible token to withdraw from the bridge\n * @param amount Amount in native token decimals to withdraw\n * @param fee Amount in native token decimals to save to the contract as fees\n * @param pool Destination chain's pool to use to swap SynERC20 -> Asset. The nodes determine this by using PoolConfig.sol.\n * @param swapTokenIndex Specifies which of the underlying LP assets the nodes should attempt to redeem for\n * @param swapMinAmount Specifies the minimum amount of the underlying asset needed for the nodes to execute the redeem/swap\n * @param swapDeadline Specificies the deadline that the nodes are allowed to try to redeem/swap the LP token\n * @param kappa kappa\n **/\n function withdrawAndRemove(\n address to,\n IERC20 token,\n uint256 amount,\n uint256 fee,\n ISwap pool,\n uint8 swapTokenIndex,\n uint256 swapMinAmount,\n uint256 swapDeadline,\n bytes32 kappa\n ) external nonReentrant whenNotPaused {\n require(\n hasRole(NODEGROUP_ROLE, msg.sender),\n \"Caller is not a node group\"\n );\n require(amount > fee, \"Amount must be greater than fee\");\n require(!kappaMap[kappa], \"Kappa is already present\");\n kappaMap[kappa] = true;\n fees[address(token)] = fees[address(token)].add(fee);\n // first check to make sure more will be given than min amount required\n uint256 expectedOutput = ISwap(pool).calculateRemoveLiquidityOneToken(\n amount.sub(fee),\n swapTokenIndex\n );\n\n if (expectedOutput >= swapMinAmount) {\n token.safeIncreaseAllowance(address(pool), amount.sub(fee));\n try\n ISwap(pool).removeLiquidityOneToken(\n amount.sub(fee),\n swapTokenIndex,\n swapMinAmount,\n swapDeadline\n )\n returns (uint256 finalSwappedAmount) {\n // Swap succeeded, transfer swapped asset\n IERC20 swappedTokenTo = ISwap(pool).getToken(swapTokenIndex);\n swappedTokenTo.safeTransfer(to, finalSwappedAmount);\n emit TokenWithdrawAndRemove(\n to,\n token,\n finalSwappedAmount,\n fee,\n swapTokenIndex,\n swapMinAmount,\n swapDeadline,\n true,\n kappa\n );\n } catch {\n IERC20(token).safeTransfer(to, amount.sub(fee));\n emit TokenWithdrawAndRemove(\n to,\n token,\n amount.sub(fee),\n fee,\n swapTokenIndex,\n swapMinAmount,\n swapDeadline,\n false,\n kappa\n );\n }\n } else {\n token.safeTransfer(to, amount.sub(fee));\n emit TokenWithdrawAndRemove(\n to,\n token,\n amount.sub(fee),\n fee,\n swapTokenIndex,\n swapMinAmount,\n swapDeadline,\n false,\n kappa\n );\n }\n }\n\n // BRIDGE FUNCTIONS TO HANDLE DIFF ADDRESSES\n /**\n * @notice Relays to nodes that (typically) a wrapped synAsset ERC20 token has been burned and the underlying needs to be redeeemed on the native chain\n * @param to address on other chain to redeem underlying assets to\n * @param chainId which underlying chain to bridge assets onto\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n **/\n function redeemV2(\n bytes32 to,\n uint256 chainId,\n ERC20Burnable token,\n uint256 amount\n ) external nonReentrant whenNotPaused {\n emit TokenRedeemV2(to, chainId, token, amount);\n token.burnFrom(msg.sender, amount);\n }\n}\n" + }, + "contracts/bridge/SynapseERC20.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.6.12;\n\nimport \"@openzeppelin/contracts-upgradeable/token/ERC20/ERC20Upgradeable.sol\";\nimport \"@openzeppelin/contracts-upgradeable/token/ERC20/ERC20BurnableUpgradeable.sol\";\nimport \"@openzeppelin/contracts-upgradeable/drafts/ERC20PermitUpgradeable.sol\";\nimport \"@openzeppelin/contracts-upgradeable/access/AccessControlUpgradeable.sol\";\nimport \"@openzeppelin/contracts-upgradeable/proxy/Initializable.sol\";\n\ncontract SynapseERC20 is\n Initializable,\n ContextUpgradeable,\n AccessControlUpgradeable,\n ERC20BurnableUpgradeable,\n ERC20PermitUpgradeable\n{\n bytes32 public constant MINTER_ROLE = keccak256(\"MINTER_ROLE\");\n\n /**\n * @notice Initializes this ERC20 contract with the given parameters.\n * @param name Token name\n * @param symbol Token symbol\n * @param decimals Token name\n * @param owner admin address to be initialized with\n */\n function initialize(\n string memory name,\n string memory symbol,\n uint8 decimals,\n address owner\n ) external initializer {\n __Context_init_unchained();\n __AccessControl_init_unchained();\n __ERC20_init_unchained(name, symbol);\n __ERC20Burnable_init_unchained();\n _setupDecimals(decimals);\n __ERC20Permit_init(name);\n _setupRole(DEFAULT_ADMIN_ROLE, owner);\n }\n\n function mint(address to, uint256 amount) external {\n require(hasRole(MINTER_ROLE, msg.sender), \"Not a minter\");\n _mint(to, amount);\n }\n}\n" + }, + "@openzeppelin/contracts-upgradeable/drafts/ERC20PermitUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.5 <0.8.0;\n\nimport \"../token/ERC20/ERC20Upgradeable.sol\";\nimport \"./IERC20PermitUpgradeable.sol\";\nimport \"../cryptography/ECDSAUpgradeable.sol\";\nimport \"../utils/CountersUpgradeable.sol\";\nimport \"./EIP712Upgradeable.sol\";\nimport \"../proxy/Initializable.sol\";\n\n/**\n * @dev Implementation of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in\n * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612].\n *\n * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by\n * presenting a message signed by the account. By not relying on `{IERC20-approve}`, the token holder account doesn't\n * need to send a transaction, and thus is not required to hold Ether at all.\n *\n * _Available since v3.4._\n */\nabstract contract ERC20PermitUpgradeable is Initializable, ERC20Upgradeable, IERC20PermitUpgradeable, EIP712Upgradeable {\n using CountersUpgradeable for CountersUpgradeable.Counter;\n\n mapping (address => CountersUpgradeable.Counter) private _nonces;\n\n // solhint-disable-next-line var-name-mixedcase\n bytes32 private _PERMIT_TYPEHASH;\n\n /**\n * @dev Initializes the {EIP712} domain separator using the `name` parameter, and setting `version` to `\"1\"`.\n *\n * It's a good idea to use the same `name` that is defined as the ERC20 token name.\n */\n function __ERC20Permit_init(string memory name) internal initializer {\n __Context_init_unchained();\n __EIP712_init_unchained(name, \"1\");\n __ERC20Permit_init_unchained(name);\n }\n\n function __ERC20Permit_init_unchained(string memory name) internal initializer {\n _PERMIT_TYPEHASH = keccak256(\"Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)\");\n }\n\n /**\n * @dev See {IERC20Permit-permit}.\n */\n function permit(address owner, address spender, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s) public virtual override {\n // solhint-disable-next-line not-rely-on-time\n require(block.timestamp <= deadline, \"ERC20Permit: expired deadline\");\n\n bytes32 structHash = keccak256(\n abi.encode(\n _PERMIT_TYPEHASH,\n owner,\n spender,\n value,\n _nonces[owner].current(),\n deadline\n )\n );\n\n bytes32 hash = _hashTypedDataV4(structHash);\n\n address signer = ECDSAUpgradeable.recover(hash, v, r, s);\n require(signer == owner, \"ERC20Permit: invalid signature\");\n\n _nonces[owner].increment();\n _approve(owner, spender, value);\n }\n\n /**\n * @dev See {IERC20Permit-nonces}.\n */\n function nonces(address owner) public view override returns (uint256) {\n return _nonces[owner].current();\n }\n\n /**\n * @dev See {IERC20Permit-DOMAIN_SEPARATOR}.\n */\n // solhint-disable-next-line func-name-mixedcase\n function DOMAIN_SEPARATOR() external view override returns (bytes32) {\n return _domainSeparatorV4();\n }\n uint256[49] private __gap;\n}\n" + }, + "@openzeppelin/contracts-upgradeable/drafts/IERC20PermitUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <0.8.0;\n\n/**\n * @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in\n * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612].\n *\n * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by\n * presenting a message signed by the account. By not relying on `{IERC20-approve}`, the token holder account doesn't\n * need to send a transaction, and thus is not required to hold Ether at all.\n */\ninterface IERC20PermitUpgradeable {\n /**\n * @dev Sets `value` as the allowance of `spender` over `owner`'s tokens,\n * given `owner`'s signed approval.\n *\n * IMPORTANT: The same issues {IERC20-approve} has related to transaction\n * ordering also apply here.\n *\n * Emits an {Approval} event.\n *\n * Requirements:\n *\n * - `spender` cannot be the zero address.\n * - `deadline` must be a timestamp in the future.\n * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner`\n * over the EIP712-formatted function arguments.\n * - the signature must use ``owner``'s current nonce (see {nonces}).\n *\n * For more information on the signature format, see the\n * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP\n * section].\n */\n function permit(address owner, address spender, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s) external;\n\n /**\n * @dev Returns the current nonce for `owner`. This value must be\n * included whenever a signature is generated for {permit}.\n *\n * Every successful call to {permit} increases ``owner``'s nonce by one. This\n * prevents a signature from being used multiple times.\n */\n function nonces(address owner) external view returns (uint256);\n\n /**\n * @dev Returns the domain separator used in the encoding of the signature for `permit`, as defined by {EIP712}.\n */\n // solhint-disable-next-line func-name-mixedcase\n function DOMAIN_SEPARATOR() external view returns (bytes32);\n}\n" + }, + "@openzeppelin/contracts-upgradeable/cryptography/ECDSAUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <0.8.0;\n\n/**\n * @dev Elliptic Curve Digital Signature Algorithm (ECDSA) operations.\n *\n * These functions can be used to verify that a message was signed by the holder\n * of the private keys of a given address.\n */\nlibrary ECDSAUpgradeable {\n /**\n * @dev Returns the address that signed a hashed message (`hash`) with\n * `signature`. This address can then be used for verification purposes.\n *\n * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:\n * this function rejects them by requiring the `s` value to be in the lower\n * half order, and the `v` value to be either 27 or 28.\n *\n * IMPORTANT: `hash` _must_ be the result of a hash operation for the\n * verification to be secure: it is possible to craft signatures that\n * recover to arbitrary addresses for non-hashed data. A safe way to ensure\n * this is by receiving a hash of the original message (which may otherwise\n * be too long), and then calling {toEthSignedMessageHash} on it.\n */\n function recover(bytes32 hash, bytes memory signature) internal pure returns (address) {\n // Check the signature length\n if (signature.length != 65) {\n revert(\"ECDSA: invalid signature length\");\n }\n\n // Divide the signature in r, s and v variables\n bytes32 r;\n bytes32 s;\n uint8 v;\n\n // ecrecover takes the signature parameters, and the only way to get them\n // currently is to use assembly.\n // solhint-disable-next-line no-inline-assembly\n assembly {\n r := mload(add(signature, 0x20))\n s := mload(add(signature, 0x40))\n v := byte(0, mload(add(signature, 0x60)))\n }\n\n return recover(hash, v, r, s);\n }\n\n /**\n * @dev Overload of {ECDSA-recover-bytes32-bytes-} that receives the `v`,\n * `r` and `s` signature fields separately.\n */\n function recover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) internal pure returns (address) {\n // EIP-2 still allows signature malleability for ecrecover(). Remove this possibility and make the signature\n // unique. Appendix F in the Ethereum Yellow paper (https://ethereum.github.io/yellowpaper/paper.pdf), defines\n // the valid range for s in (281): 0 < s < secp256k1n ÷ 2 + 1, and for v in (282): v ∈ {27, 28}. Most\n // signatures from current libraries generate a unique signature with an s-value in the lower half order.\n //\n // If your library generates malleable signatures, such as s-values in the upper range, calculate a new s-value\n // with 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 - s1 and flip v from 27 to 28 or\n // vice versa. If your library also generates signatures with 0/1 for v instead 27/28, add 27 to v to accept\n // these malleable signatures as well.\n require(uint256(s) <= 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0, \"ECDSA: invalid signature 's' value\");\n require(v == 27 || v == 28, \"ECDSA: invalid signature 'v' value\");\n\n // If the signature is valid (and not malleable), return the signer address\n address signer = ecrecover(hash, v, r, s);\n require(signer != address(0), \"ECDSA: invalid signature\");\n\n return signer;\n }\n\n /**\n * @dev Returns an Ethereum Signed Message, created from a `hash`. This\n * replicates the behavior of the\n * https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_sign[`eth_sign`]\n * JSON-RPC method.\n *\n * See {recover}.\n */\n function toEthSignedMessageHash(bytes32 hash) internal pure returns (bytes32) {\n // 32 is the length in bytes of hash,\n // enforced by the type signature above\n return keccak256(abi.encodePacked(\"\\x19Ethereum Signed Message:\\n32\", hash));\n }\n}\n" + }, + "@openzeppelin/contracts-upgradeable/utils/CountersUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <0.8.0;\n\nimport \"../math/SafeMathUpgradeable.sol\";\n\n/**\n * @title Counters\n * @author Matt Condon (@shrugs)\n * @dev Provides counters that can only be incremented or decremented by one. This can be used e.g. to track the number\n * of elements in a mapping, issuing ERC721 ids, or counting request ids.\n *\n * Include with `using Counters for Counters.Counter;`\n * Since it is not possible to overflow a 256 bit integer with increments of one, `increment` can skip the {SafeMath}\n * overflow check, thereby saving gas. This does assume however correct usage, in that the underlying `_value` is never\n * directly accessed.\n */\nlibrary CountersUpgradeable {\n using SafeMathUpgradeable for uint256;\n\n struct Counter {\n // This variable should never be directly accessed by users of the library: interactions must be restricted to\n // the library's function. As of Solidity v0.5.2, this cannot be enforced, though there is a proposal to add\n // this feature: see https://github.com/ethereum/solidity/issues/4637\n uint256 _value; // default: 0\n }\n\n function current(Counter storage counter) internal view returns (uint256) {\n return counter._value;\n }\n\n function increment(Counter storage counter) internal {\n // The {SafeMath} overflow check can be skipped here, see the comment at the top\n counter._value += 1;\n }\n\n function decrement(Counter storage counter) internal {\n counter._value = counter._value.sub(1);\n }\n}\n" + }, + "@openzeppelin/contracts-upgradeable/drafts/EIP712Upgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <0.8.0;\nimport \"../proxy/Initializable.sol\";\n\n/**\n * @dev https://eips.ethereum.org/EIPS/eip-712[EIP 712] is a standard for hashing and signing of typed structured data.\n *\n * The encoding specified in the EIP is very generic, and such a generic implementation in Solidity is not feasible,\n * thus this contract does not implement the encoding itself. Protocols need to implement the type-specific encoding\n * they need in their contracts using a combination of `abi.encode` and `keccak256`.\n *\n * This contract implements the EIP 712 domain separator ({_domainSeparatorV4}) that is used as part of the encoding\n * scheme, and the final step of the encoding to obtain the message digest that is then signed via ECDSA\n * ({_hashTypedDataV4}).\n *\n * The implementation of the domain separator was designed to be as efficient as possible while still properly updating\n * the chain id to protect against replay attacks on an eventual fork of the chain.\n *\n * NOTE: This contract implements the version of the encoding known as \"v4\", as implemented by the JSON RPC method\n * https://docs.metamask.io/guide/signing-data.html[`eth_signTypedDataV4` in MetaMask].\n *\n * _Available since v3.4._\n */\nabstract contract EIP712Upgradeable is Initializable {\n /* solhint-disable var-name-mixedcase */\n bytes32 private _HASHED_NAME;\n bytes32 private _HASHED_VERSION;\n bytes32 private constant _TYPE_HASH = keccak256(\"EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)\");\n /* solhint-enable var-name-mixedcase */\n\n /**\n * @dev Initializes the domain separator and parameter caches.\n *\n * The meaning of `name` and `version` is specified in\n * https://eips.ethereum.org/EIPS/eip-712#definition-of-domainseparator[EIP 712]:\n *\n * - `name`: the user readable name of the signing domain, i.e. the name of the DApp or the protocol.\n * - `version`: the current major version of the signing domain.\n *\n * NOTE: These parameters cannot be changed except through a xref:learn::upgrading-smart-contracts.adoc[smart\n * contract upgrade].\n */\n function __EIP712_init(string memory name, string memory version) internal initializer {\n __EIP712_init_unchained(name, version);\n }\n\n function __EIP712_init_unchained(string memory name, string memory version) internal initializer {\n bytes32 hashedName = keccak256(bytes(name));\n bytes32 hashedVersion = keccak256(bytes(version));\n _HASHED_NAME = hashedName;\n _HASHED_VERSION = hashedVersion;\n }\n\n /**\n * @dev Returns the domain separator for the current chain.\n */\n function _domainSeparatorV4() internal view returns (bytes32) {\n return _buildDomainSeparator(_TYPE_HASH, _EIP712NameHash(), _EIP712VersionHash());\n }\n\n function _buildDomainSeparator(bytes32 typeHash, bytes32 name, bytes32 version) private view returns (bytes32) {\n return keccak256(\n abi.encode(\n typeHash,\n name,\n version,\n _getChainId(),\n address(this)\n )\n );\n }\n\n /**\n * @dev Given an already https://eips.ethereum.org/EIPS/eip-712#definition-of-hashstruct[hashed struct], this\n * function returns the hash of the fully encoded EIP712 message for this domain.\n *\n * This hash can be used together with {ECDSA-recover} to obtain the signer of a message. For example:\n *\n * ```solidity\n * bytes32 digest = _hashTypedDataV4(keccak256(abi.encode(\n * keccak256(\"Mail(address to,string contents)\"),\n * mailTo,\n * keccak256(bytes(mailContents))\n * )));\n * address signer = ECDSA.recover(digest, signature);\n * ```\n */\n function _hashTypedDataV4(bytes32 structHash) internal view virtual returns (bytes32) {\n return keccak256(abi.encodePacked(\"\\x19\\x01\", _domainSeparatorV4(), structHash));\n }\n\n function _getChainId() private view returns (uint256 chainId) {\n this; // silence state mutability warning without generating bytecode - see https://github.com/ethereum/solidity/issues/2691\n // solhint-disable-next-line no-inline-assembly\n assembly {\n chainId := chainid()\n }\n }\n\n /**\n * @dev The hash of the name parameter for the EIP712 domain.\n *\n * NOTE: This function reads from storage by default, but can be redefined to return a constant value if gas costs\n * are a concern.\n */\n function _EIP712NameHash() internal virtual view returns (bytes32) {\n return _HASHED_NAME;\n }\n\n /**\n * @dev The hash of the version parameter for the EIP712 domain.\n *\n * NOTE: This function reads from storage by default, but can be redefined to return a constant value if gas costs\n * are a concern.\n */\n function _EIP712VersionHash() internal virtual view returns (bytes32) {\n return _HASHED_VERSION;\n }\n uint256[50] private __gap;\n}\n" + }, + "contracts/auxiliary/DummyWethProxy.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.6.12;\nimport \"@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol\";\nimport \"@openzeppelin/contracts-upgradeable/proxy/Initializable.sol\";\n\ninterface IWETH9 {\n function name() external view returns (string memory);\n\n function symbol() external view returns (string memory);\n\n function decimals() external view returns (uint8);\n\n function balanceOf(address) external view returns (uint256);\n\n function allowance(address, address) external view returns (uint256);\n\n receive() external payable;\n\n function deposit() external payable;\n\n function withdraw(uint256 wad) external;\n\n function totalSupply() external view returns (uint256);\n\n function approve(address guy, uint256 wad) external returns (bool);\n\n function transfer(address dst, uint256 wad) external returns (bool);\n\n function transferFrom(\n address src,\n address dst,\n uint256 wad\n ) external returns (bool);\n}\n\ncontract DummyWethProxy is Initializable, OwnableUpgradeable {\n function initialize() external initializer {\n __Ownable_init();\n }\n\n IWETH9 public WETH;\n\n function setWETHAddress(address payable _weth) external onlyOwner {\n WETH = IWETH9(_weth);\n }\n\n function withdrawToSelf(uint256 amount) external {\n WETH.withdraw(amount);\n }\n\n function rescue(uint256 amount) external onlyOwner {\n WETH.transfer(owner(), amount);\n }\n\n receive() external payable {}\n\n fallback() external payable {}\n}\n" + }, + "contracts/amm/helper/test/TestMathUtils.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.6.12;\n\nimport \"../../MathUtils.sol\";\n\ncontract TestMathUtils {\n using MathUtils for uint256;\n\n function difference(uint256 a, uint256 b) public pure returns (uint256) {\n return a.difference(b);\n }\n\n function within1(uint256 a, uint256 b) public pure returns (bool) {\n return a.within1(b);\n }\n}\n" + }, + "contracts/bridge/ERC20Migrator.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.6.12;\n\nimport \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/SafeERC20.sol\";\nimport \"@openzeppelin/contracts/math/SafeMath.sol\";\n\n/**\n * @title ERC20Migrator\n * @dev This contract can be used to migrate an ERC20 token from one\n * contract to another, where each token holder has to opt-in to the migration.\n * To opt-in, users must approve for this contract the number of tokens they\n * want to migrate. Once the allowance is set up, anyone can trigger the\n * migration to the new token contract. In this way, token holders \"turn in\"\n * their old balance and will be minted an equal amount in the new token.\n * The new token contract must be mintable.\n * ```\n */\n\ninterface IERC20Mintable is IERC20 {\n function mint(address to, uint256 amount) external;\n}\n\ncontract ERC20Migrator {\n using SafeERC20 for IERC20;\n using SafeMath for uint256;\n\n // Address of the old token contract\n IERC20 private _legacyToken;\n\n // Address of the new token contract\n IERC20Mintable private _newToken;\n\n /**\n * @param legacyToken address of the old token contract\n */\n constructor(IERC20 legacyToken, IERC20Mintable newToken) public {\n _legacyToken = legacyToken;\n _newToken = newToken;\n }\n\n /**\n * @dev Returns the legacy token that is being migrated.\n */\n function legacyToken() external view returns (IERC20) {\n return _legacyToken;\n }\n\n /**\n * @dev Returns the new token to which we are migrating.\n */\n function newToken() external view returns (IERC20) {\n return _newToken;\n }\n\n /**\n * @dev Transfers part of an account's balance in the old token to this\n * contract, and mints the same amount of new tokens for that account.\n * @param amount amount of tokens to be migrated\n */\n function migrate(uint256 amount) external {\n _legacyToken.safeTransferFrom(msg.sender, address(this), amount);\n uint256 amountToMint = amount.mul(5).div(2);\n _newToken.mint(msg.sender, amountToMint);\n }\n}\n" + }, + "contracts/bridge/ECDSANodeManagement.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.6.12;\n\nimport \"./utils/AddressArrayUtils.sol\";\nimport \"@openzeppelin/contracts/math/SafeMath.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/SafeERC20.sol\";\n\ncontract ECDSANodeManagement {\n using AddressArrayUtils for address[];\n using SafeMath for uint256;\n using SafeERC20 for IERC20;\n\n // Status of the keep.\n // Active means the keep is active.\n // Closed means the keep was closed happily.\n // Terminated means the keep was closed due to misbehavior.\n enum Status {\n Active,\n Closed,\n Terminated\n }\n\n // Address of the keep's owner.\n address public owner;\n\n // List of keep members' addresses.\n address[] public members;\n\n // Minimum number of honest keep members required to produce a signature.\n uint256 public honestThreshold;\n\n // Keep's ECDSA public key serialized to 64-bytes, where X and Y coordinates\n // are padded with zeros to 32-byte each.\n bytes public publicKey;\n\n // The timestamp at which keep has been created and key generation process\n // started.\n uint256 internal keyGenerationStartTimestamp;\n\n // Map stores public key by member addresses. All members should submit the\n // same public key.\n mapping(address => bytes) internal submittedPublicKeys;\n\n // The current status of the keep.\n // If the keep is Active members monitor it and support requests from the\n // keep owner.\n // If the owner decides to close the keep the flag is set to Closed.\n // If the owner seizes member bonds the flag is set to Terminated.\n Status internal status;\n\n // Flags execution of contract initialization.\n bool internal isInitialized;\n\n // Notification that the submitted public key does not match a key submitted\n // by other member. The event contains address of the member who tried to\n // submit a public key and a conflicting public key submitted already by other\n // member.\n event ConflictingPublicKeySubmitted(\n address indexed submittingMember,\n bytes conflictingPublicKey\n );\n\n // Notification that keep's ECDSA public key has been successfully established.\n event PublicKeyPublished(bytes publicKey);\n\n // Notification that the keep was closed by the owner.\n // Members no longer need to support this keep.\n event KeepClosed();\n\n // Notification that the keep has been terminated by the owner.\n // Members no longer need to support this keep.\n event KeepTerminated();\n\n /// @notice Returns keep's ECDSA public key.\n /// @return Keep's ECDSA public key.\n function getPublicKey() external view returns (bytes memory) {\n return publicKey;\n }\n\n /// @notice Submits a public key to the keep.\n /// @dev Public key is published successfully if all members submit the same\n /// value. In case of conflicts with others members submissions it will emit\n /// `ConflictingPublicKeySubmitted` event. When all submitted keys match\n /// it will store the key as keep's public key and emit a `PublicKeyPublished`\n /// event.\n /// @param _publicKey Signer's public key.\n function submitPublicKey(bytes calldata _publicKey) external onlyMember {\n require(\n !hasMemberSubmittedPublicKey(msg.sender),\n \"Member already submitted a public key\"\n );\n\n require(_publicKey.length == 64, \"Public key must be 64 bytes long\");\n\n submittedPublicKeys[msg.sender] = _publicKey;\n\n // Check if public keys submitted by all keep members are the same as\n // the currently submitted one.\n uint256 matchingPublicKeysCount = 0;\n for (uint256 i = 0; i < members.length; i++) {\n if (\n keccak256(submittedPublicKeys[members[i]]) !=\n keccak256(_publicKey)\n ) {\n // Emit an event only if compared member already submitted a value.\n if (hasMemberSubmittedPublicKey(members[i])) {\n emit ConflictingPublicKeySubmitted(\n msg.sender,\n submittedPublicKeys[members[i]]\n );\n }\n } else {\n matchingPublicKeysCount++;\n }\n }\n\n if (matchingPublicKeysCount != members.length) {\n return;\n }\n\n // All submitted signatures match.\n publicKey = _publicKey;\n emit PublicKeyPublished(_publicKey);\n }\n\n /// @notice Gets the owner of the keep.\n /// @return Address of the keep owner.\n function getOwner() external view returns (address) {\n return owner;\n }\n\n /// @notice Gets the timestamp the keep was opened at.\n /// @return Timestamp the keep was opened at.\n function getOpenedTimestamp() external view returns (uint256) {\n return keyGenerationStartTimestamp;\n }\n\n /// @notice Closes keep when owner decides that they no longer need it.\n /// Releases bonds to the keep members.\n /// @dev The function can be called only by the owner of the keep and only\n /// if the keep has not been already closed.\n function closeKeep() public onlyOwner onlyWhenActive {\n markAsClosed();\n }\n\n /// @notice Returns true if the keep is active.\n /// @return true if the keep is active, false otherwise.\n function isActive() public view returns (bool) {\n return status == Status.Active;\n }\n\n /// @notice Returns true if the keep is closed and members no longer support\n /// this keep.\n /// @return true if the keep is closed, false otherwise.\n function isClosed() public view returns (bool) {\n return status == Status.Closed;\n }\n\n /// @notice Returns true if the keep has been terminated.\n /// Keep is terminated when bonds are seized and members no longer support\n /// this keep.\n /// @return true if the keep has been terminated, false otherwise.\n function isTerminated() public view returns (bool) {\n return status == Status.Terminated;\n }\n\n /// @notice Returns members of the keep.\n /// @return List of the keep members' addresses.\n function getMembers() public view returns (address[] memory) {\n return members;\n }\n\n /// @notice Initialization function.\n /// @dev We use clone factory to create new keep. That is why this contract\n /// doesn't have a constructor. We provide keep parameters for each instance\n /// function after cloning instances from the master contract.\n /// Initialization must happen in the same transaction in which the clone is\n /// created.\n /// @param _owner Address of the keep owner.\n /// @param _members Addresses of the keep members.\n /// @param _honestThreshold Minimum number of honest keep members.\n function initialize(\n address _owner,\n address[] memory _members,\n uint256 _honestThreshold\n ) public {\n require(!isInitialized, \"Contract already initialized\");\n require(_owner != address(0));\n owner = _owner;\n members = _members;\n honestThreshold = _honestThreshold;\n\n status = Status.Active;\n isInitialized = true;\n\n /* solium-disable-next-line security/no-block-members*/\n keyGenerationStartTimestamp = block.timestamp;\n }\n\n /// @notice Checks if the member already submitted a public key.\n /// @param _member Address of the member.\n /// @return True if member already submitted a public key, else false.\n function hasMemberSubmittedPublicKey(address _member)\n internal\n view\n returns (bool)\n {\n return submittedPublicKeys[_member].length != 0;\n }\n\n /// @notice Marks the keep as closed.\n /// Keep can be marked as closed only when there is no signing in progress\n /// or the requested signing process has timed out.\n function markAsClosed() internal {\n status = Status.Closed;\n emit KeepClosed();\n }\n\n /// @notice Marks the keep as terminated.\n /// Keep can be marked as terminated only when there is no signing in progress\n /// or the requested signing process has timed out.\n function markAsTerminated() internal {\n status = Status.Terminated;\n emit KeepTerminated();\n }\n\n /// @notice Coverts a public key to an ethereum address.\n /// @param _publicKey Public key provided as 64-bytes concatenation of\n /// X and Y coordinates (32-bytes each).\n /// @return Ethereum address.\n function publicKeyToAddress(bytes memory _publicKey)\n internal\n pure\n returns (address)\n {\n // We hash the public key and then truncate last 20 bytes of the digest\n // which is the ethereum address.\n return address(uint160(uint256(keccak256(_publicKey))));\n }\n\n /// @notice Terminates the keep.\n function terminateKeep() internal {\n markAsTerminated();\n }\n\n /// @notice Checks if the caller is the keep's owner.\n /// @dev Throws an error if called by any account other than owner.\n modifier onlyOwner() {\n require(owner == msg.sender, \"Caller is not the keep owner\");\n _;\n }\n\n /// @notice Checks if the caller is a keep member.\n /// @dev Throws an error if called by any account other than one of the members.\n modifier onlyMember() {\n require(members.contains(msg.sender), \"Caller is not the keep member\");\n _;\n }\n\n /// @notice Checks if the keep is currently active.\n /// @dev Throws an error if called when the keep has been already closed.\n modifier onlyWhenActive() {\n require(isActive(), \"Keep is not active\");\n _;\n }\n}\n" + }, + "contracts/bridge/utils/AddressArrayUtils.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.6.12;\n\nlibrary AddressArrayUtils {\n function contains(address[] memory self, address _address)\n internal\n pure\n returns (bool)\n {\n for (uint256 i = 0; i < self.length; i++) {\n if (_address == self[i]) {\n return true;\n }\n }\n return false;\n }\n}" + }, + "contracts/bridge/testing/NodeEnv.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.6.12;\npragma experimental ABIEncoderV2;\n\nimport '@openzeppelin/contracts/access/AccessControl.sol';\nimport \"../utils/EnumerableStringMap.sol\";\n\n/**\n * @title NodeEnv contract\n * @author Synapse Authors\n * @notice This contract implements a key-value store for storing variables on which synapse nodes must coordinate\n * methods are purposely arbitrary to allow these fields to be defined in synapse improvement proposals.\n * @notice This token is used for configuring different tokens on the bridge and mapping them across chains.\n**/\ncontract NodeEnv is AccessControl {\n using EnumerableStringMap for EnumerableStringMap.StringToStringMap;\n // BRIDGEMANAGER_ROLE owns the bridge. They are the only user that can call setters on this contract\n bytes32 public constant BRIDGEMANAGER_ROLE = keccak256('BRIDGEMANAGER_ROLE');\n // _config stores the config\n EnumerableStringMap.StringToStringMap private _config; // key is tokenAddress,chainID\n\n // ConfigUpdate is emitted when the config is updated by the user\n event ConfigUpdate(\n string key\n );\n\n constructor() public {\n _setupRole(DEFAULT_ADMIN_ROLE, msg.sender);\n _setupRole(BRIDGEMANAGER_ROLE, msg.sender);\n }\n\n /**\n * @notice get the length of the config\n *\n * @dev this is useful for enumerating through all keys in the env\n */\n function keyCount()\n external\n view\n returns (uint256){\n return _config.length();\n }\n\n /**\n * @notice gets the key/value pair by it's index\n *\n * Requirements:\n *\n * - `index` must be strictly less than {length}.\n */\n function keyValueByIndex(uint256 index) external view returns(string memory, string memory){\n return _config.at(index);\n }\n\n /**\n * @notice gets the value associated with the key\n */\n function get(string calldata _key) external view returns(string memory){\n string memory key = _key;\n return _config.get(key);\n }\n\n /**\n * @notice sets the key\n *\n * @dev caller must have bridge manager role\n */\n function set(string calldata _key, string calldata _value) external returns(bool) {\n require(\n hasRole(BRIDGEMANAGER_ROLE, msg.sender),\n 'Caller is not Bridge Manager'\n );\n string memory key = _key;\n string memory value = _value;\n\n return _config.set(key, value);\n }\n}" + }, + "contracts/bridge/utils/EnumerableStringMap.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.6.12;\n\nimport \"@openzeppelin/contracts/utils/EnumerableSet.sol\";\n\n/**\n * @title EnumerableStringMap\n * @dev Library for managing an enumerable variant of Solidity's\n * https://solidity.readthedocs.io/en/latest/types.html#mapping-types[`mapping`]\n * type.\n *\n * Maps have the following properties:\n *\n * - Entries are added, removed, and checked for existence in constant time\n * (O(1)).\n * - Entries are enumerated in O(n). No guarantees are made on the ordering.\n *\n * this isn't a terribly gas efficient implementation because it emphasizes usability over gas efficiency\n * by allowing arbitrary length string memorys. If Gettetrs/Setters are going to be used frequently in contracts\n * consider using the OpenZeppeling Bytes32 implementation\n *\n * this also differs from the OpenZeppelin implementation by keccac256 hashing the string memorys\n * so we can use enumerable bytes32 set\n */\nlibrary EnumerableStringMap {\n using EnumerableSet for EnumerableSet.Bytes32Set;\n\n // To implement this library for multiple types with as little code\n // repetition as possible, we write it in terms of a generic Map type with\n // bytes32 keys and values.\n // The Map implementation uses private functions, and user-facing\n // implementations (such as Uint256ToAddressMap) are just wrappers around\n // the underlying Map.\n // This means that we can only create new EnumerableMaps for types that fit\n // in bytes32.\n\n struct Map {\n // Storage of keys as a set\n EnumerableSet.Bytes32Set _keys;\n // Mapping of keys to resulting values to allow key lookup in the set\n mapping(bytes32 => string) _hashKeyMap;\n // values\n mapping(bytes32 => string) _values;\n }\n\n /**\n * @dev Adds a key-value pair to a map, or updates the value for an existing\n * key. O(1).\n *\n * Returns true if the key was added to the map, that is if it was not\n * already present.\n */\n function _set(\n Map storage map,\n string memory key,\n string memory value\n ) private returns (bool) {\n bytes32 keyHash = keccak256(abi.encodePacked(key));\n map._values[keyHash] = value;\n map._hashKeyMap[keyHash] = key;\n return map._keys.add(keyHash);\n }\n\n /**\n * @dev Removes a key-value pair from a map. O(1).\n *\n * Returns true if the key was removed from the map, that is if it was present.\n */\n function _remove(Map storage map, bytes32 keyHash) private returns (bool) {\n delete map._values[keyHash];\n delete map._hashKeyMap[keyHash];\n return map._keys.remove(keyHash);\n }\n\n /**\n * @dev Returns true if the key is in the map. O(1).\n */\n function _contains(Map storage map, bytes32 keyHash) private view returns (bool) {\n return map._keys.contains(keyHash);\n }\n\n /**\n * @dev Returns the number of key-value pairs in the map. O(1).\n */\n function _length(Map storage map) private view returns (uint256) {\n return map._keys.length();\n }\n\n /**\n * @dev Returns the key-value pair stored at position `index` in the map. O(1).\n *\n * Note that there are no guarantees on the ordering of entries inside the\n * array, and it may change when more entries are added or removed.\n *\n * Requirements:\n *\n * - `index` must be strictly less than {length}.\n */\n function _at(Map storage map, uint256 index) private view returns (string memory, string memory) {\n bytes32 keyHash = map._keys.at(index);\n return (map._hashKeyMap[keyHash], map._values[keyHash]);\n }\n\n /**\n * @dev Tries to returns the value associated with `key`. O(1).\n * Does not revert if `key` is not in the map.\n */\n function _tryGet(Map storage map, bytes32 keyHash) private view returns (bool, string memory) {\n string memory value = map._values[keyHash];\n if (keccak256(bytes(value)) == keccak256(bytes(\"\"))) {\n return (_contains(map, keyHash), \"\");\n } else {\n return (true, value);\n }\n }\n\n /**\n * @dev Returns the value associated with `key`. O(1).\n *\n * Requirements:\n *\n * - `key` must be in the map.\n */\n function _get(Map storage map, bytes32 keyHash) private view returns (string memory) {\n string memory value = map._values[keyHash];\n require(_contains(map, keyHash), \"EnumerableMap: nonexistent key\");\n return value;\n }\n\n // StringToStringMap\n struct StringToStringMap {\n Map _inner;\n }\n\n /**\n * @dev Adds a key-value pair to a map, or updates the value for an existing\n * key. O(1).\n *\n * Returns true if the key was added to the map, that is if it was not\n * already present.\n */\n function set(\n StringToStringMap storage map,\n string memory key,\n string memory value\n ) internal returns (bool) {\n return _set(map._inner, key, value);\n }\n\n /**\n * @dev Removes a value from a set. O(1).\n *\n * Returns true if the key was removed from the map, that is if it was present.\n */\n function remove(StringToStringMap storage map, string memory key) internal returns (bool) {\n return _remove(map._inner, keccak256(abi.encodePacked(key)));\n }\n\n /**\n * @dev Returns true if the key is in the map. O(1).\n */\n function contains(StringToStringMap storage map, string memory key) internal view returns (bool) {\n return _contains(map._inner, keccak256(abi.encodePacked(key)));\n }\n\n /**\n * @dev Returns the number of elements in the map. O(1).\n */\n function length(StringToStringMap storage map) internal view returns (uint256) {\n return _length(map._inner);\n }\n\n /**\n * @dev Returns the element stored at position `index` in the set. O(1).\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(StringToStringMap storage map, uint256 index) internal view returns (string memory, string memory) {\n return _at(map._inner, index);\n }\n\n /**\n * @dev Tries to returns the value associated with `key`. O(1).\n * Does not revert if `key` is not in the map.\n *\n * _Available since v3.4._\n */\n function tryGet(StringToStringMap storage map, uint256 key) internal view returns (bool, string memory) {\n (bool success, string memory value) = _tryGet(map._inner, bytes32(key));\n return (success, value);\n }\n\n /**\n * @dev Returns the value associated with `key`. O(1).\n *\n * Requirements:\n *\n * - `key` must be in the map.\n */\n function get(StringToStringMap storage map, string memory key) internal view returns (string memory) {\n return _get(map._inner, keccak256(abi.encodePacked(key)));\n }\n}" + }, + "contracts/bridge/PoolConfig.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.6.12;\npragma experimental ABIEncoderV2;\n\nimport \"@openzeppelin/contracts/access/AccessControl.sol\";\n\ncontract PoolConfig is AccessControl {\n bytes32 public constant BRIDGEMANAGER_ROLE =\n keccak256(\"BRIDGEMANAGER_ROLE\");\n mapping(address => mapping(uint256 => Pool)) private _pool; // key is tokenAddress,chainID\n\n struct Pool {\n address tokenAddress;\n uint256 chainId;\n address poolAddress;\n bool metaswap;\n }\n\n constructor() public {\n _setupRole(DEFAULT_ADMIN_ROLE, msg.sender);\n _setupRole(BRIDGEMANAGER_ROLE, msg.sender);\n }\n\n function getPoolConfig(address tokenAddress, uint256 chainID)\n external\n view\n returns (Pool memory)\n {\n return _pool[tokenAddress][chainID];\n }\n\n function setPoolConfig(\n address tokenAddress,\n uint256 chainID,\n address poolAddress,\n bool metaswap\n ) external returns (Pool memory) {\n require(\n hasRole(BRIDGEMANAGER_ROLE, msg.sender),\n \"Caller is not Bridge Manager\"\n );\n Pool memory newPool = Pool(\n tokenAddress,\n chainID,\n poolAddress,\n metaswap\n );\n _pool[tokenAddress][chainID] = newPool;\n return newPool;\n }\n}\n" + }, + "contracts/bridge/BridgeConfigV3.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.6.12;\npragma experimental ABIEncoderV2;\n\nimport \"@openzeppelin/contracts/access/AccessControl.sol\";\nimport \"@openzeppelin/contracts/math/SafeMath.sol\";\n\n/**\n * @title BridgeConfig contract\n * @notice This token is used for configuring different tokens on the bridge and mapping them across chains.\n **/\n\ncontract BridgeConfigV3 is AccessControl {\n using SafeMath for uint256;\n bytes32 public constant BRIDGEMANAGER_ROLE =\n keccak256(\"BRIDGEMANAGER_ROLE\");\n bytes32[] private _allTokenIDs;\n mapping(bytes32 => Token[]) private _allTokens; // key is tokenID\n mapping(uint256 => mapping(string => bytes32)) private _tokenIDMap; // key is chainID,tokenAddress\n mapping(bytes32 => mapping(uint256 => Token)) private _tokens; // key is tokenID,chainID\n mapping(address => mapping(uint256 => Pool)) private _pool; // key is tokenAddress,chainID\n mapping(uint256 => uint256) private _maxGasPrice; // key is tokenID,chainID\n uint256 public constant bridgeConfigVersion = 3;\n\n // the denominator used to calculate fees. For example, an\n // LP fee might be something like tradeAmount.mul(fee).div(FEE_DENOMINATOR)\n uint256 private constant FEE_DENOMINATOR = 10**10;\n\n // this struct must be initialized using setTokenConfig for each token that directly interacts with the bridge\n struct Token {\n uint256 chainId;\n string tokenAddress;\n uint8 tokenDecimals;\n uint256 maxSwap;\n uint256 minSwap;\n uint256 swapFee;\n uint256 maxSwapFee;\n uint256 minSwapFee;\n bool hasUnderlying;\n bool isUnderlying;\n }\n\n struct Pool {\n address tokenAddress;\n uint256 chainId;\n address poolAddress;\n bool metaswap;\n }\n\n constructor() public {\n _setupRole(DEFAULT_ADMIN_ROLE, msg.sender);\n }\n\n /**\n * @notice Returns a list of all existing token IDs converted to strings\n */\n function getAllTokenIDs() public view returns (string[] memory result) {\n uint256 length = _allTokenIDs.length;\n result = new string[](length);\n for (uint256 i = 0; i < length; ++i) {\n result[i] = toString(_allTokenIDs[i]);\n }\n }\n\n function _getTokenID(string memory tokenAddress, uint256 chainID)\n internal\n view\n returns (string memory)\n {\n return toString(_tokenIDMap[chainID][tokenAddress]);\n }\n\n function getTokenID(string memory tokenAddress, uint256 chainID)\n public\n view\n returns (string memory)\n {\n return _getTokenID(_toLower(tokenAddress), chainID);\n }\n\n /**\n * @notice Returns the token ID (string) of the cross-chain token inputted\n * @param tokenAddress address of token to get ID for\n * @param chainID chainID of which to get token ID for\n */\n function getTokenID(address tokenAddress, uint256 chainID)\n public\n view\n returns (string memory)\n {\n return _getTokenID(_toLower(toString(tokenAddress)), chainID);\n }\n\n /**\n * @notice Returns the full token config struct\n * @param tokenID String input of the token ID for the token\n * @param chainID Chain ID of which token address + config to get\n */\n function getToken(string memory tokenID, uint256 chainID)\n public\n view\n returns (Token memory token)\n {\n return _tokens[toBytes32(tokenID)][chainID];\n }\n\n /**\n * @notice Returns the full token config struct\n * @param tokenID String input of the token ID for the token\n * @param chainID Chain ID of which token address + config to get\n */\n function getTokenByID(string memory tokenID, uint256 chainID)\n public\n view\n returns (Token memory token)\n {\n return _tokens[toBytes32(tokenID)][chainID];\n }\n\n /**\n * @notice Returns token config struct, given an address and chainID\n * @param tokenAddress Matches the token ID by using a combo of address + chain ID\n * @param chainID Chain ID of which token to get config for\n */\n function getTokenByAddress(string memory tokenAddress, uint256 chainID)\n public\n view\n returns (Token memory token)\n {\n return _tokens[_tokenIDMap[chainID][_toLower(tokenAddress)]][chainID];\n }\n\n function getTokenByEVMAddress(address tokenAddress, uint256 chainID)\n public\n view\n returns (Token memory token)\n {\n return\n _tokens[_tokenIDMap[chainID][_toLower(toString(tokenAddress))]][\n chainID\n ];\n }\n\n /**\n * @notice Returns true if the token has an underlying token -- meaning the token is deposited into the bridge\n * @param tokenID String to check if it is a withdraw/underlying token\n */\n function hasUnderlyingToken(string memory tokenID)\n public\n view\n returns (bool)\n {\n bytes32 bytesTokenID = toBytes32(tokenID);\n Token[] memory _mcTokens = _allTokens[bytesTokenID];\n for (uint256 i = 0; i < _mcTokens.length; ++i) {\n if (_mcTokens[i].hasUnderlying) {\n return true;\n }\n }\n return false;\n }\n\n /**\n * @notice Returns which token is the underlying token to withdraw\n * @param tokenID string token ID\n */\n function getUnderlyingToken(string memory tokenID)\n public\n view\n returns (Token memory token)\n {\n bytes32 bytesTokenID = toBytes32(tokenID);\n Token[] memory _mcTokens = _allTokens[bytesTokenID];\n for (uint256 i = 0; i < _mcTokens.length; ++i) {\n if (_mcTokens[i].isUnderlying) {\n return _mcTokens[i];\n }\n }\n }\n\n /**\n @notice Public function returning if token ID exists given a string\n */\n function isTokenIDExist(string memory tokenID) public view returns (bool) {\n return _isTokenIDExist(toBytes32(tokenID));\n }\n\n /**\n @notice Internal function returning if token ID exists given bytes32 version of the ID\n */\n function _isTokenIDExist(bytes32 tokenID) internal view returns (bool) {\n for (uint256 i = 0; i < _allTokenIDs.length; ++i) {\n if (_allTokenIDs[i] == tokenID) {\n return true;\n }\n }\n return false;\n }\n\n /**\n * @notice Internal function which handles logic of setting token ID and dealing with mappings\n * @param tokenID bytes32 version of ID\n * @param chainID which chain to set the token config for\n * @param tokenToAdd Token object to set the mapping to\n */\n function _setTokenConfig(\n bytes32 tokenID,\n uint256 chainID,\n Token memory tokenToAdd\n ) internal returns (bool) {\n _tokens[tokenID][chainID] = tokenToAdd;\n if (!_isTokenIDExist(tokenID)) {\n _allTokenIDs.push(tokenID);\n }\n\n Token[] storage _mcTokens = _allTokens[tokenID];\n for (uint256 i = 0; i < _mcTokens.length; ++i) {\n if (_mcTokens[i].chainId == chainID) {\n string memory oldToken = _mcTokens[i].tokenAddress;\n if (!compareStrings(tokenToAdd.tokenAddress, oldToken)) {\n _mcTokens[i].tokenAddress = tokenToAdd.tokenAddress;\n _tokenIDMap[chainID][oldToken] = keccak256(\"\");\n _tokenIDMap[chainID][tokenToAdd.tokenAddress] = tokenID;\n }\n }\n }\n _mcTokens.push(tokenToAdd);\n _tokenIDMap[chainID][tokenToAdd.tokenAddress] = tokenID;\n return true;\n }\n\n /**\n * @notice Main write function of this contract - Handles creating the struct and passing it to the internal logic function\n * @param tokenID string ID to set the token config object form\n * @param chainID chain ID to use for the token config object\n * @param tokenAddress token address of the token on the given chain\n * @param tokenDecimals decimals of token\n * @param maxSwap maximum amount of token allowed to be transferred at once - in native token decimals\n * @param minSwap minimum amount of token needed to be transferred at once - in native token decimals\n * @param swapFee percent based swap fee -- 10e6 == 10bps\n * @param maxSwapFee max swap fee to be charged - in native token decimals\n * @param minSwapFee min swap fee to be charged - in native token decimals - especially useful for mainnet ETH\n * @param hasUnderlying bool which represents whether this is a global mint token or one to withdraw()\n * @param isUnderlying bool which represents if this token is the one to withdraw on the given chain\n */\n function setTokenConfig(\n string calldata tokenID,\n uint256 chainID,\n address tokenAddress,\n uint8 tokenDecimals,\n uint256 maxSwap,\n uint256 minSwap,\n uint256 swapFee,\n uint256 maxSwapFee,\n uint256 minSwapFee,\n bool hasUnderlying,\n bool isUnderlying\n ) public returns (bool) {\n require(hasRole(BRIDGEMANAGER_ROLE, msg.sender));\n return\n setTokenConfig(\n tokenID,\n chainID,\n toString(tokenAddress),\n tokenDecimals,\n maxSwap,\n minSwap,\n swapFee,\n maxSwapFee,\n minSwapFee,\n hasUnderlying,\n isUnderlying\n );\n }\n\n /**\n * @notice Main write function of this contract - Handles creating the struct and passing it to the internal logic function\n * @param tokenID string ID to set the token config object form\n * @param chainID chain ID to use for the token config object\n * @param tokenAddress token address of the token on the given chain\n * @param tokenDecimals decimals of token\n * @param maxSwap maximum amount of token allowed to be transferred at once - in native token decimals\n * @param minSwap minimum amount of token needed to be transferred at once - in native token decimals\n * @param swapFee percent based swap fee -- 10e6 == 10bps\n * @param maxSwapFee max swap fee to be charged - in native token decimals\n * @param minSwapFee min swap fee to be charged - in native token decimals - especially useful for mainnet ETH\n * @param hasUnderlying bool which represents whether this is a global mint token or one to withdraw()\n * @param isUnderlying bool which represents if this token is the one to withdraw on the given chain\n */\n function setTokenConfig(\n string calldata tokenID,\n uint256 chainID,\n string memory tokenAddress,\n uint8 tokenDecimals,\n uint256 maxSwap,\n uint256 minSwap,\n uint256 swapFee,\n uint256 maxSwapFee,\n uint256 minSwapFee,\n bool hasUnderlying,\n bool isUnderlying\n ) public returns (bool) {\n require(hasRole(BRIDGEMANAGER_ROLE, msg.sender));\n Token memory tokenToAdd;\n tokenToAdd.tokenAddress = _toLower(tokenAddress);\n tokenToAdd.tokenDecimals = tokenDecimals;\n tokenToAdd.maxSwap = maxSwap;\n tokenToAdd.minSwap = minSwap;\n tokenToAdd.swapFee = swapFee;\n tokenToAdd.maxSwapFee = maxSwapFee;\n tokenToAdd.minSwapFee = minSwapFee;\n tokenToAdd.hasUnderlying = hasUnderlying;\n tokenToAdd.isUnderlying = isUnderlying;\n tokenToAdd.chainId = chainID;\n\n return _setTokenConfig(toBytes32(tokenID), chainID, tokenToAdd);\n }\n\n function _calculateSwapFee(\n string memory tokenAddress,\n uint256 chainID,\n uint256 amount\n ) internal view returns (uint256) {\n Token memory token = _tokens[_tokenIDMap[chainID][tokenAddress]][\n chainID\n ];\n uint256 calculatedSwapFee = amount.mul(token.swapFee).div(\n FEE_DENOMINATOR\n );\n if (\n calculatedSwapFee > token.minSwapFee &&\n calculatedSwapFee < token.maxSwapFee\n ) {\n return calculatedSwapFee;\n } else if (calculatedSwapFee > token.maxSwapFee) {\n return token.maxSwapFee;\n } else {\n return token.minSwapFee;\n }\n }\n\n /**\n * @notice Calculates bridge swap fee based on the destination chain's token transfer.\n * @dev This means the fee should be calculated based on the chain that the nodes emit a tx on\n * @param tokenAddress address of the destination token to query token config for\n * @param chainID destination chain ID to query the token config for\n * @param amount in native token decimals\n * @return Fee calculated in token decimals\n */\n function calculateSwapFee(\n string memory tokenAddress,\n uint256 chainID,\n uint256 amount\n ) external view returns (uint256) {\n return _calculateSwapFee(_toLower(tokenAddress), chainID, amount);\n }\n\n /**\n * @notice Calculates bridge swap fee based on the destination chain's token transfer.\n * @dev This means the fee should be calculated based on the chain that the nodes emit a tx on\n * @param tokenAddress address of the destination token to query token config for\n * @param chainID destination chain ID to query the token config for\n * @param amount in native token decimals\n * @return Fee calculated in token decimals\n */\n function calculateSwapFee(\n address tokenAddress,\n uint256 chainID,\n uint256 amount\n ) external view returns (uint256) {\n return\n _calculateSwapFee(\n _toLower(toString(tokenAddress)),\n chainID,\n amount\n );\n }\n\n // GAS PRICING\n\n /**\n * @notice sets the max gas price for a chain\n */\n function setMaxGasPrice(uint256 chainID, uint256 maxPrice) public {\n require(hasRole(BRIDGEMANAGER_ROLE, msg.sender));\n _maxGasPrice[chainID] = maxPrice;\n }\n\n /**\n * @notice gets the max gas price for a chain\n */\n function getMaxGasPrice(uint256 chainID) public view returns (uint256) {\n return _maxGasPrice[chainID];\n }\n\n // POOL CONFIG\n\n function getPoolConfig(address tokenAddress, uint256 chainID)\n external\n view\n returns (Pool memory)\n {\n return _pool[tokenAddress][chainID];\n }\n\n function setPoolConfig(\n address tokenAddress,\n uint256 chainID,\n address poolAddress,\n bool metaswap\n ) external returns (Pool memory) {\n require(\n hasRole(BRIDGEMANAGER_ROLE, msg.sender),\n \"Caller is not Bridge Manager\"\n );\n Pool memory newPool = Pool(\n tokenAddress,\n chainID,\n poolAddress,\n metaswap\n );\n _pool[tokenAddress][chainID] = newPool;\n return newPool;\n }\n\n // UTILITY FUNCTIONS\n\n function toString(bytes32 data) internal pure returns (string memory) {\n uint8 i = 0;\n while (i < 32 && data[i] != 0) {\n ++i;\n }\n bytes memory bs = new bytes(i);\n for (uint8 j = 0; j < i; ++j) {\n bs[j] = data[j];\n }\n return string(bs);\n }\n\n // toBytes32 converts a string to a bytes 32\n function toBytes32(string memory str)\n internal\n pure\n returns (bytes32 result)\n {\n require(bytes(str).length <= 32);\n assembly {\n result := mload(add(str, 32))\n }\n }\n\n function toString(address x) internal pure returns (string memory) {\n bytes memory s = new bytes(40);\n for (uint256 i = 0; i < 20; i++) {\n bytes1 b = bytes1(uint8(uint256(uint160(x)) / (2**(8 * (19 - i)))));\n bytes1 hi = bytes1(uint8(b) / 16);\n bytes1 lo = bytes1(uint8(b) - 16 * uint8(hi));\n s[2 * i] = char(hi);\n s[2 * i + 1] = char(lo);\n }\n\n string memory addrPrefix = \"0x\";\n\n return concat(addrPrefix, string(s));\n }\n\n function concat(string memory _x, string memory _y)\n internal\n pure\n returns (string memory)\n {\n bytes memory _xBytes = bytes(_x);\n bytes memory _yBytes = bytes(_y);\n\n string memory _tmpValue = new string(_xBytes.length + _yBytes.length);\n bytes memory _newValue = bytes(_tmpValue);\n\n uint256 i;\n uint256 j;\n\n for (i = 0; i < _xBytes.length; i++) {\n _newValue[j++] = _xBytes[i];\n }\n\n for (i = 0; i < _yBytes.length; i++) {\n _newValue[j++] = _yBytes[i];\n }\n\n return string(_newValue);\n }\n\n function char(bytes1 b) internal pure returns (bytes1 c) {\n if (uint8(b) < 10) {\n c = bytes1(uint8(b) + 0x30);\n } else {\n c = bytes1(uint8(b) + 0x57);\n }\n }\n\n function compareStrings(string memory a, string memory b)\n internal\n pure\n returns (bool)\n {\n return (keccak256(abi.encodePacked((a))) ==\n keccak256(abi.encodePacked((b))));\n }\n\n function _toLower(string memory str) internal pure returns (string memory) {\n bytes memory bStr = bytes(str);\n bytes memory bLower = new bytes(bStr.length);\n for (uint256 i = 0; i < bStr.length; i++) {\n // Uppercase character...\n if ((uint8(bStr[i]) >= 65) && (uint8(bStr[i]) <= 90)) {\n // So we add 32 to make it lowercase\n bLower[i] = bytes1(uint8(bStr[i]) + 32);\n } else {\n bLower[i] = bStr[i];\n }\n }\n return string(bLower);\n }\n}\n" + }, + "contracts/bridge/wrappers/GMXWrapper.sol": { + "content": "// SPDX-License-Identifier: MIT\n\nimport '@openzeppelin/contracts/math/SafeMath.sol';\n\npragma solidity 0.6.12;\n\ninterface IGMX {\n function burn(address _account, uint256 _amount) external;\n function balanceOf(address account) external view returns (uint256);\n function mint(address _account, uint256 _amount) external;\n}\n\ncontract GMXWrapper {\n using SafeMath for uint256;\n\n address constant public gmx = 0x62edc0692BD897D2295872a9FFCac5425011c661;\n address constant public bridge = 0xC05e61d0E7a63D27546389B7aD62FdFf5A91aACE;\n\n function transfer(address _recipient, uint256 _amount) external returns (bool) {\n require(msg.sender == bridge);\n _transfer(msg.sender, _recipient, _amount);\n return true;\n }\n\n function _transfer(address _sender, address _recipient, uint256 _amount) private {\n require(_sender != address(0), \"BaseToken: transfer from the zero address\");\n require(_recipient != address(0), \"BaseToken: transfer to the zero address\");\n IGMX(gmx).burn(_sender, _amount);\n IGMX(gmx).mint(_recipient, _amount);\n }\n\n function mint(address _addr, uint256 _amount) external {\n require(msg.sender == bridge);\n uint256 preMint = IGMX(gmx).balanceOf(_addr);\n IGMX(gmx).mint(_addr, _amount);\n uint256 postMint = IGMX(gmx).balanceOf(_addr);\n require(preMint.add(_amount) == postMint, \"Mint incomplete\");\n }\n\n function burnFrom(address _addr, uint256 _amount) external {\n require(msg.sender == bridge);\n uint256 preBurn = IGMX(gmx).balanceOf(_addr);\n IGMX(gmx).burn(_addr, _amount);\n uint256 postBurn = IGMX(gmx).balanceOf(_addr);\n require(postBurn.add(_amount) == preBurn, \"Burn incomplete\");\n }\n}" + }, + "contracts/amm/SwapEthWrapper.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.6.12;\n\nimport \"@openzeppelin/contracts/math/SafeMath.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/SafeERC20.sol\";\nimport \"./Swap.sol\";\nimport \"./interfaces/IWETH9.sol\";\n\n/**\n * @title SwapEthWrapper\n * @notice A wrapper contract for Swap contracts that have WETH as one of the pooled tokens.\n * @author Jongseung Lim (@weeb_mcgee)\n */\ncontract SwapEthWrapper {\n using SafeERC20 for IERC20;\n using SafeMath for uint256;\n\n // constants\n uint8 private constant MAX_UINT8 = 2**8 - 1;\n uint256 private constant MAX_UINT256 = 2**256 - 1;\n\n // immutables\n Swap public immutable SWAP;\n LPToken public immutable LP_TOKEN;\n address payable public immutable WETH_ADDRESS;\n address public immutable OWNER;\n uint8 public immutable WETH_INDEX;\n\n IERC20[] public pooledTokens;\n\n /**\n * @notice Deploys this contract with given WETH9 address and Swap address. It will attempt to\n * fetch information about the given Swap pool. If the Swap pool does not contain WETH9,\n * this call will be reverted. Owner address must be given so that `rescue()` function\n * can be limited.\n * @param wethAddress address to the WETH9 contract\n * @param swap address to the Swap contract that has WETH9 as one of the tokens\n * @param owner address that will be allowed to call `rescue()`\n */\n constructor(\n address payable wethAddress,\n Swap swap,\n address owner\n ) public {\n (, , , , , , LPToken lpToken) = swap.swapStorage();\n uint8 wethIndex = MAX_UINT8;\n\n for (uint8 i = 0; i < MAX_UINT8; i++) {\n try swap.getToken(i) returns (IERC20 token) {\n pooledTokens.push(token);\n if (address(token) == wethAddress) {\n wethIndex = i;\n }\n // Approve pooled tokens to be used by Swap\n token.approve(address(swap), MAX_UINT256);\n } catch {\n break;\n }\n }\n require(wethIndex != MAX_UINT8, \"WETH was not found in the swap pool\");\n\n // Set immutable variables\n WETH_INDEX = wethIndex;\n WETH_ADDRESS = wethAddress;\n SWAP = swap;\n LP_TOKEN = lpToken;\n OWNER = owner;\n\n // Approve LPToken to be used by Swap\n lpToken.approve(address(swap), MAX_UINT256);\n }\n\n /**\n * @notice Add liquidity to the pool with the given amounts of tokens.\n * @dev The msg.value of this call should match the value in amounts array\n * in position of WETH9.\n * @param amounts the amounts of each token to add, in their native precision\n * @param minToMint the minimum LP tokens adding this amount of liquidity\n * should mint, otherwise revert. Handy for front-running mitigation\n * @param deadline latest timestamp to accept this transaction\n * @return amount of LP token user minted and received\n */\n function addLiquidity(\n uint256[] memory amounts,\n uint256 minToMint,\n uint256 deadline\n ) external payable returns (uint256) {\n // If using ETH, deposit them to WETH.\n require(msg.value == amounts[WETH_INDEX], \"INCORRECT_MSG_VALUE\");\n if (msg.value > 0) {\n IWETH9(WETH_ADDRESS).deposit{value: msg.value}();\n }\n // Go through amounts array and transfer respective tokens to this contract.\n for (uint256 i = 0; i < amounts.length; i++) {\n uint256 amount = amounts[i];\n if (i != WETH_INDEX && amount > 0) {\n pooledTokens[i].safeTransferFrom(\n msg.sender,\n address(this),\n amount\n );\n }\n }\n // Add the assets to the pool\n uint256 lpTokenAmount = SWAP.addLiquidity(amounts, minToMint, deadline);\n // Send the LPToken to msg.sender\n IERC20(address(LP_TOKEN)).safeTransfer(msg.sender, lpTokenAmount);\n return lpTokenAmount;\n }\n\n /**\n * @notice Burn LP tokens to remove liquidity from the pool.\n * @dev Liquidity can always be removed, even when the pool is paused. Caller\n * will receive ETH instead of WETH9.\n * @param amount the amount of LP tokens to burn\n * @param minAmounts the minimum amounts of each token in the pool\n * acceptable for this burn. Useful as a front-running mitigation\n * @param deadline latest timestamp to accept this transaction\n * @return amounts of tokens user received\n */\n function removeLiquidity(\n uint256 amount,\n uint256[] calldata minAmounts,\n uint256 deadline\n ) external returns (uint256[] memory) {\n // Transfer LPToken from msg.sender to this contract.\n IERC20(address(LP_TOKEN)).safeTransferFrom(\n msg.sender,\n address(this),\n amount\n );\n // Remove liquidity\n uint256[] memory amounts = SWAP.removeLiquidity(\n amount,\n minAmounts,\n deadline\n );\n // Send the tokens back to the user\n for (uint256 i = 0; i < amounts.length; i++) {\n if (i != WETH_INDEX) {\n pooledTokens[i].safeTransfer(msg.sender, amounts[i]);\n } else {\n IWETH9(WETH_ADDRESS).withdraw(amounts[i]);\n // slither-disable-next-line arbitrary-send\n (bool success, ) = msg.sender.call{value: amounts[i]}(\"\");\n require(success, \"ETH_TRANSFER_FAILED\");\n }\n }\n return amounts;\n }\n\n /**\n * @notice Remove liquidity from the pool all in one token.\n * @dev Caller will receive ETH instead of WETH9.\n * @param tokenAmount the amount of the token you want to receive\n * @param tokenIndex the index of the token you want to receive\n * @param minAmount the minimum amount to withdraw, otherwise revert\n * @param deadline latest timestamp to accept this transaction\n * @return amount of chosen token user received\n */\n function removeLiquidityOneToken(\n uint256 tokenAmount,\n uint8 tokenIndex,\n uint256 minAmount,\n uint256 deadline\n ) external returns (uint256) {\n // Transfer LPToken from msg.sender to this contract.\n IERC20(address(LP_TOKEN)).safeTransferFrom(\n msg.sender,\n address(this),\n tokenAmount\n );\n // Withdraw via single token\n uint256 amount = SWAP.removeLiquidityOneToken(\n tokenAmount,\n tokenIndex,\n minAmount,\n deadline\n );\n // Transfer the token to msg.sender accordingly\n if (tokenIndex != WETH_INDEX) {\n pooledTokens[tokenIndex].safeTransfer(msg.sender, amount);\n } else {\n IWETH9(WETH_ADDRESS).withdraw(amount);\n // slither-disable-next-line arbitrary-send\n (bool success, ) = msg.sender.call{value: amount}(\"\");\n require(success, \"ETH_TRANSFER_FAILED\");\n }\n return amount;\n }\n\n /**\n * @notice Remove liquidity from the pool, weighted differently than the\n * pool's current balances.\n * @dev Caller will receive ETH instead of WETH9.\n * @param amounts how much of each token to withdraw\n * @param maxBurnAmount the max LP token provider is willing to pay to\n * remove liquidity. Useful as a front-running mitigation.\n * @param deadline latest timestamp to accept this transaction\n * @return amount of LP tokens burned\n */\n function removeLiquidityImbalance(\n uint256[] calldata amounts,\n uint256 maxBurnAmount,\n uint256 deadline\n ) external returns (uint256) {\n // Transfer LPToken from msg.sender to this contract.\n IERC20(address(LP_TOKEN)).safeTransferFrom(\n msg.sender,\n address(this),\n maxBurnAmount\n );\n // Withdraw in imbalanced ratio\n uint256 burnedLpTokenAmount = SWAP.removeLiquidityImbalance(\n amounts,\n maxBurnAmount,\n deadline\n );\n // Send the tokens back to the user\n for (uint256 i = 0; i < amounts.length; i++) {\n if (i != WETH_INDEX) {\n pooledTokens[i].safeTransfer(msg.sender, amounts[i]);\n } else {\n IWETH9(WETH_ADDRESS).withdraw(amounts[i]);\n // slither-disable-next-line arbitrary-send\n (bool success, ) = msg.sender.call{value: amounts[i]}(\"\");\n require(success, \"ETH_TRANSFER_FAILED\");\n }\n }\n // Send any extra LP tokens back as well\n uint256 extraLpTokenAmount = maxBurnAmount.sub(burnedLpTokenAmount);\n if (extraLpTokenAmount > 0) {\n IERC20(address(LP_TOKEN)).safeTransfer(\n msg.sender,\n extraLpTokenAmount\n );\n }\n return burnedLpTokenAmount;\n }\n\n /**\n * @notice Swap two tokens using the underlying pool. If tokenIndexFrom\n * represents WETH9 in the pool, the caller must set msg.value equal to dx.\n * If the user is swapping to WETH9 in the pool, the user will receive ETH instead.\n * @param tokenIndexFrom the token the user wants to swap from\n * @param tokenIndexTo the token the user wants to swap to\n * @param dx the amount of tokens the user wants to swap from\n * @param minDy the min amount the user would like to receive, or revert.\n * @param deadline latest timestamp to accept this transaction\n */\n function swap(\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx,\n uint256 minDy,\n uint256 deadline\n ) external payable returns (uint256) {\n // Transfer tokens from msg.sender to this contract\n if (tokenIndexFrom != WETH_INDEX) {\n IERC20(pooledTokens[tokenIndexFrom]).safeTransferFrom(\n msg.sender,\n address(this),\n dx\n );\n } else {\n require(msg.value == dx, \"INCORRECT_MSG_VALUE\");\n IWETH9(WETH_ADDRESS).deposit{value: msg.value}();\n }\n // Execute swap\n uint256 dy = SWAP.swap(\n tokenIndexFrom,\n tokenIndexTo,\n dx,\n minDy,\n deadline\n );\n // Transfer the swapped tokens to msg.sender\n if (tokenIndexTo != WETH_INDEX) {\n IERC20(pooledTokens[tokenIndexTo]).safeTransfer(msg.sender, dy);\n } else {\n IWETH9(WETH_ADDRESS).withdraw(dy);\n // slither-disable-next-line arbitrary-send\n (bool success, ) = msg.sender.call{value: dy}(\"\");\n require(success, \"ETH_TRANSFER_FAILED\");\n }\n return dy;\n }\n\n /**\n * @notice Rescues any of the ETH, the pooled tokens, or the LPToken that may be stuck\n * in this contract. Only the OWNER can call this function.\n */\n function rescue() external {\n require(msg.sender == OWNER, \"CALLED_BY_NON_OWNER\");\n IERC20[] memory tokens = pooledTokens;\n for (uint256 i = 0; i < tokens.length; i++) {\n tokens[i].safeTransfer(\n msg.sender,\n tokens[i].balanceOf(address(this))\n );\n }\n IERC20 lpToken_ = IERC20(address(LP_TOKEN));\n lpToken_.safeTransfer(msg.sender, lpToken_.balanceOf(address(this)));\n // slither-disable-next-line arbitrary-send\n (bool success, ) = msg.sender.call{value: address(this).balance}(\"\");\n require(success, \"ETH_TRANSFER_FAILED\");\n }\n\n receive() external payable {}\n\n // VIEW FUNCTIONS\n\n /**\n * @notice A simple method to calculate prices from deposits or\n * withdrawals, excluding fees but including slippage. This is\n * helpful as an input into the various \"min\" parameters on calls\n * to fight front-running\n *\n * @dev This shouldn't be used outside frontends for user estimates.\n *\n * @param amounts an array of token amounts to deposit or withdrawal,\n * corresponding to pooledTokens. The amount should be in each\n * pooled token's native precision. If a token charges a fee on transfers,\n * use the amount that gets transferred after the fee.\n * @param deposit whether this is a deposit or a withdrawal\n * @return token amount the user will receive\n */\n function calculateTokenAmount(uint256[] calldata amounts, bool deposit)\n external\n view\n returns (uint256)\n {\n return SWAP.calculateTokenAmount(amounts, deposit);\n }\n\n /**\n * @notice A simple method to calculate amount of each underlying\n * tokens that is returned upon burning given amount of LP tokens\n * @param amount the amount of LP tokens that would be burned on withdrawal\n * @return array of token balances that the user will receive\n */\n function calculateRemoveLiquidity(uint256 amount)\n external\n view\n returns (uint256[] memory)\n {\n return SWAP.calculateRemoveLiquidity(amount);\n }\n\n /**\n * @notice Calculate the amount of underlying token available to withdraw\n * when withdrawing via only single token\n * @param tokenAmount the amount of LP token to burn\n * @param tokenIndex index of which token will be withdrawn\n * @return availableTokenAmount calculated amount of underlying token\n * available to withdraw\n */\n function calculateRemoveLiquidityOneToken(\n uint256 tokenAmount,\n uint8 tokenIndex\n ) external view returns (uint256 availableTokenAmount) {\n return SWAP.calculateRemoveLiquidityOneToken(tokenAmount, tokenIndex);\n }\n}\n" + }, + "contracts/amm/interfaces/IWETH9.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.4.0;\n\ninterface IWETH9 {\n function name() external view returns (string memory);\n\n function symbol() external view returns (string memory);\n\n function decimals() external view returns (uint8);\n\n function balanceOf(address) external view returns (uint256);\n\n function allowance(address, address) external view returns (uint256);\n\n receive() external payable;\n\n function deposit() external payable;\n\n function withdraw(uint256 wad) external;\n\n function totalSupply() external view returns (uint256);\n\n function approve(address guy, uint256 wad) external returns (bool);\n\n function transfer(address dst, uint256 wad) external returns (bool);\n\n function transferFrom(\n address src,\n address dst,\n uint256 wad\n ) external returns (bool);\n}\n" + }, + "contracts/amm/helper/BaseSwapDeposit.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.6.12;\n\nimport \"@openzeppelin/contracts/math/SafeMath.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/SafeERC20.sol\";\nimport \"../interfaces/ISwap.sol\";\nimport \"@openzeppelin/contracts/utils/ReentrancyGuard.sol\";\n\ncontract BaseSwapDeposit is ReentrancyGuard {\n using SafeERC20 for IERC20;\n using SafeMath for uint256;\n\n ISwap public baseSwap;\n IERC20[] public baseTokens;\n\n uint256 constant MAX_UINT256 = 2**256 - 1;\n\n constructor(ISwap _baseSwap) public {\n baseSwap = _baseSwap;\n // Check and approve base level tokens to be deposited to the base Swap contract\n {\n uint8 i;\n for (; i < 32; i++) {\n try _baseSwap.getToken(i) returns (IERC20 token) {\n baseTokens.push(token);\n token.safeApprove(address(_baseSwap), MAX_UINT256);\n } catch {\n break;\n }\n }\n require(i > 1, \"baseSwap must have at least 2 tokens\");\n }\n }\n\n // Mutative functions\n\n /**\n * @notice Swap two underlying tokens using the meta pool and the base pool\n * @param tokenIndexFrom the token the user wants to swap from\n * @param tokenIndexTo the token the user wants to swap to\n * @param dx the amount of tokens the user wants to swap from\n * @param minDy the min amount the user would like to receive, or revert.\n * @param deadline latest timestamp to accept this transaction\n */\n function swap(\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx,\n uint256 minDy,\n uint256 deadline\n ) external nonReentrant returns (uint256) {\n baseTokens[tokenIndexFrom].safeTransferFrom(msg.sender, address(this), dx);\n uint256 tokenToAmount =\n baseSwap.swap(\n tokenIndexFrom,\n tokenIndexTo,\n dx,\n minDy,\n deadline\n );\n baseTokens[tokenIndexTo].safeTransfer(msg.sender, tokenToAmount);\n return tokenToAmount;\n }\n\n /**\n * @notice Calculate amount of tokens you receive on swap\n * @param tokenIndexFrom the token the user wants to sell\n * @param tokenIndexTo the token the user wants to buy\n * @param dx the amount of tokens the user wants to sell. If the token charges\n * a fee on transfers, use the amount that gets transferred after the fee.\n * @return amount of tokens the user will receive\n */\n function calculateSwap(\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx\n ) external view returns (uint256) {\n return\n baseSwap.calculateSwap(tokenIndexFrom, tokenIndexTo, dx);\n }\n\n /**\n * @notice Returns the address of the pooled token at given index. Reverts if tokenIndex is out of range.\n * @param index the index of the token\n * @return address of the token at given index\n */\n function getToken(uint256 index) external view returns (IERC20) {\n require(index < baseTokens.length, \"index out of range\");\n return baseTokens[index];\n }\n\n}" + }, + "@openzeppelin/contracts/utils/ReentrancyGuard.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <0.8.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 () internal {\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" + }, + "contracts/amm/AaveSwapWrapper.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.6.12;\n\nimport \"@openzeppelin/contracts/math/SafeMath.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/SafeERC20.sol\";\nimport \"./Swap.sol\";\n\ninterface ILendingPool {\n /**\n * @dev Deposits an `amount` of underlying asset into the reserve, receiving in return overlying aTokens.\n * - E.g. User deposits 100 USDC and gets in return 100 aUSDC\n * @param asset The address of the underlying asset to deposit\n * @param amount The amount to be deposited\n * @param onBehalfOf The address that will receive the aTokens, same as msg.sender if the user\n * wants to receive them on his own wallet, or a different address if the beneficiary of aTokens\n * is a different wallet\n * @param referralCode Code used to register the integrator originating the operation, for potential rewards.\n * 0 if the action is executed directly by the user, without any middle-man\n **/\n function deposit(\n address asset,\n uint256 amount,\n address onBehalfOf,\n uint16 referralCode\n ) external;\n\n /**\n * @dev Withdraws an `amount` of underlying asset from the reserve, burning the equivalent aTokens owned\n * E.g. User has 100 aUSDC, calls withdraw() and receives 100 USDC, burning the 100 aUSDC\n * @param asset The address of the underlying asset to withdraw\n * @param amount The underlying amount to be withdrawn\n * - Send the value type(uint256).max in order to withdraw the whole aToken balance\n * @param to Address that will receive the underlying, same as msg.sender if the user\n * wants to receive it on his own wallet, or a different address if the beneficiary is a\n * different wallet\n * @return The final amount withdrawn\n **/\n function withdraw(\n address asset,\n uint256 amount,\n address to\n ) external returns (uint256);\n}\n\n/**\n * @title AaveSwapWrapper\n * @notice A wrapper contract for interacting with aTokens\n */\ncontract AaveSwapWrapper {\n using SafeERC20 for IERC20;\n using SafeMath for uint256;\n mapping(uint8 => bool) private isUnderlyingIndex;\n\n // constants\n uint8 private constant MAX_UINT8 = 2**8 - 1;\n uint256 private constant MAX_UINT256 = 2**256 - 1;\n\n // immutables\n Swap public immutable SWAP;\n LPToken public immutable LP_TOKEN;\n address public immutable OWNER;\n IERC20[] public POOLED_TOKENS;\n IERC20[] public UNDERLYING_TOKENS;\n ILendingPool public LENDING_POOL;\n\n constructor(\n Swap swap,\n IERC20[] memory underlyingTokens,\n address lendingPool,\n address owner\n ) public {\n (, , , , , , LPToken lpToken) = swap.swapStorage();\n for (uint8 i = 0; i < MAX_UINT8; i++) {\n try swap.getToken(i) returns (IERC20 token) {\n POOLED_TOKENS.push(token);\n // Approve pooled tokens to be used by Swap\n token.approve(address(swap), MAX_UINT256);\n } catch {\n break;\n }\n }\n\n for (uint8 i = 0; i < POOLED_TOKENS.length; i++) {\n if (POOLED_TOKENS[i] == underlyingTokens[i]) {\n isUnderlyingIndex[i] = true;\n } else {\n isUnderlyingIndex[i] = false;\n underlyingTokens[i].approve(lendingPool, MAX_UINT256);\n }\n }\n\n // Set immutable variables\n SWAP = swap;\n LP_TOKEN = lpToken;\n OWNER = owner;\n UNDERLYING_TOKENS = underlyingTokens;\n LENDING_POOL = ILendingPool(lendingPool);\n\n // Approve LPToken to be used by Swap\n lpToken.approve(address(swap), MAX_UINT256);\n }\n\n /**\n * @notice Add liquidity to the pool with the given amounts of tokens.\n * @param amounts the amounts of each token to add, in their native precision\n * @param minToMint the minimum LP tokens adding this amount of liquidity\n * should mint, otherwise revert. Handy for front-running mitigation\n * @param deadline latest timestamp to accept this transaction\n * @return amount of LP token user minted and received\n */\n function addLiquidity(\n uint256[] memory amounts,\n uint256 minToMint,\n uint256 deadline\n ) external returns (uint256) {\n // Go through amounts array and transfer respective tokens to this contract.\n for (uint8 i = 0; i < amounts.length; i++) {\n uint256 amount = amounts[i];\n if (amount > 0) {\n UNDERLYING_TOKENS[i].safeTransferFrom(\n msg.sender,\n address(this),\n amount\n );\n if (isUnderlyingIndex[i] == false) {\n LENDING_POOL.deposit(\n address(UNDERLYING_TOKENS[i]),\n amount,\n address(this),\n 0\n );\n }\n }\n }\n\n // Add the assets to the pool\n uint256 lpTokenAmount = SWAP.addLiquidity(amounts, minToMint, deadline);\n // Send the LPToken to msg.sender\n IERC20(address(LP_TOKEN)).safeTransfer(msg.sender, lpTokenAmount);\n return lpTokenAmount;\n }\n\n /**\n * @notice Burn LP tokens to remove liquidity from the pool.\n * @dev Liquidity can always be removed, even when the pool is paused. Caller\n * will receive ETH instead of WETH9.\n * @param amount the amount of LP tokens to burn\n * @param minAmounts the minimum amounts of each token in the pool\n * acceptable for this burn. Useful as a front-running mitigation\n * @param deadline latest timestamp to accept this transaction\n * @return amounts of tokens user received\n */\n function removeLiquidity(\n uint256 amount,\n uint256[] calldata minAmounts,\n uint256 deadline\n ) external returns (uint256[] memory) {\n // Transfer LPToken from msg.sender to this contract.\n IERC20(address(LP_TOKEN)).safeTransferFrom(\n msg.sender,\n address(this),\n amount\n );\n // Remove liquidity\n uint256[] memory amounts = SWAP.removeLiquidity(\n amount,\n minAmounts,\n deadline\n );\n // Send the tokens back to the user\n for (uint8 i = 0; i < amounts.length; i++) {\n if (isUnderlyingIndex[i] == true) {\n UNDERLYING_TOKENS[i].safeTransfer(msg.sender, amounts[i]);\n } else {\n LENDING_POOL.withdraw(\n address(UNDERLYING_TOKENS[i]),\n amounts[i],\n msg.sender\n );\n // underlyingTokens[i].safeTransfer(msg.sender, amounts[i]);\n }\n }\n return amounts;\n }\n\n /**\n * @notice Remove liquidity from the pool all in one token.\n * @dev Caller will receive ETH instead of WETH9.\n * @param tokenAmount the amount of the token you want to receive\n * @param tokenIndex the index of the token you want to receive\n * @param minAmount the minimum amount to withdraw, otherwise revert\n * @param deadline latest timestamp to accept this transaction\n * @return amount of chosen token user received\n */\n function removeLiquidityOneToken(\n uint256 tokenAmount,\n uint8 tokenIndex,\n uint256 minAmount,\n uint256 deadline\n ) external returns (uint256) {\n // Transfer LPToken from msg.sender to this contract.\n IERC20(address(LP_TOKEN)).safeTransferFrom(\n msg.sender,\n address(this),\n tokenAmount\n );\n // Withdraw via single token\n uint256 amount = SWAP.removeLiquidityOneToken(\n tokenAmount,\n tokenIndex,\n minAmount,\n deadline\n );\n // Transfer the token to msg.sender accordingly\n if (isUnderlyingIndex[tokenIndex] == true) {\n UNDERLYING_TOKENS[tokenIndex].safeTransfer(msg.sender, amount);\n } else {\n LENDING_POOL.withdraw(\n address(UNDERLYING_TOKENS[tokenIndex]),\n amount,\n msg.sender\n );\n }\n return amount;\n }\n\n /**\n * @notice Swap two tokens using the underlying pool. If tokenIndexFrom\n * represents WETH9 in the pool, the caller must set msg.value equal to dx.\n * If the user is swapping to WETH9 in the pool, the user will receive ETH instead.\n * @param tokenIndexFrom the token the user wants to swap from\n * @param tokenIndexTo the token the user wants to swap to\n * @param dx the amount of tokens the user wants to swap from\n * @param minDy the min amount the user would like to receive, or revert.\n * @param deadline latest timestamp to accept this transaction\n */\n function swap(\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx,\n uint256 minDy,\n uint256 deadline\n ) external returns (uint256) {\n // Transfer tokens from msg.sender to this contract\n UNDERLYING_TOKENS[tokenIndexFrom].safeTransferFrom(\n msg.sender,\n address(this),\n dx\n );\n if (isUnderlyingIndex[tokenIndexFrom] == false) {\n LENDING_POOL.deposit(\n address(UNDERLYING_TOKENS[tokenIndexFrom]),\n dx,\n address(this),\n 0\n );\n }\n // Execute swap\n uint256 dy = SWAP.swap(\n tokenIndexFrom,\n tokenIndexTo,\n dx,\n minDy,\n deadline\n );\n // Transfer the swapped tokens to msg.sender\n if (isUnderlyingIndex[tokenIndexTo] == false) {\n LENDING_POOL.withdraw(\n address(UNDERLYING_TOKENS[tokenIndexTo]),\n dy,\n msg.sender\n );\n } else {\n UNDERLYING_TOKENS[tokenIndexTo].safeTransfer(msg.sender, dy);\n }\n return dy;\n }\n\n /**\n * @notice Rescues any of the ETH, the pooled tokens, or the LPToken that may be stuck\n * in this contract. Only the OWNER can call this function.\n */\n function rescue() external {\n require(msg.sender == OWNER, \"CALLED_BY_NON_OWNER\");\n IERC20[] memory tokens = POOLED_TOKENS;\n for (uint256 i = 0; i < tokens.length; i++) {\n tokens[i].safeTransfer(\n msg.sender,\n tokens[i].balanceOf(address(this))\n );\n }\n\n for (uint256 i = 0; i < UNDERLYING_TOKENS.length; i++) {\n UNDERLYING_TOKENS[i].safeTransfer(\n msg.sender,\n UNDERLYING_TOKENS[i].balanceOf(address(this))\n );\n }\n\n IERC20 lpToken_ = IERC20(address(LP_TOKEN));\n lpToken_.safeTransfer(msg.sender, lpToken_.balanceOf(address(this)));\n }\n\n // VIEW FUNCTIONS\n\n /**\n * @notice Calculate amount of tokens you receive on swap\n * @param tokenIndexFrom the token the user wants to sell\n * @param tokenIndexTo the token the user wants to buy\n * @param dx the amount of tokens the user wants to sell. If the token charges\n * a fee on transfers, use the amount that gets transferred after the fee.\n * @return amount of tokens the user will receive\n */\n function calculateSwap(\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx\n ) external view virtual returns (uint256) {\n return SWAP.calculateSwap(tokenIndexFrom, tokenIndexTo, dx);\n }\n\n /**\n * @notice A simple method to calculate prices from deposits or\n * withdrawals, excluding fees but including slippage. This is\n * helpful as an input into the various \"min\" parameters on calls\n * to fight front-running\n *\n * @dev This shouldn't be used outside frontends for user estimates.\n *\n * @param amounts an array of token amounts to deposit or withdrawal,\n * corresponding to pooledTokens. The amount should be in each\n * pooled token's native precision. If a token charges a fee on transfers,\n * use the amount that gets transferred after the fee.\n * @param deposit whether this is a deposit or a withdrawal\n * @return token amount the user will receive\n */\n function calculateTokenAmount(uint256[] calldata amounts, bool deposit)\n external\n view\n returns (uint256)\n {\n return SWAP.calculateTokenAmount(amounts, deposit);\n }\n\n /**\n * @notice A simple method to calculate amount of each underlying\n * tokens that is returned upon burning given amount of LP tokens\n * @param amount the amount of LP tokens that would be burned on withdrawal\n * @return array of token balances that the user will receive\n */\n function calculateRemoveLiquidity(uint256 amount)\n external\n view\n returns (uint256[] memory)\n {\n return SWAP.calculateRemoveLiquidity(amount);\n }\n\n /**\n * @notice Calculate the amount of underlying token available to withdraw\n * when withdrawing via only single token\n * @param tokenAmount the amount of LP token to burn\n * @param tokenIndex index of which token will be withdrawn\n * @return availableTokenAmount calculated amount of underlying token\n * available to withdraw\n */\n function calculateRemoveLiquidityOneToken(\n uint256 tokenAmount,\n uint8 tokenIndex\n ) external view returns (uint256 availableTokenAmount) {\n return SWAP.calculateRemoveLiquidityOneToken(tokenAmount, tokenIndex);\n }\n\n /**\n * @notice Return address of the pooled token at given index. Reverts if tokenIndex is out of range.\n * @param index the index of the token\n * @return address of the token at given index\n */\n function getToken(uint8 index) public view virtual returns (IERC20) {\n if (index < UNDERLYING_TOKENS.length) {\n return UNDERLYING_TOKENS[index];\n } else {\n revert();\n }\n }\n}\n" + }, + "contracts/bridge/ECDSAFactory.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.6.12;\n\nimport \"@openzeppelin/contracts/access/Ownable.sol\";\nimport \"@openzeppelin/contracts/proxy/Clones.sol\";\nimport \"./interfaces/IECDSANodeManagement.sol\";\n\ncontract ECDSAFactory is Ownable {\n event ECDSANodeGroupCreated(\n address indexed keepAddress,\n address[] members,\n address indexed owner,\n uint256 honestThreshold\n );\n\n struct LatestNodeGroup {\n address keepAddress;\n address[] members;\n address owner;\n uint256 honestThreshold;\n }\n\n LatestNodeGroup public latestNodeGroup;\n\n constructor() public Ownable() {}\n\n /// @notice Returns members of the keep.\n /// @return List of the keep members' addresses.\n function getMembers() public view returns (address[] memory) {\n return latestNodeGroup.members;\n }\n\n /**\n @notice Deploys a new node \n @param nodeMgmtAddress address of the ECDSANodeManagement contract to initialize with\n @param owner Owner of the ECDSANodeManagement contract who can determine if the node group is closed or active\n @param members Array of node group members addresses\n @param honestThreshold Number of signers to process a transaction \n @return Address of the newest node management contract created\n **/\n function deploy(\n address nodeMgmtAddress,\n address owner,\n address[] memory members,\n uint256 honestThreshold\n ) external onlyOwner returns (address) {\n address nodeClone = Clones.clone(nodeMgmtAddress);\n IECDSANodeManagement(nodeClone).initialize(\n owner,\n members,\n honestThreshold\n );\n\n latestNodeGroup.keepAddress = nodeClone;\n latestNodeGroup.members = members;\n latestNodeGroup.owner = owner;\n latestNodeGroup.honestThreshold = honestThreshold;\n\n emit ECDSANodeGroupCreated(nodeClone, members, owner, honestThreshold);\n return nodeClone;\n }\n}\n" + }, + "contracts/bridge/interfaces/IECDSANodeManagement.sol": { + "content": "// SPDX-License-Identifier: MIT\n\n\npragma solidity 0.6.12;\n\n/**\n * @title IECDSANodeManagement interface\n * @notice Interface for the ECDSA node management interface.\n * @dev implement this interface to develop a a factory-patterned ECDSA node management contract\n **/\ninterface IECDSANodeManagement { \n function initialize(\n address _owner,\n address[] memory _members,\n uint256 _honestThreshold) external;\n}\n\n" + }, + "contracts/auxiliary/DummyWeth.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.6.12;\nimport \"@openzeppelin/contracts/access/Ownable.sol\";\n\ninterface IWETH9 {\n function name() external view returns (string memory);\n\n function symbol() external view returns (string memory);\n\n function decimals() external view returns (uint8);\n\n function balanceOf(address) external view returns (uint256);\n\n function allowance(address, address) external view returns (uint256);\n\n receive() external payable;\n\n function deposit() external payable;\n\n function withdraw(uint256 wad) external;\n\n function totalSupply() external view returns (uint256);\n\n function approve(address guy, uint256 wad) external returns (bool);\n\n function transfer(address dst, uint256 wad) external returns (bool);\n\n function transferFrom(\n address src,\n address dst,\n uint256 wad\n ) external returns (bool);\n}\n\ncontract DummyWeth is Ownable {\n IWETH9 public WETH;\n\n function setWETHAddress(address payable _weth) external onlyOwner {\n WETH = IWETH9(_weth);\n }\n\n function withdrawToSelf(uint256 amount) external {\n WETH.withdraw(amount);\n }\n\n function rescue(uint256 amount) external onlyOwner {\n WETH.transfer(owner(), amount);\n }\n\n receive() external payable {}\n\n fallback() external payable {}\n}\n" + } + }, + "settings": { + "optimizer": { + "enabled": true, + "runs": 10000 + }, + "outputSelection": { + "*": { + "*": [ + "abi", + "evm.bytecode", + "evm.deployedBytecode", + "evm.methodIdentifiers", + "metadata", + "devdoc", + "userdoc", + "storageLayout", + "evm.gasEstimates", + "devdoc", + "userdoc" + ], + "": [ + "ast" + ] + } + }, + "metadata": { + "useLiteralContent": true + } + } +} \ No newline at end of file diff --git a/deployments/dfk/solcInputs/cefd51132bfcd0aab10340ca057c092d.json b/deployments/dfk/solcInputs/cefd51132bfcd0aab10340ca057c092d.json new file mode 100644 index 000000000..e998e3ea2 --- /dev/null +++ b/deployments/dfk/solcInputs/cefd51132bfcd0aab10340ca057c092d.json @@ -0,0 +1,295 @@ +{ + "language": "Solidity", + "sources": { + "contracts/amm/AaveSwap.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.6.12;\n\nimport \"./Swap.sol\";\n\n/**\n * @title AaveSwap - A StableSwap implementation in solidity, integrated with Aave.\n * @notice This contract is responsible for custody of closely pegged assets (eg. group of stablecoins)\n * and automatic market making system. Users become an LP (Liquidity Provider) by depositing their tokens\n * in desired ratios for an exchange of the pool token that represents their share of the pool.\n * Users can burn pool tokens and withdraw their share of token(s).\n *\n * Each time a swap between the pooled tokens happens, a set fee incurs which effectively gets\n * distributed to the LPs.\n *\n * In case of emergencies, admin can pause additional deposits, swaps, or single-asset withdraws - which\n * stops the ratio of the tokens in the pool from changing.\n * Users can always withdraw their tokens via multi-asset withdraws.\n *\n * @dev Most of the logic is stored as a library `SwapUtils` for the sake of reducing contract's\n * deployment size.\n */\n\ncontract AaveSwap is Swap {\n address internal AAVE_REWARDS;\n address internal AAVE_LENDING_POOL;\n address internal REWARD_TOKEN;\n address internal REWARD_RECEIVER;\n address[] internal AAVE_ASSETS;\n\n /**\n * @notice Initializes this Swap contract with the given parameters.\n * This will also clone a LPToken contract that represents users'\n * LP positions. The owner of LPToken will be this contract - which means\n * only this contract is allowed to mint/burn tokens.\n *\n * @param _pooledTokens an array of ERC20s this pool will accept\n * @param decimals the decimals to use for each pooled token,\n * eg 8 for WBTC. Cannot be larger than POOL_PRECISION_DECIMALS\n * @param lpTokenName the long-form name of the token to be deployed\n * @param lpTokenSymbol the short symbol for the token to be deployed\n * @param _a the amplification coefficient * n * (n - 1). See the\n * StableSwap paper for details\n * @param _fee default swap fee to be initialized with\n * @param _adminFee default adminFee to be initialized with\n * @param lpTokenTargetAddress the address of an existing LPToken contract to use as a target\n */\n function initialize(\n IERC20[] memory _pooledTokens,\n uint8[] memory decimals,\n string memory lpTokenName,\n string memory lpTokenSymbol,\n uint256 _a,\n uint256 _fee,\n uint256 _adminFee,\n address lpTokenTargetAddress\n ) public virtual override initializer {\n Swap.initialize(\n _pooledTokens,\n decimals,\n lpTokenName,\n lpTokenSymbol,\n _a,\n _fee,\n _adminFee,\n lpTokenTargetAddress\n );\n AAVE_REWARDS = 0x01D83Fe6A10D2f2B7AF17034343746188272cAc9;\n AAVE_LENDING_POOL = 0x4F01AeD16D97E3aB5ab2B501154DC9bb0F1A5A2C;\n REWARD_TOKEN = 0xB31f66AA3C1e785363F0875A1B74E27b85FD66c7;\n AAVE_ASSETS = [0x53f7c5869a859F0AeC3D334ee8B4Cf01E3492f21];\n REWARD_RECEIVER = msg.sender;\n }\n\n function setRewardReceiver(address _reward_receiver) external onlyOwner {\n REWARD_RECEIVER = _reward_receiver;\n }\n\n function claimAaveRewards() external {\n AAVE_REWARDS.call(\n abi.encodeWithSignature(\n \"claimRewards(address[],uint256,address)\",\n AAVE_ASSETS,\n type(uint256).max,\n REWARD_RECEIVER\n )\n );\n }\n}\n" + }, + "contracts/amm/Swap.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.6.12;\n\nimport \"@openzeppelin/contracts/math/SafeMath.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/SafeERC20.sol\";\nimport \"@openzeppelin/contracts/proxy/Clones.sol\";\nimport \"@openzeppelin/contracts-upgradeable/utils/ReentrancyGuardUpgradeable.sol\";\nimport \"./OwnerPausableUpgradeable.sol\";\nimport \"./SwapUtils.sol\";\nimport \"./AmplificationUtils.sol\";\n\n/**\n * @title Swap - A StableSwap implementation in solidity.\n * @notice This contract is responsible for custody of closely pegged assets (eg. group of stablecoins)\n * and automatic market making system. Users become an LP (Liquidity Provider) by depositing their tokens\n * in desired ratios for an exchange of the pool token that represents their share of the pool.\n * Users can burn pool tokens and withdraw their share of token(s).\n *\n * Each time a swap between the pooled tokens happens, a set fee incurs which effectively gets\n * distributed to the LPs.\n *\n * In case of emergencies, admin can pause additional deposits, swaps, or single-asset withdraws - which\n * stops the ratio of the tokens in the pool from changing.\n * Users can always withdraw their tokens via multi-asset withdraws.\n *\n * @dev Most of the logic is stored as a library `SwapUtils` for the sake of reducing contract's\n * deployment size.\n */\ncontract Swap is OwnerPausableUpgradeable, ReentrancyGuardUpgradeable {\n using SafeERC20 for IERC20;\n using SafeMath for uint256;\n using SwapUtils for SwapUtils.Swap;\n using AmplificationUtils for SwapUtils.Swap;\n\n // Struct storing data responsible for automatic market maker functionalities. In order to\n // access this data, this contract uses SwapUtils library. For more details, see SwapUtils.sol\n SwapUtils.Swap public swapStorage;\n\n // Maps token address to an index in the pool. Used to prevent duplicate tokens in the pool.\n // getTokenIndex function also relies on this mapping to retrieve token index.\n mapping(address => uint8) private tokenIndexes;\n\n /*** EVENTS ***/\n\n // events replicated from SwapUtils to make the ABI easier for dumb\n // clients\n event TokenSwap(\n address indexed buyer,\n uint256 tokensSold,\n uint256 tokensBought,\n uint128 soldId,\n uint128 boughtId\n );\n event AddLiquidity(\n address indexed provider,\n uint256[] tokenAmounts,\n uint256[] fees,\n uint256 invariant,\n uint256 lpTokenSupply\n );\n event RemoveLiquidity(\n address indexed provider,\n uint256[] tokenAmounts,\n uint256 lpTokenSupply\n );\n event RemoveLiquidityOne(\n address indexed provider,\n uint256 lpTokenAmount,\n uint256 lpTokenSupply,\n uint256 boughtId,\n uint256 tokensBought\n );\n event RemoveLiquidityImbalance(\n address indexed provider,\n uint256[] tokenAmounts,\n uint256[] fees,\n uint256 invariant,\n uint256 lpTokenSupply\n );\n event NewAdminFee(uint256 newAdminFee);\n event NewSwapFee(uint256 newSwapFee);\n event RampA(\n uint256 oldA,\n uint256 newA,\n uint256 initialTime,\n uint256 futureTime\n );\n event StopRampA(uint256 currentA, uint256 time);\n\n /**\n * @notice Initializes this Swap contract with the given parameters.\n * This will also clone a LPToken contract that represents users'\n * LP positions. The owner of LPToken will be this contract - which means\n * only this contract is allowed to mint/burn tokens.\n *\n * @param _pooledTokens an array of ERC20s this pool will accept\n * @param decimals the decimals to use for each pooled token,\n * eg 8 for WBTC. Cannot be larger than POOL_PRECISION_DECIMALS\n * @param lpTokenName the long-form name of the token to be deployed\n * @param lpTokenSymbol the short symbol for the token to be deployed\n * @param _a the amplification coefficient * n * (n - 1). See the\n * StableSwap paper for details\n * @param _fee default swap fee to be initialized with\n * @param _adminFee default adminFee to be initialized with\n * @param lpTokenTargetAddress the address of an existing LPToken contract to use as a target\n */\n function initialize(\n IERC20[] memory _pooledTokens,\n uint8[] memory decimals,\n string memory lpTokenName,\n string memory lpTokenSymbol,\n uint256 _a,\n uint256 _fee,\n uint256 _adminFee,\n address lpTokenTargetAddress\n ) public virtual initializer {\n __OwnerPausable_init();\n __ReentrancyGuard_init();\n // Check _pooledTokens and precisions parameter\n require(_pooledTokens.length > 1, \"_pooledTokens.length <= 1\");\n require(_pooledTokens.length <= 32, \"_pooledTokens.length > 32\");\n require(\n _pooledTokens.length == decimals.length,\n \"_pooledTokens decimals mismatch\"\n );\n\n uint256[] memory precisionMultipliers = new uint256[](decimals.length);\n\n for (uint8 i = 0; i < _pooledTokens.length; i++) {\n if (i > 0) {\n // Check if index is already used. Check if 0th element is a duplicate.\n require(\n tokenIndexes[address(_pooledTokens[i])] == 0 &&\n _pooledTokens[0] != _pooledTokens[i],\n \"Duplicate tokens\"\n );\n }\n require(\n address(_pooledTokens[i]) != address(0),\n \"The 0 address isn't an ERC-20\"\n );\n require(\n decimals[i] <= SwapUtils.POOL_PRECISION_DECIMALS,\n \"Token decimals exceeds max\"\n );\n precisionMultipliers[i] =\n 10 **\n uint256(SwapUtils.POOL_PRECISION_DECIMALS).sub(\n uint256(decimals[i])\n );\n tokenIndexes[address(_pooledTokens[i])] = i;\n }\n\n // Check _a, _fee, _adminFee parameters\n require(_a < AmplificationUtils.MAX_A, \"_a exceeds maximum\");\n require(_fee < SwapUtils.MAX_SWAP_FEE, \"_fee exceeds maximum\");\n require(\n _adminFee < SwapUtils.MAX_ADMIN_FEE,\n \"_adminFee exceeds maximum\"\n );\n\n // Clone and initialize a LPToken contract\n LPToken lpToken = LPToken(Clones.clone(lpTokenTargetAddress));\n require(\n lpToken.initialize(lpTokenName, lpTokenSymbol),\n \"could not init lpToken clone\"\n );\n\n // Initialize swapStorage struct\n swapStorage.lpToken = lpToken;\n swapStorage.pooledTokens = _pooledTokens;\n swapStorage.tokenPrecisionMultipliers = precisionMultipliers;\n swapStorage.balances = new uint256[](_pooledTokens.length);\n swapStorage.initialA = _a.mul(AmplificationUtils.A_PRECISION);\n swapStorage.futureA = _a.mul(AmplificationUtils.A_PRECISION);\n // swapStorage.initialATime = 0;\n // swapStorage.futureATime = 0;\n swapStorage.swapFee = _fee;\n swapStorage.adminFee = _adminFee;\n }\n\n /*** MODIFIERS ***/\n\n /**\n * @notice Modifier to check deadline against current timestamp\n * @param deadline latest timestamp to accept this transaction\n */\n modifier deadlineCheck(uint256 deadline) {\n require(block.timestamp <= deadline, \"Deadline not met\");\n _;\n }\n\n /*** VIEW FUNCTIONS ***/\n\n /**\n * @notice Return A, the amplification coefficient * n * (n - 1)\n * @dev See the StableSwap paper for details\n * @return A parameter\n */\n function getA() external view virtual returns (uint256) {\n return swapStorage.getA();\n }\n\n /**\n * @notice Return A in its raw precision form\n * @dev See the StableSwap paper for details\n * @return A parameter in its raw precision form\n */\n function getAPrecise() external view virtual returns (uint256) {\n return swapStorage.getAPrecise();\n }\n\n /**\n * @notice Return address of the pooled token at given index. Reverts if tokenIndex is out of range.\n * @param index the index of the token\n * @return address of the token at given index\n */\n function getToken(uint8 index) public view virtual returns (IERC20) {\n require(index < swapStorage.pooledTokens.length, \"Out of range\");\n return swapStorage.pooledTokens[index];\n }\n\n /**\n * @notice Return the index of the given token address. Reverts if no matching\n * token is found.\n * @param tokenAddress address of the token\n * @return the index of the given token address\n */\n function getTokenIndex(address tokenAddress)\n public\n view\n virtual\n returns (uint8)\n {\n uint8 index = tokenIndexes[tokenAddress];\n require(\n address(getToken(index)) == tokenAddress,\n \"Token does not exist\"\n );\n return index;\n }\n\n /**\n * @notice Return current balance of the pooled token at given index\n * @param index the index of the token\n * @return current balance of the pooled token at given index with token's native precision\n */\n function getTokenBalance(uint8 index)\n external\n view\n virtual\n returns (uint256)\n {\n require(index < swapStorage.pooledTokens.length, \"Index out of range\");\n return swapStorage.balances[index];\n }\n\n /**\n * @notice Get the virtual price, to help calculate profit\n * @return the virtual price, scaled to the POOL_PRECISION_DECIMALS\n */\n function getVirtualPrice() external view virtual returns (uint256) {\n return swapStorage.getVirtualPrice();\n }\n\n /**\n * @notice Calculate amount of tokens you receive on swap\n * @param tokenIndexFrom the token the user wants to sell\n * @param tokenIndexTo the token the user wants to buy\n * @param dx the amount of tokens the user wants to sell. If the token charges\n * a fee on transfers, use the amount that gets transferred after the fee.\n * @return amount of tokens the user will receive\n */\n function calculateSwap(\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx\n ) external view virtual returns (uint256) {\n return swapStorage.calculateSwap(tokenIndexFrom, tokenIndexTo, dx);\n }\n\n /**\n * @notice A simple method to calculate prices from deposits or\n * withdrawals, excluding fees but including slippage. This is\n * helpful as an input into the various \"min\" parameters on calls\n * to fight front-running\n *\n * @dev This shouldn't be used outside frontends for user estimates.\n *\n * @param amounts an array of token amounts to deposit or withdrawal,\n * corresponding to pooledTokens. The amount should be in each\n * pooled token's native precision. If a token charges a fee on transfers,\n * use the amount that gets transferred after the fee.\n * @param deposit whether this is a deposit or a withdrawal\n * @return token amount the user will receive\n */\n function calculateTokenAmount(uint256[] calldata amounts, bool deposit)\n external\n view\n virtual\n returns (uint256)\n {\n return swapStorage.calculateTokenAmount(amounts, deposit);\n }\n\n /**\n * @notice A simple method to calculate amount of each underlying\n * tokens that is returned upon burning given amount of LP tokens\n * @param amount the amount of LP tokens that would be burned on withdrawal\n * @return array of token balances that the user will receive\n */\n function calculateRemoveLiquidity(uint256 amount)\n external\n view\n virtual\n returns (uint256[] memory)\n {\n return swapStorage.calculateRemoveLiquidity(amount);\n }\n\n /**\n * @notice Calculate the amount of underlying token available to withdraw\n * when withdrawing via only single token\n * @param tokenAmount the amount of LP token to burn\n * @param tokenIndex index of which token will be withdrawn\n * @return availableTokenAmount calculated amount of underlying token\n * available to withdraw\n */\n function calculateRemoveLiquidityOneToken(\n uint256 tokenAmount,\n uint8 tokenIndex\n ) external view virtual returns (uint256 availableTokenAmount) {\n return swapStorage.calculateWithdrawOneToken(tokenAmount, tokenIndex);\n }\n\n /**\n * @notice This function reads the accumulated amount of admin fees of the token with given index\n * @param index Index of the pooled token\n * @return admin's token balance in the token's precision\n */\n function getAdminBalance(uint256 index)\n external\n view\n virtual\n returns (uint256)\n {\n return swapStorage.getAdminBalance(index);\n }\n\n /*** STATE MODIFYING FUNCTIONS ***/\n\n /**\n * @notice Swap two tokens using this pool\n * @param tokenIndexFrom the token the user wants to swap from\n * @param tokenIndexTo the token the user wants to swap to\n * @param dx the amount of tokens the user wants to swap from\n * @param minDy the min amount the user would like to receive, or revert.\n * @param deadline latest timestamp to accept this transaction\n */\n function swap(\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx,\n uint256 minDy,\n uint256 deadline\n )\n external\n virtual\n nonReentrant\n whenNotPaused\n deadlineCheck(deadline)\n returns (uint256)\n {\n return swapStorage.swap(tokenIndexFrom, tokenIndexTo, dx, minDy);\n }\n\n /**\n * @notice Add liquidity to the pool with the given amounts of tokens\n * @param amounts the amounts of each token to add, in their native precision\n * @param minToMint the minimum LP tokens adding this amount of liquidity\n * should mint, otherwise revert. Handy for front-running mitigation\n * @param deadline latest timestamp to accept this transaction\n * @return amount of LP token user minted and received\n */\n function addLiquidity(\n uint256[] calldata amounts,\n uint256 minToMint,\n uint256 deadline\n )\n external\n virtual\n nonReentrant\n whenNotPaused\n deadlineCheck(deadline)\n returns (uint256)\n {\n return swapStorage.addLiquidity(amounts, minToMint);\n }\n\n /**\n * @notice Burn LP tokens to remove liquidity from the pool. Withdraw fee that decays linearly\n * over period of 4 weeks since last deposit will apply.\n * @dev Liquidity can always be removed, even when the pool is paused.\n * @param amount the amount of LP tokens to burn\n * @param minAmounts the minimum amounts of each token in the pool\n * acceptable for this burn. Useful as a front-running mitigation\n * @param deadline latest timestamp to accept this transaction\n * @return amounts of tokens user received\n */\n function removeLiquidity(\n uint256 amount,\n uint256[] calldata minAmounts,\n uint256 deadline\n )\n external\n virtual\n nonReentrant\n deadlineCheck(deadline)\n returns (uint256[] memory)\n {\n return swapStorage.removeLiquidity(amount, minAmounts);\n }\n\n /**\n * @notice Remove liquidity from the pool all in one token. Withdraw fee that decays linearly\n * over period of 4 weeks since last deposit will apply.\n * @param tokenAmount the amount of the token you want to receive\n * @param tokenIndex the index of the token you want to receive\n * @param minAmount the minimum amount to withdraw, otherwise revert\n * @param deadline latest timestamp to accept this transaction\n * @return amount of chosen token user received\n */\n function removeLiquidityOneToken(\n uint256 tokenAmount,\n uint8 tokenIndex,\n uint256 minAmount,\n uint256 deadline\n )\n external\n virtual\n nonReentrant\n whenNotPaused\n deadlineCheck(deadline)\n returns (uint256)\n {\n return\n swapStorage.removeLiquidityOneToken(\n tokenAmount,\n tokenIndex,\n minAmount\n );\n }\n\n /**\n * @notice Remove liquidity from the pool, weighted differently than the\n * pool's current balances. Withdraw fee that decays linearly\n * over period of 4 weeks since last deposit will apply.\n * @param amounts how much of each token to withdraw\n * @param maxBurnAmount the max LP token provider is willing to pay to\n * remove liquidity. Useful as a front-running mitigation.\n * @param deadline latest timestamp to accept this transaction\n * @return amount of LP tokens burned\n */\n function removeLiquidityImbalance(\n uint256[] calldata amounts,\n uint256 maxBurnAmount,\n uint256 deadline\n )\n external\n virtual\n nonReentrant\n whenNotPaused\n deadlineCheck(deadline)\n returns (uint256)\n {\n return swapStorage.removeLiquidityImbalance(amounts, maxBurnAmount);\n }\n\n /*** ADMIN FUNCTIONS ***/\n\n /**\n * @notice Withdraw all admin fees to the contract owner\n */\n function withdrawAdminFees() external onlyOwner {\n swapStorage.withdrawAdminFees(owner());\n }\n\n /**\n * @notice Update the admin fee. Admin fee takes portion of the swap fee.\n * @param newAdminFee new admin fee to be applied on future transactions\n */\n function setAdminFee(uint256 newAdminFee) external onlyOwner {\n swapStorage.setAdminFee(newAdminFee);\n }\n\n /**\n * @notice Update the swap fee to be applied on swaps\n * @param newSwapFee new swap fee to be applied on future transactions\n */\n function setSwapFee(uint256 newSwapFee) external onlyOwner {\n swapStorage.setSwapFee(newSwapFee);\n }\n\n /**\n * @notice Start ramping up or down A parameter towards given futureA and futureTime\n * Checks if the change is too rapid, and commits the new A value only when it falls under\n * the limit range.\n * @param futureA the new A to ramp towards\n * @param futureTime timestamp when the new A should be reached\n */\n function rampA(uint256 futureA, uint256 futureTime) external onlyOwner {\n swapStorage.rampA(futureA, futureTime);\n }\n\n /**\n * @notice Stop ramping A immediately. Reverts if ramp A is already stopped.\n */\n function stopRampA() external onlyOwner {\n swapStorage.stopRampA();\n }\n}\n" + }, + "@openzeppelin/contracts/math/SafeMath.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <0.8.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" + }, + "@openzeppelin/contracts/token/ERC20/SafeERC20.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <0.8.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" + }, + "@openzeppelin/contracts/proxy/Clones.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <0.8.0;\n\n/**\n * @dev https://eips.ethereum.org/EIPS/eip-1167[EIP 1167] is a standard for\n * deploying minimal proxy contracts, also known as \"clones\".\n *\n * > To simply and cheaply clone contract functionality in an immutable way, this standard specifies\n * > a minimal bytecode implementation that delegates all calls to a known, fixed address.\n *\n * The library includes functions to deploy a proxy using either `create` (traditional deployment) or `create2`\n * (salted deterministic deployment). It also includes functions to predict the addresses of clones deployed using the\n * deterministic method.\n *\n * _Available since v3.4._\n */\nlibrary Clones {\n /**\n * @dev Deploys and returns the address of a clone that mimics the behaviour of `master`.\n *\n * This function uses the create opcode, which should never revert.\n */\n function clone(address master) internal returns (address instance) {\n // solhint-disable-next-line no-inline-assembly\n assembly {\n let ptr := mload(0x40)\n mstore(ptr, 0x3d602d80600a3d3981f3363d3d373d3d3d363d73000000000000000000000000)\n mstore(add(ptr, 0x14), shl(0x60, master))\n mstore(add(ptr, 0x28), 0x5af43d82803e903d91602b57fd5bf30000000000000000000000000000000000)\n instance := create(0, ptr, 0x37)\n }\n require(instance != address(0), \"ERC1167: create failed\");\n }\n\n /**\n * @dev Deploys and returns the address of a clone that mimics the behaviour of `master`.\n *\n * This function uses the create2 opcode and a `salt` to deterministically deploy\n * the clone. Using the same `master` and `salt` multiple time will revert, since\n * the clones cannot be deployed twice at the same address.\n */\n function cloneDeterministic(address master, bytes32 salt) internal returns (address instance) {\n // solhint-disable-next-line no-inline-assembly\n assembly {\n let ptr := mload(0x40)\n mstore(ptr, 0x3d602d80600a3d3981f3363d3d373d3d3d363d73000000000000000000000000)\n mstore(add(ptr, 0x14), shl(0x60, master))\n mstore(add(ptr, 0x28), 0x5af43d82803e903d91602b57fd5bf30000000000000000000000000000000000)\n instance := create2(0, ptr, 0x37, salt)\n }\n require(instance != address(0), \"ERC1167: create2 failed\");\n }\n\n /**\n * @dev Computes the address of a clone deployed using {Clones-cloneDeterministic}.\n */\n function predictDeterministicAddress(address master, bytes32 salt, address deployer) internal pure returns (address predicted) {\n // solhint-disable-next-line no-inline-assembly\n assembly {\n let ptr := mload(0x40)\n mstore(ptr, 0x3d602d80600a3d3981f3363d3d373d3d3d363d73000000000000000000000000)\n mstore(add(ptr, 0x14), shl(0x60, master))\n mstore(add(ptr, 0x28), 0x5af43d82803e903d91602b57fd5bf3ff00000000000000000000000000000000)\n mstore(add(ptr, 0x38), shl(0x60, deployer))\n mstore(add(ptr, 0x4c), salt)\n mstore(add(ptr, 0x6c), keccak256(ptr, 0x37))\n predicted := keccak256(add(ptr, 0x37), 0x55)\n }\n }\n\n /**\n * @dev Computes the address of a clone deployed using {Clones-cloneDeterministic}.\n */\n function predictDeterministicAddress(address master, bytes32 salt) internal view returns (address predicted) {\n return predictDeterministicAddress(master, salt, address(this));\n }\n}\n" + }, + "@openzeppelin/contracts-upgradeable/utils/ReentrancyGuardUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <0.8.0;\nimport \"../proxy/Initializable.sol\";\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 ReentrancyGuardUpgradeable is Initializable {\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 function __ReentrancyGuard_init() internal initializer {\n __ReentrancyGuard_init_unchained();\n }\n\n function __ReentrancyGuard_init_unchained() internal initializer {\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 uint256[49] private __gap;\n}\n" + }, + "contracts/amm/OwnerPausableUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.6.12;\n\nimport \"@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol\";\nimport \"@openzeppelin/contracts-upgradeable/utils/PausableUpgradeable.sol\";\n\n/**\n * @title OwnerPausable\n * @notice An ownable contract allows the owner to pause and unpause the\n * contract without a delay.\n * @dev Only methods using the provided modifiers will be paused.\n */\nabstract contract OwnerPausableUpgradeable is\n OwnableUpgradeable,\n PausableUpgradeable\n{\n function __OwnerPausable_init() internal initializer {\n __Context_init_unchained();\n __Ownable_init_unchained();\n __Pausable_init_unchained();\n }\n\n /**\n * @notice Pause the contract. Revert if already paused.\n */\n function pause() external onlyOwner {\n PausableUpgradeable._pause();\n }\n\n /**\n * @notice Unpause the contract. Revert if already unpaused.\n */\n function unpause() external onlyOwner {\n PausableUpgradeable._unpause();\n }\n}\n" + }, + "contracts/amm/SwapUtils.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.6.12;\n\nimport \"@openzeppelin/contracts/math/SafeMath.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/SafeERC20.sol\";\nimport \"./AmplificationUtils.sol\";\nimport \"./LPToken.sol\";\nimport \"./MathUtils.sol\";\n\n/**\n * @title SwapUtils library\n * @notice A library to be used within Swap.sol. Contains functions responsible for custody and AMM functionalities.\n * @dev Contracts relying on this library must initialize SwapUtils.Swap struct then use this library\n * for SwapUtils.Swap struct. Note that this library contains both functions called by users and admins.\n * Admin functions should be protected within contracts using this library.\n */\nlibrary SwapUtils {\n using SafeERC20 for IERC20;\n using SafeMath for uint256;\n using MathUtils for uint256;\n\n /*** EVENTS ***/\n\n event TokenSwap(\n address indexed buyer,\n uint256 tokensSold,\n uint256 tokensBought,\n uint128 soldId,\n uint128 boughtId\n );\n event AddLiquidity(\n address indexed provider,\n uint256[] tokenAmounts,\n uint256[] fees,\n uint256 invariant,\n uint256 lpTokenSupply\n );\n event RemoveLiquidity(\n address indexed provider,\n uint256[] tokenAmounts,\n uint256 lpTokenSupply\n );\n event RemoveLiquidityOne(\n address indexed provider,\n uint256 lpTokenAmount,\n uint256 lpTokenSupply,\n uint256 boughtId,\n uint256 tokensBought\n );\n event RemoveLiquidityImbalance(\n address indexed provider,\n uint256[] tokenAmounts,\n uint256[] fees,\n uint256 invariant,\n uint256 lpTokenSupply\n );\n event NewAdminFee(uint256 newAdminFee);\n event NewSwapFee(uint256 newSwapFee);\n\n struct Swap {\n // variables around the ramp management of A,\n // the amplification coefficient * n * (n - 1)\n // see https://www.curve.fi/stableswap-paper.pdf for details\n uint256 initialA;\n uint256 futureA;\n uint256 initialATime;\n uint256 futureATime;\n // fee calculation\n uint256 swapFee;\n uint256 adminFee;\n LPToken lpToken;\n // contract references for all tokens being pooled\n IERC20[] pooledTokens;\n // multipliers for each pooled token's precision to get to POOL_PRECISION_DECIMALS\n // for example, TBTC has 18 decimals, so the multiplier should be 1. WBTC\n // has 8, so the multiplier should be 10 ** 18 / 10 ** 8 => 10 ** 10\n uint256[] tokenPrecisionMultipliers;\n // the pool balance of each token, in the token's precision\n // the contract's actual token balance might differ\n uint256[] balances;\n }\n\n // Struct storing variables used in calculations in the\n // calculateWithdrawOneTokenDY function to avoid stack too deep errors\n struct CalculateWithdrawOneTokenDYInfo {\n uint256 d0;\n uint256 d1;\n uint256 newY;\n uint256 feePerToken;\n uint256 preciseA;\n }\n\n // Struct storing variables used in calculations in the\n // {add,remove}Liquidity functions to avoid stack too deep errors\n struct ManageLiquidityInfo {\n uint256 d0;\n uint256 d1;\n uint256 d2;\n uint256 preciseA;\n LPToken lpToken;\n uint256 totalSupply;\n uint256[] balances;\n uint256[] multipliers;\n }\n\n // the precision all pools tokens will be converted to\n uint8 public constant POOL_PRECISION_DECIMALS = 18;\n\n // the denominator used to calculate admin and LP fees. For example, an\n // LP fee might be something like tradeAmount.mul(fee).div(FEE_DENOMINATOR)\n uint256 private constant FEE_DENOMINATOR = 10**10;\n\n // Max swap fee is 1% or 100bps of each swap\n uint256 public constant MAX_SWAP_FEE = 10**8;\n\n // Max adminFee is 100% of the swapFee\n // adminFee does not add additional fee on top of swapFee\n // Instead it takes a certain % of the swapFee. Therefore it has no impact on the\n // users but only on the earnings of LPs\n uint256 public constant MAX_ADMIN_FEE = 10**10;\n\n // Constant value used as max loop limit\n uint256 private constant MAX_LOOP_LIMIT = 256;\n\n /*** VIEW & PURE FUNCTIONS ***/\n\n function _getAPrecise(Swap storage self) internal view returns (uint256) {\n return AmplificationUtils._getAPrecise(self);\n }\n\n /**\n * @notice Calculate the dy, the amount of selected token that user receives and\n * the fee of withdrawing in one token\n * @param tokenAmount the amount to withdraw in the pool's precision\n * @param tokenIndex which token will be withdrawn\n * @param self Swap struct to read from\n * @return the amount of token user will receive\n */\n function calculateWithdrawOneToken(\n Swap storage self,\n uint256 tokenAmount,\n uint8 tokenIndex\n ) external view returns (uint256) {\n (uint256 availableTokenAmount, ) = _calculateWithdrawOneToken(\n self,\n tokenAmount,\n tokenIndex,\n self.lpToken.totalSupply()\n );\n return availableTokenAmount;\n }\n\n function _calculateWithdrawOneToken(\n Swap storage self,\n uint256 tokenAmount,\n uint8 tokenIndex,\n uint256 totalSupply\n ) internal view returns (uint256, uint256) {\n uint256 dy;\n uint256 newY;\n uint256 currentY;\n\n (dy, newY, currentY) = calculateWithdrawOneTokenDY(\n self,\n tokenIndex,\n tokenAmount,\n totalSupply\n );\n\n // dy_0 (without fees)\n // dy, dy_0 - dy\n\n uint256 dySwapFee = currentY\n .sub(newY)\n .div(self.tokenPrecisionMultipliers[tokenIndex])\n .sub(dy);\n\n return (dy, dySwapFee);\n }\n\n /**\n * @notice Calculate the dy of withdrawing in one token\n * @param self Swap struct to read from\n * @param tokenIndex which token will be withdrawn\n * @param tokenAmount the amount to withdraw in the pools precision\n * @return the d and the new y after withdrawing one token\n */\n function calculateWithdrawOneTokenDY(\n Swap storage self,\n uint8 tokenIndex,\n uint256 tokenAmount,\n uint256 totalSupply\n )\n internal\n view\n returns (\n uint256,\n uint256,\n uint256\n )\n {\n // Get the current D, then solve the stableswap invariant\n // y_i for D - tokenAmount\n uint256[] memory xp = _xp(self);\n\n require(tokenIndex < xp.length, \"Token index out of range\");\n\n\n CalculateWithdrawOneTokenDYInfo memory v\n = CalculateWithdrawOneTokenDYInfo(0, 0, 0, 0, 0);\n v.preciseA = _getAPrecise(self);\n v.d0 = getD(xp, v.preciseA);\n v.d1 = v.d0.sub(tokenAmount.mul(v.d0).div(totalSupply));\n\n require(tokenAmount <= xp[tokenIndex], \"Withdraw exceeds available\");\n\n v.newY = getYD(v.preciseA, tokenIndex, xp, v.d1);\n\n uint256[] memory xpReduced = new uint256[](xp.length);\n\n v.feePerToken = _feePerToken(self.swapFee, xp.length);\n for (uint256 i = 0; i < xp.length; i++) {\n uint256 xpi = xp[i];\n // if i == tokenIndex, dxExpected = xp[i] * d1 / d0 - newY\n // else dxExpected = xp[i] - (xp[i] * d1 / d0)\n // xpReduced[i] -= dxExpected * fee / FEE_DENOMINATOR\n xpReduced[i] = xpi.sub(\n (\n (i == tokenIndex)\n ? xpi.mul(v.d1).div(v.d0).sub(v.newY)\n : xpi.sub(xpi.mul(v.d1).div(v.d0))\n )\n .mul(v.feePerToken)\n .div(FEE_DENOMINATOR)\n );\n }\n\n uint256 dy = xpReduced[tokenIndex].sub(\n getYD(v.preciseA, tokenIndex, xpReduced, v.d1)\n );\n dy = dy.sub(1).div(self.tokenPrecisionMultipliers[tokenIndex]);\n\n return (dy, v.newY, xp[tokenIndex]);\n }\n\n /**\n * @notice Calculate the price of a token in the pool with given\n * precision-adjusted balances and a particular D.\n *\n * @dev This is accomplished via solving the invariant iteratively.\n * See the StableSwap paper and Curve.fi implementation for further details.\n *\n * x_1**2 + x1 * (sum' - (A*n**n - 1) * D / (A * n**n)) = D ** (n + 1) / (n ** (2 * n) * prod' * A)\n * x_1**2 + b*x_1 = c\n * x_1 = (x_1**2 + c) / (2*x_1 + b)\n *\n * @param a the amplification coefficient * n * (n - 1). See the StableSwap paper for details.\n * @param tokenIndex Index of token we are calculating for.\n * @param xp a precision-adjusted set of pool balances. Array should be\n * the same cardinality as the pool.\n * @param d the stableswap invariant\n * @return the price of the token, in the same precision as in xp\n */\n function getYD(\n uint256 a,\n uint8 tokenIndex,\n uint256[] memory xp,\n uint256 d\n ) internal pure returns (uint256) {\n uint256 numTokens = xp.length;\n require(tokenIndex < numTokens, \"Token not found\");\n\n uint256 c = d;\n uint256 s;\n uint256 nA = a.mul(numTokens);\n\n for (uint256 i = 0; i < numTokens; i++) {\n if (i != tokenIndex) {\n s = s.add(xp[i]);\n c = c.mul(d).div(xp[i].mul(numTokens));\n // If we were to protect the division loss we would have to keep the denominator separate\n // and divide at the end. However this leads to overflow with large numTokens or/and D.\n // c = c * D * D * D * ... overflow!\n }\n }\n c = c.mul(d).mul(AmplificationUtils.A_PRECISION).div(nA.mul(numTokens));\n\n uint256 b = s.add(d.mul(AmplificationUtils.A_PRECISION).div(nA));\n uint256 yPrev;\n uint256 y = d;\n for (uint256 i = 0; i < MAX_LOOP_LIMIT; i++) {\n yPrev = y;\n y = y.mul(y).add(c).div(y.mul(2).add(b).sub(d));\n if (y.within1(yPrev)) {\n return y;\n }\n }\n revert(\"Approximation did not converge\");\n }\n\n /**\n * @notice Get D, the StableSwap invariant, based on a set of balances and a particular A.\n * @param xp a precision-adjusted set of pool balances. Array should be the same cardinality\n * as the pool.\n * @param a the amplification coefficient * n * (n - 1) in A_PRECISION.\n * See the StableSwap paper for details\n * @return the invariant, at the precision of the pool\n */\n function getD(uint256[] memory xp, uint256 a)\n internal\n pure\n returns (uint256)\n {\n uint256 numTokens = xp.length;\n uint256 s;\n for (uint256 i = 0; i < numTokens; i++) {\n s = s.add(xp[i]);\n }\n if (s == 0) {\n return 0;\n }\n\n uint256 prevD;\n uint256 d = s;\n uint256 nA = a.mul(numTokens);\n\n for (uint256 i = 0; i < MAX_LOOP_LIMIT; i++) {\n uint256 dP = d;\n for (uint256 j = 0; j < numTokens; j++) {\n dP = dP.mul(d).div(xp[j].mul(numTokens));\n // If we were to protect the division loss we would have to keep the denominator separate\n // and divide at the end. However this leads to overflow with large numTokens or/and D.\n // dP = dP * D * D * D * ... overflow!\n }\n prevD = d;\n d = nA\n .mul(s)\n .div(AmplificationUtils.A_PRECISION)\n .add(dP.mul(numTokens))\n .mul(d)\n .div(\n nA\n .sub(AmplificationUtils.A_PRECISION)\n .mul(d)\n .div(AmplificationUtils.A_PRECISION)\n .add(numTokens.add(1).mul(dP))\n );\n if (d.within1(prevD)) {\n return d;\n }\n }\n\n // Convergence should occur in 4 loops or less. If this is reached, there may be something wrong\n // with the pool. If this were to occur repeatedly, LPs should withdraw via `removeLiquidity()`\n // function which does not rely on D.\n revert(\"D does not converge\");\n }\n\n /**\n * @notice Given a set of balances and precision multipliers, return the\n * precision-adjusted balances.\n *\n * @param balances an array of token balances, in their native precisions.\n * These should generally correspond with pooled tokens.\n *\n * @param precisionMultipliers an array of multipliers, corresponding to\n * the amounts in the balances array. When multiplied together they\n * should yield amounts at the pool's precision.\n *\n * @return an array of amounts \"scaled\" to the pool's precision\n */\n function _xp(\n uint256[] memory balances,\n uint256[] memory precisionMultipliers\n ) internal pure returns (uint256[] memory) {\n uint256 numTokens = balances.length;\n require(\n numTokens == precisionMultipliers.length,\n \"Balances must match multipliers\"\n );\n uint256[] memory xp = new uint256[](numTokens);\n for (uint256 i = 0; i < numTokens; i++) {\n xp[i] = balances[i].mul(precisionMultipliers[i]);\n }\n return xp;\n }\n\n /**\n * @notice Return the precision-adjusted balances of all tokens in the pool\n * @param self Swap struct to read from\n * @return the pool balances \"scaled\" to the pool's precision, allowing\n * them to be more easily compared.\n */\n function _xp(Swap storage self) internal view returns (uint256[] memory) {\n return _xp(self.balances, self.tokenPrecisionMultipliers);\n }\n\n /**\n * @notice Get the virtual price, to help calculate profit\n * @param self Swap struct to read from\n * @return the virtual price, scaled to precision of POOL_PRECISION_DECIMALS\n */\n function getVirtualPrice(Swap storage self)\n external\n view\n returns (uint256)\n {\n uint256 d = getD(_xp(self), _getAPrecise(self));\n LPToken lpToken = self.lpToken;\n uint256 supply = lpToken.totalSupply();\n if (supply > 0) {\n return d.mul(10**uint256(POOL_PRECISION_DECIMALS)).div(supply);\n }\n return 0;\n }\n\n /**\n * @notice Calculate the new balances of the tokens given the indexes of the token\n * that is swapped from (FROM) and the token that is swapped to (TO).\n * This function is used as a helper function to calculate how much TO token\n * the user should receive on swap.\n *\n * @param preciseA precise form of amplification coefficient\n * @param tokenIndexFrom index of FROM token\n * @param tokenIndexTo index of TO token\n * @param x the new total amount of FROM token\n * @param xp balances of the tokens in the pool\n * @return the amount of TO token that should remain in the pool\n */\n function getY(\n uint256 preciseA,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 x,\n uint256[] memory xp\n ) internal pure returns (uint256) {\n uint256 numTokens = xp.length;\n require(\n tokenIndexFrom != tokenIndexTo,\n \"Can't compare token to itself\"\n );\n require(\n tokenIndexFrom < numTokens && tokenIndexTo < numTokens,\n \"Tokens must be in pool\"\n );\n\n uint256 d = getD(xp, preciseA);\n uint256 c = d;\n uint256 s;\n uint256 nA = numTokens.mul(preciseA);\n\n uint256 _x;\n for (uint256 i = 0; i < numTokens; i++) {\n if (i == tokenIndexFrom) {\n _x = x;\n } else if (i != tokenIndexTo) {\n _x = xp[i];\n } else {\n continue;\n }\n s = s.add(_x);\n c = c.mul(d).div(_x.mul(numTokens));\n // If we were to protect the division loss we would have to keep the denominator separate\n // and divide at the end. However this leads to overflow with large numTokens or/and D.\n // c = c * D * D * D * ... overflow!\n }\n c = c.mul(d).mul(AmplificationUtils.A_PRECISION).div(nA.mul(numTokens));\n uint256 b = s.add(d.mul(AmplificationUtils.A_PRECISION).div(nA));\n uint256 yPrev;\n uint256 y = d;\n\n // iterative approximation\n for (uint256 i = 0; i < MAX_LOOP_LIMIT; i++) {\n yPrev = y;\n y = y.mul(y).add(c).div(y.mul(2).add(b).sub(d));\n if (y.within1(yPrev)) {\n return y;\n }\n }\n revert(\"Approximation did not converge\");\n }\n\n /**\n * @notice Externally calculates a swap between two tokens.\n * @param self Swap struct to read from\n * @param tokenIndexFrom the token to sell\n * @param tokenIndexTo the token to buy\n * @param dx the number of tokens to sell. If the token charges a fee on transfers,\n * use the amount that gets transferred after the fee.\n * @return dy the number of tokens the user will get\n */\n function calculateSwap(\n Swap storage self,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx\n ) external view returns (uint256 dy) {\n (dy, ) = _calculateSwap(\n self,\n tokenIndexFrom,\n tokenIndexTo,\n dx,\n self.balances\n );\n }\n\n /**\n * @notice Internally calculates a swap between two tokens.\n *\n * @dev The caller is expected to transfer the actual amounts (dx and dy)\n * using the token contracts.\n *\n * @param self Swap struct to read from\n * @param tokenIndexFrom the token to sell\n * @param tokenIndexTo the token to buy\n * @param dx the number of tokens to sell. If the token charges a fee on transfers,\n * use the amount that gets transferred after the fee.\n * @return dy the number of tokens the user will get\n * @return dyFee the associated fee\n */\n function _calculateSwap(\n Swap storage self,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx,\n uint256[] memory balances\n ) internal view returns (uint256 dy, uint256 dyFee) {\n uint256[] memory multipliers = self.tokenPrecisionMultipliers;\n uint256[] memory xp = _xp(balances, multipliers);\n require(\n tokenIndexFrom < xp.length && tokenIndexTo < xp.length,\n \"Token index out of range\"\n );\n uint256 x = dx.mul(multipliers[tokenIndexFrom]).add(xp[tokenIndexFrom]);\n uint256 y = getY(\n _getAPrecise(self),\n tokenIndexFrom,\n tokenIndexTo,\n x,\n xp\n );\n dy = xp[tokenIndexTo].sub(y).sub(1);\n dyFee = dy.mul(self.swapFee).div(FEE_DENOMINATOR);\n dy = dy.sub(dyFee).div(multipliers[tokenIndexTo]);\n }\n\n /**\n * @notice A simple method to calculate amount of each underlying\n * tokens that is returned upon burning given amount of\n * LP tokens\n *\n * @param amount the amount of LP tokens that would to be burned on\n * withdrawal\n * @return array of amounts of tokens user will receive\n */\n function calculateRemoveLiquidity(Swap storage self, uint256 amount)\n external\n view\n returns (uint256[] memory)\n {\n return\n _calculateRemoveLiquidity(\n self.balances,\n amount,\n self.lpToken.totalSupply()\n );\n }\n\n function _calculateRemoveLiquidity(\n uint256[] memory balances,\n uint256 amount,\n uint256 totalSupply\n ) internal pure returns (uint256[] memory) {\n require(amount <= totalSupply, \"Cannot exceed total supply\");\n\n uint256[] memory amounts = new uint256[](balances.length);\n\n for (uint256 i = 0; i < balances.length; i++) {\n amounts[i] = balances[i].mul(amount).div(totalSupply);\n }\n return amounts;\n }\n\n /**\n * @notice A simple method to calculate prices from deposits or\n * withdrawals, excluding fees but including slippage. This is\n * helpful as an input into the various \"min\" parameters on calls\n * to fight front-running\n *\n * @dev This shouldn't be used outside frontends for user estimates.\n *\n * @param self Swap struct to read from\n * @param amounts an array of token amounts to deposit or withdrawal,\n * corresponding to pooledTokens. The amount should be in each\n * pooled token's native precision. If a token charges a fee on transfers,\n * use the amount that gets transferred after the fee.\n * @param deposit whether this is a deposit or a withdrawal\n * @return if deposit was true, total amount of lp token that will be minted and if\n * deposit was false, total amount of lp token that will be burned\n */\n function calculateTokenAmount(\n Swap storage self,\n uint256[] calldata amounts,\n bool deposit\n ) external view returns (uint256) {\n uint256 a = _getAPrecise(self);\n uint256[] memory balances = self.balances;\n uint256[] memory multipliers = self.tokenPrecisionMultipliers;\n\n uint256 d0 = getD(_xp(balances, multipliers), a);\n for (uint256 i = 0; i < balances.length; i++) {\n if (deposit) {\n balances[i] = balances[i].add(amounts[i]);\n } else {\n balances[i] = balances[i].sub(\n amounts[i],\n \"Cannot withdraw more than available\"\n );\n }\n }\n uint256 d1 = getD(_xp(balances, multipliers), a);\n uint256 totalSupply = self.lpToken.totalSupply();\n\n if (deposit) {\n return d1.sub(d0).mul(totalSupply).div(d0);\n } else {\n return d0.sub(d1).mul(totalSupply).div(d0);\n }\n }\n\n /**\n * @notice return accumulated amount of admin fees of the token with given index\n * @param self Swap struct to read from\n * @param index Index of the pooled token\n * @return admin balance in the token's precision\n */\n function getAdminBalance(Swap storage self, uint256 index)\n external\n view\n returns (uint256)\n {\n require(index < self.pooledTokens.length, \"Token index out of range\");\n return\n self.pooledTokens[index].balanceOf(address(this)).sub(\n self.balances[index]\n );\n }\n\n /**\n * @notice internal helper function to calculate fee per token multiplier used in\n * swap fee calculations\n * @param swapFee swap fee for the tokens\n * @param numTokens number of tokens pooled\n */\n function _feePerToken(uint256 swapFee, uint256 numTokens)\n internal\n pure\n returns (uint256)\n {\n return swapFee.mul(numTokens).div(numTokens.sub(1).mul(4));\n }\n\n /*** STATE MODIFYING FUNCTIONS ***/\n\n /**\n * @notice swap two tokens in the pool\n * @param self Swap struct to read from and write to\n * @param tokenIndexFrom the token the user wants to sell\n * @param tokenIndexTo the token the user wants to buy\n * @param dx the amount of tokens the user wants to sell\n * @param minDy the min amount the user would like to receive, or revert.\n * @return amount of token user received on swap\n */\n function swap(\n Swap storage self,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx,\n uint256 minDy\n ) external returns (uint256) {\n {\n IERC20 tokenFrom = self.pooledTokens[tokenIndexFrom];\n require(\n dx <= tokenFrom.balanceOf(msg.sender),\n \"Cannot swap more than you own\"\n );\n // Transfer tokens first to see if a fee was charged on transfer\n uint256 beforeBalance = tokenFrom.balanceOf(address(this));\n tokenFrom.safeTransferFrom(msg.sender, address(this), dx);\n\n // Use the actual transferred amount for AMM math\n dx = tokenFrom.balanceOf(address(this)).sub(beforeBalance);\n }\n\n uint256 dy;\n uint256 dyFee;\n uint256[] memory balances = self.balances;\n (dy, dyFee) = _calculateSwap(\n self,\n tokenIndexFrom,\n tokenIndexTo,\n dx,\n balances\n );\n require(dy >= minDy, \"Swap didn't result in min tokens\");\n\n uint256 dyAdminFee = dyFee.mul(self.adminFee).div(FEE_DENOMINATOR).div(\n self.tokenPrecisionMultipliers[tokenIndexTo]\n );\n\n self.balances[tokenIndexFrom] = balances[tokenIndexFrom].add(dx);\n self.balances[tokenIndexTo] = balances[tokenIndexTo].sub(dy).sub(\n dyAdminFee\n );\n\n self.pooledTokens[tokenIndexTo].safeTransfer(msg.sender, dy);\n\n emit TokenSwap(msg.sender, dx, dy, tokenIndexFrom, tokenIndexTo);\n\n return dy;\n }\n\n /**\n * @notice Add liquidity to the pool\n * @param self Swap struct to read from and write to\n * @param amounts the amounts of each token to add, in their native precision\n * @param minToMint the minimum LP tokens adding this amount of liquidity\n * should mint, otherwise revert. Handy for front-running mitigation\n * allowed addresses. If the pool is not in the guarded launch phase, this parameter will be ignored.\n * @return amount of LP token user received\n */\n function addLiquidity(\n Swap storage self,\n uint256[] memory amounts,\n uint256 minToMint\n ) external returns (uint256) {\n IERC20[] memory pooledTokens = self.pooledTokens;\n require(\n amounts.length == pooledTokens.length,\n \"Amounts must match pooled tokens\"\n );\n\n // current state\n ManageLiquidityInfo memory v = ManageLiquidityInfo(\n 0,\n 0,\n 0,\n _getAPrecise(self),\n self.lpToken,\n 0,\n self.balances,\n self.tokenPrecisionMultipliers\n );\n v.totalSupply = v.lpToken.totalSupply();\n\n if (v.totalSupply != 0) {\n v.d0 = getD(_xp(v.balances, v.multipliers), v.preciseA);\n }\n\n uint256[] memory newBalances = new uint256[](pooledTokens.length);\n\n for (uint256 i = 0; i < pooledTokens.length; i++) {\n require(\n v.totalSupply != 0 || amounts[i] > 0,\n \"Must supply all tokens in pool\"\n );\n\n // Transfer tokens first to see if a fee was charged on transfer\n if (amounts[i] != 0) {\n uint256 beforeBalance = pooledTokens[i].balanceOf(\n address(this)\n );\n pooledTokens[i].safeTransferFrom(\n msg.sender,\n address(this),\n amounts[i]\n );\n\n // Update the amounts[] with actual transfer amount\n amounts[i] = pooledTokens[i].balanceOf(address(this)).sub(\n beforeBalance\n );\n }\n\n newBalances[i] = v.balances[i].add(amounts[i]);\n }\n\n // invariant after change\n v.d1 = getD(_xp(newBalances, v.multipliers), v.preciseA);\n require(v.d1 > v.d0, \"D should increase\");\n\n // updated to reflect fees and calculate the user's LP tokens\n v.d2 = v.d1;\n uint256[] memory fees = new uint256[](pooledTokens.length);\n\n if (v.totalSupply != 0) {\n uint256 feePerToken = _feePerToken(\n self.swapFee,\n pooledTokens.length\n );\n for (uint256 i = 0; i < pooledTokens.length; i++) {\n uint256 idealBalance = v.d1.mul(v.balances[i]).div(v.d0);\n fees[i] = feePerToken\n .mul(idealBalance.difference(newBalances[i]))\n .div(FEE_DENOMINATOR);\n self.balances[i] = newBalances[i].sub(\n fees[i].mul(self.adminFee).div(FEE_DENOMINATOR)\n );\n newBalances[i] = newBalances[i].sub(fees[i]);\n }\n v.d2 = getD(_xp(newBalances, v.multipliers), v.preciseA);\n } else {\n // the initial depositor doesn't pay fees\n self.balances = newBalances;\n }\n\n uint256 toMint;\n if (v.totalSupply == 0) {\n toMint = v.d1;\n } else {\n toMint = v.d2.sub(v.d0).mul(v.totalSupply).div(v.d0);\n }\n\n require(toMint >= minToMint, \"Couldn't mint min requested\");\n\n // mint the user's LP tokens\n v.lpToken.mint(msg.sender, toMint);\n\n emit AddLiquidity(\n msg.sender,\n amounts,\n fees,\n v.d1,\n v.totalSupply.add(toMint)\n );\n\n return toMint;\n }\n\n /**\n * @notice Burn LP tokens to remove liquidity from the pool.\n * @dev Liquidity can always be removed, even when the pool is paused.\n * @param self Swap struct to read from and write to\n * @param amount the amount of LP tokens to burn\n * @param minAmounts the minimum amounts of each token in the pool\n * acceptable for this burn. Useful as a front-running mitigation\n * @return amounts of tokens the user received\n */\n function removeLiquidity(\n Swap storage self,\n uint256 amount,\n uint256[] calldata minAmounts\n ) external returns (uint256[] memory) {\n LPToken lpToken = self.lpToken;\n IERC20[] memory pooledTokens = self.pooledTokens;\n require(amount <= lpToken.balanceOf(msg.sender), \">LP.balanceOf\");\n require(\n minAmounts.length == pooledTokens.length,\n \"minAmounts must match poolTokens\"\n );\n\n uint256[] memory balances = self.balances;\n uint256 totalSupply = lpToken.totalSupply();\n\n uint256[] memory amounts = _calculateRemoveLiquidity(\n balances,\n amount,\n totalSupply\n );\n\n for (uint256 i = 0; i < amounts.length; i++) {\n require(amounts[i] >= minAmounts[i], \"amounts[i] < minAmounts[i]\");\n self.balances[i] = balances[i].sub(amounts[i]);\n pooledTokens[i].safeTransfer(msg.sender, amounts[i]);\n }\n\n lpToken.burnFrom(msg.sender, amount);\n\n emit RemoveLiquidity(msg.sender, amounts, totalSupply.sub(amount));\n\n return amounts;\n }\n\n /**\n * @notice Remove liquidity from the pool all in one token.\n * @param self Swap struct to read from and write to\n * @param tokenAmount the amount of the lp tokens to burn\n * @param tokenIndex the index of the token you want to receive\n * @param minAmount the minimum amount to withdraw, otherwise revert\n * @return amount chosen token that user received\n */\n function removeLiquidityOneToken(\n Swap storage self,\n uint256 tokenAmount,\n uint8 tokenIndex,\n uint256 minAmount\n ) external returns (uint256) {\n LPToken lpToken = self.lpToken;\n IERC20[] memory pooledTokens = self.pooledTokens;\n\n require(tokenAmount <= lpToken.balanceOf(msg.sender), \">LP.balanceOf\");\n require(tokenIndex < pooledTokens.length, \"Token not found\");\n\n uint256 totalSupply = lpToken.totalSupply();\n\n (uint256 dy, uint256 dyFee) = _calculateWithdrawOneToken(\n self,\n tokenAmount,\n tokenIndex,\n totalSupply\n );\n\n require(dy >= minAmount, \"dy < minAmount\");\n\n self.balances[tokenIndex] = self.balances[tokenIndex].sub(\n dy.add(dyFee.mul(self.adminFee).div(FEE_DENOMINATOR))\n );\n lpToken.burnFrom(msg.sender, tokenAmount);\n pooledTokens[tokenIndex].safeTransfer(msg.sender, dy);\n\n emit RemoveLiquidityOne(\n msg.sender,\n tokenAmount,\n totalSupply,\n tokenIndex,\n dy\n );\n\n return dy;\n }\n\n /**\n * @notice Remove liquidity from the pool, weighted differently than the\n * pool's current balances.\n *\n * @param self Swap struct to read from and write to\n * @param amounts how much of each token to withdraw\n * @param maxBurnAmount the max LP token provider is willing to pay to\n * remove liquidity. Useful as a front-running mitigation.\n * @return actual amount of LP tokens burned in the withdrawal\n */\n function removeLiquidityImbalance(\n Swap storage self,\n uint256[] memory amounts,\n uint256 maxBurnAmount\n ) public returns (uint256) {\n ManageLiquidityInfo memory v = ManageLiquidityInfo(\n 0,\n 0,\n 0,\n _getAPrecise(self),\n self.lpToken,\n 0,\n self.balances,\n self.tokenPrecisionMultipliers\n );\n v.totalSupply = v.lpToken.totalSupply();\n\n IERC20[] memory pooledTokens = self.pooledTokens;\n\n require(\n amounts.length == pooledTokens.length,\n \"Amounts should match pool tokens\"\n );\n\n require(\n maxBurnAmount <= v.lpToken.balanceOf(msg.sender) &&\n maxBurnAmount != 0,\n \">LP.balanceOf\"\n );\n\n uint256 feePerToken = _feePerToken(self.swapFee, pooledTokens.length);\n uint256[] memory fees = new uint256[](pooledTokens.length);\n {\n uint256[] memory balances1 = new uint256[](pooledTokens.length);\n v.d0 = getD(_xp(v.balances, v.multipliers), v.preciseA);\n for (uint256 i = 0; i < pooledTokens.length; i++) {\n balances1[i] = v.balances[i].sub(\n amounts[i],\n \"Cannot withdraw more than available\"\n );\n }\n v.d1 = getD(_xp(balances1, v.multipliers), v.preciseA);\n\n for (uint256 i = 0; i < pooledTokens.length; i++) {\n uint256 idealBalance = v.d1.mul(v.balances[i]).div(v.d0);\n uint256 difference = idealBalance.difference(balances1[i]);\n fees[i] = feePerToken.mul(difference).div(FEE_DENOMINATOR);\n self.balances[i] = balances1[i].sub(\n fees[i].mul(self.adminFee).div(FEE_DENOMINATOR)\n );\n balances1[i] = balances1[i].sub(fees[i]);\n }\n\n v.d2 = getD(_xp(balances1, v.multipliers), v.preciseA);\n }\n uint256 tokenAmount = v.d0.sub(v.d2).mul(v.totalSupply).div(v.d0);\n require(tokenAmount != 0, \"Burnt amount cannot be zero\");\n tokenAmount = tokenAmount.add(1);\n\n require(tokenAmount <= maxBurnAmount, \"tokenAmount > maxBurnAmount\");\n\n v.lpToken.burnFrom(msg.sender, tokenAmount);\n\n for (uint256 i = 0; i < pooledTokens.length; i++) {\n pooledTokens[i].safeTransfer(msg.sender, amounts[i]);\n }\n\n emit RemoveLiquidityImbalance(\n msg.sender,\n amounts,\n fees,\n v.d1,\n v.totalSupply.sub(tokenAmount)\n );\n\n return tokenAmount;\n }\n\n /**\n * @notice withdraw all admin fees to a given address\n * @param self Swap struct to withdraw fees from\n * @param to Address to send the fees to\n */\n function withdrawAdminFees(Swap storage self, address to) external {\n IERC20[] memory pooledTokens = self.pooledTokens;\n for (uint256 i = 0; i < pooledTokens.length; i++) {\n IERC20 token = pooledTokens[i];\n uint256 balance = token.balanceOf(address(this)).sub(\n self.balances[i]\n );\n if (balance != 0) {\n token.safeTransfer(to, balance);\n }\n }\n }\n\n /**\n * @notice Sets the admin fee\n * @dev adminFee cannot be higher than 100% of the swap fee\n * @param self Swap struct to update\n * @param newAdminFee new admin fee to be applied on future transactions\n */\n function setAdminFee(Swap storage self, uint256 newAdminFee) external {\n require(newAdminFee <= MAX_ADMIN_FEE, \"Fee is too high\");\n self.adminFee = newAdminFee;\n\n emit NewAdminFee(newAdminFee);\n }\n\n /**\n * @notice update the swap fee\n * @dev fee cannot be higher than 1% of each swap\n * @param self Swap struct to update\n * @param newSwapFee new swap fee to be applied on future transactions\n */\n function setSwapFee(Swap storage self, uint256 newSwapFee) external {\n require(newSwapFee <= MAX_SWAP_FEE, \"Fee is too high\");\n self.swapFee = newSwapFee;\n\n emit NewSwapFee(newSwapFee);\n }\n}\n" + }, + "contracts/amm/AmplificationUtils.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.6.12;\n\nimport \"@openzeppelin/contracts/token/ERC20/SafeERC20.sol\";\nimport \"./SwapUtils.sol\";\n\n/**\n * @title AmplificationUtils library\n * @notice A library to calculate and ramp the A parameter of a given `SwapUtils.Swap` struct.\n * This library assumes the struct is fully validated.\n */\nlibrary AmplificationUtils {\n using SafeMath for uint256;\n\n event RampA(\n uint256 oldA,\n uint256 newA,\n uint256 initialTime,\n uint256 futureTime\n );\n event StopRampA(uint256 currentA, uint256 time);\n\n // Constant values used in ramping A calculations\n uint256 public constant A_PRECISION = 100;\n uint256 public constant MAX_A = 10**6;\n uint256 private constant MAX_A_CHANGE = 2;\n uint256 private constant MIN_RAMP_TIME = 7 days;\n\n /**\n * @notice Return A, the amplification coefficient * n * (n - 1)\n * @dev See the StableSwap paper for details\n * @param self Swap struct to read from\n * @return A parameter\n */\n function getA(SwapUtils.Swap storage self) external view returns (uint256) {\n return _getAPrecise(self).div(A_PRECISION);\n }\n\n /**\n * @notice Return A in its raw precision\n * @dev See the StableSwap paper for details\n * @param self Swap struct to read from\n * @return A parameter in its raw precision form\n */\n function getAPrecise(SwapUtils.Swap storage self)\n external\n view\n returns (uint256)\n {\n return _getAPrecise(self);\n }\n\n /**\n * @notice Return A in its raw precision\n * @dev See the StableSwap paper for details\n * @param self Swap struct to read from\n * @return A parameter in its raw precision form\n */\n function _getAPrecise(SwapUtils.Swap storage self)\n internal\n view\n returns (uint256)\n {\n uint256 t1 = self.futureATime; // time when ramp is finished\n uint256 a1 = self.futureA; // final A value when ramp is finished\n\n if (block.timestamp < t1) {\n uint256 t0 = self.initialATime; // time when ramp is started\n uint256 a0 = self.initialA; // initial A value when ramp is started\n if (a1 > a0) {\n // a0 + (a1 - a0) * (block.timestamp - t0) / (t1 - t0)\n return\n a0.add(\n a1.sub(a0).mul(block.timestamp.sub(t0)).div(t1.sub(t0))\n );\n } else {\n // a0 - (a0 - a1) * (block.timestamp - t0) / (t1 - t0)\n return\n a0.sub(\n a0.sub(a1).mul(block.timestamp.sub(t0)).div(t1.sub(t0))\n );\n }\n } else {\n return a1;\n }\n }\n\n /**\n * @notice Start ramping up or down A parameter towards given futureA_ and futureTime_\n * Checks if the change is too rapid, and commits the new A value only when it falls under\n * the limit range.\n * @param self Swap struct to update\n * @param futureA_ the new A to ramp towards\n * @param futureTime_ timestamp when the new A should be reached\n */\n function rampA(\n SwapUtils.Swap storage self,\n uint256 futureA_,\n uint256 futureTime_\n ) external {\n require(\n block.timestamp >= self.initialATime.add(1 days),\n \"Wait 1 day before starting ramp\"\n );\n require(\n futureTime_ >= block.timestamp.add(MIN_RAMP_TIME),\n \"Insufficient ramp time\"\n );\n require(\n futureA_ > 0 && futureA_ < MAX_A,\n \"futureA_ must be > 0 and < MAX_A\"\n );\n\n uint256 initialAPrecise = _getAPrecise(self);\n uint256 futureAPrecise = futureA_.mul(A_PRECISION);\n\n if (futureAPrecise < initialAPrecise) {\n require(\n futureAPrecise.mul(MAX_A_CHANGE) >= initialAPrecise,\n \"futureA_ is too small\"\n );\n } else {\n require(\n futureAPrecise <= initialAPrecise.mul(MAX_A_CHANGE),\n \"futureA_ is too large\"\n );\n }\n\n self.initialA = initialAPrecise;\n self.futureA = futureAPrecise;\n self.initialATime = block.timestamp;\n self.futureATime = futureTime_;\n\n emit RampA(\n initialAPrecise,\n futureAPrecise,\n block.timestamp,\n futureTime_\n );\n }\n\n /**\n * @notice Stops ramping A immediately. Once this function is called, rampA()\n * cannot be called for another 24 hours\n * @param self Swap struct to update\n */\n function stopRampA(SwapUtils.Swap storage self) external {\n require(self.futureATime > block.timestamp, \"Ramp is already stopped\");\n\n uint256 currentA = _getAPrecise(self);\n self.initialA = currentA;\n self.futureA = currentA;\n self.initialATime = block.timestamp;\n self.futureATime = block.timestamp;\n\n emit StopRampA(currentA, block.timestamp);\n }\n}\n" + }, + "@openzeppelin/contracts/token/ERC20/IERC20.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <0.8.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" + }, + "@openzeppelin/contracts/utils/Address.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.2 <0.8.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" + }, + "@openzeppelin/contracts-upgradeable/proxy/Initializable.sol": { + "content": "// SPDX-License-Identifier: MIT\n\n// solhint-disable-next-line compiler-version\npragma solidity >=0.4.24 <0.8.0;\n\nimport \"../utils/AddressUpgradeable.sol\";\n\n/**\n * @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed\n * behind a proxy. Since a proxied contract can't have a constructor, it's common to move constructor logic to an\n * external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer\n * function so it can only be called once. The {initializer} modifier provided by this contract will have this effect.\n *\n * TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as\n * possible by providing the encoded function call as the `_data` argument to {UpgradeableProxy-constructor}.\n *\n * CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure\n * that all initializers are idempotent. This is not verified automatically as constructors are by Solidity.\n */\nabstract contract Initializable {\n\n /**\n * @dev Indicates that the contract has been initialized.\n */\n bool private _initialized;\n\n /**\n * @dev Indicates that the contract is in the process of being initialized.\n */\n bool private _initializing;\n\n /**\n * @dev Modifier to protect an initializer function from being invoked twice.\n */\n modifier initializer() {\n require(_initializing || _isConstructor() || !_initialized, \"Initializable: contract is already initialized\");\n\n bool isTopLevelCall = !_initializing;\n if (isTopLevelCall) {\n _initializing = true;\n _initialized = true;\n }\n\n _;\n\n if (isTopLevelCall) {\n _initializing = false;\n }\n }\n\n /// @dev Returns true if and only if the function is running in the constructor\n function _isConstructor() private view returns (bool) {\n return !AddressUpgradeable.isContract(address(this));\n }\n}\n" + }, + "@openzeppelin/contracts-upgradeable/utils/AddressUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.2 <0.8.0;\n\n/**\n * @dev Collection of functions related to the address type\n */\nlibrary AddressUpgradeable {\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 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" + }, + "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <0.8.0;\n\nimport \"../utils/ContextUpgradeable.sol\";\nimport \"../proxy/Initializable.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 OwnableUpgradeable is Initializable, ContextUpgradeable {\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 function __Ownable_init() internal initializer {\n __Context_init_unchained();\n __Ownable_init_unchained();\n }\n\n function __Ownable_init_unchained() internal initializer {\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 uint256[49] private __gap;\n}\n" + }, + "@openzeppelin/contracts-upgradeable/utils/PausableUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <0.8.0;\n\nimport \"./ContextUpgradeable.sol\";\nimport \"../proxy/Initializable.sol\";\n\n/**\n * @dev Contract module which allows children to implement an emergency stop\n * mechanism that can be triggered by an authorized account.\n *\n * This module is used through inheritance. It will make available the\n * modifiers `whenNotPaused` and `whenPaused`, which can be applied to\n * the functions of your contract. Note that they will not be pausable by\n * simply including this module, only once the modifiers are put in place.\n */\nabstract contract PausableUpgradeable is Initializable, ContextUpgradeable {\n /**\n * @dev Emitted when the pause is triggered by `account`.\n */\n event Paused(address account);\n\n /**\n * @dev Emitted when the pause is lifted by `account`.\n */\n event Unpaused(address account);\n\n bool private _paused;\n\n /**\n * @dev Initializes the contract in unpaused state.\n */\n function __Pausable_init() internal initializer {\n __Context_init_unchained();\n __Pausable_init_unchained();\n }\n\n function __Pausable_init_unchained() internal initializer {\n _paused = false;\n }\n\n /**\n * @dev Returns true if the contract is paused, and false otherwise.\n */\n function paused() public view virtual returns (bool) {\n return _paused;\n }\n\n /**\n * @dev Modifier to make a function callable only when the contract is not paused.\n *\n * Requirements:\n *\n * - The contract must not be paused.\n */\n modifier whenNotPaused() {\n require(!paused(), \"Pausable: paused\");\n _;\n }\n\n /**\n * @dev Modifier to make a function callable only when the contract is paused.\n *\n * Requirements:\n *\n * - The contract must be paused.\n */\n modifier whenPaused() {\n require(paused(), \"Pausable: not paused\");\n _;\n }\n\n /**\n * @dev Triggers stopped state.\n *\n * Requirements:\n *\n * - The contract must not be paused.\n */\n function _pause() internal virtual whenNotPaused {\n _paused = true;\n emit Paused(_msgSender());\n }\n\n /**\n * @dev Returns to normal state.\n *\n * Requirements:\n *\n * - The contract must be paused.\n */\n function _unpause() internal virtual whenPaused {\n _paused = false;\n emit Unpaused(_msgSender());\n }\n uint256[49] private __gap;\n}\n" + }, + "@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <0.8.0;\nimport \"../proxy/Initializable.sol\";\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 ContextUpgradeable is Initializable {\n function __Context_init() internal initializer {\n __Context_init_unchained();\n }\n\n function __Context_init_unchained() internal initializer {\n }\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 uint256[50] private __gap;\n}\n" + }, + "contracts/amm/LPToken.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.6.12;\n\nimport \"@openzeppelin/contracts-upgradeable/token/ERC20/ERC20BurnableUpgradeable.sol\";\nimport \"@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol\";\nimport \"./interfaces/ISwap.sol\";\n\n/**\n * @title Liquidity Provider Token\n * @notice This token is an ERC20 detailed token with added capability to be minted by the owner.\n * It is used to represent user's shares when providing liquidity to swap contracts.\n * @dev Only Swap contracts should initialize and own LPToken contracts.\n */\ncontract LPToken is ERC20BurnableUpgradeable, OwnableUpgradeable {\n using SafeMathUpgradeable for uint256;\n\n /**\n * @notice Initializes this LPToken contract with the given name and symbol\n * @dev The caller of this function will become the owner. A Swap contract should call this\n * in its initializer function.\n * @param name name of this token\n * @param symbol symbol of this token\n */\n function initialize(string memory name, string memory symbol)\n external\n initializer\n returns (bool)\n {\n __Context_init_unchained();\n __ERC20_init_unchained(name, symbol);\n __Ownable_init_unchained();\n return true;\n }\n\n /**\n * @notice Mints the given amount of LPToken to the recipient.\n * @dev only owner can call this mint function\n * @param recipient address of account to receive the tokens\n * @param amount amount of tokens to mint\n */\n function mint(address recipient, uint256 amount) external onlyOwner {\n require(amount != 0, \"LPToken: cannot mint 0\");\n _mint(recipient, amount);\n }\n\n /**\n * @dev Overrides ERC20._beforeTokenTransfer() which get called on every transfers including\n * minting and burning. * This assumes the owner is set to a Swap contract's address.\n */\n function _beforeTokenTransfer(\n address from,\n address to,\n uint256 amount\n ) internal virtual override(ERC20Upgradeable) {\n super._beforeTokenTransfer(from, to, amount);\n require(to != address(this), \"LPToken: cannot send to itself\");\n }\n}\n" + }, + "contracts/amm/MathUtils.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.6.12;\n\nimport \"@openzeppelin/contracts/math/SafeMath.sol\";\n\n/**\n * @title MathUtils library\n * @notice A library to be used in conjunction with SafeMath. Contains functions for calculating\n * differences between two uint256.\n */\nlibrary MathUtils {\n /**\n * @notice Compares a and b and returns true if the difference between a and b\n * is less than 1 or equal to each other.\n * @param a uint256 to compare with\n * @param b uint256 to compare with\n * @return True if the difference between a and b is less than 1 or equal,\n * otherwise return false\n */\n function within1(uint256 a, uint256 b) internal pure returns (bool) {\n return (difference(a, b) <= 1);\n }\n\n /**\n * @notice Calculates absolute difference between a and b\n * @param a uint256 to compare with\n * @param b uint256 to compare with\n * @return Difference between a and b\n */\n function difference(uint256 a, uint256 b) internal pure returns (uint256) {\n if (a > b) {\n return a - b;\n }\n return b - a;\n }\n}\n" + }, + "@openzeppelin/contracts-upgradeable/token/ERC20/ERC20BurnableUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <0.8.0;\n\nimport \"../../utils/ContextUpgradeable.sol\";\nimport \"./ERC20Upgradeable.sol\";\nimport \"../../proxy/Initializable.sol\";\n\n/**\n * @dev Extension of {ERC20} that allows token holders to destroy both their own\n * tokens and those that they have an allowance for, in a way that can be\n * recognized off-chain (via event analysis).\n */\nabstract contract ERC20BurnableUpgradeable is Initializable, ContextUpgradeable, ERC20Upgradeable {\n function __ERC20Burnable_init() internal initializer {\n __Context_init_unchained();\n __ERC20Burnable_init_unchained();\n }\n\n function __ERC20Burnable_init_unchained() internal initializer {\n }\n using SafeMathUpgradeable for uint256;\n\n /**\n * @dev Destroys `amount` tokens from the caller.\n *\n * See {ERC20-_burn}.\n */\n function burn(uint256 amount) public virtual {\n _burn(_msgSender(), amount);\n }\n\n /**\n * @dev Destroys `amount` tokens from `account`, deducting from the caller's\n * allowance.\n *\n * See {ERC20-_burn} and {ERC20-allowance}.\n *\n * Requirements:\n *\n * - the caller must have allowance for ``accounts``'s tokens of at least\n * `amount`.\n */\n function burnFrom(address account, uint256 amount) public virtual {\n uint256 decreasedAllowance = allowance(account, _msgSender()).sub(amount, \"ERC20: burn amount exceeds allowance\");\n\n _approve(account, _msgSender(), decreasedAllowance);\n _burn(account, amount);\n }\n uint256[50] private __gap;\n}\n" + }, + "contracts/amm/interfaces/ISwap.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.6.12;\n\nimport \"@openzeppelin/contracts/token/ERC20/ERC20.sol\";\n\ninterface ISwap {\n // pool data view functions\n function getA() external view returns (uint256);\n\n function getToken(uint8 index) external view returns (IERC20);\n\n function getTokenIndex(address tokenAddress) external view returns (uint8);\n\n function getTokenBalance(uint8 index) external view returns (uint256);\n\n function getVirtualPrice() external view returns (uint256);\n\n // min return calculation functions\n function calculateSwap(\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx\n ) external view returns (uint256);\n\n function calculateTokenAmount(uint256[] calldata amounts, bool deposit)\n external\n view\n returns (uint256);\n\n function calculateRemoveLiquidity(uint256 amount)\n external\n view\n returns (uint256[] memory);\n\n function calculateRemoveLiquidityOneToken(\n uint256 tokenAmount,\n uint8 tokenIndex\n ) external view returns (uint256 availableTokenAmount);\n\n // state modifying functions\n function initialize(\n IERC20[] memory pooledTokens,\n uint8[] memory decimals,\n string memory lpTokenName,\n string memory lpTokenSymbol,\n uint256 a,\n uint256 fee,\n uint256 adminFee,\n address lpTokenTargetAddress\n ) external;\n\n function swap(\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx,\n uint256 minDy,\n uint256 deadline\n ) external returns (uint256);\n\n function addLiquidity(\n uint256[] calldata amounts,\n uint256 minToMint,\n uint256 deadline\n ) external returns (uint256);\n\n function removeLiquidity(\n uint256 amount,\n uint256[] calldata minAmounts,\n uint256 deadline\n ) external returns (uint256[] memory);\n\n function removeLiquidityOneToken(\n uint256 tokenAmount,\n uint8 tokenIndex,\n uint256 minAmount,\n uint256 deadline\n ) external returns (uint256);\n\n function removeLiquidityImbalance(\n uint256[] calldata amounts,\n uint256 maxBurnAmount,\n uint256 deadline\n ) external returns (uint256);\n}\n" + }, + "@openzeppelin/contracts-upgradeable/token/ERC20/ERC20Upgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <0.8.0;\n\nimport \"../../utils/ContextUpgradeable.sol\";\nimport \"./IERC20Upgradeable.sol\";\nimport \"../../math/SafeMathUpgradeable.sol\";\nimport \"../../proxy/Initializable.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 ERC20Upgradeable is Initializable, ContextUpgradeable, IERC20Upgradeable {\n using SafeMathUpgradeable 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 function __ERC20_init(string memory name_, string memory symbol_) internal initializer {\n __Context_init_unchained();\n __ERC20_init_unchained(name_, symbol_);\n }\n\n function __ERC20_init_unchained(string memory name_, string memory symbol_) internal initializer {\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 uint256[44] private __gap;\n}\n" + }, + "@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <0.8.0;\n\n/**\n * @dev Interface of the ERC20 standard as defined in the EIP.\n */\ninterface IERC20Upgradeable {\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" + }, + "@openzeppelin/contracts-upgradeable/math/SafeMathUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <0.8.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 SafeMathUpgradeable {\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" + }, + "@openzeppelin/contracts/token/ERC20/ERC20.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <0.8.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_) public {\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" + }, + "@openzeppelin/contracts/utils/Context.sol": { + "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" + }, + "contracts/amm/SwapFlashLoan.sol": { + "content": "// SPDX-License-Identifier: MIT WITH AGPL-3.0-only\n\npragma solidity 0.6.12;\n\nimport \"./Swap.sol\";\nimport \"./interfaces/IFlashLoanReceiver.sol\";\n\n/**\n * @title Swap - A StableSwap implementation in solidity.\n * @notice This contract is responsible for custody of closely pegged assets (eg. group of stablecoins)\n * and automatic market making system. Users become an LP (Liquidity Provider) by depositing their tokens\n * in desired ratios for an exchange of the pool token that represents their share of the pool.\n * Users can burn pool tokens and withdraw their share of token(s).\n *\n * Each time a swap between the pooled tokens happens, a set fee incurs which effectively gets\n * distributed to the LPs.\n *\n * In case of emergencies, admin can pause additional deposits, swaps, or single-asset withdraws - which\n * stops the ratio of the tokens in the pool from changing.\n * Users can always withdraw their tokens via multi-asset withdraws.\n *\n * @dev Most of the logic is stored as a library `SwapUtils` for the sake of reducing contract's\n * deployment size.\n */\ncontract SwapFlashLoan is Swap {\n // Total fee that is charged on all flashloans in BPS. Borrowers must repay the amount plus the flash loan fee.\n // This fee is split between the protocol and the pool.\n uint256 public flashLoanFeeBPS;\n // Share of the flash loan fee that goes to the protocol in BPS. A portion of each flash loan fee is allocated\n // to the protocol rather than the pool.\n uint256 public protocolFeeShareBPS;\n // Max BPS for limiting flash loan fee settings.\n uint256 public constant MAX_BPS = 10000;\n\n /*** EVENTS ***/\n event FlashLoan(\n address indexed receiver,\n uint8 tokenIndex,\n uint256 amount,\n uint256 amountFee,\n uint256 protocolFee\n );\n\n /**\n * @notice Initializes this Swap contract with the given parameters.\n * This will also clone a LPToken contract that represents users'\n * LP positions. The owner of LPToken will be this contract - which means\n * only this contract is allowed to mint/burn tokens.\n *\n * @param _pooledTokens an array of ERC20s this pool will accept\n * @param decimals the decimals to use for each pooled token,\n * eg 8 for WBTC. Cannot be larger than POOL_PRECISION_DECIMALS\n * @param lpTokenName the long-form name of the token to be deployed\n * @param lpTokenSymbol the short symbol for the token to be deployed\n * @param _a the amplification coefficient * n * (n - 1). See the\n * StableSwap paper for details\n * @param _fee default swap fee to be initialized with\n * @param _adminFee default adminFee to be initialized with\n * @param lpTokenTargetAddress the address of an existing LPToken contract to use as a target\n */\n function initialize(\n IERC20[] memory _pooledTokens,\n uint8[] memory decimals,\n string memory lpTokenName,\n string memory lpTokenSymbol,\n uint256 _a,\n uint256 _fee,\n uint256 _adminFee,\n address lpTokenTargetAddress\n ) public virtual override initializer {\n Swap.initialize(\n _pooledTokens,\n decimals,\n lpTokenName,\n lpTokenSymbol,\n _a,\n _fee,\n _adminFee,\n lpTokenTargetAddress\n );\n flashLoanFeeBPS = 8; // 8 bps\n protocolFeeShareBPS = 0; // 0 bps\n }\n\n /*** STATE MODIFYING FUNCTIONS ***/\n\n /**\n * @notice Borrow the specified token from this pool for this transaction only. This function will call\n * `IFlashLoanReceiver(receiver).executeOperation` and the `receiver` must return the full amount of the token\n * and the associated fee by the end of the callback transaction. If the conditions are not met, this call\n * is reverted.\n * @param receiver the address of the receiver of the token. This address must implement the IFlashLoanReceiver\n * interface and the callback function `executeOperation`.\n * @param token the protocol fee in bps to be applied on the total flash loan fee\n * @param amount the total amount to borrow in this transaction\n * @param params optional data to pass along to the callback function\n */\n function flashLoan(\n address receiver,\n IERC20 token,\n uint256 amount,\n bytes memory params\n ) external nonReentrant {\n uint8 tokenIndex = getTokenIndex(address(token));\n uint256 availableLiquidityBefore = token.balanceOf(address(this));\n uint256 protocolBalanceBefore = availableLiquidityBefore.sub(\n swapStorage.balances[tokenIndex]\n );\n require(\n amount > 0 && availableLiquidityBefore >= amount,\n \"invalid amount\"\n );\n\n // Calculate the additional amount of tokens the pool should end up with\n uint256 amountFee = amount.mul(flashLoanFeeBPS).div(10000);\n // Calculate the portion of the fee that will go to the protocol\n uint256 protocolFee = amountFee.mul(protocolFeeShareBPS).div(10000);\n require(amountFee > 0, \"amount is small for a flashLoan\");\n\n // Transfer the requested amount of tokens\n token.safeTransfer(receiver, amount);\n\n // Execute callback function on receiver\n IFlashLoanReceiver(receiver).executeOperation(\n address(this),\n address(token),\n amount,\n amountFee,\n params\n );\n\n uint256 availableLiquidityAfter = token.balanceOf(address(this));\n require(\n availableLiquidityAfter >= availableLiquidityBefore.add(amountFee),\n \"flashLoan fee is not met\"\n );\n\n swapStorage.balances[tokenIndex] = availableLiquidityAfter\n .sub(protocolBalanceBefore)\n .sub(protocolFee);\n emit FlashLoan(receiver, tokenIndex, amount, amountFee, protocolFee);\n }\n\n /*** ADMIN FUNCTIONS ***/\n\n /**\n * @notice Updates the flash loan fee parameters. This function can only be called by the owner.\n * @param newFlashLoanFeeBPS the total fee in bps to be applied on future flash loans\n * @param newProtocolFeeShareBPS the protocol fee in bps to be applied on the total flash loan fee\n */\n function setFlashLoanFees(\n uint256 newFlashLoanFeeBPS,\n uint256 newProtocolFeeShareBPS\n ) external onlyOwner {\n require(\n newFlashLoanFeeBPS > 0 &&\n newFlashLoanFeeBPS <= MAX_BPS &&\n newProtocolFeeShareBPS <= MAX_BPS,\n \"fees are not in valid range\"\n );\n flashLoanFeeBPS = newFlashLoanFeeBPS;\n protocolFeeShareBPS = newProtocolFeeShareBPS;\n }\n}\n" + }, + "contracts/amm/interfaces/IFlashLoanReceiver.sol": { + "content": "// SPDX-License-Identifier: AGPL-3.0-only\n\npragma solidity 0.6.12;\n\n/**\n * @title IFlashLoanReceiver interface\n * @notice Interface for the Nerve fee IFlashLoanReceiver. Modified from Aave's IFlashLoanReceiver interface.\n * https://github.com/aave/aave-protocol/blob/4b4545fb583fd4f400507b10f3c3114f45b8a037/contracts/flashloan/interfaces/IFlashLoanReceiver.sol\n * @author Aave\n * @dev implement this interface to develop a flashloan-compatible flashLoanReceiver contract\n **/\ninterface IFlashLoanReceiver {\n function executeOperation(\n address pool,\n address token,\n uint256 amount,\n uint256 fee,\n bytes calldata params\n ) external;\n}\n" + }, + "contracts/amm/helper/FlashLoanBorrowerExample.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.6.12;\n\nimport \"@openzeppelin/contracts/math/SafeMath.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/SafeERC20.sol\";\nimport \"../interfaces/IFlashLoanReceiver.sol\";\nimport \"../interfaces/ISwapFlashLoan.sol\";\nimport \"hardhat/console.sol\";\n\ncontract FlashLoanBorrowerExample is IFlashLoanReceiver {\n using SafeMath for uint256;\n\n // Typical executeOperation function should do the 3 following actions\n // 1. Check if the flashLoan was successful\n // 2. Do actions with the borrowed tokens\n // 3. Repay the debt to the `pool`\n function executeOperation(\n address pool,\n address token,\n uint256 amount,\n uint256 fee,\n bytes calldata params\n ) external override {\n // 1. Check if the flashLoan was valid\n require(\n IERC20(token).balanceOf(address(this)) >= amount,\n \"flashloan is broken?\"\n );\n\n // 2. Do actions with the borrowed token\n bytes32 paramsHash = keccak256(params);\n if (paramsHash == keccak256(bytes(\"dontRepayDebt\"))) {\n return;\n } else if (paramsHash == keccak256(bytes(\"reentrancy_addLiquidity\"))) {\n ISwapFlashLoan(pool).addLiquidity(\n new uint256[](0),\n 0,\n block.timestamp\n );\n } else if (paramsHash == keccak256(bytes(\"reentrancy_swap\"))) {\n ISwapFlashLoan(pool).swap(1, 0, 1e6, 0, now);\n } else if (\n paramsHash == keccak256(bytes(\"reentrancy_removeLiquidity\"))\n ) {\n ISwapFlashLoan(pool).removeLiquidity(1e18, new uint256[](0), now);\n } else if (\n paramsHash == keccak256(bytes(\"reentrancy_removeLiquidityOneToken\"))\n ) {\n ISwapFlashLoan(pool).removeLiquidityOneToken(1e18, 0, 1e18, now);\n }\n\n // 3. Payback debt\n uint256 totalDebt = amount.add(fee);\n IERC20(token).transfer(pool, totalDebt);\n }\n\n function flashLoan(\n ISwapFlashLoan swap,\n IERC20 token,\n uint256 amount,\n bytes memory params\n ) external {\n swap.flashLoan(address(this), token, amount, params);\n }\n}\n" + }, + "contracts/amm/interfaces/ISwapFlashLoan.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.6.12;\n\nimport \"./ISwap.sol\";\n\ninterface ISwapFlashLoan is ISwap {\n function flashLoan(\n address receiver,\n IERC20 token,\n uint256 amount,\n bytes memory params\n ) external;\n}\n" + }, + "hardhat/console.sol": { + "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" + }, + "contracts/amm/helper/test/TestSwapReturnValues.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.6.12;\n\nimport \"../../interfaces/ISwap.sol\";\nimport \"hardhat/console.sol\";\n\ncontract TestSwapReturnValues {\n using SafeMath for uint256;\n\n ISwap public swap;\n IERC20 public lpToken;\n uint8 public n;\n\n uint256 public constant MAX_INT = 2**256 - 1;\n\n constructor(\n ISwap swapContract,\n IERC20 lpTokenContract,\n uint8 numOfTokens\n ) public {\n swap = swapContract;\n lpToken = lpTokenContract;\n n = numOfTokens;\n\n // Pre-approve tokens\n for (uint8 i; i < n; i++) {\n swap.getToken(i).approve(address(swap), MAX_INT);\n }\n lpToken.approve(address(swap), MAX_INT);\n }\n\n function test_swap(\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx,\n uint256 minDy\n ) public {\n uint256 balanceBefore =\n swap.getToken(tokenIndexTo).balanceOf(address(this));\n uint256 returnValue =\n swap.swap(tokenIndexFrom, tokenIndexTo, dx, minDy, block.timestamp);\n uint256 balanceAfter =\n swap.getToken(tokenIndexTo).balanceOf(address(this));\n\n console.log(\n \"swap: Expected %s, got %s\",\n balanceAfter.sub(balanceBefore),\n returnValue\n );\n\n require(\n returnValue == balanceAfter.sub(balanceBefore),\n \"swap()'s return value does not match received amount\"\n );\n }\n\n function test_addLiquidity(uint256[] calldata amounts, uint256 minToMint)\n public\n {\n uint256 balanceBefore = lpToken.balanceOf(address(this));\n uint256 returnValue = swap.addLiquidity(amounts, minToMint, MAX_INT);\n uint256 balanceAfter = lpToken.balanceOf(address(this));\n\n console.log(\n \"addLiquidity: Expected %s, got %s\",\n balanceAfter.sub(balanceBefore),\n returnValue\n );\n\n require(\n returnValue == balanceAfter.sub(balanceBefore),\n \"addLiquidity()'s return value does not match minted amount\"\n );\n }\n\n function test_removeLiquidity(uint256 amount, uint256[] memory minAmounts)\n public\n {\n uint256[] memory balanceBefore = new uint256[](n);\n uint256[] memory balanceAfter = new uint256[](n);\n\n for (uint8 i = 0; i < n; i++) {\n balanceBefore[i] = swap.getToken(i).balanceOf(address(this));\n }\n\n uint256[] memory returnValue =\n swap.removeLiquidity(amount, minAmounts, MAX_INT);\n\n for (uint8 i = 0; i < n; i++) {\n balanceAfter[i] = swap.getToken(i).balanceOf(address(this));\n console.log(\n \"removeLiquidity: Expected %s, got %s\",\n balanceAfter[i].sub(balanceBefore[i]),\n returnValue[i]\n );\n require(\n balanceAfter[i].sub(balanceBefore[i]) == returnValue[i],\n \"removeLiquidity()'s return value does not match received amounts of tokens\"\n );\n }\n }\n\n function test_removeLiquidityImbalance(\n uint256[] calldata amounts,\n uint256 maxBurnAmount\n ) public {\n uint256 balanceBefore = lpToken.balanceOf(address(this));\n uint256 returnValue =\n swap.removeLiquidityImbalance(amounts, maxBurnAmount, MAX_INT);\n uint256 balanceAfter = lpToken.balanceOf(address(this));\n\n console.log(\n \"removeLiquidityImbalance: Expected %s, got %s\",\n balanceBefore.sub(balanceAfter),\n returnValue\n );\n\n require(\n returnValue == balanceBefore.sub(balanceAfter),\n \"removeLiquidityImbalance()'s return value does not match burned lpToken amount\"\n );\n }\n\n function test_removeLiquidityOneToken(\n uint256 tokenAmount,\n uint8 tokenIndex,\n uint256 minAmount\n ) public {\n uint256 balanceBefore =\n swap.getToken(tokenIndex).balanceOf(address(this));\n uint256 returnValue =\n swap.removeLiquidityOneToken(\n tokenAmount,\n tokenIndex,\n minAmount,\n MAX_INT\n );\n uint256 balanceAfter =\n swap.getToken(tokenIndex).balanceOf(address(this));\n\n console.log(\n \"removeLiquidityOneToken: Expected %s, got %s\",\n balanceAfter.sub(balanceBefore),\n returnValue\n );\n\n require(\n returnValue == balanceAfter.sub(balanceBefore),\n \"removeLiquidityOneToken()'s return value does not match received token amount\"\n );\n }\n}\n" + }, + "contracts/amm/SwapDeployer.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.6.12;\n\nimport \"@openzeppelin/contracts/access/Ownable.sol\";\nimport \"@openzeppelin/contracts/proxy/Clones.sol\";\nimport \"./interfaces/ISwap.sol\";\n\ncontract SwapDeployer is Ownable {\n event NewSwapPool(\n address indexed deployer,\n address swapAddress,\n IERC20[] pooledTokens\n );\n\n constructor() public Ownable() {}\n\n function deploy(\n address swapAddress,\n IERC20[] memory _pooledTokens,\n uint8[] memory decimals,\n string memory lpTokenName,\n string memory lpTokenSymbol,\n uint256 _a,\n uint256 _fee,\n uint256 _adminFee,\n address lpTokenTargetAddress\n ) external returns (address) {\n address swapClone = Clones.clone(swapAddress);\n ISwap(swapClone).initialize(\n _pooledTokens,\n decimals,\n lpTokenName,\n lpTokenSymbol,\n _a,\n _fee,\n _adminFee,\n lpTokenTargetAddress\n );\n Ownable(swapClone).transferOwnership(owner());\n emit NewSwapPool(msg.sender, swapClone, _pooledTokens);\n return swapClone;\n }\n}\n" + }, + "@openzeppelin/contracts/access/Ownable.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <0.8.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 () internal {\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" + }, + "contracts/bridge/SynapseERC20Factory.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.6.12;\n\nimport \"@openzeppelin/contracts/access/Ownable.sol\";\nimport \"@openzeppelin/contracts/proxy/Clones.sol\";\nimport \"./interfaces/ISynapseERC20.sol\";\n\ncontract SynapseERC20Factory {\n constructor() public {}\n\n event SynapseERC20Created(address contractAddress);\n\n /**\n * @notice Deploys a new node\n * @param synapseERC20Address address of the synapseERC20Address contract to initialize with\n * @param name Token name\n * @param symbol Token symbol\n * @param decimals Token name\n * @param owner admin address to be initialized with\n * @return Address of the newest node management contract created\n **/\n function deploy(\n address synapseERC20Address,\n string memory name,\n string memory symbol,\n uint8 decimals,\n address owner\n ) external returns (address) {\n address synERC20Clone = Clones.clone(synapseERC20Address);\n ISynapseERC20(synERC20Clone).initialize(name, symbol, decimals, owner);\n\n emit SynapseERC20Created(synERC20Clone);\n\n return synERC20Clone;\n }\n}\n" + }, + "contracts/bridge/interfaces/ISynapseERC20.sol": { + "content": "// SPDX-License-Identifier: MIT\n\n\npragma solidity 0.6.12;\n\ninterface ISynapseERC20 { \n function initialize(\n string memory _name, string memory _symbol, uint8 _decimals, address owner) external;\n\n function mint(address to, uint256 amount) external;\n}\n\n" + }, + "contracts/bridge/ECDSAFactory.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.6.12;\n\nimport \"@openzeppelin/contracts/access/Ownable.sol\";\nimport \"@openzeppelin/contracts/proxy/Clones.sol\";\nimport \"./interfaces/IECDSANodeManagement.sol\";\n\ncontract ECDSAFactory is Ownable {\n event ECDSANodeGroupCreated(\n address indexed keepAddress,\n address[] members,\n address indexed owner,\n uint256 honestThreshold\n );\n\n struct LatestNodeGroup {\n address keepAddress;\n address[] members;\n address owner;\n uint256 honestThreshold;\n }\n\n LatestNodeGroup public latestNodeGroup;\n\n constructor() public Ownable() {}\n\n /// @notice Returns members of the keep.\n /// @return List of the keep members' addresses.\n function getMembers() public view returns (address[] memory) {\n return latestNodeGroup.members;\n }\n\n /**\n @notice Deploys a new node \n @param nodeMgmtAddress address of the ECDSANodeManagement contract to initialize with\n @param owner Owner of the ECDSANodeManagement contract who can determine if the node group is closed or active\n @param members Array of node group members addresses\n @param honestThreshold Number of signers to process a transaction \n @return Address of the newest node management contract created\n **/\n function deploy(\n address nodeMgmtAddress,\n address owner,\n address[] memory members,\n uint256 honestThreshold\n ) external onlyOwner returns (address) {\n address nodeClone = Clones.clone(nodeMgmtAddress);\n IECDSANodeManagement(nodeClone).initialize(\n owner,\n members,\n honestThreshold\n );\n\n latestNodeGroup.keepAddress = nodeClone;\n latestNodeGroup.members = members;\n latestNodeGroup.owner = owner;\n latestNodeGroup.honestThreshold = honestThreshold;\n\n emit ECDSANodeGroupCreated(nodeClone, members, owner, honestThreshold);\n return nodeClone;\n }\n}\n" + }, + "contracts/bridge/interfaces/IECDSANodeManagement.sol": { + "content": "// SPDX-License-Identifier: MIT\n\n\npragma solidity 0.6.12;\n\n/**\n * @title IECDSANodeManagement interface\n * @notice Interface for the ECDSA node management interface.\n * @dev implement this interface to develop a a factory-patterned ECDSA node management contract\n **/\ninterface IECDSANodeManagement { \n function initialize(\n address _owner,\n address[] memory _members,\n uint256 _honestThreshold) external;\n}\n\n" + }, + "contracts/auxiliary/DummyWeth.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.6.12;\nimport \"@openzeppelin/contracts/access/Ownable.sol\";\n\ninterface IWETH9 {\n function name() external view returns (string memory);\n\n function symbol() external view returns (string memory);\n\n function decimals() external view returns (uint8);\n\n function balanceOf(address) external view returns (uint256);\n\n function allowance(address, address) external view returns (uint256);\n\n receive() external payable;\n\n function deposit() external payable;\n\n function withdraw(uint256 wad) external;\n\n function totalSupply() external view returns (uint256);\n\n function approve(address guy, uint256 wad) external returns (bool);\n\n function transfer(address dst, uint256 wad) external returns (bool);\n\n function transferFrom(\n address src,\n address dst,\n uint256 wad\n ) external returns (bool);\n}\n\ncontract DummyWeth is Ownable {\n IWETH9 public WETH;\n\n function setWETHAddress(address payable _weth) external onlyOwner {\n WETH = IWETH9(_weth);\n }\n\n function withdrawToSelf(uint256 amount) external {\n WETH.withdraw(amount);\n }\n\n function rescue(uint256 amount) external onlyOwner {\n WETH.transfer(owner(), amount);\n }\n\n receive() external payable {}\n\n fallback() external payable {}\n}\n" + }, + "@openzeppelin/contracts/token/ERC20/ERC20Burnable.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <0.8.0;\n\nimport \"../../utils/Context.sol\";\nimport \"./ERC20.sol\";\n\n/**\n * @dev Extension of {ERC20} that allows token holders to destroy both their own\n * tokens and those that they have an allowance for, in a way that can be\n * recognized off-chain (via event analysis).\n */\nabstract contract ERC20Burnable is Context, ERC20 {\n using SafeMath for uint256;\n\n /**\n * @dev Destroys `amount` tokens from the caller.\n *\n * See {ERC20-_burn}.\n */\n function burn(uint256 amount) public virtual {\n _burn(_msgSender(), amount);\n }\n\n /**\n * @dev Destroys `amount` tokens from `account`, deducting from the caller's\n * allowance.\n *\n * See {ERC20-_burn} and {ERC20-allowance}.\n *\n * Requirements:\n *\n * - the caller must have allowance for ``accounts``'s tokens of at least\n * `amount`.\n */\n function burnFrom(address account, uint256 amount) public virtual {\n uint256 decreasedAllowance = allowance(account, _msgSender()).sub(amount, \"ERC20: burn amount exceeds allowance\");\n\n _approve(account, _msgSender(), decreasedAllowance);\n _burn(account, amount);\n }\n}\n" + }, + "contracts/bridge/testing/SynapseToken.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity >=0.6.0 <0.8.0;\n\n\nimport \"@openzeppelin/contracts/token/ERC20/ERC20.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/ERC20Burnable.sol\";\nimport \"@openzeppelin/contracts/access/AccessControl.sol\";\nimport \"@openzeppelin/contracts/drafts/ERC20Permit.sol\";\n\ncontract Synapse is ERC20, ERC20Burnable, AccessControl, ERC20Permit {\n bytes32 public constant MINTER_ROLE = keccak256(\"MINTER_ROLE\");\n\n constructor() public ERC20(\"Synapse\", \"SYN\") ERC20Permit(\"Synapse\") {\n _setupRole(DEFAULT_ADMIN_ROLE, msg.sender);\n _setupRole(MINTER_ROLE, msg.sender);\n }\n\n function mint(address to, uint256 amount) external {\n require(hasRole(MINTER_ROLE, msg.sender));\n _mint(to, amount);\n }\n}" + }, + "@openzeppelin/contracts/access/AccessControl.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <0.8.0;\n\nimport \"../utils/EnumerableSet.sol\";\nimport \"../utils/Address.sol\";\nimport \"../utils/Context.sol\";\n\n/**\n * @dev Contract module that allows children to implement role-based access\n * control mechanisms.\n *\n * Roles are referred to by their `bytes32` identifier. These should be exposed\n * in the external API and be unique. The best way to achieve this is by\n * using `public constant` hash digests:\n *\n * ```\n * bytes32 public constant MY_ROLE = keccak256(\"MY_ROLE\");\n * ```\n *\n * Roles can be used to represent a set of permissions. To restrict access to a\n * function call, use {hasRole}:\n *\n * ```\n * function foo() public {\n * require(hasRole(MY_ROLE, msg.sender));\n * ...\n * }\n * ```\n *\n * Roles can be granted and revoked dynamically via the {grantRole} and\n * {revokeRole} functions. Each role has an associated admin role, and only\n * accounts that have a role's admin role can call {grantRole} and {revokeRole}.\n *\n * By default, the admin role for all roles is `DEFAULT_ADMIN_ROLE`, which means\n * that only accounts with this role will be able to grant or revoke other\n * roles. More complex role relationships can be created by using\n * {_setRoleAdmin}.\n *\n * WARNING: The `DEFAULT_ADMIN_ROLE` is also its own admin: it has permission to\n * grant and revoke this role. Extra precautions should be taken to secure\n * accounts that have been granted it.\n */\nabstract contract AccessControl is Context {\n using EnumerableSet for EnumerableSet.AddressSet;\n using Address for address;\n\n struct RoleData {\n EnumerableSet.AddressSet members;\n bytes32 adminRole;\n }\n\n mapping (bytes32 => RoleData) private _roles;\n\n bytes32 public constant DEFAULT_ADMIN_ROLE = 0x00;\n\n /**\n * @dev Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole`\n *\n * `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite\n * {RoleAdminChanged} not being emitted signaling this.\n *\n * _Available since v3.1._\n */\n event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole);\n\n /**\n * @dev Emitted when `account` is granted `role`.\n *\n * `sender` is the account that originated the contract call, an admin role\n * bearer except when using {_setupRole}.\n */\n event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender);\n\n /**\n * @dev Emitted when `account` is revoked `role`.\n *\n * `sender` is the account that originated the contract call:\n * - if using `revokeRole`, it is the admin role bearer\n * - if using `renounceRole`, it is the role bearer (i.e. `account`)\n */\n event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender);\n\n /**\n * @dev Returns `true` if `account` has been granted `role`.\n */\n function hasRole(bytes32 role, address account) public view returns (bool) {\n return _roles[role].members.contains(account);\n }\n\n /**\n * @dev Returns the number of accounts that have `role`. Can be used\n * together with {getRoleMember} to enumerate all bearers of a role.\n */\n function getRoleMemberCount(bytes32 role) public view returns (uint256) {\n return _roles[role].members.length();\n }\n\n /**\n * @dev Returns one of the accounts that have `role`. `index` must be a\n * value between 0 and {getRoleMemberCount}, non-inclusive.\n *\n * Role bearers are not sorted in any particular way, and their ordering may\n * change at any point.\n *\n * WARNING: When using {getRoleMember} and {getRoleMemberCount}, make sure\n * you perform all queries on the same block. See the following\n * https://forum.openzeppelin.com/t/iterating-over-elements-on-enumerableset-in-openzeppelin-contracts/2296[forum post]\n * for more information.\n */\n function getRoleMember(bytes32 role, uint256 index) public view returns (address) {\n return _roles[role].members.at(index);\n }\n\n /**\n * @dev Returns the admin role that controls `role`. See {grantRole} and\n * {revokeRole}.\n *\n * To change a role's admin, use {_setRoleAdmin}.\n */\n function getRoleAdmin(bytes32 role) public view returns (bytes32) {\n return _roles[role].adminRole;\n }\n\n /**\n * @dev Grants `role` to `account`.\n *\n * If `account` had not been already granted `role`, emits a {RoleGranted}\n * event.\n *\n * Requirements:\n *\n * - the caller must have ``role``'s admin role.\n */\n function grantRole(bytes32 role, address account) public virtual {\n require(hasRole(_roles[role].adminRole, _msgSender()), \"AccessControl: sender must be an admin to grant\");\n\n _grantRole(role, account);\n }\n\n /**\n * @dev Revokes `role` from `account`.\n *\n * If `account` had been granted `role`, emits a {RoleRevoked} event.\n *\n * Requirements:\n *\n * - the caller must have ``role``'s admin role.\n */\n function revokeRole(bytes32 role, address account) public virtual {\n require(hasRole(_roles[role].adminRole, _msgSender()), \"AccessControl: sender must be an admin to revoke\");\n\n _revokeRole(role, account);\n }\n\n /**\n * @dev Revokes `role` from the calling account.\n *\n * Roles are often managed via {grantRole} and {revokeRole}: this function's\n * purpose is to provide a mechanism for accounts to lose their privileges\n * if they are compromised (such as when a trusted device is misplaced).\n *\n * If the calling account had been granted `role`, emits a {RoleRevoked}\n * event.\n *\n * Requirements:\n *\n * - the caller must be `account`.\n */\n function renounceRole(bytes32 role, address account) public virtual {\n require(account == _msgSender(), \"AccessControl: can only renounce roles for self\");\n\n _revokeRole(role, account);\n }\n\n /**\n * @dev Grants `role` to `account`.\n *\n * If `account` had not been already granted `role`, emits a {RoleGranted}\n * event. Note that unlike {grantRole}, this function doesn't perform any\n * checks on the calling account.\n *\n * [WARNING]\n * ====\n * This function should only be called from the constructor when setting\n * up the initial roles for the system.\n *\n * Using this function in any other way is effectively circumventing the admin\n * system imposed by {AccessControl}.\n * ====\n */\n function _setupRole(bytes32 role, address account) internal virtual {\n _grantRole(role, account);\n }\n\n /**\n * @dev Sets `adminRole` as ``role``'s admin role.\n *\n * Emits a {RoleAdminChanged} event.\n */\n function _setRoleAdmin(bytes32 role, bytes32 adminRole) internal virtual {\n emit RoleAdminChanged(role, _roles[role].adminRole, adminRole);\n _roles[role].adminRole = adminRole;\n }\n\n function _grantRole(bytes32 role, address account) private {\n if (_roles[role].members.add(account)) {\n emit RoleGranted(role, account, _msgSender());\n }\n }\n\n function _revokeRole(bytes32 role, address account) private {\n if (_roles[role].members.remove(account)) {\n emit RoleRevoked(role, account, _msgSender());\n }\n }\n}\n" + }, + "@openzeppelin/contracts/drafts/ERC20Permit.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.5 <0.8.0;\n\nimport \"../token/ERC20/ERC20.sol\";\nimport \"./IERC20Permit.sol\";\nimport \"../cryptography/ECDSA.sol\";\nimport \"../utils/Counters.sol\";\nimport \"./EIP712.sol\";\n\n/**\n * @dev Implementation of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in\n * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612].\n *\n * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by\n * presenting a message signed by the account. By not relying on `{IERC20-approve}`, the token holder account doesn't\n * need to send a transaction, and thus is not required to hold Ether at all.\n *\n * _Available since v3.4._\n */\nabstract contract ERC20Permit is ERC20, IERC20Permit, EIP712 {\n using Counters for Counters.Counter;\n\n mapping (address => Counters.Counter) private _nonces;\n\n // solhint-disable-next-line var-name-mixedcase\n bytes32 private immutable _PERMIT_TYPEHASH = keccak256(\"Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)\");\n\n /**\n * @dev Initializes the {EIP712} domain separator using the `name` parameter, and setting `version` to `\"1\"`.\n *\n * It's a good idea to use the same `name` that is defined as the ERC20 token name.\n */\n constructor(string memory name) internal EIP712(name, \"1\") {\n }\n\n /**\n * @dev See {IERC20Permit-permit}.\n */\n function permit(address owner, address spender, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s) public virtual override {\n // solhint-disable-next-line not-rely-on-time\n require(block.timestamp <= deadline, \"ERC20Permit: expired deadline\");\n\n bytes32 structHash = keccak256(\n abi.encode(\n _PERMIT_TYPEHASH,\n owner,\n spender,\n value,\n _nonces[owner].current(),\n deadline\n )\n );\n\n bytes32 hash = _hashTypedDataV4(structHash);\n\n address signer = ECDSA.recover(hash, v, r, s);\n require(signer == owner, \"ERC20Permit: invalid signature\");\n\n _nonces[owner].increment();\n _approve(owner, spender, value);\n }\n\n /**\n * @dev See {IERC20Permit-nonces}.\n */\n function nonces(address owner) public view override returns (uint256) {\n return _nonces[owner].current();\n }\n\n /**\n * @dev See {IERC20Permit-DOMAIN_SEPARATOR}.\n */\n // solhint-disable-next-line func-name-mixedcase\n function DOMAIN_SEPARATOR() external view override returns (bytes32) {\n return _domainSeparatorV4();\n }\n}\n" + }, + "@openzeppelin/contracts/utils/EnumerableSet.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <0.8.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" + }, + "@openzeppelin/contracts/drafts/IERC20Permit.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <0.8.0;\n\n/**\n * @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in\n * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612].\n *\n * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by\n * presenting a message signed by the account. By not relying on `{IERC20-approve}`, the token holder account doesn't\n * need to send a transaction, and thus is not required to hold Ether at all.\n */\ninterface IERC20Permit {\n /**\n * @dev Sets `value` as the allowance of `spender` over `owner`'s tokens,\n * given `owner`'s signed approval.\n *\n * IMPORTANT: The same issues {IERC20-approve} has related to transaction\n * ordering also apply here.\n *\n * Emits an {Approval} event.\n *\n * Requirements:\n *\n * - `spender` cannot be the zero address.\n * - `deadline` must be a timestamp in the future.\n * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner`\n * over the EIP712-formatted function arguments.\n * - the signature must use ``owner``'s current nonce (see {nonces}).\n *\n * For more information on the signature format, see the\n * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP\n * section].\n */\n function permit(address owner, address spender, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s) external;\n\n /**\n * @dev Returns the current nonce for `owner`. This value must be\n * included whenever a signature is generated for {permit}.\n *\n * Every successful call to {permit} increases ``owner``'s nonce by one. This\n * prevents a signature from being used multiple times.\n */\n function nonces(address owner) external view returns (uint256);\n\n /**\n * @dev Returns the domain separator used in the encoding of the signature for `permit`, as defined by {EIP712}.\n */\n // solhint-disable-next-line func-name-mixedcase\n function DOMAIN_SEPARATOR() external view returns (bytes32);\n}\n" + }, + "@openzeppelin/contracts/cryptography/ECDSA.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <0.8.0;\n\n/**\n * @dev Elliptic Curve Digital Signature Algorithm (ECDSA) operations.\n *\n * These functions can be used to verify that a message was signed by the holder\n * of the private keys of a given address.\n */\nlibrary ECDSA {\n /**\n * @dev Returns the address that signed a hashed message (`hash`) with\n * `signature`. This address can then be used for verification purposes.\n *\n * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:\n * this function rejects them by requiring the `s` value to be in the lower\n * half order, and the `v` value to be either 27 or 28.\n *\n * IMPORTANT: `hash` _must_ be the result of a hash operation for the\n * verification to be secure: it is possible to craft signatures that\n * recover to arbitrary addresses for non-hashed data. A safe way to ensure\n * this is by receiving a hash of the original message (which may otherwise\n * be too long), and then calling {toEthSignedMessageHash} on it.\n */\n function recover(bytes32 hash, bytes memory signature) internal pure returns (address) {\n // Check the signature length\n if (signature.length != 65) {\n revert(\"ECDSA: invalid signature length\");\n }\n\n // Divide the signature in r, s and v variables\n bytes32 r;\n bytes32 s;\n uint8 v;\n\n // ecrecover takes the signature parameters, and the only way to get them\n // currently is to use assembly.\n // solhint-disable-next-line no-inline-assembly\n assembly {\n r := mload(add(signature, 0x20))\n s := mload(add(signature, 0x40))\n v := byte(0, mload(add(signature, 0x60)))\n }\n\n return recover(hash, v, r, s);\n }\n\n /**\n * @dev Overload of {ECDSA-recover-bytes32-bytes-} that receives the `v`,\n * `r` and `s` signature fields separately.\n */\n function recover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) internal pure returns (address) {\n // EIP-2 still allows signature malleability for ecrecover(). Remove this possibility and make the signature\n // unique. Appendix F in the Ethereum Yellow paper (https://ethereum.github.io/yellowpaper/paper.pdf), defines\n // the valid range for s in (281): 0 < s < secp256k1n ÷ 2 + 1, and for v in (282): v ∈ {27, 28}. Most\n // signatures from current libraries generate a unique signature with an s-value in the lower half order.\n //\n // If your library generates malleable signatures, such as s-values in the upper range, calculate a new s-value\n // with 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 - s1 and flip v from 27 to 28 or\n // vice versa. If your library also generates signatures with 0/1 for v instead 27/28, add 27 to v to accept\n // these malleable signatures as well.\n require(uint256(s) <= 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0, \"ECDSA: invalid signature 's' value\");\n require(v == 27 || v == 28, \"ECDSA: invalid signature 'v' value\");\n\n // If the signature is valid (and not malleable), return the signer address\n address signer = ecrecover(hash, v, r, s);\n require(signer != address(0), \"ECDSA: invalid signature\");\n\n return signer;\n }\n\n /**\n * @dev Returns an Ethereum Signed Message, created from a `hash`. This\n * replicates the behavior of the\n * https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_sign[`eth_sign`]\n * JSON-RPC method.\n *\n * See {recover}.\n */\n function toEthSignedMessageHash(bytes32 hash) internal pure returns (bytes32) {\n // 32 is the length in bytes of hash,\n // enforced by the type signature above\n return keccak256(abi.encodePacked(\"\\x19Ethereum Signed Message:\\n32\", hash));\n }\n}\n" + }, + "@openzeppelin/contracts/utils/Counters.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <0.8.0;\n\nimport \"../math/SafeMath.sol\";\n\n/**\n * @title Counters\n * @author Matt Condon (@shrugs)\n * @dev Provides counters that can only be incremented or decremented by one. This can be used e.g. to track the number\n * of elements in a mapping, issuing ERC721 ids, or counting request ids.\n *\n * Include with `using Counters for Counters.Counter;`\n * Since it is not possible to overflow a 256 bit integer with increments of one, `increment` can skip the {SafeMath}\n * overflow check, thereby saving gas. This does assume however correct usage, in that the underlying `_value` is never\n * directly accessed.\n */\nlibrary Counters {\n using SafeMath for uint256;\n\n struct Counter {\n // This variable should never be directly accessed by users of the library: interactions must be restricted to\n // the library's function. As of Solidity v0.5.2, this cannot be enforced, though there is a proposal to add\n // this feature: see https://github.com/ethereum/solidity/issues/4637\n uint256 _value; // default: 0\n }\n\n function current(Counter storage counter) internal view returns (uint256) {\n return counter._value;\n }\n\n function increment(Counter storage counter) internal {\n // The {SafeMath} overflow check can be skipped here, see the comment at the top\n counter._value += 1;\n }\n\n function decrement(Counter storage counter) internal {\n counter._value = counter._value.sub(1);\n }\n}\n" + }, + "@openzeppelin/contracts/drafts/EIP712.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <0.8.0;\n\n/**\n * @dev https://eips.ethereum.org/EIPS/eip-712[EIP 712] is a standard for hashing and signing of typed structured data.\n *\n * The encoding specified in the EIP is very generic, and such a generic implementation in Solidity is not feasible,\n * thus this contract does not implement the encoding itself. Protocols need to implement the type-specific encoding\n * they need in their contracts using a combination of `abi.encode` and `keccak256`.\n *\n * This contract implements the EIP 712 domain separator ({_domainSeparatorV4}) that is used as part of the encoding\n * scheme, and the final step of the encoding to obtain the message digest that is then signed via ECDSA\n * ({_hashTypedDataV4}).\n *\n * The implementation of the domain separator was designed to be as efficient as possible while still properly updating\n * the chain id to protect against replay attacks on an eventual fork of the chain.\n *\n * NOTE: This contract implements the version of the encoding known as \"v4\", as implemented by the JSON RPC method\n * https://docs.metamask.io/guide/signing-data.html[`eth_signTypedDataV4` in MetaMask].\n *\n * _Available since v3.4._\n */\nabstract contract EIP712 {\n /* solhint-disable var-name-mixedcase */\n // Cache the domain separator as an immutable value, but also store the chain id that it corresponds to, in order to\n // invalidate the cached domain separator if the chain id changes.\n bytes32 private immutable _CACHED_DOMAIN_SEPARATOR;\n uint256 private immutable _CACHED_CHAIN_ID;\n\n bytes32 private immutable _HASHED_NAME;\n bytes32 private immutable _HASHED_VERSION;\n bytes32 private immutable _TYPE_HASH;\n /* solhint-enable var-name-mixedcase */\n\n /**\n * @dev Initializes the domain separator and parameter caches.\n *\n * The meaning of `name` and `version` is specified in\n * https://eips.ethereum.org/EIPS/eip-712#definition-of-domainseparator[EIP 712]:\n *\n * - `name`: the user readable name of the signing domain, i.e. the name of the DApp or the protocol.\n * - `version`: the current major version of the signing domain.\n *\n * NOTE: These parameters cannot be changed except through a xref:learn::upgrading-smart-contracts.adoc[smart\n * contract upgrade].\n */\n constructor(string memory name, string memory version) internal {\n bytes32 hashedName = keccak256(bytes(name));\n bytes32 hashedVersion = keccak256(bytes(version));\n bytes32 typeHash = keccak256(\"EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)\");\n _HASHED_NAME = hashedName;\n _HASHED_VERSION = hashedVersion;\n _CACHED_CHAIN_ID = _getChainId();\n _CACHED_DOMAIN_SEPARATOR = _buildDomainSeparator(typeHash, hashedName, hashedVersion);\n _TYPE_HASH = typeHash;\n }\n\n /**\n * @dev Returns the domain separator for the current chain.\n */\n function _domainSeparatorV4() internal view virtual returns (bytes32) {\n if (_getChainId() == _CACHED_CHAIN_ID) {\n return _CACHED_DOMAIN_SEPARATOR;\n } else {\n return _buildDomainSeparator(_TYPE_HASH, _HASHED_NAME, _HASHED_VERSION);\n }\n }\n\n function _buildDomainSeparator(bytes32 typeHash, bytes32 name, bytes32 version) private view returns (bytes32) {\n return keccak256(\n abi.encode(\n typeHash,\n name,\n version,\n _getChainId(),\n address(this)\n )\n );\n }\n\n /**\n * @dev Given an already https://eips.ethereum.org/EIPS/eip-712#definition-of-hashstruct[hashed struct], this\n * function returns the hash of the fully encoded EIP712 message for this domain.\n *\n * This hash can be used together with {ECDSA-recover} to obtain the signer of a message. For example:\n *\n * ```solidity\n * bytes32 digest = _hashTypedDataV4(keccak256(abi.encode(\n * keccak256(\"Mail(address to,string contents)\"),\n * mailTo,\n * keccak256(bytes(mailContents))\n * )));\n * address signer = ECDSA.recover(digest, signature);\n * ```\n */\n function _hashTypedDataV4(bytes32 structHash) internal view virtual returns (bytes32) {\n return keccak256(abi.encodePacked(\"\\x19\\x01\", _domainSeparatorV4(), structHash));\n }\n\n function _getChainId() private view returns (uint256 chainId) {\n this; // silence state mutability warning without generating bytecode - see https://github.com/ethereum/solidity/issues/2691\n // solhint-disable-next-line no-inline-assembly\n assembly {\n chainId := chainid()\n }\n }\n}\n" + }, + "contracts/bridge/wrappers/MigratorBridgeZap.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.6.12;\n\nimport '@openzeppelin/contracts/token/ERC20/IERC20.sol';\nimport '@openzeppelin/contracts/token/ERC20/SafeERC20.sol';\nimport '@openzeppelin/contracts/math/SafeMath.sol';\n\nimport '../interfaces/ISynapseBridge.sol';\nimport '../interfaces/IERC20Migrator.sol';\n\ncontract MigratorBridgeZap {\n using SafeERC20 for IERC20;\n using SafeMath for uint256;\n \n ISynapseBridge constant synapseBridge = ISynapseBridge(0xd123f70AE324d34A9E76b67a27bf77593bA8749f);\n IERC20Migrator constant erc20Migrator = IERC20Migrator(0xf0284FB86adA5E4D82555C529677eEA3B2C3E022); \n IERC20 constant legacyToken = IERC20(0x42F6f551ae042cBe50C739158b4f0CAC0Edb9096);\n IERC20 constant newToken = IERC20(0xa4080f1778e69467E905B8d6F72f6e441f9e9484);\n uint256 constant MAX_UINT256 = 2**256 - 1;\n\n constructor() public {\n legacyToken.safeApprove(address(erc20Migrator), MAX_UINT256);\n newToken.safeApprove(address(synapseBridge), MAX_UINT256);\n }\n\n function migrate(uint256 amount) external {\n legacyToken.safeTransferFrom(msg.sender, address(this), amount);\n erc20Migrator.migrate(amount);\n newToken.safeTransfer(msg.sender, amount.mul(5).div(2));\n }\n\n function migrateAndBridge(uint256 amount, address to, uint256 chainId) external {\n legacyToken.safeTransferFrom(msg.sender, address(this), amount);\n erc20Migrator.migrate(amount);\n synapseBridge.redeem(to, chainId, newToken, amount.mul(5).div(2));\n }\n}" + }, + "contracts/bridge/interfaces/ISynapseBridge.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.6.12;\n\nimport '@openzeppelin/contracts/token/ERC20/SafeERC20.sol';\nimport '@openzeppelin/contracts/token/ERC20/ERC20Burnable.sol';\n\ninterface ISynapseBridge {\n using SafeERC20 for IERC20;\n\n function deposit(\n address to,\n uint256 chainId,\n IERC20 token,\n uint256 amount\n ) external;\n\n function depositAndSwap(\n address to,\n uint256 chainId,\n IERC20 token,\n uint256 amount,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 minDy,\n uint256 deadline\n ) external;\n\n function redeem(\n address to,\n uint256 chainId,\n IERC20 token,\n uint256 amount\n ) external;\n\n\n function redeemv2(\n bytes32 to,\n uint256 chainId,\n IERC20 token,\n uint256 amount\n ) external;\n\n\n function redeemAndSwap(\n address to,\n uint256 chainId,\n IERC20 token,\n uint256 amount,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 minDy,\n uint256 deadline\n ) external;\n\n function redeemAndRemove(\n address to,\n uint256 chainId,\n IERC20 token,\n uint256 amount,\n uint8 liqTokenIndex,\n uint256 liqMinAmount,\n uint256 liqDeadline\n ) external;\n}\n" + }, + "contracts/bridge/interfaces/IERC20Migrator.sol": { + "content": "// SPDX-License-Identifier: MIT\n\n\npragma solidity 0.6.12;\n\ninterface IERC20Migrator { \n function migrate(uint256 amount) external;\n}\n\n" + }, + "contracts/bridge/wrappers/MoonriverBridgeZap.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.6.12;\n\nimport \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/SafeERC20.sol\";\nimport \"../interfaces/ISwap.sol\";\nimport \"../interfaces/ISynapseBridge.sol\";\nimport \"../interfaces/IWETH9.sol\";\n\ninterface IFrax {\n function exchangeCanonicalForOld(address bridge_token_address, uint256 token_amount) external returns (uint256);\n}\n\ncontract MoonriverBridgeZap {\n using SafeERC20 for IERC20;\n\n ISynapseBridge synapseBridge;\n address payable public immutable WETH_ADDRESS;\n IFrax private constant CANOLICAL_FRAX = IFrax(0x1A93B23281CC1CDE4C4741353F3064709A16197d);\n IERC20 private constant SYN_FRAX = IERC20(0xE96AC70907ffF3Efee79f502C985A7A21Bce407d);\n\n mapping(address => address) public swapMap;\n mapping(address => IERC20[]) public swapTokensMap;\n\n uint256 constant MAX_UINT256 = 2**256 - 1;\n\n constructor(\n address payable _wethAddress,\n address _swapOne,\n address tokenOne,\n address _swapTwo,\n address tokenTwo,\n ISynapseBridge _synapseBridge\n ) public {\n WETH_ADDRESS = _wethAddress;\n synapseBridge = _synapseBridge;\n swapMap[tokenOne] = _swapOne;\n swapMap[tokenTwo] = _swapTwo;\n IERC20(_wethAddress).safeIncreaseAllowance(address(_synapseBridge), MAX_UINT256);\n if (address(_swapOne) != address(0)) {\n {\n uint8 i;\n for (; i < 32; i++) {\n try ISwap(_swapOne).getToken(i) returns (\n IERC20 token\n ) {\n swapTokensMap[_swapOne].push(token);\n token.safeApprove(address(_swapOne), MAX_UINT256);\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n } catch {\n break;\n }\n }\n require(i > 1, \"swap must have at least 2 tokens\");\n }\n }\n if (address(_swapTwo) != address(0)) {\n {\n uint8 i;\n for (; i < 32; i++) {\n try ISwap(_swapTwo).getToken(i) returns (\n IERC20 token\n ) {\n swapTokensMap[_swapTwo].push(token);\n token.safeApprove(address(_swapTwo), MAX_UINT256);\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n } catch {\n break;\n }\n }\n require(i > 1, \"swap must have at least 2 tokens\");\n }\n }\n }\n\n /**\n * @notice Calculate amount of tokens you receive on swap\n * @param tokenIndexFrom the token the user wants to sell\n * @param tokenIndexTo the token the user wants to buy\n * @param dx the amount of tokens the user wants to sell. If the token charges\n * a fee on transfers, use the amount that gets transferred after the fee.\n * @return amount of tokens the user will receive\n */\n function calculateSwap(\n IERC20 token,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx\n ) external view virtual returns (uint256) {\n ISwap swap = ISwap(\n swapMap[address(token)]\n );\n return swap.calculateSwap(tokenIndexFrom, tokenIndexTo, dx);\n }\n\n function swapAndRedeem(\n address to,\n uint256 chainId,\n IERC20 token,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx,\n uint256 minDy,\n uint256 deadline\n ) external {\n ISwap swap = ISwap(swapMap[address(token)]);\n require(address(swap) != address(0), \"Swap is 0x00\");\n IERC20[] memory tokens = swapTokensMap[address(swap)];\n tokens[tokenIndexFrom].safeTransferFrom(\n msg.sender,\n address(this),\n dx\n );\n // swap\n\n uint256 swappedAmount = swap.swap(\n tokenIndexFrom,\n tokenIndexTo,\n dx,\n minDy,\n deadline\n );\n // deposit into bridge, gets nUSD\n if (\n token.allowance(address(this), address(synapseBridge)) <\n swappedAmount\n ) {\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n }\n synapseBridge.redeem(to, chainId, token, swappedAmount);\n }\n\n function swapAndRedeemAndSwap(\n address to,\n uint256 chainId,\n IERC20 token,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx,\n uint256 minDy,\n uint256 deadline,\n uint8 swapTokenIndexFrom,\n uint8 swapTokenIndexTo,\n uint256 swapMinDy,\n uint256 swapDeadline\n ) external {\n require(\n address(swapMap[address(token)]) != address(0),\n \"Swap is 0x00\"\n );\n IERC20[] memory tokens = swapTokensMap[\n swapMap[address(token)]\n ];\n tokens[tokenIndexFrom].safeTransferFrom(\n msg.sender,\n address(this),\n dx\n );\n // swap\n\n uint256 swappedAmount = ISwap(swapMap[address(token)]).swap(tokenIndexFrom, tokenIndexTo, dx, minDy, deadline);\n // deposit into bridge, gets nUSD\n if (\n token.allowance(address(this), address(synapseBridge)) <\n swappedAmount\n ) {\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n }\n synapseBridge.redeemAndSwap(\n to,\n chainId,\n token,\n swappedAmount,\n swapTokenIndexFrom,\n swapTokenIndexTo,\n swapMinDy,\n swapDeadline\n );\n }\n\n function swapAndRedeemAndRemove(\n address to,\n uint256 chainId,\n IERC20 token,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx,\n uint256 minDy,\n uint256 deadline,\n uint8 liqTokenIndex,\n uint256 liqMinAmount,\n uint256 liqDeadline\n ) external {\n ISwap swap = ISwap(swapMap[address(token)]);\n require(address(swap) != address(0), \"Swap is 0x00\");\n IERC20[] memory tokens = swapTokensMap[address(swap)];\n tokens[tokenIndexFrom].safeTransferFrom(\n msg.sender,\n address(this),\n dx\n );\n // swap\n\n uint256 swappedAmount = swap.swap(\n tokenIndexFrom,\n tokenIndexTo,\n dx,\n minDy,\n deadline\n );\n // deposit into bridge, gets nUSD\n if (\n token.allowance(address(this), address(synapseBridge)) <\n swappedAmount\n ) {\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n }\n synapseBridge.redeemAndRemove(\n to,\n chainId,\n token,\n swappedAmount,\n liqTokenIndex,\n liqMinAmount,\n liqDeadline\n );\n }\n\n /**\n * @notice wraps SynapseBridge redeem()\n * @param to address on other chain to redeem underlying assets to\n * @param chainId which underlying chain to bridge assets onto\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n **/\n function redeem(\n address to,\n uint256 chainId,\n IERC20 token,\n uint256 amount\n ) external {\n token.safeTransferFrom(msg.sender, address(this), amount);\n if (address(token) == address(CANOLICAL_FRAX)) {\n uint256 swappedAmount = CANOLICAL_FRAX.exchangeCanonicalForOld(address(SYN_FRAX), amount);\n if (SYN_FRAX.allowance(address(this), address(synapseBridge)) < amount) {\n SYN_FRAX.safeApprove(address(synapseBridge), MAX_UINT256);\n }\n synapseBridge.redeem(to, chainId, SYN_FRAX, swappedAmount);\n } else {\n if (token.allowance(address(this), address(synapseBridge)) < amount) {\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n }\n synapseBridge.redeem(to, chainId, token, amount);\n }\n }\n\n /**\n * @notice Wraps SynapseBridge redeemv2() function\n * @param to address on other chain to bridge assets to\n * @param chainId which chain to bridge assets onto\n * @param token ERC20 compatible token to redeem into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n **/\n function redeemv2(\n bytes32 to,\n uint256 chainId,\n IERC20 token,\n uint256 amount\n ) external {\n token.safeTransferFrom(msg.sender, address(this), amount);\n\n if (token.allowance(address(this), address(synapseBridge)) < amount) {\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n }\n synapseBridge.redeemv2(to, chainId, token, amount);\n }\n\n /**\n * @notice wraps SynapseBridge redeem()\n * @param to address on other chain to redeem underlying assets to\n * @param chainId which underlying chain to bridge assets onto\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n **/\n function deposit(\n address to,\n uint256 chainId,\n IERC20 token,\n uint256 amount\n ) external {\n token.safeTransferFrom(msg.sender, address(this), amount);\n if (token.allowance(address(this), address(synapseBridge)) < amount) {\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n }\n synapseBridge.deposit(to, chainId, token, amount);\n }\n\n /**\n * @notice Wraps SynapseBridge deposit() function to make it compatible w/ ETH -> WETH conversions\n * @param to address on other chain to bridge assets to\n * @param chainId which chain to bridge assets onto\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n **/\n function depositETH(\n address to,\n uint256 chainId,\n uint256 amount\n ) external payable {\n require(msg.value > 0 && msg.value == amount, 'INCORRECT MSG VALUE');\n IWETH9(WETH_ADDRESS).deposit{value: msg.value}();\n synapseBridge.deposit(to, chainId, IERC20(WETH_ADDRESS), amount);\n }\n\n\n\n function swapETHAndRedeem(\n address to,\n uint256 chainId,\n IERC20 token,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx,\n uint256 minDy,\n uint256 deadline\n ) external payable {\n require(WETH_ADDRESS != address(0), \"WETH 0\");\n require(msg.value > 0 && msg.value == dx, \"INCORRECT MSG VALUE\");\n ISwap swap = ISwap(swapMap[address(token)]);\n require(address(swap) != address(0), \"Swap is 0x00\");\n IWETH9(WETH_ADDRESS).deposit{value: msg.value}();\n\n // swap\n uint256 swappedAmount = swap.swap(\n tokenIndexFrom,\n tokenIndexTo,\n dx,\n minDy,\n deadline\n );\n synapseBridge.redeem(to, chainId, token, swappedAmount);\n }\n\n /**\n * @notice Wraps redeemAndSwap on SynapseBridge.sol\n * Relays to nodes that (typically) a wrapped synAsset ERC20 token has been burned and the underlying needs to be redeeemed on the native chain. This function indicates to the nodes that they should attempt to redeem the LP token for the underlying assets (E.g \"swap\" out of the LP token)\n * @param to address on other chain to redeem underlying assets to\n * @param chainId which underlying chain to bridge assets onto\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n * @param tokenIndexFrom the token the user wants to swap from\n * @param tokenIndexTo the token the user wants to swap to\n * @param minDy the min amount the user would like to receive, or revert to only minting the SynERC20 token crosschain.\n * @param deadline latest timestamp to accept this transaction\n **/\n function redeemAndSwap(\n address to,\n uint256 chainId,\n IERC20 token,\n uint256 amount,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 minDy,\n uint256 deadline\n ) external {\n token.safeTransferFrom(msg.sender, address(this), amount);\n if (token.allowance(address(this), address(synapseBridge)) < amount) {\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n }\n synapseBridge.redeemAndSwap(\n to,\n chainId,\n token,\n amount,\n tokenIndexFrom,\n tokenIndexTo,\n minDy,\n deadline\n );\n }\n\n /**\n * @notice Wraps redeemAndRemove on SynapseBridge\n * Relays to nodes that (typically) a wrapped synAsset ERC20 token has been burned and the underlying needs to be redeeemed on the native chain. This function indicates to the nodes that they should attempt to redeem the LP token for the underlying assets (E.g \"swap\" out of the LP token)\n * @param to address on other chain to redeem underlying assets to\n * @param chainId which underlying chain to bridge assets onto\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount of (typically) LP token to pass to the nodes to attempt to removeLiquidity() with to redeem for the underlying assets of the LP token\n * @param liqTokenIndex Specifies which of the underlying LP assets the nodes should attempt to redeem for\n * @param liqMinAmount Specifies the minimum amount of the underlying asset needed for the nodes to execute the redeem/swap\n * @param liqDeadline Specificies the deadline that the nodes are allowed to try to redeem/swap the LP token\n **/\n function redeemAndRemove(\n address to,\n uint256 chainId,\n IERC20 token,\n uint256 amount,\n uint8 liqTokenIndex,\n uint256 liqMinAmount,\n uint256 liqDeadline\n ) external {\n token.safeTransferFrom(msg.sender, address(this), amount);\n if (token.allowance(address(this), address(synapseBridge)) < amount) {\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n }\n synapseBridge.redeemAndRemove(\n to,\n chainId,\n token,\n amount,\n liqTokenIndex,\n liqMinAmount,\n liqDeadline\n );\n }\n}\n" + }, + "contracts/bridge/interfaces/ISwap.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.6.12;\n\nimport '@openzeppelin/contracts/token/ERC20/ERC20.sol';\n\ninterface ISwap {\n // pool data view functions\n function getA() external view returns (uint256);\n\n function getToken(uint8 index) external view returns (IERC20);\n\n function getTokenIndex(address tokenAddress) external view returns (uint8);\n\n function getTokenBalance(uint8 index) external view returns (uint256);\n\n function getVirtualPrice() external view returns (uint256);\n\n // min return calculation functions\n function calculateSwap(\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx\n ) external view returns (uint256);\n\n function calculateTokenAmount(uint256[] calldata amounts, bool deposit)\n external\n view\n returns (uint256);\n\n function calculateRemoveLiquidity(uint256 amount)\n external\n view\n returns (uint256[] memory);\n\n function calculateRemoveLiquidityOneToken(\n uint256 tokenAmount,\n uint8 tokenIndex\n ) external view returns (uint256 availableTokenAmount);\n\n // state modifying functions\n function initialize(\n IERC20[] memory pooledTokens,\n uint8[] memory decimals,\n string memory lpTokenName,\n string memory lpTokenSymbol,\n uint256 a,\n uint256 fee,\n uint256 adminFee,\n address lpTokenTargetAddress\n ) external;\n\n function swap(\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx,\n uint256 minDy,\n uint256 deadline\n ) external returns (uint256);\n\n function addLiquidity(\n uint256[] calldata amounts,\n uint256 minToMint,\n uint256 deadline\n ) external returns (uint256);\n\n function removeLiquidity(\n uint256 amount,\n uint256[] calldata minAmounts,\n uint256 deadline\n ) external returns (uint256[] memory);\n\n function removeLiquidityOneToken(\n uint256 tokenAmount,\n uint8 tokenIndex,\n uint256 minAmount,\n uint256 deadline\n ) external returns (uint256);\n\n function removeLiquidityImbalance(\n uint256[] calldata amounts,\n uint256 maxBurnAmount,\n uint256 deadline\n ) external returns (uint256);\n}\n" + }, + "contracts/bridge/interfaces/IWETH9.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.4.0;\n\ninterface IWETH9 {\n function name() external view returns (string memory);\n\n function symbol() external view returns (string memory);\n\n function decimals() external view returns (uint8);\n\n function balanceOf(address) external view returns (uint256);\n\n function allowance(address, address) external view returns (uint256);\n\n receive() external payable;\n\n function deposit() external payable;\n\n function withdraw(uint256 wad) external;\n\n function totalSupply() external view returns (uint256);\n\n function approve(address guy, uint256 wad) external returns (bool);\n\n function transfer(address dst, uint256 wad) external returns (bool);\n\n function transferFrom(\n address src,\n address dst,\n uint256 wad\n ) external returns (bool);\n}" + }, + "contracts/bridge/wrappers/L2BridgeZap.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.6.12;\n\nimport \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/SafeERC20.sol\";\nimport \"../interfaces/ISwap.sol\";\nimport \"../interfaces/ISynapseBridge.sol\";\nimport \"../interfaces/IWETH9.sol\";\n\ncontract L2BridgeZap {\n using SafeERC20 for IERC20;\n\n ISynapseBridge synapseBridge;\n address payable public immutable WETH_ADDRESS;\n\n mapping(address => address) public swapMap;\n mapping(address => IERC20[]) public swapTokensMap;\n\n uint256 constant MAX_UINT256 = 2**256 - 1;\n\n constructor(\n address payable _wethAddress,\n address _swapOne,\n address tokenOne,\n address _swapTwo,\n address tokenTwo,\n ISynapseBridge _synapseBridge\n ) public {\n WETH_ADDRESS = _wethAddress;\n synapseBridge = _synapseBridge;\n swapMap[tokenOne] = _swapOne;\n swapMap[tokenTwo] = _swapTwo;\n if (_wethAddress != address(0)) {\n IERC20(_wethAddress).safeIncreaseAllowance(address(_synapseBridge), MAX_UINT256);\n }\n if (address(_swapOne) != address(0)) {\n {\n uint8 i;\n for (; i < 32; i++) {\n try ISwap(_swapOne).getToken(i) returns (\n IERC20 token\n ) {\n swapTokensMap[_swapOne].push(token);\n token.safeApprove(address(_swapOne), MAX_UINT256);\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n } catch {\n break;\n }\n }\n require(i > 1, \"swap must have at least 2 tokens\");\n }\n }\n if (address(_swapTwo) != address(0)) {\n {\n uint8 i;\n for (; i < 32; i++) {\n try ISwap(_swapTwo).getToken(i) returns (\n IERC20 token\n ) {\n swapTokensMap[_swapTwo].push(token);\n token.safeApprove(address(_swapTwo), MAX_UINT256);\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n } catch {\n break;\n }\n }\n require(i > 1, \"swap must have at least 2 tokens\");\n }\n }\n }\n\n /**\n * @notice Calculate amount of tokens you receive on swap\n * @param tokenIndexFrom the token the user wants to sell\n * @param tokenIndexTo the token the user wants to buy\n * @param dx the amount of tokens the user wants to sell. If the token charges\n * a fee on transfers, use the amount that gets transferred after the fee.\n * @return amount of tokens the user will receive\n */\n function calculateSwap(\n IERC20 token,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx\n ) external view virtual returns (uint256) {\n ISwap swap = ISwap(\n swapMap[address(token)]\n );\n return swap.calculateSwap(tokenIndexFrom, tokenIndexTo, dx);\n }\n\n function swapAndRedeem(\n address to,\n uint256 chainId,\n IERC20 token,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx,\n uint256 minDy,\n uint256 deadline\n ) external {\n ISwap swap = ISwap(swapMap[address(token)]);\n require(address(swap) != address(0), \"Swap is 0x00\");\n IERC20[] memory tokens = swapTokensMap[address(swap)];\n tokens[tokenIndexFrom].safeTransferFrom(\n msg.sender,\n address(this),\n dx\n );\n // swap\n\n uint256 swappedAmount = swap.swap(\n tokenIndexFrom,\n tokenIndexTo,\n dx,\n minDy,\n deadline\n );\n // deposit into bridge, gets nUSD\n if (\n token.allowance(address(this), address(synapseBridge)) <\n swappedAmount\n ) {\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n }\n synapseBridge.redeem(to, chainId, token, swappedAmount);\n }\n\n function swapAndRedeemAndSwap(\n address to,\n uint256 chainId,\n IERC20 token,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx,\n uint256 minDy,\n uint256 deadline,\n uint8 swapTokenIndexFrom,\n uint8 swapTokenIndexTo,\n uint256 swapMinDy,\n uint256 swapDeadline\n ) external {\n require(\n address(swapMap[address(token)]) != address(0),\n \"Swap is 0x00\"\n );\n IERC20[] memory tokens = swapTokensMap[\n swapMap[address(token)]\n ];\n tokens[tokenIndexFrom].safeTransferFrom(\n msg.sender,\n address(this),\n dx\n );\n // swap\n\n uint256 swappedAmount = ISwap(swapMap[address(token)]).swap(tokenIndexFrom, tokenIndexTo, dx, minDy, deadline);\n // deposit into bridge, gets nUSD\n if (\n token.allowance(address(this), address(synapseBridge)) <\n swappedAmount\n ) {\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n }\n synapseBridge.redeemAndSwap(\n to,\n chainId,\n token,\n swappedAmount,\n swapTokenIndexFrom,\n swapTokenIndexTo,\n swapMinDy,\n swapDeadline\n );\n }\n\n function swapAndRedeemAndRemove(\n address to,\n uint256 chainId,\n IERC20 token,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx,\n uint256 minDy,\n uint256 deadline,\n uint8 liqTokenIndex,\n uint256 liqMinAmount,\n uint256 liqDeadline\n ) external {\n ISwap swap = ISwap(swapMap[address(token)]);\n require(address(swap) != address(0), \"Swap is 0x00\");\n IERC20[] memory tokens = swapTokensMap[address(swap)];\n tokens[tokenIndexFrom].safeTransferFrom(\n msg.sender,\n address(this),\n dx\n );\n // swap\n\n uint256 swappedAmount = swap.swap(\n tokenIndexFrom,\n tokenIndexTo,\n dx,\n minDy,\n deadline\n );\n // deposit into bridge, gets nUSD\n if (\n token.allowance(address(this), address(synapseBridge)) <\n swappedAmount\n ) {\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n }\n synapseBridge.redeemAndRemove(\n to,\n chainId,\n token,\n swappedAmount,\n liqTokenIndex,\n liqMinAmount,\n liqDeadline\n );\n }\n\n /**\n * @notice wraps SynapseBridge redeem()\n * @param to address on other chain to redeem underlying assets to\n * @param chainId which underlying chain to bridge assets onto\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n **/\n function redeem(\n address to,\n uint256 chainId,\n IERC20 token,\n uint256 amount\n ) external {\n token.safeTransferFrom(msg.sender, address(this), amount);\n if (token.allowance(address(this), address(synapseBridge)) < amount) {\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n }\n synapseBridge.redeem(to, chainId, token, amount);\n }\n\n /**\n * @notice wraps SynapseBridge redeem()\n * @param to address on other chain to redeem underlying assets to\n * @param chainId which underlying chain to bridge assets onto\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n **/\n function deposit(\n address to,\n uint256 chainId,\n IERC20 token,\n uint256 amount\n ) external {\n token.safeTransferFrom(msg.sender, address(this), amount);\n if (token.allowance(address(this), address(synapseBridge)) < amount) {\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n }\n synapseBridge.deposit(to, chainId, token, amount);\n }\n\n /**\n * @notice Wraps SynapseBridge deposit() function to make it compatible w/ ETH -> WETH conversions\n * @param to address on other chain to bridge assets to\n * @param chainId which chain to bridge assets onto\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n **/\n function depositETH(\n address to,\n uint256 chainId,\n uint256 amount\n ) external payable {\n require(msg.value > 0 && msg.value == amount, 'INCORRECT MSG VALUE');\n IWETH9(WETH_ADDRESS).deposit{value: msg.value}();\n synapseBridge.deposit(to, chainId, IERC20(WETH_ADDRESS), amount);\n }\n\n\n function swapETHAndRedeem(\n address to,\n uint256 chainId,\n IERC20 token,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx,\n uint256 minDy,\n uint256 deadline\n ) external payable {\n require(WETH_ADDRESS != address(0), \"WETH 0\");\n require(msg.value > 0 && msg.value == dx, \"INCORRECT MSG VALUE\");\n ISwap swap = ISwap(swapMap[address(token)]);\n require(address(swap) != address(0), \"Swap is 0x00\");\n IWETH9(WETH_ADDRESS).deposit{value: msg.value}();\n\n // swap\n uint256 swappedAmount = swap.swap(\n tokenIndexFrom,\n tokenIndexTo,\n dx,\n minDy,\n deadline\n );\n synapseBridge.redeem(to, chainId, token, swappedAmount);\n }\n\n\n function swapETHAndRedeemAndSwap(\n address to,\n uint256 chainId,\n IERC20 token,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx,\n uint256 minDy,\n uint256 deadline,\n uint8 swapTokenIndexFrom,\n uint8 swapTokenIndexTo,\n uint256 swapMinDy,\n uint256 swapDeadline\n ) external payable {\n require(WETH_ADDRESS != address(0), \"WETH 0\");\n require(msg.value > 0 && msg.value == dx, \"INCORRECT MSG VALUE\");\n ISwap swap = ISwap(swapMap[address(token)]);\n require(address(swap) != address(0), \"Swap is 0x00\");\n IWETH9(WETH_ADDRESS).deposit{value: msg.value}();\n\n // swap\n uint256 swappedAmount = swap.swap(\n tokenIndexFrom,\n tokenIndexTo,\n dx,\n minDy,\n deadline\n );\n synapseBridge.redeemAndSwap(to, chainId, token, swappedAmount,swapTokenIndexFrom,\n swapTokenIndexTo,\n swapMinDy,\n swapDeadline);\n }\n\n\n /**\n * @notice Wraps redeemAndSwap on SynapseBridge.sol\n * Relays to nodes that (typically) a wrapped synAsset ERC20 token has been burned and the underlying needs to be redeeemed on the native chain. This function indicates to the nodes that they should attempt to redeem the LP token for the underlying assets (E.g \"swap\" out of the LP token)\n * @param to address on other chain to redeem underlying assets to\n * @param chainId which underlying chain to bridge assets onto\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n * @param tokenIndexFrom the token the user wants to swap from\n * @param tokenIndexTo the token the user wants to swap to\n * @param minDy the min amount the user would like to receive, or revert to only minting the SynERC20 token crosschain.\n * @param deadline latest timestamp to accept this transaction\n **/\n function redeemAndSwap(\n address to,\n uint256 chainId,\n IERC20 token,\n uint256 amount,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 minDy,\n uint256 deadline\n ) external {\n token.safeTransferFrom(msg.sender, address(this), amount);\n if (token.allowance(address(this), address(synapseBridge)) < amount) {\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n }\n synapseBridge.redeemAndSwap(\n to,\n chainId,\n token,\n amount,\n tokenIndexFrom,\n tokenIndexTo,\n minDy,\n deadline\n );\n }\n\n /**\n * @notice Wraps redeemAndRemove on SynapseBridge\n * Relays to nodes that (typically) a wrapped synAsset ERC20 token has been burned and the underlying needs to be redeeemed on the native chain. This function indicates to the nodes that they should attempt to redeem the LP token for the underlying assets (E.g \"swap\" out of the LP token)\n * @param to address on other chain to redeem underlying assets to\n * @param chainId which underlying chain to bridge assets onto\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount of (typically) LP token to pass to the nodes to attempt to removeLiquidity() with to redeem for the underlying assets of the LP token\n * @param liqTokenIndex Specifies which of the underlying LP assets the nodes should attempt to redeem for\n * @param liqMinAmount Specifies the minimum amount of the underlying asset needed for the nodes to execute the redeem/swap\n * @param liqDeadline Specificies the deadline that the nodes are allowed to try to redeem/swap the LP token\n **/\n function redeemAndRemove(\n address to,\n uint256 chainId,\n IERC20 token,\n uint256 amount,\n uint8 liqTokenIndex,\n uint256 liqMinAmount,\n uint256 liqDeadline\n ) external {\n token.safeTransferFrom(msg.sender, address(this), amount);\n if (token.allowance(address(this), address(synapseBridge)) < amount) {\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n }\n synapseBridge.redeemAndRemove(\n to,\n chainId,\n token,\n amount,\n liqTokenIndex,\n liqMinAmount,\n liqDeadline\n );\n }\n\n /**\n * @notice Wraps SynapseBridge redeemv2() function\n * @param to address on other chain to bridge assets to\n * @param chainId which chain to bridge assets onto\n * @param token ERC20 compatible token to redeem into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n **/\n function redeemv2(\n bytes32 to,\n uint256 chainId,\n IERC20 token,\n uint256 amount\n ) external {\n token.safeTransferFrom(msg.sender, address(this), amount);\n\n if (token.allowance(address(this), address(synapseBridge)) < amount) {\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n }\n synapseBridge.redeemv2(to, chainId, token, amount);\n }\n}\n" + }, + "contracts/bridge/wrappers/L1BridgeZap.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.6.12;\n\nimport '@openzeppelin/contracts/token/ERC20/IERC20.sol';\nimport '@openzeppelin/contracts/token/ERC20/SafeERC20.sol';\nimport '../interfaces/ISwap.sol';\nimport '../interfaces/ISynapseBridge.sol';\nimport \"../interfaces/IWETH9.sol\";\n\n\n/**\n * @title L1BridgeZap\n * @notice This contract is responsible for handling user Zaps into the SynapseBridge contract, through the Synapse Swap contracts. It does so\n * It does so by combining the action of addLiquidity() to the base swap pool, and then calling either deposit() or depositAndSwap() on the bridge.\n * This is done in hopes of automating portions of the bridge user experience to users, while keeping the SynapseBridge contract logic small.\n *\n * @dev This contract should be deployed with a base Swap.sol address and a SynapseBridge.sol address, otherwise, it will not function.\n */\ncontract L1BridgeZap {\n using SafeERC20 for IERC20;\n\n uint256 constant MAX_UINT256 = 2**256 - 1;\n \n ISwap baseSwap;\n ISynapseBridge synapseBridge;\n IERC20[] public baseTokens;\n address payable public immutable WETH_ADDRESS;\n \n\n /**\n * @notice Constructs the contract, approves each token inside of baseSwap to be used by baseSwap (needed for addLiquidity())\n */\n constructor(address payable _wethAddress, ISwap _baseSwap, ISynapseBridge _synapseBridge) public {\n WETH_ADDRESS = _wethAddress;\n baseSwap = _baseSwap;\n synapseBridge = _synapseBridge;\n IERC20(_wethAddress).safeIncreaseAllowance(address(_synapseBridge), MAX_UINT256);\n {\n uint8 i;\n for (; i < 32; i++) {\n try _baseSwap.getToken(i) returns (IERC20 token) {\n baseTokens.push(token);\n token.safeIncreaseAllowance(address(_baseSwap), MAX_UINT256);\n } catch {\n break;\n }\n }\n require(i > 1, 'baseSwap must have at least 2 tokens');\n }\n }\n \n /**\n * @notice Wraps SynapseBridge deposit() function to make it compatible w/ ETH -> WETH conversions\n * @param to address on other chain to bridge assets to\n * @param chainId which chain to bridge assets onto\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n **/\n function depositETH(\n address to,\n uint256 chainId,\n uint256 amount\n ) external payable {\n require(msg.value > 0 && msg.value == amount, 'INCORRECT MSG VALUE');\n IWETH9(WETH_ADDRESS).deposit{value: msg.value}();\n synapseBridge.deposit(to, chainId, IERC20(WETH_ADDRESS), amount);\n }\n\n /**\n * @notice Wraps SynapseBridge depositAndSwap() function to make it compatible w/ ETH -> WETH conversions\n * @param to address on other chain to bridge assets to\n * @param chainId which chain to bridge assets onto\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n * @param tokenIndexFrom the token the user wants to swap from\n * @param tokenIndexTo the token the user wants to swap to\n * @param minDy the min amount the user would like to receive, or revert to only minting the SynERC20 token crosschain.\n * @param deadline latest timestamp to accept this transaction\n **/\n function depositETHAndSwap(\n address to,\n uint256 chainId,\n uint256 amount,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 minDy,\n uint256 deadline\n ) external payable {\n require(msg.value > 0 && msg.value == amount, 'INCORRECT MSG VALUE');\n IWETH9(WETH_ADDRESS).deposit{value: msg.value}();\n synapseBridge.depositAndSwap(to, chainId, IERC20(WETH_ADDRESS), amount, tokenIndexFrom, tokenIndexTo, minDy, deadline);\n }\n\n\n /**\n * @notice A simple method to calculate prices from deposits or\n * withdrawals, excluding fees but including slippage. This is\n * helpful as an input into the various \"min\" parameters on calls\n * to fight front-running\n *\n * @dev This shouldn't be used outside frontends for user estimates.\n *\n * @param amounts an array of token amounts to deposit or withdrawal,\n * corresponding to pooledTokens. The amount should be in each\n * pooled token's native precision.\n * @param deposit whether this is a deposit or a withdrawal\n * @return token amount the user will receive\n */\n function calculateTokenAmount(uint256[] calldata amounts, bool deposit)\n external\n view\n virtual\n returns (uint256)\n {\n return baseSwap.calculateTokenAmount(amounts, deposit);\n }\n\n /**\n * @notice Calculate the amount of underlying token available to withdraw\n * when withdrawing via only single token\n * @param tokenAmount the amount of LP token to burn\n * @param tokenIndex index of which token will be withdrawn\n * @return availableTokenAmount calculated amount of underlying token\n * available to withdraw\n */\n function calculateRemoveLiquidityOneToken(\n uint256 tokenAmount,\n uint8 tokenIndex\n ) external view virtual returns (uint256 availableTokenAmount) {\n return baseSwap.calculateRemoveLiquidityOneToken(tokenAmount, tokenIndex);\n }\n\n\n /**\n * @notice Combines adding liquidity to the given Swap, and calls deposit() on the bridge using that LP token\n * @param to address on other chain to bridge assets to\n * @param chainId which chain to bridge assets onto\n * @param token ERC20 compatible token to deposit into the bridge\n * @param liquidityAmounts the amounts of each token to add, in their native precision\n * @param minToMint the minimum LP tokens adding this amount of liquidity\n * should mint, otherwise revert. Handy for front-running mitigation\n * @param deadline latest timestamp to accept this transaction\n **/\n function zapAndDeposit(\n address to,\n uint256 chainId,\n IERC20 token,\n uint256[] calldata liquidityAmounts,\n uint256 minToMint,\n uint256 deadline\n ) external {\n // add liquidity\n for (uint256 i = 0; i < baseTokens.length; i++) {\n if (liquidityAmounts[i] != 0) {\n baseTokens[i].safeTransferFrom(\n msg.sender,\n address(this),\n liquidityAmounts[i]\n );\n }\n }\n\n uint256 liqAdded = baseSwap.addLiquidity(\n liquidityAmounts,\n minToMint,\n deadline\n );\n // deposit into bridge, gets nUSD\n if (token.allowance(address(this), address(synapseBridge)) < liqAdded) {\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n }\n synapseBridge.deposit(to, chainId, token, liqAdded);\n }\n\n /**\n * @notice Combines adding liquidity to the given Swap, and calls depositAndSwap() on the bridge using that LP token\n * @param to address on other chain to bridge assets to\n * @param chainId which chain to bridge assets onto\n * @param token ERC20 compatible token to deposit into the bridge\n * @param liquidityAmounts the amounts of each token to add, in their native precision\n * @param minToMint the minimum LP tokens adding this amount of liquidity\n * should mint, otherwise revert. Handy for front-running mitigation\n * @param liqDeadline latest timestamp to accept this transaction\n * @param tokenIndexFrom the token the user wants to swap from\n * @param tokenIndexTo the token the user wants to swap to\n * @param minDy the min amount the user would like to receive, or revert to only minting the SynERC20 token crosschain.\n * @param swapDeadline latest timestamp to accept this transaction\n **/\n function zapAndDepositAndSwap(\n address to,\n uint256 chainId,\n IERC20 token,\n uint256[] calldata liquidityAmounts,\n uint256 minToMint,\n uint256 liqDeadline,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 minDy,\n uint256 swapDeadline\n ) external {\n // add liquidity\n for (uint256 i = 0; i < baseTokens.length; i++) {\n if (liquidityAmounts[i] != 0) {\n baseTokens[i].safeTransferFrom(\n msg.sender,\n address(this),\n liquidityAmounts[i]\n );\n }\n }\n\n uint256 liqAdded = baseSwap.addLiquidity(\n liquidityAmounts,\n minToMint,\n liqDeadline\n );\n // deposit into bridge, bridge attemps to swap into desired asset\n if (token.allowance(address(this), address(synapseBridge)) < liqAdded) {\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n }\n synapseBridge.depositAndSwap(\n to,\n chainId,\n token,\n liqAdded,\n tokenIndexFrom,\n tokenIndexTo,\n minDy,\n swapDeadline\n );\n }\n\n /**\n * @notice Wraps SynapseBridge deposit() function\n * @param to address on other chain to bridge assets to\n * @param chainId which chain to bridge assets onto\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n **/\n function deposit(\n address to,\n uint256 chainId,\n IERC20 token,\n uint256 amount\n ) external {\n token.safeTransferFrom(msg.sender, address(this), amount);\n\n if (token.allowance(address(this), address(synapseBridge)) < amount) {\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n }\n synapseBridge.deposit(to, chainId, token, amount);\n }\n \n /**\n * @notice Wraps SynapseBridge depositAndSwap() function\n * @param to address on other chain to bridge assets to\n * @param chainId which chain to bridge assets onto\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n * @param tokenIndexFrom the token the user wants to swap from\n * @param tokenIndexTo the token the user wants to swap to\n * @param minDy the min amount the user would like to receive, or revert to only minting the SynERC20 token crosschain.\n * @param deadline latest timestamp to accept this transaction\n **/\n function depositAndSwap(\n address to,\n uint256 chainId,\n IERC20 token,\n uint256 amount,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 minDy,\n uint256 deadline\n ) external {\n token.safeTransferFrom(msg.sender, address(this), amount);\n \n if (token.allowance(address(this), address(synapseBridge)) < amount) {\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n }\n synapseBridge.depositAndSwap(to, chainId, token, amount, tokenIndexFrom, tokenIndexTo, minDy, deadline);\n }\n\n\n /**\n * @notice Wraps SynapseBridge redeem() function\n * @param to address on other chain to bridge assets to\n * @param chainId which chain to bridge assets onto\n * @param token ERC20 compatible token to redeem into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n **/\n function redeem(\n address to,\n uint256 chainId,\n IERC20 token,\n uint256 amount\n ) external {\n token.safeTransferFrom(msg.sender, address(this), amount);\n\n if (token.allowance(address(this), address(synapseBridge)) < amount) {\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n }\n synapseBridge.redeem(to, chainId, token, amount);\n }\n\n /**\n * @notice Wraps SynapseBridge redeemv2() function\n * @param to address on other chain to bridge assets to\n * @param chainId which chain to bridge assets onto\n * @param token ERC20 compatible token to redeem into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n **/\n function redeemv2(\n bytes32 to,\n uint256 chainId,\n IERC20 token,\n uint256 amount\n ) external {\n token.safeTransferFrom(msg.sender, address(this), amount);\n\n if (token.allowance(address(this), address(synapseBridge)) < amount) {\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n }\n synapseBridge.redeemv2(to, chainId, token, amount);\n }\n\n}\n" + }, + "contracts/bridge/wrappers/HarmonyBridgeZap.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.6.12;\n\nimport \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/SafeERC20.sol\";\nimport \"../interfaces/ISwap.sol\";\nimport \"../interfaces/ISynapseBridge.sol\";\nimport \"../interfaces/IWETH9.sol\";\n\ninterface IFrax {\n function exchangeCanonicalForOld(address bridge_token_address, uint256 token_amount) external returns (uint256);\n}\n\ncontract HarmonyBridgeZap {\n using SafeERC20 for IERC20;\n\n ISynapseBridge synapseBridge;\n address payable public immutable WETH_ADDRESS;\n IFrax private constant CANOLICAL_FRAX = IFrax(0xFa7191D292d5633f702B0bd7E3E3BcCC0e633200);\n IERC20 private constant SYN_FRAX = IERC20(0x1852F70512298d56e9c8FDd905e02581E04ddb2a);\n\n mapping(address => address) public swapMap;\n mapping(address => IERC20[]) public swapTokensMap;\n\n uint256 constant MAX_UINT256 = 2**256 - 1;\n\n constructor(\n address payable _wethAddress,\n address _swapOne,\n address tokenOne,\n address _swapTwo,\n address tokenTwo,\n ISynapseBridge _synapseBridge\n ) public {\n WETH_ADDRESS = _wethAddress;\n synapseBridge = _synapseBridge;\n swapMap[tokenOne] = _swapOne;\n swapMap[tokenTwo] = _swapTwo;\n\n if (address(_swapOne) != address(0)) {\n {\n uint8 i;\n for (; i < 32; i++) {\n try ISwap(_swapOne).getToken(i) returns (\n IERC20 token\n ) {\n swapTokensMap[_swapOne].push(token);\n token.safeApprove(address(_swapOne), MAX_UINT256);\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n } catch {\n break;\n }\n }\n require(i > 1, \"swap must have at least 2 tokens\");\n }\n }\n if (address(_swapTwo) != address(0)) {\n {\n uint8 i;\n for (; i < 32; i++) {\n try ISwap(_swapTwo).getToken(i) returns (\n IERC20 token\n ) {\n swapTokensMap[_swapTwo].push(token);\n token.safeApprove(address(_swapTwo), MAX_UINT256);\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n } catch {\n break;\n }\n }\n require(i > 1, \"swap must have at least 2 tokens\");\n }\n }\n }\n\n /**\n * @notice Calculate amount of tokens you receive on swap\n * @param tokenIndexFrom the token the user wants to sell\n * @param tokenIndexTo the token the user wants to buy\n * @param dx the amount of tokens the user wants to sell. If the token charges\n * a fee on transfers, use the amount that gets transferred after the fee.\n * @return amount of tokens the user will receive\n */\n function calculateSwap(\n IERC20 token,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx\n ) external view virtual returns (uint256) {\n ISwap swap = ISwap(\n swapMap[address(token)]\n );\n return swap.calculateSwap(tokenIndexFrom, tokenIndexTo, dx);\n }\n\n function swapAndRedeem(\n address to,\n uint256 chainId,\n IERC20 token,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx,\n uint256 minDy,\n uint256 deadline\n ) external {\n ISwap swap = ISwap(swapMap[address(token)]);\n require(address(swap) != address(0), \"Swap is 0x00\");\n IERC20[] memory tokens = swapTokensMap[address(swap)];\n tokens[tokenIndexFrom].safeTransferFrom(\n msg.sender,\n address(this),\n dx\n );\n // swap\n\n uint256 swappedAmount = swap.swap(\n tokenIndexFrom,\n tokenIndexTo,\n dx,\n minDy,\n deadline\n );\n // deposit into bridge, gets nUSD\n if (\n token.allowance(address(this), address(synapseBridge)) <\n swappedAmount\n ) {\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n }\n synapseBridge.redeem(to, chainId, token, swappedAmount);\n }\n\n function swapAndRedeemAndSwap(\n address to,\n uint256 chainId,\n IERC20 token,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx,\n uint256 minDy,\n uint256 deadline,\n uint8 swapTokenIndexFrom,\n uint8 swapTokenIndexTo,\n uint256 swapMinDy,\n uint256 swapDeadline\n ) external {\n require(\n address(swapMap[address(token)]) != address(0),\n \"Swap is 0x00\"\n );\n IERC20[] memory tokens = swapTokensMap[\n swapMap[address(token)]\n ];\n tokens[tokenIndexFrom].safeTransferFrom(\n msg.sender,\n address(this),\n dx\n );\n // swap\n\n uint256 swappedAmount = ISwap(swapMap[address(token)]).swap(tokenIndexFrom, tokenIndexTo, dx, minDy, deadline);\n // deposit into bridge, gets nUSD\n if (\n token.allowance(address(this), address(synapseBridge)) <\n swappedAmount\n ) {\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n }\n synapseBridge.redeemAndSwap(\n to,\n chainId,\n token,\n swappedAmount,\n swapTokenIndexFrom,\n swapTokenIndexTo,\n swapMinDy,\n swapDeadline\n );\n }\n\n function swapAndRedeemAndRemove(\n address to,\n uint256 chainId,\n IERC20 token,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx,\n uint256 minDy,\n uint256 deadline,\n uint8 liqTokenIndex,\n uint256 liqMinAmount,\n uint256 liqDeadline\n ) external {\n ISwap swap = ISwap(swapMap[address(token)]);\n require(address(swap) != address(0), \"Swap is 0x00\");\n IERC20[] memory tokens = swapTokensMap[address(swap)];\n tokens[tokenIndexFrom].safeTransferFrom(\n msg.sender,\n address(this),\n dx\n );\n // swap\n\n uint256 swappedAmount = swap.swap(\n tokenIndexFrom,\n tokenIndexTo,\n dx,\n minDy,\n deadline\n );\n // deposit into bridge, gets nUSD\n if (\n token.allowance(address(this), address(synapseBridge)) <\n swappedAmount\n ) {\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n }\n synapseBridge.redeemAndRemove(\n to,\n chainId,\n token,\n swappedAmount,\n liqTokenIndex,\n liqMinAmount,\n liqDeadline\n );\n }\n\n /**\n * @notice wraps SynapseBridge redeem()\n * @param to address on other chain to redeem underlying assets to\n * @param chainId which underlying chain to bridge assets onto\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n **/\n function redeem(\n address to,\n uint256 chainId,\n IERC20 token,\n uint256 amount\n ) external {\n token.safeTransferFrom(msg.sender, address(this), amount);\n if (address(token) == address(CANOLICAL_FRAX)) {\n uint256 swappedAmount = CANOLICAL_FRAX.exchangeCanonicalForOld(address(SYN_FRAX), amount);\n if (SYN_FRAX.allowance(address(this), address(synapseBridge)) < amount) {\n SYN_FRAX.safeApprove(address(synapseBridge), MAX_UINT256);\n }\n synapseBridge.redeem(to, chainId, SYN_FRAX, swappedAmount);\n } else {\n if (token.allowance(address(this), address(synapseBridge)) < amount) {\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n }\n synapseBridge.redeem(to, chainId, token, amount);\n }\n \n }\n\n /**\n * @notice Wraps SynapseBridge redeemv2() function\n * @param to address on other chain to bridge assets to\n * @param chainId which chain to bridge assets onto\n * @param token ERC20 compatible token to redeem into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n **/\n function redeemv2(\n bytes32 to,\n uint256 chainId,\n IERC20 token,\n uint256 amount\n ) external {\n token.safeTransferFrom(msg.sender, address(this), amount);\n\n if (token.allowance(address(this), address(synapseBridge)) < amount) {\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n }\n synapseBridge.redeemv2(to, chainId, token, amount);\n }\n\n /**\n * @notice wraps SynapseBridge redeem()\n * @param to address on other chain to redeem underlying assets to\n * @param chainId which underlying chain to bridge assets onto\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n **/\n function deposit(\n address to,\n uint256 chainId,\n IERC20 token,\n uint256 amount\n ) external {\n token.safeTransferFrom(msg.sender, address(this), amount);\n if (token.allowance(address(this), address(synapseBridge)) < amount) {\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n }\n synapseBridge.deposit(to, chainId, token, amount);\n }\n\n function swapETHAndRedeem(\n address to,\n uint256 chainId,\n IERC20 token,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx,\n uint256 minDy,\n uint256 deadline\n ) external payable {\n require(WETH_ADDRESS != address(0), \"WETH 0\");\n require(msg.value > 0 && msg.value == dx, \"INCORRECT MSG VALUE\");\n ISwap swap = ISwap(swapMap[address(token)]);\n require(address(swap) != address(0), \"Swap is 0x00\");\n IWETH9(WETH_ADDRESS).deposit{value: msg.value}();\n\n // swap\n uint256 swappedAmount = swap.swap(\n tokenIndexFrom,\n tokenIndexTo,\n dx,\n minDy,\n deadline\n );\n synapseBridge.redeem(to, chainId, token, swappedAmount);\n }\n\n /**\n * @notice Wraps redeemAndSwap on SynapseBridge.sol\n * Relays to nodes that (typically) a wrapped synAsset ERC20 token has been burned and the underlying needs to be redeeemed on the native chain. This function indicates to the nodes that they should attempt to redeem the LP token for the underlying assets (E.g \"swap\" out of the LP token)\n * @param to address on other chain to redeem underlying assets to\n * @param chainId which underlying chain to bridge assets onto\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n * @param tokenIndexFrom the token the user wants to swap from\n * @param tokenIndexTo the token the user wants to swap to\n * @param minDy the min amount the user would like to receive, or revert to only minting the SynERC20 token crosschain.\n * @param deadline latest timestamp to accept this transaction\n **/\n function redeemAndSwap(\n address to,\n uint256 chainId,\n IERC20 token,\n uint256 amount,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 minDy,\n uint256 deadline\n ) external {\n token.safeTransferFrom(msg.sender, address(this), amount);\n if (token.allowance(address(this), address(synapseBridge)) < amount) {\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n }\n synapseBridge.redeemAndSwap(\n to,\n chainId,\n token,\n amount,\n tokenIndexFrom,\n tokenIndexTo,\n minDy,\n deadline\n );\n }\n\n /**\n * @notice Wraps redeemAndRemove on SynapseBridge\n * Relays to nodes that (typically) a wrapped synAsset ERC20 token has been burned and the underlying needs to be redeeemed on the native chain. This function indicates to the nodes that they should attempt to redeem the LP token for the underlying assets (E.g \"swap\" out of the LP token)\n * @param to address on other chain to redeem underlying assets to\n * @param chainId which underlying chain to bridge assets onto\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount of (typically) LP token to pass to the nodes to attempt to removeLiquidity() with to redeem for the underlying assets of the LP token\n * @param liqTokenIndex Specifies which of the underlying LP assets the nodes should attempt to redeem for\n * @param liqMinAmount Specifies the minimum amount of the underlying asset needed for the nodes to execute the redeem/swap\n * @param liqDeadline Specificies the deadline that the nodes are allowed to try to redeem/swap the LP token\n **/\n function redeemAndRemove(\n address to,\n uint256 chainId,\n IERC20 token,\n uint256 amount,\n uint8 liqTokenIndex,\n uint256 liqMinAmount,\n uint256 liqDeadline\n ) external {\n token.safeTransferFrom(msg.sender, address(this), amount);\n if (token.allowance(address(this), address(synapseBridge)) < amount) {\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n }\n synapseBridge.redeemAndRemove(\n to,\n chainId,\n token,\n amount,\n liqTokenIndex,\n liqMinAmount,\n liqDeadline\n );\n }\n}\n" + }, + "contracts/bridge/SynapseBridge.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.6.12;\n\nimport \"@openzeppelin/contracts-upgradeable/proxy/Initializable.sol\";\nimport \"@openzeppelin/contracts-upgradeable/access/AccessControlUpgradeable.sol\";\nimport \"@openzeppelin/contracts-upgradeable/utils/ReentrancyGuardUpgradeable.sol\";\nimport \"@openzeppelin/contracts-upgradeable/utils/PausableUpgradeable.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/SafeERC20.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/ERC20Burnable.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport \"@openzeppelin/contracts/math/SafeMath.sol\";\n\nimport \"./interfaces/ISwap.sol\";\nimport \"./interfaces/IWETH9.sol\";\n\ninterface IERC20Mintable is IERC20 {\n function mint(address to, uint256 amount) external;\n}\n\ncontract SynapseBridge is\n Initializable,\n AccessControlUpgradeable,\n ReentrancyGuardUpgradeable,\n PausableUpgradeable\n{\n using SafeERC20 for IERC20;\n using SafeERC20 for IERC20Mintable;\n using SafeMath for uint256;\n\n bytes32 public constant NODEGROUP_ROLE = keccak256(\"NODEGROUP_ROLE\");\n bytes32 public constant GOVERNANCE_ROLE = keccak256(\"GOVERNANCE_ROLE\");\n\n mapping(address => uint256) private fees;\n\n uint256 public startBlockNumber;\n uint256 public constant bridgeVersion = 6;\n uint256 public chainGasAmount;\n address payable public WETH_ADDRESS;\n\n mapping(bytes32 => bool) private kappaMap;\n\n receive() external payable {}\n\n function initialize() external initializer {\n startBlockNumber = block.number;\n _setupRole(DEFAULT_ADMIN_ROLE, msg.sender);\n __AccessControl_init();\n }\n\n function setChainGasAmount(uint256 amount) external {\n require(hasRole(GOVERNANCE_ROLE, msg.sender), \"Not governance\");\n chainGasAmount = amount;\n }\n\n function setWethAddress(address payable _wethAddress) external {\n require(hasRole(DEFAULT_ADMIN_ROLE, msg.sender), \"Not admin\");\n WETH_ADDRESS = _wethAddress;\n }\n\n function addKappas(bytes32[] calldata kappas) external {\n require(hasRole(GOVERNANCE_ROLE, msg.sender), \"Not governance\");\n for (uint256 i = 0; i < kappas.length; ++i) {\n kappaMap[kappas[i]] = true;\n }\n }\n\n event TokenDeposit(\n address indexed to,\n uint256 chainId,\n IERC20 token,\n uint256 amount\n );\n event TokenRedeem(\n address indexed to,\n uint256 chainId,\n IERC20 token,\n uint256 amount\n );\n event TokenWithdraw(\n address indexed to,\n IERC20 token,\n uint256 amount,\n uint256 fee,\n bytes32 indexed kappa\n );\n event TokenMint(\n address indexed to,\n IERC20Mintable token,\n uint256 amount,\n uint256 fee,\n bytes32 indexed kappa\n );\n event TokenDepositAndSwap(\n address indexed to,\n uint256 chainId,\n IERC20 token,\n uint256 amount,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 minDy,\n uint256 deadline\n );\n event TokenMintAndSwap(\n address indexed to,\n IERC20Mintable token,\n uint256 amount,\n uint256 fee,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 minDy,\n uint256 deadline,\n bool swapSuccess,\n bytes32 indexed kappa\n );\n event TokenRedeemAndSwap(\n address indexed to,\n uint256 chainId,\n IERC20 token,\n uint256 amount,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 minDy,\n uint256 deadline\n );\n event TokenRedeemAndRemove(\n address indexed to,\n uint256 chainId,\n IERC20 token,\n uint256 amount,\n uint8 swapTokenIndex,\n uint256 swapMinAmount,\n uint256 swapDeadline\n );\n event TokenWithdrawAndRemove(\n address indexed to,\n IERC20 token,\n uint256 amount,\n uint256 fee,\n uint8 swapTokenIndex,\n uint256 swapMinAmount,\n uint256 swapDeadline,\n bool swapSuccess,\n bytes32 indexed kappa\n );\n\n // v2 events\n event TokenRedeemV2(\n bytes32 indexed to,\n uint256 chainId,\n IERC20 token,\n uint256 amount\n );\n\n // VIEW FUNCTIONS ***/\n function getFeeBalance(address tokenAddress)\n external\n view\n returns (uint256)\n {\n return fees[tokenAddress];\n }\n\n function kappaExists(bytes32 kappa) external view returns (bool) {\n return kappaMap[kappa];\n }\n\n // FEE FUNCTIONS ***/\n /**\n * * @notice withdraw specified ERC20 token fees to a given address\n * * @param token ERC20 token in which fees acccumulated to transfer\n * * @param to Address to send the fees to\n */\n function withdrawFees(IERC20 token, address to) external whenNotPaused {\n require(hasRole(GOVERNANCE_ROLE, msg.sender), \"Not governance\");\n require(to != address(0), \"Address is 0x000\");\n if (fees[address(token)] != 0) {\n token.safeTransfer(to, fees[address(token)]);\n fees[address(token)] = 0;\n }\n }\n\n // PAUSABLE FUNCTIONS ***/\n function pause() external {\n require(hasRole(GOVERNANCE_ROLE, msg.sender), \"Not governance\");\n _pause();\n }\n\n function unpause() external {\n require(hasRole(GOVERNANCE_ROLE, msg.sender), \"Not governance\");\n _unpause();\n }\n\n /**\n * @notice Relays to nodes to transfers an ERC20 token cross-chain\n * @param to address on other chain to bridge assets to\n * @param chainId which chain to bridge assets onto\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n **/\n function deposit(\n address to,\n uint256 chainId,\n IERC20 token,\n uint256 amount\n ) external nonReentrant whenNotPaused {\n emit TokenDeposit(to, chainId, token, amount);\n token.safeTransferFrom(msg.sender, address(this), amount);\n }\n\n /**\n * @notice Relays to nodes that (typically) a wrapped synAsset ERC20 token has been burned and the underlying needs to be redeeemed on the native chain\n * @param to address on other chain to redeem underlying assets to\n * @param chainId which underlying chain to bridge assets onto\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n **/\n function redeem(\n address to,\n uint256 chainId,\n ERC20Burnable token,\n uint256 amount\n ) external nonReentrant whenNotPaused {\n emit TokenRedeem(to, chainId, token, amount);\n token.burnFrom(msg.sender, amount);\n }\n\n /**\n * @notice Function to be called by the node group to withdraw the underlying assets from the contract\n * @param to address on chain to send underlying assets to\n * @param token ERC20 compatible token to withdraw from the bridge\n * @param amount Amount in native token decimals to withdraw\n * @param fee Amount in native token decimals to save to the contract as fees\n * @param kappa kappa\n **/\n function withdraw(\n address to,\n IERC20 token,\n uint256 amount,\n uint256 fee,\n bytes32 kappa\n ) external nonReentrant whenNotPaused {\n require(\n hasRole(NODEGROUP_ROLE, msg.sender),\n \"Caller is not a node group\"\n );\n require(amount > fee, \"Amount must be greater than fee\");\n require(!kappaMap[kappa], \"Kappa is already present\");\n kappaMap[kappa] = true;\n fees[address(token)] = fees[address(token)].add(fee);\n if (address(token) == WETH_ADDRESS && WETH_ADDRESS != address(0)) {\n IWETH9(WETH_ADDRESS).withdraw(amount.sub(fee));\n (bool success, ) = to.call{value: amount.sub(fee)}(\"\");\n require(success, \"ETH_TRANSFER_FAILED\");\n emit TokenWithdraw(to, token, amount, fee, kappa);\n } else {\n emit TokenWithdraw(to, token, amount, fee, kappa);\n token.safeTransfer(to, amount.sub(fee));\n }\n }\n\n /**\n * @notice Nodes call this function to mint a SynERC20 (or any asset that the bridge is given minter access to). This is called by the nodes after a TokenDeposit event is emitted.\n * @dev This means the SynapseBridge.sol contract must have minter access to the token attempting to be minted\n * @param to address on other chain to redeem underlying assets to\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain post-fees\n * @param fee Amount in native token decimals to save to the contract as fees\n * @param kappa kappa\n **/\n function mint(\n address payable to,\n IERC20Mintable token,\n uint256 amount,\n uint256 fee,\n bytes32 kappa\n ) external nonReentrant whenNotPaused {\n require(\n hasRole(NODEGROUP_ROLE, msg.sender),\n \"Caller is not a node group\"\n );\n require(amount > fee, \"Amount must be greater than fee\");\n require(!kappaMap[kappa], \"Kappa is already present\");\n kappaMap[kappa] = true;\n fees[address(token)] = fees[address(token)].add(fee);\n emit TokenMint(to, token, amount.sub(fee), fee, kappa);\n token.mint(address(this), amount);\n IERC20(token).safeTransfer(to, amount.sub(fee));\n if (chainGasAmount != 0 && address(this).balance > chainGasAmount) {\n to.call.value(chainGasAmount)(\"\");\n }\n }\n\n /**\n * @notice Relays to nodes to both transfer an ERC20 token cross-chain, and then have the nodes execute a swap through a liquidity pool on behalf of the user.\n * @param to address on other chain to bridge assets to\n * @param chainId which chain to bridge assets onto\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n * @param tokenIndexFrom the token the user wants to swap from\n * @param tokenIndexTo the token the user wants to swap to\n * @param minDy the min amount the user would like to receive, or revert to only minting the SynERC20 token crosschain.\n * @param deadline latest timestamp to accept this transaction\n **/\n function depositAndSwap(\n address to,\n uint256 chainId,\n IERC20 token,\n uint256 amount,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 minDy,\n uint256 deadline\n ) external nonReentrant whenNotPaused {\n emit TokenDepositAndSwap(\n to,\n chainId,\n token,\n amount,\n tokenIndexFrom,\n tokenIndexTo,\n minDy,\n deadline\n );\n token.safeTransferFrom(msg.sender, address(this), amount);\n }\n\n /**\n * @notice Relays to nodes that (typically) a wrapped synAsset ERC20 token has been burned and the underlying needs to be redeeemed on the native chain. This function indicates to the nodes that they should attempt to redeem the LP token for the underlying assets (E.g \"swap\" out of the LP token)\n * @param to address on other chain to redeem underlying assets to\n * @param chainId which underlying chain to bridge assets onto\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n * @param tokenIndexFrom the token the user wants to swap from\n * @param tokenIndexTo the token the user wants to swap to\n * @param minDy the min amount the user would like to receive, or revert to only minting the SynERC20 token crosschain.\n * @param deadline latest timestamp to accept this transaction\n **/\n function redeemAndSwap(\n address to,\n uint256 chainId,\n ERC20Burnable token,\n uint256 amount,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 minDy,\n uint256 deadline\n ) external nonReentrant whenNotPaused {\n emit TokenRedeemAndSwap(\n to,\n chainId,\n token,\n amount,\n tokenIndexFrom,\n tokenIndexTo,\n minDy,\n deadline\n );\n token.burnFrom(msg.sender, amount);\n }\n\n /**\n * @notice Relays to nodes that (typically) a wrapped synAsset ERC20 token has been burned and the underlying needs to be redeeemed on the native chain. This function indicates to the nodes that they should attempt to redeem the LP token for the underlying assets (E.g \"swap\" out of the LP token)\n * @param to address on other chain to redeem underlying assets to\n * @param chainId which underlying chain to bridge assets onto\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n * @param swapTokenIndex Specifies which of the underlying LP assets the nodes should attempt to redeem for\n * @param swapMinAmount Specifies the minimum amount of the underlying asset needed for the nodes to execute the redeem/swap\n * @param swapDeadline Specificies the deadline that the nodes are allowed to try to redeem/swap the LP token\n **/\n function redeemAndRemove(\n address to,\n uint256 chainId,\n ERC20Burnable token,\n uint256 amount,\n uint8 swapTokenIndex,\n uint256 swapMinAmount,\n uint256 swapDeadline\n ) external nonReentrant whenNotPaused {\n emit TokenRedeemAndRemove(\n to,\n chainId,\n token,\n amount,\n swapTokenIndex,\n swapMinAmount,\n swapDeadline\n );\n token.burnFrom(msg.sender, amount);\n }\n\n /**\n * @notice Nodes call this function to mint a SynERC20 (or any asset that the bridge is given minter access to), and then attempt to swap the SynERC20 into the desired destination asset. This is called by the nodes after a TokenDepositAndSwap event is emitted.\n * @dev This means the BridgeDeposit.sol contract must have minter access to the token attempting to be minted\n * @param to address on other chain to redeem underlying assets to\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain post-fees\n * @param fee Amount in native token decimals to save to the contract as fees\n * @param pool Destination chain's pool to use to swap SynERC20 -> Asset. The nodes determine this by using PoolConfig.sol.\n * @param tokenIndexFrom Index of the SynERC20 asset in the pool\n * @param tokenIndexTo Index of the desired final asset\n * @param minDy Minumum amount (in final asset decimals) that must be swapped for, otherwise the user will receive the SynERC20.\n * @param deadline Epoch time of the deadline that the swap is allowed to be executed.\n * @param kappa kappa\n **/\n function mintAndSwap(\n address payable to,\n IERC20Mintable token,\n uint256 amount,\n uint256 fee,\n ISwap pool,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 minDy,\n uint256 deadline,\n bytes32 kappa\n ) external nonReentrant whenNotPaused {\n require(\n hasRole(NODEGROUP_ROLE, msg.sender),\n \"Caller is not a node group\"\n );\n require(amount > fee, \"Amount must be greater than fee\");\n require(!kappaMap[kappa], \"Kappa is already present\");\n kappaMap[kappa] = true;\n fees[address(token)] = fees[address(token)].add(fee);\n // Transfer gas airdrop\n if (chainGasAmount != 0 && address(this).balance > chainGasAmount) {\n to.call.value(chainGasAmount)(\"\");\n }\n // first check to make sure more will be given than min amount required\n uint256 expectedOutput = ISwap(pool).calculateSwap(\n tokenIndexFrom,\n tokenIndexTo,\n amount.sub(fee)\n );\n\n if (expectedOutput >= minDy) {\n // proceed with swap\n token.mint(address(this), amount);\n token.safeIncreaseAllowance(address(pool), amount);\n try\n ISwap(pool).swap(\n tokenIndexFrom,\n tokenIndexTo,\n amount.sub(fee),\n minDy,\n deadline\n )\n returns (uint256 finalSwappedAmount) {\n // Swap succeeded, transfer swapped asset\n IERC20 swappedTokenTo = ISwap(pool).getToken(tokenIndexTo);\n if (\n address(swappedTokenTo) == WETH_ADDRESS &&\n WETH_ADDRESS != address(0)\n ) {\n IWETH9(WETH_ADDRESS).withdraw(finalSwappedAmount);\n (bool success, ) = to.call{value: finalSwappedAmount}(\"\");\n require(success, \"ETH_TRANSFER_FAILED\");\n emit TokenMintAndSwap(\n to,\n token,\n finalSwappedAmount,\n fee,\n tokenIndexFrom,\n tokenIndexTo,\n minDy,\n deadline,\n true,\n kappa\n );\n } else {\n swappedTokenTo.safeTransfer(to, finalSwappedAmount);\n emit TokenMintAndSwap(\n to,\n token,\n finalSwappedAmount,\n fee,\n tokenIndexFrom,\n tokenIndexTo,\n minDy,\n deadline,\n true,\n kappa\n );\n }\n } catch {\n IERC20(token).safeTransfer(to, amount.sub(fee));\n emit TokenMintAndSwap(\n to,\n token,\n amount.sub(fee),\n fee,\n tokenIndexFrom,\n tokenIndexTo,\n minDy,\n deadline,\n false,\n kappa\n );\n }\n } else {\n token.mint(address(this), amount);\n IERC20(token).safeTransfer(to, amount.sub(fee));\n emit TokenMintAndSwap(\n to,\n token,\n amount.sub(fee),\n fee,\n tokenIndexFrom,\n tokenIndexTo,\n minDy,\n deadline,\n false,\n kappa\n );\n }\n }\n\n /**\n * @notice Function to be called by the node group to withdraw the underlying assets from the contract\n * @param to address on chain to send underlying assets to\n * @param token ERC20 compatible token to withdraw from the bridge\n * @param amount Amount in native token decimals to withdraw\n * @param fee Amount in native token decimals to save to the contract as fees\n * @param pool Destination chain's pool to use to swap SynERC20 -> Asset. The nodes determine this by using PoolConfig.sol.\n * @param swapTokenIndex Specifies which of the underlying LP assets the nodes should attempt to redeem for\n * @param swapMinAmount Specifies the minimum amount of the underlying asset needed for the nodes to execute the redeem/swap\n * @param swapDeadline Specificies the deadline that the nodes are allowed to try to redeem/swap the LP token\n * @param kappa kappa\n **/\n function withdrawAndRemove(\n address to,\n IERC20 token,\n uint256 amount,\n uint256 fee,\n ISwap pool,\n uint8 swapTokenIndex,\n uint256 swapMinAmount,\n uint256 swapDeadline,\n bytes32 kappa\n ) external nonReentrant whenNotPaused {\n require(\n hasRole(NODEGROUP_ROLE, msg.sender),\n \"Caller is not a node group\"\n );\n require(amount > fee, \"Amount must be greater than fee\");\n require(!kappaMap[kappa], \"Kappa is already present\");\n kappaMap[kappa] = true;\n fees[address(token)] = fees[address(token)].add(fee);\n // first check to make sure more will be given than min amount required\n uint256 expectedOutput = ISwap(pool).calculateRemoveLiquidityOneToken(\n amount.sub(fee),\n swapTokenIndex\n );\n\n if (expectedOutput >= swapMinAmount) {\n token.safeIncreaseAllowance(address(pool), amount.sub(fee));\n try\n ISwap(pool).removeLiquidityOneToken(\n amount.sub(fee),\n swapTokenIndex,\n swapMinAmount,\n swapDeadline\n )\n returns (uint256 finalSwappedAmount) {\n // Swap succeeded, transfer swapped asset\n IERC20 swappedTokenTo = ISwap(pool).getToken(swapTokenIndex);\n swappedTokenTo.safeTransfer(to, finalSwappedAmount);\n emit TokenWithdrawAndRemove(\n to,\n token,\n finalSwappedAmount,\n fee,\n swapTokenIndex,\n swapMinAmount,\n swapDeadline,\n true,\n kappa\n );\n } catch {\n IERC20(token).safeTransfer(to, amount.sub(fee));\n emit TokenWithdrawAndRemove(\n to,\n token,\n amount.sub(fee),\n fee,\n swapTokenIndex,\n swapMinAmount,\n swapDeadline,\n false,\n kappa\n );\n }\n } else {\n token.safeTransfer(to, amount.sub(fee));\n emit TokenWithdrawAndRemove(\n to,\n token,\n amount.sub(fee),\n fee,\n swapTokenIndex,\n swapMinAmount,\n swapDeadline,\n false,\n kappa\n );\n }\n }\n\n // BRIDGE FUNCTIONS TO HANDLE DIFF ADDRESSES\n /**\n * @notice Relays to nodes that (typically) a wrapped synAsset ERC20 token has been burned and the underlying needs to be redeeemed on the native chain\n * @param to address on other chain to redeem underlying assets to\n * @param chainId which underlying chain to bridge assets onto\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n **/\n function redeemV2(\n bytes32 to,\n uint256 chainId,\n ERC20Burnable token,\n uint256 amount\n ) external nonReentrant whenNotPaused {\n emit TokenRedeemV2(to, chainId, token, amount);\n token.burnFrom(msg.sender, amount);\n }\n}\n" + }, + "@openzeppelin/contracts-upgradeable/access/AccessControlUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <0.8.0;\n\nimport \"../utils/EnumerableSetUpgradeable.sol\";\nimport \"../utils/AddressUpgradeable.sol\";\nimport \"../utils/ContextUpgradeable.sol\";\nimport \"../proxy/Initializable.sol\";\n\n/**\n * @dev Contract module that allows children to implement role-based access\n * control mechanisms.\n *\n * Roles are referred to by their `bytes32` identifier. These should be exposed\n * in the external API and be unique. The best way to achieve this is by\n * using `public constant` hash digests:\n *\n * ```\n * bytes32 public constant MY_ROLE = keccak256(\"MY_ROLE\");\n * ```\n *\n * Roles can be used to represent a set of permissions. To restrict access to a\n * function call, use {hasRole}:\n *\n * ```\n * function foo() public {\n * require(hasRole(MY_ROLE, msg.sender));\n * ...\n * }\n * ```\n *\n * Roles can be granted and revoked dynamically via the {grantRole} and\n * {revokeRole} functions. Each role has an associated admin role, and only\n * accounts that have a role's admin role can call {grantRole} and {revokeRole}.\n *\n * By default, the admin role for all roles is `DEFAULT_ADMIN_ROLE`, which means\n * that only accounts with this role will be able to grant or revoke other\n * roles. More complex role relationships can be created by using\n * {_setRoleAdmin}.\n *\n * WARNING: The `DEFAULT_ADMIN_ROLE` is also its own admin: it has permission to\n * grant and revoke this role. Extra precautions should be taken to secure\n * accounts that have been granted it.\n */\nabstract contract AccessControlUpgradeable is Initializable, ContextUpgradeable {\n function __AccessControl_init() internal initializer {\n __Context_init_unchained();\n __AccessControl_init_unchained();\n }\n\n function __AccessControl_init_unchained() internal initializer {\n }\n using EnumerableSetUpgradeable for EnumerableSetUpgradeable.AddressSet;\n using AddressUpgradeable for address;\n\n struct RoleData {\n EnumerableSetUpgradeable.AddressSet members;\n bytes32 adminRole;\n }\n\n mapping (bytes32 => RoleData) private _roles;\n\n bytes32 public constant DEFAULT_ADMIN_ROLE = 0x00;\n\n /**\n * @dev Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole`\n *\n * `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite\n * {RoleAdminChanged} not being emitted signaling this.\n *\n * _Available since v3.1._\n */\n event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole);\n\n /**\n * @dev Emitted when `account` is granted `role`.\n *\n * `sender` is the account that originated the contract call, an admin role\n * bearer except when using {_setupRole}.\n */\n event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender);\n\n /**\n * @dev Emitted when `account` is revoked `role`.\n *\n * `sender` is the account that originated the contract call:\n * - if using `revokeRole`, it is the admin role bearer\n * - if using `renounceRole`, it is the role bearer (i.e. `account`)\n */\n event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender);\n\n /**\n * @dev Returns `true` if `account` has been granted `role`.\n */\n function hasRole(bytes32 role, address account) public view returns (bool) {\n return _roles[role].members.contains(account);\n }\n\n /**\n * @dev Returns the number of accounts that have `role`. Can be used\n * together with {getRoleMember} to enumerate all bearers of a role.\n */\n function getRoleMemberCount(bytes32 role) public view returns (uint256) {\n return _roles[role].members.length();\n }\n\n /**\n * @dev Returns one of the accounts that have `role`. `index` must be a\n * value between 0 and {getRoleMemberCount}, non-inclusive.\n *\n * Role bearers are not sorted in any particular way, and their ordering may\n * change at any point.\n *\n * WARNING: When using {getRoleMember} and {getRoleMemberCount}, make sure\n * you perform all queries on the same block. See the following\n * https://forum.openzeppelin.com/t/iterating-over-elements-on-enumerableset-in-openzeppelin-contracts/2296[forum post]\n * for more information.\n */\n function getRoleMember(bytes32 role, uint256 index) public view returns (address) {\n return _roles[role].members.at(index);\n }\n\n /**\n * @dev Returns the admin role that controls `role`. See {grantRole} and\n * {revokeRole}.\n *\n * To change a role's admin, use {_setRoleAdmin}.\n */\n function getRoleAdmin(bytes32 role) public view returns (bytes32) {\n return _roles[role].adminRole;\n }\n\n /**\n * @dev Grants `role` to `account`.\n *\n * If `account` had not been already granted `role`, emits a {RoleGranted}\n * event.\n *\n * Requirements:\n *\n * - the caller must have ``role``'s admin role.\n */\n function grantRole(bytes32 role, address account) public virtual {\n require(hasRole(_roles[role].adminRole, _msgSender()), \"AccessControl: sender must be an admin to grant\");\n\n _grantRole(role, account);\n }\n\n /**\n * @dev Revokes `role` from `account`.\n *\n * If `account` had been granted `role`, emits a {RoleRevoked} event.\n *\n * Requirements:\n *\n * - the caller must have ``role``'s admin role.\n */\n function revokeRole(bytes32 role, address account) public virtual {\n require(hasRole(_roles[role].adminRole, _msgSender()), \"AccessControl: sender must be an admin to revoke\");\n\n _revokeRole(role, account);\n }\n\n /**\n * @dev Revokes `role` from the calling account.\n *\n * Roles are often managed via {grantRole} and {revokeRole}: this function's\n * purpose is to provide a mechanism for accounts to lose their privileges\n * if they are compromised (such as when a trusted device is misplaced).\n *\n * If the calling account had been granted `role`, emits a {RoleRevoked}\n * event.\n *\n * Requirements:\n *\n * - the caller must be `account`.\n */\n function renounceRole(bytes32 role, address account) public virtual {\n require(account == _msgSender(), \"AccessControl: can only renounce roles for self\");\n\n _revokeRole(role, account);\n }\n\n /**\n * @dev Grants `role` to `account`.\n *\n * If `account` had not been already granted `role`, emits a {RoleGranted}\n * event. Note that unlike {grantRole}, this function doesn't perform any\n * checks on the calling account.\n *\n * [WARNING]\n * ====\n * This function should only be called from the constructor when setting\n * up the initial roles for the system.\n *\n * Using this function in any other way is effectively circumventing the admin\n * system imposed by {AccessControl}.\n * ====\n */\n function _setupRole(bytes32 role, address account) internal virtual {\n _grantRole(role, account);\n }\n\n /**\n * @dev Sets `adminRole` as ``role``'s admin role.\n *\n * Emits a {RoleAdminChanged} event.\n */\n function _setRoleAdmin(bytes32 role, bytes32 adminRole) internal virtual {\n emit RoleAdminChanged(role, _roles[role].adminRole, adminRole);\n _roles[role].adminRole = adminRole;\n }\n\n function _grantRole(bytes32 role, address account) private {\n if (_roles[role].members.add(account)) {\n emit RoleGranted(role, account, _msgSender());\n }\n }\n\n function _revokeRole(bytes32 role, address account) private {\n if (_roles[role].members.remove(account)) {\n emit RoleRevoked(role, account, _msgSender());\n }\n }\n uint256[49] private __gap;\n}\n" + }, + "@openzeppelin/contracts-upgradeable/utils/EnumerableSetUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <0.8.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 EnumerableSetUpgradeable {\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" + }, + "contracts/bridge/MoonriverSynapseBridge.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.6.12;\n\nimport \"@openzeppelin/contracts-upgradeable/proxy/Initializable.sol\";\nimport \"@openzeppelin/contracts-upgradeable/access/AccessControlUpgradeable.sol\";\nimport \"@openzeppelin/contracts-upgradeable/utils/ReentrancyGuardUpgradeable.sol\";\nimport \"@openzeppelin/contracts-upgradeable/utils/PausableUpgradeable.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/SafeERC20.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/ERC20Burnable.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport \"@openzeppelin/contracts/math/SafeMath.sol\";\n\nimport \"./interfaces/ISwap.sol\";\nimport \"./interfaces/IWETH9.sol\";\n\ninterface IERC20Mintable is IERC20 {\n function mint(address to, uint256 amount) external;\n}\n\ninterface IFrax {\n function exchangeOldForCanonical(\n address bridge_token_address,\n uint256 token_amount\n ) external returns (uint256);\n}\n\ncontract MRSynapseBridge is\n Initializable,\n AccessControlUpgradeable,\n ReentrancyGuardUpgradeable,\n PausableUpgradeable\n{\n using SafeERC20 for IERC20;\n using SafeERC20 for IERC20Mintable;\n using SafeMath for uint256;\n\n bytes32 public constant NODEGROUP_ROLE = keccak256(\"NODEGROUP_ROLE\");\n bytes32 public constant GOVERNANCE_ROLE = keccak256(\"GOVERNANCE_ROLE\");\n\n mapping(address => uint256) private fees;\n\n uint256 public startBlockNumber;\n uint256 public constant bridgeVersion = 6;\n uint256 public chainGasAmount;\n address payable public WETH_ADDRESS;\n\n mapping(bytes32 => bool) private kappaMap;\n\n receive() external payable {}\n\n function initialize() external initializer {\n startBlockNumber = block.number;\n _setupRole(DEFAULT_ADMIN_ROLE, msg.sender);\n __AccessControl_init();\n }\n\n function setChainGasAmount(uint256 amount) external {\n require(hasRole(GOVERNANCE_ROLE, msg.sender), \"Not governance\");\n chainGasAmount = amount;\n }\n\n function setWethAddress(address payable _wethAddress) external {\n require(hasRole(DEFAULT_ADMIN_ROLE, msg.sender), \"Not admin\");\n WETH_ADDRESS = _wethAddress;\n }\n\n function addKappas(bytes32[] calldata kappas) external {\n require(hasRole(GOVERNANCE_ROLE, msg.sender), \"Not governance\");\n for (uint256 i = 0; i < kappas.length; ++i) {\n kappaMap[kappas[i]] = true;\n }\n }\n\n event TokenDeposit(\n address indexed to,\n uint256 chainId,\n IERC20 token,\n uint256 amount\n );\n event TokenRedeem(\n address indexed to,\n uint256 chainId,\n IERC20 token,\n uint256 amount\n );\n event TokenWithdraw(\n address indexed to,\n IERC20 token,\n uint256 amount,\n uint256 fee,\n bytes32 indexed kappa\n );\n event TokenMint(\n address indexed to,\n IERC20Mintable token,\n uint256 amount,\n uint256 fee,\n bytes32 indexed kappa\n );\n event TokenDepositAndSwap(\n address indexed to,\n uint256 chainId,\n IERC20 token,\n uint256 amount,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 minDy,\n uint256 deadline\n );\n event TokenMintAndSwap(\n address indexed to,\n IERC20Mintable token,\n uint256 amount,\n uint256 fee,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 minDy,\n uint256 deadline,\n bool swapSuccess,\n bytes32 indexed kappa\n );\n event TokenRedeemAndSwap(\n address indexed to,\n uint256 chainId,\n IERC20 token,\n uint256 amount,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 minDy,\n uint256 deadline\n );\n event TokenRedeemAndRemove(\n address indexed to,\n uint256 chainId,\n IERC20 token,\n uint256 amount,\n uint8 swapTokenIndex,\n uint256 swapMinAmount,\n uint256 swapDeadline\n );\n event TokenWithdrawAndRemove(\n address indexed to,\n IERC20 token,\n uint256 amount,\n uint256 fee,\n uint8 swapTokenIndex,\n uint256 swapMinAmount,\n uint256 swapDeadline,\n bool swapSuccess,\n bytes32 indexed kappa\n );\n\n // v2 events\n event TokenRedeemV2(\n bytes32 indexed to,\n uint256 chainId,\n IERC20 token,\n uint256 amount\n );\n\n // VIEW FUNCTIONS ***/\n function getFeeBalance(address tokenAddress)\n external\n view\n returns (uint256)\n {\n return fees[tokenAddress];\n }\n\n function kappaExists(bytes32 kappa) external view returns (bool) {\n return kappaMap[kappa];\n }\n\n // FEE FUNCTIONS ***/\n /**\n * * @notice withdraw specified ERC20 token fees to a given address\n * * @param token ERC20 token in which fees acccumulated to transfer\n * * @param to Address to send the fees to\n */\n function withdrawFees(IERC20 token, address to) external whenNotPaused {\n require(hasRole(GOVERNANCE_ROLE, msg.sender), \"Not governance\");\n require(to != address(0), \"Address is 0x000\");\n if (fees[address(token)] != 0) {\n token.safeTransfer(to, fees[address(token)]);\n fees[address(token)] = 0;\n }\n }\n\n // PAUSABLE FUNCTIONS ***/\n function pause() external {\n require(hasRole(GOVERNANCE_ROLE, msg.sender), \"Not governance\");\n _pause();\n }\n\n function unpause() external {\n require(hasRole(GOVERNANCE_ROLE, msg.sender), \"Not governance\");\n _unpause();\n }\n\n /**\n * @notice Relays to nodes to transfers an ERC20 token cross-chain\n * @param to address on other chain to bridge assets to\n * @param chainId which chain to bridge assets onto\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n **/\n function deposit(\n address to,\n uint256 chainId,\n IERC20 token,\n uint256 amount\n ) external nonReentrant whenNotPaused {\n emit TokenDeposit(to, chainId, token, amount);\n token.safeTransferFrom(msg.sender, address(this), amount);\n }\n\n /**\n * @notice Relays to nodes that (typically) a wrapped synAsset ERC20 token has been burned and the underlying needs to be redeeemed on the native chain\n * @param to address on other chain to redeem underlying assets to\n * @param chainId which underlying chain to bridge assets onto\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n **/\n function redeem(\n address to,\n uint256 chainId,\n ERC20Burnable token,\n uint256 amount\n ) external nonReentrant whenNotPaused {\n emit TokenRedeem(to, chainId, token, amount);\n token.burnFrom(msg.sender, amount);\n }\n\n /**\n * @notice Function to be called by the node group to withdraw the underlying assets from the contract\n * @param to address on chain to send underlying assets to\n * @param token ERC20 compatible token to withdraw from the bridge\n * @param amount Amount in native token decimals to withdraw\n * @param fee Amount in native token decimals to save to the contract as fees\n * @param kappa kappa\n **/\n function withdraw(\n address to,\n IERC20 token,\n uint256 amount,\n uint256 fee,\n bytes32 kappa\n ) external nonReentrant whenNotPaused {\n require(\n hasRole(NODEGROUP_ROLE, msg.sender),\n \"Caller is not a node group\"\n );\n require(amount > fee, \"Amount must be greater than fee\");\n require(!kappaMap[kappa], \"Kappa is already present\");\n kappaMap[kappa] = true;\n fees[address(token)] = fees[address(token)].add(fee);\n if (address(token) == WETH_ADDRESS && WETH_ADDRESS != address(0)) {\n IWETH9(WETH_ADDRESS).withdraw(amount.sub(fee));\n (bool success, ) = to.call{value: amount.sub(fee)}(\"\");\n require(success, \"ETH_TRANSFER_FAILED\");\n emit TokenWithdraw(to, token, amount, fee, kappa);\n } else {\n emit TokenWithdraw(to, token, amount, fee, kappa);\n token.safeTransfer(to, amount.sub(fee));\n }\n }\n\n /**\n * @notice Nodes call this function to mint a SynERC20 (or any asset that the bridge is given minter access to). This is called by the nodes after a TokenDeposit event is emitted.\n * @dev This means the SynapseBridge.sol contract must have minter access to the token attempting to be minted\n * @param to address on other chain to redeem underlying assets to\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain post-fees\n * @param fee Amount in native token decimals to save to the contract as fees\n * @param kappa kappa\n **/\n function mint(\n address payable to,\n IERC20Mintable token,\n uint256 amount,\n uint256 fee,\n bytes32 kappa\n ) external nonReentrant whenNotPaused {\n require(\n hasRole(NODEGROUP_ROLE, msg.sender),\n \"Caller is not a node group\"\n );\n require(amount > fee, \"Amount must be greater than fee\");\n require(!kappaMap[kappa], \"Kappa is already present\");\n kappaMap[kappa] = true;\n fees[address(token)] = fees[address(token)].add(fee);\n emit TokenMint(to, token, amount.sub(fee), fee, kappa);\n token.mint(address(this), amount);\n // checks if synFRAX\n if (address(token) == 0xE96AC70907ffF3Efee79f502C985A7A21Bce407d) {\n token.safeIncreaseAllowance(\n 0x1A93B23281CC1CDE4C4741353F3064709A16197d,\n amount.sub(fee)\n );\n try\n IFrax(0x1A93B23281CC1CDE4C4741353F3064709A16197d)\n .exchangeOldForCanonical(address(token), amount.sub(fee))\n returns (uint256 canolical_tokens_out) {\n IERC20(0x1A93B23281CC1CDE4C4741353F3064709A16197d).safeTransfer(\n to,\n canolical_tokens_out\n );\n } catch {\n IERC20(token).safeTransfer(to, amount.sub(fee));\n }\n } else {\n IERC20(token).safeTransfer(to, amount.sub(fee));\n }\n if (chainGasAmount != 0 && address(this).balance > chainGasAmount) {\n to.call.value(chainGasAmount)(\"\");\n }\n }\n\n /**\n * @notice Relays to nodes to both transfer an ERC20 token cross-chain, and then have the nodes execute a swap through a liquidity pool on behalf of the user.\n * @param to address on other chain to bridge assets to\n * @param chainId which chain to bridge assets onto\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n * @param tokenIndexFrom the token the user wants to swap from\n * @param tokenIndexTo the token the user wants to swap to\n * @param minDy the min amount the user would like to receive, or revert to only minting the SynERC20 token crosschain.\n * @param deadline latest timestamp to accept this transaction\n **/\n function depositAndSwap(\n address to,\n uint256 chainId,\n IERC20 token,\n uint256 amount,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 minDy,\n uint256 deadline\n ) external nonReentrant whenNotPaused {\n emit TokenDepositAndSwap(\n to,\n chainId,\n token,\n amount,\n tokenIndexFrom,\n tokenIndexTo,\n minDy,\n deadline\n );\n token.safeTransferFrom(msg.sender, address(this), amount);\n }\n\n /**\n * @notice Relays to nodes that (typically) a wrapped synAsset ERC20 token has been burned and the underlying needs to be redeeemed on the native chain. This function indicates to the nodes that they should attempt to redeem the LP token for the underlying assets (E.g \"swap\" out of the LP token)\n * @param to address on other chain to redeem underlying assets to\n * @param chainId which underlying chain to bridge assets onto\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n * @param tokenIndexFrom the token the user wants to swap from\n * @param tokenIndexTo the token the user wants to swap to\n * @param minDy the min amount the user would like to receive, or revert to only minting the SynERC20 token crosschain.\n * @param deadline latest timestamp to accept this transaction\n **/\n function redeemAndSwap(\n address to,\n uint256 chainId,\n ERC20Burnable token,\n uint256 amount,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 minDy,\n uint256 deadline\n ) external nonReentrant whenNotPaused {\n emit TokenRedeemAndSwap(\n to,\n chainId,\n token,\n amount,\n tokenIndexFrom,\n tokenIndexTo,\n minDy,\n deadline\n );\n token.burnFrom(msg.sender, amount);\n }\n\n /**\n * @notice Relays to nodes that (typically) a wrapped synAsset ERC20 token has been burned and the underlying needs to be redeeemed on the native chain. This function indicates to the nodes that they should attempt to redeem the LP token for the underlying assets (E.g \"swap\" out of the LP token)\n * @param to address on other chain to redeem underlying assets to\n * @param chainId which underlying chain to bridge assets onto\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n * @param swapTokenIndex Specifies which of the underlying LP assets the nodes should attempt to redeem for\n * @param swapMinAmount Specifies the minimum amount of the underlying asset needed for the nodes to execute the redeem/swap\n * @param swapDeadline Specificies the deadline that the nodes are allowed to try to redeem/swap the LP token\n **/\n function redeemAndRemove(\n address to,\n uint256 chainId,\n ERC20Burnable token,\n uint256 amount,\n uint8 swapTokenIndex,\n uint256 swapMinAmount,\n uint256 swapDeadline\n ) external nonReentrant whenNotPaused {\n emit TokenRedeemAndRemove(\n to,\n chainId,\n token,\n amount,\n swapTokenIndex,\n swapMinAmount,\n swapDeadline\n );\n token.burnFrom(msg.sender, amount);\n }\n\n /**\n * @notice Nodes call this function to mint a SynERC20 (or any asset that the bridge is given minter access to), and then attempt to swap the SynERC20 into the desired destination asset. This is called by the nodes after a TokenDepositAndSwap event is emitted.\n * @dev This means the BridgeDeposit.sol contract must have minter access to the token attempting to be minted\n * @param to address on other chain to redeem underlying assets to\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain post-fees\n * @param fee Amount in native token decimals to save to the contract as fees\n * @param pool Destination chain's pool to use to swap SynERC20 -> Asset. The nodes determine this by using PoolConfig.sol.\n * @param tokenIndexFrom Index of the SynERC20 asset in the pool\n * @param tokenIndexTo Index of the desired final asset\n * @param minDy Minumum amount (in final asset decimals) that must be swapped for, otherwise the user will receive the SynERC20.\n * @param deadline Epoch time of the deadline that the swap is allowed to be executed.\n * @param kappa kappa\n **/\n function mintAndSwap(\n address payable to,\n IERC20Mintable token,\n uint256 amount,\n uint256 fee,\n ISwap pool,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 minDy,\n uint256 deadline,\n bytes32 kappa\n ) external nonReentrant whenNotPaused {\n require(\n hasRole(NODEGROUP_ROLE, msg.sender),\n \"Caller is not a node group\"\n );\n require(amount > fee, \"Amount must be greater than fee\");\n require(!kappaMap[kappa], \"Kappa is already present\");\n kappaMap[kappa] = true;\n fees[address(token)] = fees[address(token)].add(fee);\n // Transfer gas airdrop\n if (chainGasAmount != 0 && address(this).balance > chainGasAmount) {\n to.call.value(chainGasAmount)(\"\");\n }\n // first check to make sure more will be given than min amount required\n uint256 expectedOutput = ISwap(pool).calculateSwap(\n tokenIndexFrom,\n tokenIndexTo,\n amount.sub(fee)\n );\n\n if (expectedOutput >= minDy) {\n // proceed with swap\n token.mint(address(this), amount);\n token.safeIncreaseAllowance(address(pool), amount);\n try\n ISwap(pool).swap(\n tokenIndexFrom,\n tokenIndexTo,\n amount.sub(fee),\n minDy,\n deadline\n )\n returns (uint256 finalSwappedAmount) {\n // Swap succeeded, transfer swapped asset\n IERC20 swappedTokenTo = ISwap(pool).getToken(tokenIndexTo);\n if (\n address(swappedTokenTo) == WETH_ADDRESS &&\n WETH_ADDRESS != address(0)\n ) {\n IWETH9(WETH_ADDRESS).withdraw(finalSwappedAmount);\n (bool success, ) = to.call{value: finalSwappedAmount}(\"\");\n require(success, \"ETH_TRANSFER_FAILED\");\n emit TokenMintAndSwap(\n to,\n token,\n finalSwappedAmount,\n fee,\n tokenIndexFrom,\n tokenIndexTo,\n minDy,\n deadline,\n true,\n kappa\n );\n } else {\n swappedTokenTo.safeTransfer(to, finalSwappedAmount);\n emit TokenMintAndSwap(\n to,\n token,\n finalSwappedAmount,\n fee,\n tokenIndexFrom,\n tokenIndexTo,\n minDy,\n deadline,\n true,\n kappa\n );\n }\n } catch {\n IERC20(token).safeTransfer(to, amount.sub(fee));\n emit TokenMintAndSwap(\n to,\n token,\n amount.sub(fee),\n fee,\n tokenIndexFrom,\n tokenIndexTo,\n minDy,\n deadline,\n false,\n kappa\n );\n }\n } else {\n token.mint(address(this), amount);\n IERC20(token).safeTransfer(to, amount.sub(fee));\n emit TokenMintAndSwap(\n to,\n token,\n amount.sub(fee),\n fee,\n tokenIndexFrom,\n tokenIndexTo,\n minDy,\n deadline,\n false,\n kappa\n );\n }\n }\n\n /**\n * @notice Function to be called by the node group to withdraw the underlying assets from the contract\n * @param to address on chain to send underlying assets to\n * @param token ERC20 compatible token to withdraw from the bridge\n * @param amount Amount in native token decimals to withdraw\n * @param fee Amount in native token decimals to save to the contract as fees\n * @param pool Destination chain's pool to use to swap SynERC20 -> Asset. The nodes determine this by using PoolConfig.sol.\n * @param swapTokenIndex Specifies which of the underlying LP assets the nodes should attempt to redeem for\n * @param swapMinAmount Specifies the minimum amount of the underlying asset needed for the nodes to execute the redeem/swap\n * @param swapDeadline Specificies the deadline that the nodes are allowed to try to redeem/swap the LP token\n * @param kappa kappa\n **/\n function withdrawAndRemove(\n address to,\n IERC20 token,\n uint256 amount,\n uint256 fee,\n ISwap pool,\n uint8 swapTokenIndex,\n uint256 swapMinAmount,\n uint256 swapDeadline,\n bytes32 kappa\n ) external nonReentrant whenNotPaused {\n require(\n hasRole(NODEGROUP_ROLE, msg.sender),\n \"Caller is not a node group\"\n );\n require(amount > fee, \"Amount must be greater than fee\");\n require(!kappaMap[kappa], \"Kappa is already present\");\n kappaMap[kappa] = true;\n fees[address(token)] = fees[address(token)].add(fee);\n // first check to make sure more will be given than min amount required\n uint256 expectedOutput = ISwap(pool).calculateRemoveLiquidityOneToken(\n amount.sub(fee),\n swapTokenIndex\n );\n\n if (expectedOutput >= swapMinAmount) {\n token.safeIncreaseAllowance(address(pool), amount.sub(fee));\n try\n ISwap(pool).removeLiquidityOneToken(\n amount.sub(fee),\n swapTokenIndex,\n swapMinAmount,\n swapDeadline\n )\n returns (uint256 finalSwappedAmount) {\n // Swap succeeded, transfer swapped asset\n IERC20 swappedTokenTo = ISwap(pool).getToken(swapTokenIndex);\n swappedTokenTo.safeTransfer(to, finalSwappedAmount);\n emit TokenWithdrawAndRemove(\n to,\n token,\n finalSwappedAmount,\n fee,\n swapTokenIndex,\n swapMinAmount,\n swapDeadline,\n true,\n kappa\n );\n } catch {\n IERC20(token).safeTransfer(to, amount.sub(fee));\n emit TokenWithdrawAndRemove(\n to,\n token,\n amount.sub(fee),\n fee,\n swapTokenIndex,\n swapMinAmount,\n swapDeadline,\n false,\n kappa\n );\n }\n } else {\n token.safeTransfer(to, amount.sub(fee));\n emit TokenWithdrawAndRemove(\n to,\n token,\n amount.sub(fee),\n fee,\n swapTokenIndex,\n swapMinAmount,\n swapDeadline,\n false,\n kappa\n );\n }\n }\n\n // BRIDGE FUNCTIONS TO HANDLE DIFF ADDRESSES\n /**\n * @notice Relays to nodes that (typically) a wrapped synAsset ERC20 token has been burned and the underlying needs to be redeeemed on the native chain\n * @param to address on other chain to redeem underlying assets to\n * @param chainId which underlying chain to bridge assets onto\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n **/\n function redeemV2(\n bytes32 to,\n uint256 chainId,\n ERC20Burnable token,\n uint256 amount\n ) external nonReentrant whenNotPaused {\n emit TokenRedeemV2(to, chainId, token, amount);\n token.burnFrom(msg.sender, amount);\n }\n}\n" + }, + "contracts/bridge/HarmonySynapseBridge.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.6.12;\n\nimport \"@openzeppelin/contracts-upgradeable/proxy/Initializable.sol\";\nimport \"@openzeppelin/contracts-upgradeable/access/AccessControlUpgradeable.sol\";\nimport \"@openzeppelin/contracts-upgradeable/utils/ReentrancyGuardUpgradeable.sol\";\nimport \"@openzeppelin/contracts-upgradeable/utils/PausableUpgradeable.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/SafeERC20.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/ERC20Burnable.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport \"@openzeppelin/contracts/math/SafeMath.sol\";\n\nimport \"./interfaces/ISwap.sol\";\nimport \"./interfaces/IWETH9.sol\";\n\ninterface IERC20Mintable is IERC20 {\n function mint(address to, uint256 amount) external;\n}\n\ninterface IFrax {\n function exchangeOldForCanonical(\n address bridge_token_address,\n uint256 token_amount\n ) external returns (uint256);\n}\n\ncontract HarmonySynapseBridge is\n Initializable,\n AccessControlUpgradeable,\n ReentrancyGuardUpgradeable,\n PausableUpgradeable\n{\n using SafeERC20 for IERC20;\n using SafeERC20 for IERC20Mintable;\n using SafeMath for uint256;\n\n bytes32 public constant NODEGROUP_ROLE = keccak256(\"NODEGROUP_ROLE\");\n bytes32 public constant GOVERNANCE_ROLE = keccak256(\"GOVERNANCE_ROLE\");\n\n mapping(address => uint256) private fees;\n\n uint256 public startBlockNumber;\n uint256 public constant bridgeVersion = 6;\n uint256 public chainGasAmount;\n address payable public WETH_ADDRESS;\n\n mapping(bytes32 => bool) private kappaMap;\n\n receive() external payable {}\n\n function initialize() external initializer {\n startBlockNumber = block.number;\n _setupRole(DEFAULT_ADMIN_ROLE, msg.sender);\n __AccessControl_init();\n }\n\n function setChainGasAmount(uint256 amount) external {\n require(hasRole(GOVERNANCE_ROLE, msg.sender), \"Not governance\");\n chainGasAmount = amount;\n }\n\n function setWethAddress(address payable _wethAddress) external {\n require(hasRole(DEFAULT_ADMIN_ROLE, msg.sender), \"Not admin\");\n WETH_ADDRESS = _wethAddress;\n }\n\n function addKappas(bytes32[] calldata kappas) external {\n require(hasRole(GOVERNANCE_ROLE, msg.sender), \"Not governance\");\n for (uint256 i = 0; i < kappas.length; ++i) {\n kappaMap[kappas[i]] = true;\n }\n }\n\n event TokenDeposit(\n address indexed to,\n uint256 chainId,\n IERC20 token,\n uint256 amount\n );\n event TokenRedeem(\n address indexed to,\n uint256 chainId,\n IERC20 token,\n uint256 amount\n );\n event TokenWithdraw(\n address indexed to,\n IERC20 token,\n uint256 amount,\n uint256 fee,\n bytes32 indexed kappa\n );\n event TokenMint(\n address indexed to,\n IERC20Mintable token,\n uint256 amount,\n uint256 fee,\n bytes32 indexed kappa\n );\n event TokenDepositAndSwap(\n address indexed to,\n uint256 chainId,\n IERC20 token,\n uint256 amount,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 minDy,\n uint256 deadline\n );\n event TokenMintAndSwap(\n address indexed to,\n IERC20Mintable token,\n uint256 amount,\n uint256 fee,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 minDy,\n uint256 deadline,\n bool swapSuccess,\n bytes32 indexed kappa\n );\n event TokenRedeemAndSwap(\n address indexed to,\n uint256 chainId,\n IERC20 token,\n uint256 amount,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 minDy,\n uint256 deadline\n );\n event TokenRedeemAndRemove(\n address indexed to,\n uint256 chainId,\n IERC20 token,\n uint256 amount,\n uint8 swapTokenIndex,\n uint256 swapMinAmount,\n uint256 swapDeadline\n );\n event TokenWithdrawAndRemove(\n address indexed to,\n IERC20 token,\n uint256 amount,\n uint256 fee,\n uint8 swapTokenIndex,\n uint256 swapMinAmount,\n uint256 swapDeadline,\n bool swapSuccess,\n bytes32 indexed kappa\n );\n\n // v2 events\n event TokenRedeemV2(\n bytes32 indexed to,\n uint256 chainId,\n IERC20 token,\n uint256 amount\n );\n\n // VIEW FUNCTIONS ***/\n function getFeeBalance(address tokenAddress)\n external\n view\n returns (uint256)\n {\n return fees[tokenAddress];\n }\n\n function kappaExists(bytes32 kappa) external view returns (bool) {\n return kappaMap[kappa];\n }\n\n // FEE FUNCTIONS ***/\n /**\n * * @notice withdraw specified ERC20 token fees to a given address\n * * @param token ERC20 token in which fees acccumulated to transfer\n * * @param to Address to send the fees to\n */\n function withdrawFees(IERC20 token, address to) external whenNotPaused {\n require(hasRole(GOVERNANCE_ROLE, msg.sender), \"Not governance\");\n require(to != address(0), \"Address is 0x000\");\n if (fees[address(token)] != 0) {\n token.safeTransfer(to, fees[address(token)]);\n fees[address(token)] = 0;\n }\n }\n\n // PAUSABLE FUNCTIONS ***/\n function pause() external {\n require(hasRole(GOVERNANCE_ROLE, msg.sender), \"Not governance\");\n _pause();\n }\n\n function unpause() external {\n require(hasRole(GOVERNANCE_ROLE, msg.sender), \"Not governance\");\n _unpause();\n }\n\n /**\n * @notice Relays to nodes to transfers an ERC20 token cross-chain\n * @param to address on other chain to bridge assets to\n * @param chainId which chain to bridge assets onto\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n **/\n function deposit(\n address to,\n uint256 chainId,\n IERC20 token,\n uint256 amount\n ) external nonReentrant whenNotPaused {\n emit TokenDeposit(to, chainId, token, amount);\n token.safeTransferFrom(msg.sender, address(this), amount);\n }\n\n /**\n * @notice Relays to nodes that (typically) a wrapped synAsset ERC20 token has been burned and the underlying needs to be redeeemed on the native chain\n * @param to address on other chain to redeem underlying assets to\n * @param chainId which underlying chain to bridge assets onto\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n **/\n function redeem(\n address to,\n uint256 chainId,\n ERC20Burnable token,\n uint256 amount\n ) external nonReentrant whenNotPaused {\n emit TokenRedeem(to, chainId, token, amount);\n token.burnFrom(msg.sender, amount);\n }\n\n /**\n * @notice Function to be called by the node group to withdraw the underlying assets from the contract\n * @param to address on chain to send underlying assets to\n * @param token ERC20 compatible token to withdraw from the bridge\n * @param amount Amount in native token decimals to withdraw\n * @param fee Amount in native token decimals to save to the contract as fees\n * @param kappa kappa\n **/\n function withdraw(\n address to,\n IERC20 token,\n uint256 amount,\n uint256 fee,\n bytes32 kappa\n ) external nonReentrant whenNotPaused {\n require(\n hasRole(NODEGROUP_ROLE, msg.sender),\n \"Caller is not a node group\"\n );\n require(amount > fee, \"Amount must be greater than fee\");\n require(!kappaMap[kappa], \"Kappa is already present\");\n kappaMap[kappa] = true;\n fees[address(token)] = fees[address(token)].add(fee);\n if (address(token) == WETH_ADDRESS && WETH_ADDRESS != address(0)) {\n IWETH9(WETH_ADDRESS).withdraw(amount.sub(fee));\n (bool success, ) = to.call{value: amount.sub(fee)}(\"\");\n require(success, \"ETH_TRANSFER_FAILED\");\n emit TokenWithdraw(to, token, amount, fee, kappa);\n } else {\n emit TokenWithdraw(to, token, amount, fee, kappa);\n token.safeTransfer(to, amount.sub(fee));\n }\n }\n\n /**\n * @notice Nodes call this function to mint a SynERC20 (or any asset that the bridge is given minter access to). This is called by the nodes after a TokenDeposit event is emitted.\n * @dev This means the SynapseBridge.sol contract must have minter access to the token attempting to be minted\n * @param to address on other chain to redeem underlying assets to\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain post-fees\n * @param fee Amount in native token decimals to save to the contract as fees\n * @param kappa kappa\n **/\n function mint(\n address payable to,\n IERC20Mintable token,\n uint256 amount,\n uint256 fee,\n bytes32 kappa\n ) external nonReentrant whenNotPaused {\n require(\n hasRole(NODEGROUP_ROLE, msg.sender),\n \"Caller is not a node group\"\n );\n require(amount > fee, \"Amount must be greater than fee\");\n require(!kappaMap[kappa], \"Kappa is already present\");\n kappaMap[kappa] = true;\n fees[address(token)] = fees[address(token)].add(fee);\n emit TokenMint(to, token, amount.sub(fee), fee, kappa);\n token.mint(address(this), amount);\n // checks if synFRAX\n if (address(token) == 0x1852F70512298d56e9c8FDd905e02581E04ddb2a) {\n if (\n token.allowance(\n address(this),\n 0xFa7191D292d5633f702B0bd7E3E3BcCC0e633200\n ) < amount.sub(fee)\n ) {\n token.safeApprove(\n address(0xFa7191D292d5633f702B0bd7E3E3BcCC0e633200),\n 0\n );\n token.safeApprove(\n address(0xFa7191D292d5633f702B0bd7E3E3BcCC0e633200),\n type(uint256).max\n );\n }\n try\n IFrax(0xFa7191D292d5633f702B0bd7E3E3BcCC0e633200)\n .exchangeOldForCanonical(address(token), amount.sub(fee))\n returns (uint256 canolical_tokens_out) {\n IERC20(0xFa7191D292d5633f702B0bd7E3E3BcCC0e633200).safeTransfer(\n to,\n canolical_tokens_out\n );\n } catch {\n IERC20(token).safeTransfer(to, amount.sub(fee));\n }\n } else {\n IERC20(token).safeTransfer(to, amount.sub(fee));\n }\n if (chainGasAmount != 0 && address(this).balance > chainGasAmount) {\n to.call.value(chainGasAmount)(\"\");\n }\n }\n\n /**\n * @notice Relays to nodes to both transfer an ERC20 token cross-chain, and then have the nodes execute a swap through a liquidity pool on behalf of the user.\n * @param to address on other chain to bridge assets to\n * @param chainId which chain to bridge assets onto\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n * @param tokenIndexFrom the token the user wants to swap from\n * @param tokenIndexTo the token the user wants to swap to\n * @param minDy the min amount the user would like to receive, or revert to only minting the SynERC20 token crosschain.\n * @param deadline latest timestamp to accept this transaction\n **/\n function depositAndSwap(\n address to,\n uint256 chainId,\n IERC20 token,\n uint256 amount,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 minDy,\n uint256 deadline\n ) external nonReentrant whenNotPaused {\n emit TokenDepositAndSwap(\n to,\n chainId,\n token,\n amount,\n tokenIndexFrom,\n tokenIndexTo,\n minDy,\n deadline\n );\n token.safeTransferFrom(msg.sender, address(this), amount);\n }\n\n /**\n * @notice Relays to nodes that (typically) a wrapped synAsset ERC20 token has been burned and the underlying needs to be redeeemed on the native chain. This function indicates to the nodes that they should attempt to redeem the LP token for the underlying assets (E.g \"swap\" out of the LP token)\n * @param to address on other chain to redeem underlying assets to\n * @param chainId which underlying chain to bridge assets onto\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n * @param tokenIndexFrom the token the user wants to swap from\n * @param tokenIndexTo the token the user wants to swap to\n * @param minDy the min amount the user would like to receive, or revert to only minting the SynERC20 token crosschain.\n * @param deadline latest timestamp to accept this transaction\n **/\n function redeemAndSwap(\n address to,\n uint256 chainId,\n ERC20Burnable token,\n uint256 amount,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 minDy,\n uint256 deadline\n ) external nonReentrant whenNotPaused {\n emit TokenRedeemAndSwap(\n to,\n chainId,\n token,\n amount,\n tokenIndexFrom,\n tokenIndexTo,\n minDy,\n deadline\n );\n token.burnFrom(msg.sender, amount);\n }\n\n /**\n * @notice Relays to nodes that (typically) a wrapped synAsset ERC20 token has been burned and the underlying needs to be redeeemed on the native chain. This function indicates to the nodes that they should attempt to redeem the LP token for the underlying assets (E.g \"swap\" out of the LP token)\n * @param to address on other chain to redeem underlying assets to\n * @param chainId which underlying chain to bridge assets onto\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n * @param swapTokenIndex Specifies which of the underlying LP assets the nodes should attempt to redeem for\n * @param swapMinAmount Specifies the minimum amount of the underlying asset needed for the nodes to execute the redeem/swap\n * @param swapDeadline Specificies the deadline that the nodes are allowed to try to redeem/swap the LP token\n **/\n function redeemAndRemove(\n address to,\n uint256 chainId,\n ERC20Burnable token,\n uint256 amount,\n uint8 swapTokenIndex,\n uint256 swapMinAmount,\n uint256 swapDeadline\n ) external nonReentrant whenNotPaused {\n emit TokenRedeemAndRemove(\n to,\n chainId,\n token,\n amount,\n swapTokenIndex,\n swapMinAmount,\n swapDeadline\n );\n token.burnFrom(msg.sender, amount);\n }\n\n /**\n * @notice Nodes call this function to mint a SynERC20 (or any asset that the bridge is given minter access to), and then attempt to swap the SynERC20 into the desired destination asset. This is called by the nodes after a TokenDepositAndSwap event is emitted.\n * @dev This means the BridgeDeposit.sol contract must have minter access to the token attempting to be minted\n * @param to address on other chain to redeem underlying assets to\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain post-fees\n * @param fee Amount in native token decimals to save to the contract as fees\n * @param pool Destination chain's pool to use to swap SynERC20 -> Asset. The nodes determine this by using PoolConfig.sol.\n * @param tokenIndexFrom Index of the SynERC20 asset in the pool\n * @param tokenIndexTo Index of the desired final asset\n * @param minDy Minumum amount (in final asset decimals) that must be swapped for, otherwise the user will receive the SynERC20.\n * @param deadline Epoch time of the deadline that the swap is allowed to be executed.\n * @param kappa kappa\n **/\n function mintAndSwap(\n address payable to,\n IERC20Mintable token,\n uint256 amount,\n uint256 fee,\n ISwap pool,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 minDy,\n uint256 deadline,\n bytes32 kappa\n ) external nonReentrant whenNotPaused {\n require(\n hasRole(NODEGROUP_ROLE, msg.sender),\n \"Caller is not a node group\"\n );\n require(amount > fee, \"Amount must be greater than fee\");\n require(!kappaMap[kappa], \"Kappa is already present\");\n kappaMap[kappa] = true;\n fees[address(token)] = fees[address(token)].add(fee);\n // Transfer gas airdrop\n if (chainGasAmount != 0 && address(this).balance > chainGasAmount) {\n to.call.value(chainGasAmount)(\"\");\n }\n // first check to make sure more will be given than min amount required\n uint256 expectedOutput = ISwap(pool).calculateSwap(\n tokenIndexFrom,\n tokenIndexTo,\n amount.sub(fee)\n );\n\n if (expectedOutput >= minDy) {\n // proceed with swap\n token.mint(address(this), amount);\n token.safeIncreaseAllowance(address(pool), amount);\n try\n ISwap(pool).swap(\n tokenIndexFrom,\n tokenIndexTo,\n amount.sub(fee),\n minDy,\n deadline\n )\n returns (uint256 finalSwappedAmount) {\n // Swap succeeded, transfer swapped asset\n IERC20 swappedTokenTo = ISwap(pool).getToken(tokenIndexTo);\n if (\n address(swappedTokenTo) == WETH_ADDRESS &&\n WETH_ADDRESS != address(0)\n ) {\n IWETH9(WETH_ADDRESS).withdraw(finalSwappedAmount);\n (bool success, ) = to.call{value: finalSwappedAmount}(\"\");\n require(success, \"ETH_TRANSFER_FAILED\");\n emit TokenMintAndSwap(\n to,\n token,\n finalSwappedAmount,\n fee,\n tokenIndexFrom,\n tokenIndexTo,\n minDy,\n deadline,\n true,\n kappa\n );\n } else {\n swappedTokenTo.safeTransfer(to, finalSwappedAmount);\n emit TokenMintAndSwap(\n to,\n token,\n finalSwappedAmount,\n fee,\n tokenIndexFrom,\n tokenIndexTo,\n minDy,\n deadline,\n true,\n kappa\n );\n }\n } catch {\n IERC20(token).safeTransfer(to, amount.sub(fee));\n emit TokenMintAndSwap(\n to,\n token,\n amount.sub(fee),\n fee,\n tokenIndexFrom,\n tokenIndexTo,\n minDy,\n deadline,\n false,\n kappa\n );\n }\n } else {\n token.mint(address(this), amount);\n IERC20(token).safeTransfer(to, amount.sub(fee));\n emit TokenMintAndSwap(\n to,\n token,\n amount.sub(fee),\n fee,\n tokenIndexFrom,\n tokenIndexTo,\n minDy,\n deadline,\n false,\n kappa\n );\n }\n }\n\n /**\n * @notice Function to be called by the node group to withdraw the underlying assets from the contract\n * @param to address on chain to send underlying assets to\n * @param token ERC20 compatible token to withdraw from the bridge\n * @param amount Amount in native token decimals to withdraw\n * @param fee Amount in native token decimals to save to the contract as fees\n * @param pool Destination chain's pool to use to swap SynERC20 -> Asset. The nodes determine this by using PoolConfig.sol.\n * @param swapTokenIndex Specifies which of the underlying LP assets the nodes should attempt to redeem for\n * @param swapMinAmount Specifies the minimum amount of the underlying asset needed for the nodes to execute the redeem/swap\n * @param swapDeadline Specificies the deadline that the nodes are allowed to try to redeem/swap the LP token\n * @param kappa kappa\n **/\n function withdrawAndRemove(\n address to,\n IERC20 token,\n uint256 amount,\n uint256 fee,\n ISwap pool,\n uint8 swapTokenIndex,\n uint256 swapMinAmount,\n uint256 swapDeadline,\n bytes32 kappa\n ) external nonReentrant whenNotPaused {\n require(\n hasRole(NODEGROUP_ROLE, msg.sender),\n \"Caller is not a node group\"\n );\n require(amount > fee, \"Amount must be greater than fee\");\n require(!kappaMap[kappa], \"Kappa is already present\");\n kappaMap[kappa] = true;\n fees[address(token)] = fees[address(token)].add(fee);\n // first check to make sure more will be given than min amount required\n uint256 expectedOutput = ISwap(pool).calculateRemoveLiquidityOneToken(\n amount.sub(fee),\n swapTokenIndex\n );\n\n if (expectedOutput >= swapMinAmount) {\n token.safeIncreaseAllowance(address(pool), amount.sub(fee));\n try\n ISwap(pool).removeLiquidityOneToken(\n amount.sub(fee),\n swapTokenIndex,\n swapMinAmount,\n swapDeadline\n )\n returns (uint256 finalSwappedAmount) {\n // Swap succeeded, transfer swapped asset\n IERC20 swappedTokenTo = ISwap(pool).getToken(swapTokenIndex);\n swappedTokenTo.safeTransfer(to, finalSwappedAmount);\n emit TokenWithdrawAndRemove(\n to,\n token,\n finalSwappedAmount,\n fee,\n swapTokenIndex,\n swapMinAmount,\n swapDeadline,\n true,\n kappa\n );\n } catch {\n IERC20(token).safeTransfer(to, amount.sub(fee));\n emit TokenWithdrawAndRemove(\n to,\n token,\n amount.sub(fee),\n fee,\n swapTokenIndex,\n swapMinAmount,\n swapDeadline,\n false,\n kappa\n );\n }\n } else {\n token.safeTransfer(to, amount.sub(fee));\n emit TokenWithdrawAndRemove(\n to,\n token,\n amount.sub(fee),\n fee,\n swapTokenIndex,\n swapMinAmount,\n swapDeadline,\n false,\n kappa\n );\n }\n }\n\n // BRIDGE FUNCTIONS TO HANDLE DIFF ADDRESSES\n /**\n * @notice Relays to nodes that (typically) a wrapped synAsset ERC20 token has been burned and the underlying needs to be redeeemed on the native chain\n * @param to address on other chain to redeem underlying assets to\n * @param chainId which underlying chain to bridge assets onto\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n **/\n function redeemV2(\n bytes32 to,\n uint256 chainId,\n ERC20Burnable token,\n uint256 amount\n ) external nonReentrant whenNotPaused {\n emit TokenRedeemV2(to, chainId, token, amount);\n token.burnFrom(msg.sender, amount);\n }\n}\n" + }, + "contracts/bridge/SynapseERC20.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.6.12;\n\nimport \"@openzeppelin/contracts-upgradeable/token/ERC20/ERC20Upgradeable.sol\";\nimport \"@openzeppelin/contracts-upgradeable/token/ERC20/ERC20BurnableUpgradeable.sol\";\nimport \"@openzeppelin/contracts-upgradeable/drafts/ERC20PermitUpgradeable.sol\";\nimport \"@openzeppelin/contracts-upgradeable/access/AccessControlUpgradeable.sol\";\nimport \"@openzeppelin/contracts-upgradeable/proxy/Initializable.sol\";\n\ncontract SynapseERC20 is\n Initializable,\n ContextUpgradeable,\n AccessControlUpgradeable,\n ERC20BurnableUpgradeable,\n ERC20PermitUpgradeable\n{\n bytes32 public constant MINTER_ROLE = keccak256(\"MINTER_ROLE\");\n\n /**\n * @notice Initializes this ERC20 contract with the given parameters.\n * @param name Token name\n * @param symbol Token symbol\n * @param decimals Token name\n * @param owner admin address to be initialized with\n */\n function initialize(\n string memory name,\n string memory symbol,\n uint8 decimals,\n address owner\n ) external initializer {\n __Context_init_unchained();\n __AccessControl_init_unchained();\n __ERC20_init_unchained(name, symbol);\n __ERC20Burnable_init_unchained();\n _setupDecimals(decimals);\n __ERC20Permit_init(name);\n _setupRole(DEFAULT_ADMIN_ROLE, owner);\n }\n\n function mint(address to, uint256 amount) external {\n require(hasRole(MINTER_ROLE, msg.sender), \"Not a minter\");\n _mint(to, amount);\n }\n}\n" + }, + "@openzeppelin/contracts-upgradeable/drafts/ERC20PermitUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.5 <0.8.0;\n\nimport \"../token/ERC20/ERC20Upgradeable.sol\";\nimport \"./IERC20PermitUpgradeable.sol\";\nimport \"../cryptography/ECDSAUpgradeable.sol\";\nimport \"../utils/CountersUpgradeable.sol\";\nimport \"./EIP712Upgradeable.sol\";\nimport \"../proxy/Initializable.sol\";\n\n/**\n * @dev Implementation of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in\n * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612].\n *\n * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by\n * presenting a message signed by the account. By not relying on `{IERC20-approve}`, the token holder account doesn't\n * need to send a transaction, and thus is not required to hold Ether at all.\n *\n * _Available since v3.4._\n */\nabstract contract ERC20PermitUpgradeable is Initializable, ERC20Upgradeable, IERC20PermitUpgradeable, EIP712Upgradeable {\n using CountersUpgradeable for CountersUpgradeable.Counter;\n\n mapping (address => CountersUpgradeable.Counter) private _nonces;\n\n // solhint-disable-next-line var-name-mixedcase\n bytes32 private _PERMIT_TYPEHASH;\n\n /**\n * @dev Initializes the {EIP712} domain separator using the `name` parameter, and setting `version` to `\"1\"`.\n *\n * It's a good idea to use the same `name` that is defined as the ERC20 token name.\n */\n function __ERC20Permit_init(string memory name) internal initializer {\n __Context_init_unchained();\n __EIP712_init_unchained(name, \"1\");\n __ERC20Permit_init_unchained(name);\n }\n\n function __ERC20Permit_init_unchained(string memory name) internal initializer {\n _PERMIT_TYPEHASH = keccak256(\"Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)\");\n }\n\n /**\n * @dev See {IERC20Permit-permit}.\n */\n function permit(address owner, address spender, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s) public virtual override {\n // solhint-disable-next-line not-rely-on-time\n require(block.timestamp <= deadline, \"ERC20Permit: expired deadline\");\n\n bytes32 structHash = keccak256(\n abi.encode(\n _PERMIT_TYPEHASH,\n owner,\n spender,\n value,\n _nonces[owner].current(),\n deadline\n )\n );\n\n bytes32 hash = _hashTypedDataV4(structHash);\n\n address signer = ECDSAUpgradeable.recover(hash, v, r, s);\n require(signer == owner, \"ERC20Permit: invalid signature\");\n\n _nonces[owner].increment();\n _approve(owner, spender, value);\n }\n\n /**\n * @dev See {IERC20Permit-nonces}.\n */\n function nonces(address owner) public view override returns (uint256) {\n return _nonces[owner].current();\n }\n\n /**\n * @dev See {IERC20Permit-DOMAIN_SEPARATOR}.\n */\n // solhint-disable-next-line func-name-mixedcase\n function DOMAIN_SEPARATOR() external view override returns (bytes32) {\n return _domainSeparatorV4();\n }\n uint256[49] private __gap;\n}\n" + }, + "@openzeppelin/contracts-upgradeable/drafts/IERC20PermitUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <0.8.0;\n\n/**\n * @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in\n * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612].\n *\n * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by\n * presenting a message signed by the account. By not relying on `{IERC20-approve}`, the token holder account doesn't\n * need to send a transaction, and thus is not required to hold Ether at all.\n */\ninterface IERC20PermitUpgradeable {\n /**\n * @dev Sets `value` as the allowance of `spender` over `owner`'s tokens,\n * given `owner`'s signed approval.\n *\n * IMPORTANT: The same issues {IERC20-approve} has related to transaction\n * ordering also apply here.\n *\n * Emits an {Approval} event.\n *\n * Requirements:\n *\n * - `spender` cannot be the zero address.\n * - `deadline` must be a timestamp in the future.\n * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner`\n * over the EIP712-formatted function arguments.\n * - the signature must use ``owner``'s current nonce (see {nonces}).\n *\n * For more information on the signature format, see the\n * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP\n * section].\n */\n function permit(address owner, address spender, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s) external;\n\n /**\n * @dev Returns the current nonce for `owner`. This value must be\n * included whenever a signature is generated for {permit}.\n *\n * Every successful call to {permit} increases ``owner``'s nonce by one. This\n * prevents a signature from being used multiple times.\n */\n function nonces(address owner) external view returns (uint256);\n\n /**\n * @dev Returns the domain separator used in the encoding of the signature for `permit`, as defined by {EIP712}.\n */\n // solhint-disable-next-line func-name-mixedcase\n function DOMAIN_SEPARATOR() external view returns (bytes32);\n}\n" + }, + "@openzeppelin/contracts-upgradeable/cryptography/ECDSAUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <0.8.0;\n\n/**\n * @dev Elliptic Curve Digital Signature Algorithm (ECDSA) operations.\n *\n * These functions can be used to verify that a message was signed by the holder\n * of the private keys of a given address.\n */\nlibrary ECDSAUpgradeable {\n /**\n * @dev Returns the address that signed a hashed message (`hash`) with\n * `signature`. This address can then be used for verification purposes.\n *\n * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:\n * this function rejects them by requiring the `s` value to be in the lower\n * half order, and the `v` value to be either 27 or 28.\n *\n * IMPORTANT: `hash` _must_ be the result of a hash operation for the\n * verification to be secure: it is possible to craft signatures that\n * recover to arbitrary addresses for non-hashed data. A safe way to ensure\n * this is by receiving a hash of the original message (which may otherwise\n * be too long), and then calling {toEthSignedMessageHash} on it.\n */\n function recover(bytes32 hash, bytes memory signature) internal pure returns (address) {\n // Check the signature length\n if (signature.length != 65) {\n revert(\"ECDSA: invalid signature length\");\n }\n\n // Divide the signature in r, s and v variables\n bytes32 r;\n bytes32 s;\n uint8 v;\n\n // ecrecover takes the signature parameters, and the only way to get them\n // currently is to use assembly.\n // solhint-disable-next-line no-inline-assembly\n assembly {\n r := mload(add(signature, 0x20))\n s := mload(add(signature, 0x40))\n v := byte(0, mload(add(signature, 0x60)))\n }\n\n return recover(hash, v, r, s);\n }\n\n /**\n * @dev Overload of {ECDSA-recover-bytes32-bytes-} that receives the `v`,\n * `r` and `s` signature fields separately.\n */\n function recover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) internal pure returns (address) {\n // EIP-2 still allows signature malleability for ecrecover(). Remove this possibility and make the signature\n // unique. Appendix F in the Ethereum Yellow paper (https://ethereum.github.io/yellowpaper/paper.pdf), defines\n // the valid range for s in (281): 0 < s < secp256k1n ÷ 2 + 1, and for v in (282): v ∈ {27, 28}. Most\n // signatures from current libraries generate a unique signature with an s-value in the lower half order.\n //\n // If your library generates malleable signatures, such as s-values in the upper range, calculate a new s-value\n // with 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 - s1 and flip v from 27 to 28 or\n // vice versa. If your library also generates signatures with 0/1 for v instead 27/28, add 27 to v to accept\n // these malleable signatures as well.\n require(uint256(s) <= 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0, \"ECDSA: invalid signature 's' value\");\n require(v == 27 || v == 28, \"ECDSA: invalid signature 'v' value\");\n\n // If the signature is valid (and not malleable), return the signer address\n address signer = ecrecover(hash, v, r, s);\n require(signer != address(0), \"ECDSA: invalid signature\");\n\n return signer;\n }\n\n /**\n * @dev Returns an Ethereum Signed Message, created from a `hash`. This\n * replicates the behavior of the\n * https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_sign[`eth_sign`]\n * JSON-RPC method.\n *\n * See {recover}.\n */\n function toEthSignedMessageHash(bytes32 hash) internal pure returns (bytes32) {\n // 32 is the length in bytes of hash,\n // enforced by the type signature above\n return keccak256(abi.encodePacked(\"\\x19Ethereum Signed Message:\\n32\", hash));\n }\n}\n" + }, + "@openzeppelin/contracts-upgradeable/utils/CountersUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <0.8.0;\n\nimport \"../math/SafeMathUpgradeable.sol\";\n\n/**\n * @title Counters\n * @author Matt Condon (@shrugs)\n * @dev Provides counters that can only be incremented or decremented by one. This can be used e.g. to track the number\n * of elements in a mapping, issuing ERC721 ids, or counting request ids.\n *\n * Include with `using Counters for Counters.Counter;`\n * Since it is not possible to overflow a 256 bit integer with increments of one, `increment` can skip the {SafeMath}\n * overflow check, thereby saving gas. This does assume however correct usage, in that the underlying `_value` is never\n * directly accessed.\n */\nlibrary CountersUpgradeable {\n using SafeMathUpgradeable for uint256;\n\n struct Counter {\n // This variable should never be directly accessed by users of the library: interactions must be restricted to\n // the library's function. As of Solidity v0.5.2, this cannot be enforced, though there is a proposal to add\n // this feature: see https://github.com/ethereum/solidity/issues/4637\n uint256 _value; // default: 0\n }\n\n function current(Counter storage counter) internal view returns (uint256) {\n return counter._value;\n }\n\n function increment(Counter storage counter) internal {\n // The {SafeMath} overflow check can be skipped here, see the comment at the top\n counter._value += 1;\n }\n\n function decrement(Counter storage counter) internal {\n counter._value = counter._value.sub(1);\n }\n}\n" + }, + "@openzeppelin/contracts-upgradeable/drafts/EIP712Upgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <0.8.0;\nimport \"../proxy/Initializable.sol\";\n\n/**\n * @dev https://eips.ethereum.org/EIPS/eip-712[EIP 712] is a standard for hashing and signing of typed structured data.\n *\n * The encoding specified in the EIP is very generic, and such a generic implementation in Solidity is not feasible,\n * thus this contract does not implement the encoding itself. Protocols need to implement the type-specific encoding\n * they need in their contracts using a combination of `abi.encode` and `keccak256`.\n *\n * This contract implements the EIP 712 domain separator ({_domainSeparatorV4}) that is used as part of the encoding\n * scheme, and the final step of the encoding to obtain the message digest that is then signed via ECDSA\n * ({_hashTypedDataV4}).\n *\n * The implementation of the domain separator was designed to be as efficient as possible while still properly updating\n * the chain id to protect against replay attacks on an eventual fork of the chain.\n *\n * NOTE: This contract implements the version of the encoding known as \"v4\", as implemented by the JSON RPC method\n * https://docs.metamask.io/guide/signing-data.html[`eth_signTypedDataV4` in MetaMask].\n *\n * _Available since v3.4._\n */\nabstract contract EIP712Upgradeable is Initializable {\n /* solhint-disable var-name-mixedcase */\n bytes32 private _HASHED_NAME;\n bytes32 private _HASHED_VERSION;\n bytes32 private constant _TYPE_HASH = keccak256(\"EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)\");\n /* solhint-enable var-name-mixedcase */\n\n /**\n * @dev Initializes the domain separator and parameter caches.\n *\n * The meaning of `name` and `version` is specified in\n * https://eips.ethereum.org/EIPS/eip-712#definition-of-domainseparator[EIP 712]:\n *\n * - `name`: the user readable name of the signing domain, i.e. the name of the DApp or the protocol.\n * - `version`: the current major version of the signing domain.\n *\n * NOTE: These parameters cannot be changed except through a xref:learn::upgrading-smart-contracts.adoc[smart\n * contract upgrade].\n */\n function __EIP712_init(string memory name, string memory version) internal initializer {\n __EIP712_init_unchained(name, version);\n }\n\n function __EIP712_init_unchained(string memory name, string memory version) internal initializer {\n bytes32 hashedName = keccak256(bytes(name));\n bytes32 hashedVersion = keccak256(bytes(version));\n _HASHED_NAME = hashedName;\n _HASHED_VERSION = hashedVersion;\n }\n\n /**\n * @dev Returns the domain separator for the current chain.\n */\n function _domainSeparatorV4() internal view returns (bytes32) {\n return _buildDomainSeparator(_TYPE_HASH, _EIP712NameHash(), _EIP712VersionHash());\n }\n\n function _buildDomainSeparator(bytes32 typeHash, bytes32 name, bytes32 version) private view returns (bytes32) {\n return keccak256(\n abi.encode(\n typeHash,\n name,\n version,\n _getChainId(),\n address(this)\n )\n );\n }\n\n /**\n * @dev Given an already https://eips.ethereum.org/EIPS/eip-712#definition-of-hashstruct[hashed struct], this\n * function returns the hash of the fully encoded EIP712 message for this domain.\n *\n * This hash can be used together with {ECDSA-recover} to obtain the signer of a message. For example:\n *\n * ```solidity\n * bytes32 digest = _hashTypedDataV4(keccak256(abi.encode(\n * keccak256(\"Mail(address to,string contents)\"),\n * mailTo,\n * keccak256(bytes(mailContents))\n * )));\n * address signer = ECDSA.recover(digest, signature);\n * ```\n */\n function _hashTypedDataV4(bytes32 structHash) internal view virtual returns (bytes32) {\n return keccak256(abi.encodePacked(\"\\x19\\x01\", _domainSeparatorV4(), structHash));\n }\n\n function _getChainId() private view returns (uint256 chainId) {\n this; // silence state mutability warning without generating bytecode - see https://github.com/ethereum/solidity/issues/2691\n // solhint-disable-next-line no-inline-assembly\n assembly {\n chainId := chainid()\n }\n }\n\n /**\n * @dev The hash of the name parameter for the EIP712 domain.\n *\n * NOTE: This function reads from storage by default, but can be redefined to return a constant value if gas costs\n * are a concern.\n */\n function _EIP712NameHash() internal virtual view returns (bytes32) {\n return _HASHED_NAME;\n }\n\n /**\n * @dev The hash of the version parameter for the EIP712 domain.\n *\n * NOTE: This function reads from storage by default, but can be redefined to return a constant value if gas costs\n * are a concern.\n */\n function _EIP712VersionHash() internal virtual view returns (bytes32) {\n return _HASHED_VERSION;\n }\n uint256[50] private __gap;\n}\n" + }, + "contracts/auxiliary/DummyWethProxy.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.6.12;\nimport \"@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol\";\nimport \"@openzeppelin/contracts-upgradeable/proxy/Initializable.sol\";\n\ninterface IWETH9 {\n function name() external view returns (string memory);\n\n function symbol() external view returns (string memory);\n\n function decimals() external view returns (uint8);\n\n function balanceOf(address) external view returns (uint256);\n\n function allowance(address, address) external view returns (uint256);\n\n receive() external payable;\n\n function deposit() external payable;\n\n function withdraw(uint256 wad) external;\n\n function totalSupply() external view returns (uint256);\n\n function approve(address guy, uint256 wad) external returns (bool);\n\n function transfer(address dst, uint256 wad) external returns (bool);\n\n function transferFrom(\n address src,\n address dst,\n uint256 wad\n ) external returns (bool);\n}\n\ncontract DummyWethProxy is Initializable, OwnableUpgradeable {\n function initialize() external initializer {\n __Ownable_init();\n }\n\n IWETH9 public WETH;\n\n function setWETHAddress(address payable _weth) external onlyOwner {\n WETH = IWETH9(_weth);\n }\n\n function withdrawToSelf(uint256 amount) external {\n WETH.withdraw(amount);\n }\n\n function rescue(uint256 amount) external onlyOwner {\n WETH.transfer(owner(), amount);\n }\n\n receive() external payable {}\n\n fallback() external payable {}\n}\n" + }, + "contracts/amm/helper/test/TestMathUtils.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.6.12;\n\nimport \"../../MathUtils.sol\";\n\ncontract TestMathUtils {\n using MathUtils for uint256;\n\n function difference(uint256 a, uint256 b) public pure returns (uint256) {\n return a.difference(b);\n }\n\n function within1(uint256 a, uint256 b) public pure returns (bool) {\n return a.within1(b);\n }\n}\n" + }, + "contracts/bridge/ERC20Migrator.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.6.12;\n\nimport \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/SafeERC20.sol\";\nimport \"@openzeppelin/contracts/math/SafeMath.sol\";\n\n/**\n * @title ERC20Migrator\n * @dev This contract can be used to migrate an ERC20 token from one\n * contract to another, where each token holder has to opt-in to the migration.\n * To opt-in, users must approve for this contract the number of tokens they\n * want to migrate. Once the allowance is set up, anyone can trigger the\n * migration to the new token contract. In this way, token holders \"turn in\"\n * their old balance and will be minted an equal amount in the new token.\n * The new token contract must be mintable.\n * ```\n */\n\ninterface IERC20Mintable is IERC20 {\n function mint(address to, uint256 amount) external;\n}\n\ncontract ERC20Migrator {\n using SafeERC20 for IERC20;\n using SafeMath for uint256;\n\n // Address of the old token contract\n IERC20 private _legacyToken;\n\n // Address of the new token contract\n IERC20Mintable private _newToken;\n\n /**\n * @param legacyToken address of the old token contract\n */\n constructor(IERC20 legacyToken, IERC20Mintable newToken) public {\n _legacyToken = legacyToken;\n _newToken = newToken;\n }\n\n /**\n * @dev Returns the legacy token that is being migrated.\n */\n function legacyToken() external view returns (IERC20) {\n return _legacyToken;\n }\n\n /**\n * @dev Returns the new token to which we are migrating.\n */\n function newToken() external view returns (IERC20) {\n return _newToken;\n }\n\n /**\n * @dev Transfers part of an account's balance in the old token to this\n * contract, and mints the same amount of new tokens for that account.\n * @param amount amount of tokens to be migrated\n */\n function migrate(uint256 amount) external {\n _legacyToken.safeTransferFrom(msg.sender, address(this), amount);\n uint256 amountToMint = amount.mul(5).div(2);\n _newToken.mint(msg.sender, amountToMint);\n }\n}\n" + }, + "contracts/bridge/ECDSANodeManagement.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.6.12;\n\nimport \"./utils/AddressArrayUtils.sol\";\nimport \"@openzeppelin/contracts/math/SafeMath.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/SafeERC20.sol\";\n\ncontract ECDSANodeManagement {\n using AddressArrayUtils for address[];\n using SafeMath for uint256;\n using SafeERC20 for IERC20;\n\n // Status of the keep.\n // Active means the keep is active.\n // Closed means the keep was closed happily.\n // Terminated means the keep was closed due to misbehavior.\n enum Status {\n Active,\n Closed,\n Terminated\n }\n\n // Address of the keep's owner.\n address public owner;\n\n // List of keep members' addresses.\n address[] public members;\n\n // Minimum number of honest keep members required to produce a signature.\n uint256 public honestThreshold;\n\n // Keep's ECDSA public key serialized to 64-bytes, where X and Y coordinates\n // are padded with zeros to 32-byte each.\n bytes public publicKey;\n\n // The timestamp at which keep has been created and key generation process\n // started.\n uint256 internal keyGenerationStartTimestamp;\n\n // Map stores public key by member addresses. All members should submit the\n // same public key.\n mapping(address => bytes) internal submittedPublicKeys;\n\n // The current status of the keep.\n // If the keep is Active members monitor it and support requests from the\n // keep owner.\n // If the owner decides to close the keep the flag is set to Closed.\n // If the owner seizes member bonds the flag is set to Terminated.\n Status internal status;\n\n // Flags execution of contract initialization.\n bool internal isInitialized;\n\n // Notification that the submitted public key does not match a key submitted\n // by other member. The event contains address of the member who tried to\n // submit a public key and a conflicting public key submitted already by other\n // member.\n event ConflictingPublicKeySubmitted(\n address indexed submittingMember,\n bytes conflictingPublicKey\n );\n\n // Notification that keep's ECDSA public key has been successfully established.\n event PublicKeyPublished(bytes publicKey);\n\n // Notification that the keep was closed by the owner.\n // Members no longer need to support this keep.\n event KeepClosed();\n\n // Notification that the keep has been terminated by the owner.\n // Members no longer need to support this keep.\n event KeepTerminated();\n\n /// @notice Returns keep's ECDSA public key.\n /// @return Keep's ECDSA public key.\n function getPublicKey() external view returns (bytes memory) {\n return publicKey;\n }\n\n /// @notice Submits a public key to the keep.\n /// @dev Public key is published successfully if all members submit the same\n /// value. In case of conflicts with others members submissions it will emit\n /// `ConflictingPublicKeySubmitted` event. When all submitted keys match\n /// it will store the key as keep's public key and emit a `PublicKeyPublished`\n /// event.\n /// @param _publicKey Signer's public key.\n function submitPublicKey(bytes calldata _publicKey) external onlyMember {\n require(\n !hasMemberSubmittedPublicKey(msg.sender),\n \"Member already submitted a public key\"\n );\n\n require(_publicKey.length == 64, \"Public key must be 64 bytes long\");\n\n submittedPublicKeys[msg.sender] = _publicKey;\n\n // Check if public keys submitted by all keep members are the same as\n // the currently submitted one.\n uint256 matchingPublicKeysCount = 0;\n for (uint256 i = 0; i < members.length; i++) {\n if (\n keccak256(submittedPublicKeys[members[i]]) !=\n keccak256(_publicKey)\n ) {\n // Emit an event only if compared member already submitted a value.\n if (hasMemberSubmittedPublicKey(members[i])) {\n emit ConflictingPublicKeySubmitted(\n msg.sender,\n submittedPublicKeys[members[i]]\n );\n }\n } else {\n matchingPublicKeysCount++;\n }\n }\n\n if (matchingPublicKeysCount != members.length) {\n return;\n }\n\n // All submitted signatures match.\n publicKey = _publicKey;\n emit PublicKeyPublished(_publicKey);\n }\n\n /// @notice Gets the owner of the keep.\n /// @return Address of the keep owner.\n function getOwner() external view returns (address) {\n return owner;\n }\n\n /// @notice Gets the timestamp the keep was opened at.\n /// @return Timestamp the keep was opened at.\n function getOpenedTimestamp() external view returns (uint256) {\n return keyGenerationStartTimestamp;\n }\n\n /// @notice Closes keep when owner decides that they no longer need it.\n /// Releases bonds to the keep members.\n /// @dev The function can be called only by the owner of the keep and only\n /// if the keep has not been already closed.\n function closeKeep() public onlyOwner onlyWhenActive {\n markAsClosed();\n }\n\n /// @notice Returns true if the keep is active.\n /// @return true if the keep is active, false otherwise.\n function isActive() public view returns (bool) {\n return status == Status.Active;\n }\n\n /// @notice Returns true if the keep is closed and members no longer support\n /// this keep.\n /// @return true if the keep is closed, false otherwise.\n function isClosed() public view returns (bool) {\n return status == Status.Closed;\n }\n\n /// @notice Returns true if the keep has been terminated.\n /// Keep is terminated when bonds are seized and members no longer support\n /// this keep.\n /// @return true if the keep has been terminated, false otherwise.\n function isTerminated() public view returns (bool) {\n return status == Status.Terminated;\n }\n\n /// @notice Returns members of the keep.\n /// @return List of the keep members' addresses.\n function getMembers() public view returns (address[] memory) {\n return members;\n }\n\n /// @notice Initialization function.\n /// @dev We use clone factory to create new keep. That is why this contract\n /// doesn't have a constructor. We provide keep parameters for each instance\n /// function after cloning instances from the master contract.\n /// Initialization must happen in the same transaction in which the clone is\n /// created.\n /// @param _owner Address of the keep owner.\n /// @param _members Addresses of the keep members.\n /// @param _honestThreshold Minimum number of honest keep members.\n function initialize(\n address _owner,\n address[] memory _members,\n uint256 _honestThreshold\n ) public {\n require(!isInitialized, \"Contract already initialized\");\n require(_owner != address(0));\n owner = _owner;\n members = _members;\n honestThreshold = _honestThreshold;\n\n status = Status.Active;\n isInitialized = true;\n\n /* solium-disable-next-line security/no-block-members*/\n keyGenerationStartTimestamp = block.timestamp;\n }\n\n /// @notice Checks if the member already submitted a public key.\n /// @param _member Address of the member.\n /// @return True if member already submitted a public key, else false.\n function hasMemberSubmittedPublicKey(address _member)\n internal\n view\n returns (bool)\n {\n return submittedPublicKeys[_member].length != 0;\n }\n\n /// @notice Marks the keep as closed.\n /// Keep can be marked as closed only when there is no signing in progress\n /// or the requested signing process has timed out.\n function markAsClosed() internal {\n status = Status.Closed;\n emit KeepClosed();\n }\n\n /// @notice Marks the keep as terminated.\n /// Keep can be marked as terminated only when there is no signing in progress\n /// or the requested signing process has timed out.\n function markAsTerminated() internal {\n status = Status.Terminated;\n emit KeepTerminated();\n }\n\n /// @notice Coverts a public key to an ethereum address.\n /// @param _publicKey Public key provided as 64-bytes concatenation of\n /// X and Y coordinates (32-bytes each).\n /// @return Ethereum address.\n function publicKeyToAddress(bytes memory _publicKey)\n internal\n pure\n returns (address)\n {\n // We hash the public key and then truncate last 20 bytes of the digest\n // which is the ethereum address.\n return address(uint160(uint256(keccak256(_publicKey))));\n }\n\n /// @notice Terminates the keep.\n function terminateKeep() internal {\n markAsTerminated();\n }\n\n /// @notice Checks if the caller is the keep's owner.\n /// @dev Throws an error if called by any account other than owner.\n modifier onlyOwner() {\n require(owner == msg.sender, \"Caller is not the keep owner\");\n _;\n }\n\n /// @notice Checks if the caller is a keep member.\n /// @dev Throws an error if called by any account other than one of the members.\n modifier onlyMember() {\n require(members.contains(msg.sender), \"Caller is not the keep member\");\n _;\n }\n\n /// @notice Checks if the keep is currently active.\n /// @dev Throws an error if called when the keep has been already closed.\n modifier onlyWhenActive() {\n require(isActive(), \"Keep is not active\");\n _;\n }\n}\n" + }, + "contracts/bridge/utils/AddressArrayUtils.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.6.12;\n\nlibrary AddressArrayUtils {\n function contains(address[] memory self, address _address)\n internal\n pure\n returns (bool)\n {\n for (uint256 i = 0; i < self.length; i++) {\n if (_address == self[i]) {\n return true;\n }\n }\n return false;\n }\n}" + }, + "contracts/bridge/mocks/ERC20Mock.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.6.12;\n\nimport \"@openzeppelin/contracts/token/ERC20/ERC20.sol\";\n\ncontract ERC20Mock is ERC20 {\n constructor(\n string memory name,\n string memory symbol,\n uint256 supply\n ) public ERC20(name, symbol) {\n _mint(msg.sender, supply);\n }\n\n function mint(address to, uint256 amount) external {\n _mint(to, amount);\n }\n}" + }, + "contracts/bridge/interfaces/IMetaSwapDeposit.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.6.12;\nimport '@openzeppelin/contracts/token/ERC20/ERC20.sol';\n\n/**\n * @title IMetaSwapDeposit interface\n * @notice Interface for the meta swap contract.\n * @dev implement this interface to develop a a factory-patterned ECDSA node management contract\n **/\ninterface IMetaSwapDeposit {\n // min return calculation functions\n function calculateSwap(\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx\n ) external view returns (uint256);\n\n function swap(\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx,\n uint256 minDy,\n uint256 deadline\n ) external returns (uint256);\n\n function getToken(uint256 index) external view returns (IERC20);\n}\n" + }, + "contracts/amm/interfaces/IMetaSwapDeposit.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.6.12;\n\nimport \"@openzeppelin/contracts/token/ERC20/ERC20.sol\";\nimport \"./ISwap.sol\";\nimport \"./IMetaSwap.sol\";\n\ninterface IMetaSwapDeposit {\n function initialize(\n ISwap baseSwap_,\n IMetaSwap metaSwap_,\n IERC20 metaLPToken_\n ) external;\n}\n" + }, + "contracts/amm/interfaces/IMetaSwap.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.6.12;\n\nimport \"@openzeppelin/contracts/token/ERC20/ERC20.sol\";\n\ninterface IMetaSwap {\n // pool data view functions\n function getA() external view returns (uint256);\n\n function getToken(uint8 index) external view returns (IERC20);\n\n function getTokenIndex(address tokenAddress) external view returns (uint8);\n\n function getTokenBalance(uint8 index) external view returns (uint256);\n\n function getVirtualPrice() external view returns (uint256);\n\n function isGuarded() external view returns (bool);\n\n // min return calculation functions\n function calculateSwap(\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx\n ) external view returns (uint256);\n\n function calculateSwapUnderlying(\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx\n ) external view returns (uint256);\n\n function calculateTokenAmount(uint256[] calldata amounts, bool deposit)\n external\n view\n returns (uint256);\n\n function calculateRemoveLiquidity(uint256 amount)\n external\n view\n returns (uint256[] memory);\n\n function calculateRemoveLiquidityOneToken(\n uint256 tokenAmount,\n uint8 tokenIndex\n ) external view returns (uint256 availableTokenAmount);\n\n // state modifying functions\n function initializeMetaSwap(\n IERC20[] memory pooledTokens,\n uint8[] memory decimals,\n string memory lpTokenName,\n string memory lpTokenSymbol,\n uint256 a,\n uint256 fee,\n uint256 adminFee,\n address lpTokenTargetAddress,\n address baseSwap\n ) external;\n\n function swap(\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx,\n uint256 minDy,\n uint256 deadline\n ) external returns (uint256);\n\n function swapUnderlying(\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx,\n uint256 minDy,\n uint256 deadline\n ) external returns (uint256);\n\n function addLiquidity(\n uint256[] calldata amounts,\n uint256 minToMint,\n uint256 deadline\n ) external returns (uint256);\n\n function removeLiquidity(\n uint256 amount,\n uint256[] calldata minAmounts,\n uint256 deadline\n ) external returns (uint256[] memory);\n\n function removeLiquidityOneToken(\n uint256 tokenAmount,\n uint8 tokenIndex,\n uint256 minAmount,\n uint256 deadline\n ) external returns (uint256);\n\n function removeLiquidityImbalance(\n uint256[] calldata amounts,\n uint256 maxBurnAmount,\n uint256 deadline\n ) external returns (uint256);\n\n function swapStorage()\n external\n view\n returns (\n uint256 initialA,\n uint256 futureA,\n uint256 initialATime,\n uint256 futureATime,\n uint256 swapFee,\n uint256 adminFee,\n address lpToken\n );\n}\n" + }, + "contracts/amm/helper/GenericERC20.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.6.12;\n\nimport \"@openzeppelin/contracts/token/ERC20/ERC20.sol\";\nimport \"@openzeppelin/contracts/access/Ownable.sol\";\n\n/**\n * @title Generic ERC20 token\n * @notice This contract simulates a generic ERC20 token that is mintable and burnable.\n */\ncontract GenericERC20 is ERC20, Ownable {\n /**\n * @notice Deploy this contract with given name, symbol, and decimals\n * @dev the caller of this constructor will become the owner of this contract\n * @param name_ name of this token\n * @param symbol_ symbol of this token\n * @param decimals_ number of decimals this token will be based on\n */\n constructor(\n string memory name_,\n string memory symbol_,\n uint8 decimals_\n ) public ERC20(name_, symbol_) {\n _setupDecimals(decimals_);\n }\n\n /**\n * @notice Mints given amount of tokens to recipient\n * @dev only owner can call this mint function\n * @param recipient address of account to receive the tokens\n * @param amount amount of tokens to mint\n */\n function mint(address recipient, uint256 amount) external onlyOwner {\n require(amount != 0, \"amount == 0\");\n _mint(recipient, amount);\n }\n}\n" + }, + "contracts/amm/SwapEthWrapper.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.6.12;\n\nimport \"@openzeppelin/contracts/math/SafeMath.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/SafeERC20.sol\";\nimport \"./Swap.sol\";\nimport \"./interfaces/IWETH9.sol\";\n\n/**\n * @title SwapEthWrapper\n * @notice A wrapper contract for Swap contracts that have WETH as one of the pooled tokens.\n * @author Jongseung Lim (@weeb_mcgee)\n */\ncontract SwapEthWrapper {\n using SafeERC20 for IERC20;\n using SafeMath for uint256;\n\n // constants\n uint8 private constant MAX_UINT8 = 2**8 - 1;\n uint256 private constant MAX_UINT256 = 2**256 - 1;\n\n // immutables\n Swap public immutable SWAP;\n LPToken public immutable LP_TOKEN;\n address payable public immutable WETH_ADDRESS;\n address public immutable OWNER;\n uint8 public immutable WETH_INDEX;\n\n IERC20[] public pooledTokens;\n\n /**\n * @notice Deploys this contract with given WETH9 address and Swap address. It will attempt to\n * fetch information about the given Swap pool. If the Swap pool does not contain WETH9,\n * this call will be reverted. Owner address must be given so that `rescue()` function\n * can be limited.\n * @param wethAddress address to the WETH9 contract\n * @param swap address to the Swap contract that has WETH9 as one of the tokens\n * @param owner address that will be allowed to call `rescue()`\n */\n constructor(\n address payable wethAddress,\n Swap swap,\n address owner\n ) public {\n (, , , , , , LPToken lpToken) = swap.swapStorage();\n uint8 wethIndex = MAX_UINT8;\n\n for (uint8 i = 0; i < MAX_UINT8; i++) {\n try swap.getToken(i) returns (IERC20 token) {\n pooledTokens.push(token);\n if (address(token) == wethAddress) {\n wethIndex = i;\n }\n // Approve pooled tokens to be used by Swap\n token.approve(address(swap), MAX_UINT256);\n } catch {\n break;\n }\n }\n require(wethIndex != MAX_UINT8, \"WETH was not found in the swap pool\");\n\n // Set immutable variables\n WETH_INDEX = wethIndex;\n WETH_ADDRESS = wethAddress;\n SWAP = swap;\n LP_TOKEN = lpToken;\n OWNER = owner;\n\n // Approve LPToken to be used by Swap\n lpToken.approve(address(swap), MAX_UINT256);\n }\n\n /**\n * @notice Add liquidity to the pool with the given amounts of tokens.\n * @dev The msg.value of this call should match the value in amounts array\n * in position of WETH9.\n * @param amounts the amounts of each token to add, in their native precision\n * @param minToMint the minimum LP tokens adding this amount of liquidity\n * should mint, otherwise revert. Handy for front-running mitigation\n * @param deadline latest timestamp to accept this transaction\n * @return amount of LP token user minted and received\n */\n function addLiquidity(\n uint256[] memory amounts,\n uint256 minToMint,\n uint256 deadline\n ) external payable returns (uint256) {\n // If using ETH, deposit them to WETH.\n require(msg.value == amounts[WETH_INDEX], \"INCORRECT_MSG_VALUE\");\n if (msg.value > 0) {\n IWETH9(WETH_ADDRESS).deposit{value: msg.value}();\n }\n // Go through amounts array and transfer respective tokens to this contract.\n for (uint256 i = 0; i < amounts.length; i++) {\n uint256 amount = amounts[i];\n if (i != WETH_INDEX && amount > 0) {\n pooledTokens[i].safeTransferFrom(\n msg.sender,\n address(this),\n amount\n );\n }\n }\n // Add the assets to the pool\n uint256 lpTokenAmount = SWAP.addLiquidity(amounts, minToMint, deadline);\n // Send the LPToken to msg.sender\n IERC20(address(LP_TOKEN)).safeTransfer(msg.sender, lpTokenAmount);\n return lpTokenAmount;\n }\n\n /**\n * @notice Burn LP tokens to remove liquidity from the pool.\n * @dev Liquidity can always be removed, even when the pool is paused. Caller\n * will receive ETH instead of WETH9.\n * @param amount the amount of LP tokens to burn\n * @param minAmounts the minimum amounts of each token in the pool\n * acceptable for this burn. Useful as a front-running mitigation\n * @param deadline latest timestamp to accept this transaction\n * @return amounts of tokens user received\n */\n function removeLiquidity(\n uint256 amount,\n uint256[] calldata minAmounts,\n uint256 deadline\n ) external returns (uint256[] memory) {\n // Transfer LPToken from msg.sender to this contract.\n IERC20(address(LP_TOKEN)).safeTransferFrom(\n msg.sender,\n address(this),\n amount\n );\n // Remove liquidity\n uint256[] memory amounts = SWAP.removeLiquidity(\n amount,\n minAmounts,\n deadline\n );\n // Send the tokens back to the user\n for (uint256 i = 0; i < amounts.length; i++) {\n if (i != WETH_INDEX) {\n pooledTokens[i].safeTransfer(msg.sender, amounts[i]);\n } else {\n IWETH9(WETH_ADDRESS).withdraw(amounts[i]);\n // slither-disable-next-line arbitrary-send\n (bool success, ) = msg.sender.call{value: amounts[i]}(\"\");\n require(success, \"ETH_TRANSFER_FAILED\");\n }\n }\n return amounts;\n }\n\n /**\n * @notice Remove liquidity from the pool all in one token.\n * @dev Caller will receive ETH instead of WETH9.\n * @param tokenAmount the amount of the token you want to receive\n * @param tokenIndex the index of the token you want to receive\n * @param minAmount the minimum amount to withdraw, otherwise revert\n * @param deadline latest timestamp to accept this transaction\n * @return amount of chosen token user received\n */\n function removeLiquidityOneToken(\n uint256 tokenAmount,\n uint8 tokenIndex,\n uint256 minAmount,\n uint256 deadline\n ) external returns (uint256) {\n // Transfer LPToken from msg.sender to this contract.\n IERC20(address(LP_TOKEN)).safeTransferFrom(\n msg.sender,\n address(this),\n tokenAmount\n );\n // Withdraw via single token\n uint256 amount = SWAP.removeLiquidityOneToken(\n tokenAmount,\n tokenIndex,\n minAmount,\n deadline\n );\n // Transfer the token to msg.sender accordingly\n if (tokenIndex != WETH_INDEX) {\n pooledTokens[tokenIndex].safeTransfer(msg.sender, amount);\n } else {\n IWETH9(WETH_ADDRESS).withdraw(amount);\n // slither-disable-next-line arbitrary-send\n (bool success, ) = msg.sender.call{value: amount}(\"\");\n require(success, \"ETH_TRANSFER_FAILED\");\n }\n return amount;\n }\n\n /**\n * @notice Remove liquidity from the pool, weighted differently than the\n * pool's current balances.\n * @dev Caller will receive ETH instead of WETH9.\n * @param amounts how much of each token to withdraw\n * @param maxBurnAmount the max LP token provider is willing to pay to\n * remove liquidity. Useful as a front-running mitigation.\n * @param deadline latest timestamp to accept this transaction\n * @return amount of LP tokens burned\n */\n function removeLiquidityImbalance(\n uint256[] calldata amounts,\n uint256 maxBurnAmount,\n uint256 deadline\n ) external returns (uint256) {\n // Transfer LPToken from msg.sender to this contract.\n IERC20(address(LP_TOKEN)).safeTransferFrom(\n msg.sender,\n address(this),\n maxBurnAmount\n );\n // Withdraw in imbalanced ratio\n uint256 burnedLpTokenAmount = SWAP.removeLiquidityImbalance(\n amounts,\n maxBurnAmount,\n deadline\n );\n // Send the tokens back to the user\n for (uint256 i = 0; i < amounts.length; i++) {\n if (i != WETH_INDEX) {\n pooledTokens[i].safeTransfer(msg.sender, amounts[i]);\n } else {\n IWETH9(WETH_ADDRESS).withdraw(amounts[i]);\n // slither-disable-next-line arbitrary-send\n (bool success, ) = msg.sender.call{value: amounts[i]}(\"\");\n require(success, \"ETH_TRANSFER_FAILED\");\n }\n }\n // Send any extra LP tokens back as well\n uint256 extraLpTokenAmount = maxBurnAmount.sub(burnedLpTokenAmount);\n if (extraLpTokenAmount > 0) {\n IERC20(address(LP_TOKEN)).safeTransfer(\n msg.sender,\n extraLpTokenAmount\n );\n }\n return burnedLpTokenAmount;\n }\n\n /**\n * @notice Swap two tokens using the underlying pool. If tokenIndexFrom\n * represents WETH9 in the pool, the caller must set msg.value equal to dx.\n * If the user is swapping to WETH9 in the pool, the user will receive ETH instead.\n * @param tokenIndexFrom the token the user wants to swap from\n * @param tokenIndexTo the token the user wants to swap to\n * @param dx the amount of tokens the user wants to swap from\n * @param minDy the min amount the user would like to receive, or revert.\n * @param deadline latest timestamp to accept this transaction\n */\n function swap(\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx,\n uint256 minDy,\n uint256 deadline\n ) external payable returns (uint256) {\n // Transfer tokens from msg.sender to this contract\n if (tokenIndexFrom != WETH_INDEX) {\n IERC20(pooledTokens[tokenIndexFrom]).safeTransferFrom(\n msg.sender,\n address(this),\n dx\n );\n } else {\n require(msg.value == dx, \"INCORRECT_MSG_VALUE\");\n IWETH9(WETH_ADDRESS).deposit{value: msg.value}();\n }\n // Execute swap\n uint256 dy = SWAP.swap(\n tokenIndexFrom,\n tokenIndexTo,\n dx,\n minDy,\n deadline\n );\n // Transfer the swapped tokens to msg.sender\n if (tokenIndexTo != WETH_INDEX) {\n IERC20(pooledTokens[tokenIndexTo]).safeTransfer(msg.sender, dy);\n } else {\n IWETH9(WETH_ADDRESS).withdraw(dy);\n // slither-disable-next-line arbitrary-send\n (bool success, ) = msg.sender.call{value: dy}(\"\");\n require(success, \"ETH_TRANSFER_FAILED\");\n }\n return dy;\n }\n\n /**\n * @notice Rescues any of the ETH, the pooled tokens, or the LPToken that may be stuck\n * in this contract. Only the OWNER can call this function.\n */\n function rescue() external {\n require(msg.sender == OWNER, \"CALLED_BY_NON_OWNER\");\n IERC20[] memory tokens = pooledTokens;\n for (uint256 i = 0; i < tokens.length; i++) {\n tokens[i].safeTransfer(\n msg.sender,\n tokens[i].balanceOf(address(this))\n );\n }\n IERC20 lpToken_ = IERC20(address(LP_TOKEN));\n lpToken_.safeTransfer(msg.sender, lpToken_.balanceOf(address(this)));\n // slither-disable-next-line arbitrary-send\n (bool success, ) = msg.sender.call{value: address(this).balance}(\"\");\n require(success, \"ETH_TRANSFER_FAILED\");\n }\n\n receive() external payable {}\n\n // VIEW FUNCTIONS\n\n /**\n * @notice A simple method to calculate prices from deposits or\n * withdrawals, excluding fees but including slippage. This is\n * helpful as an input into the various \"min\" parameters on calls\n * to fight front-running\n *\n * @dev This shouldn't be used outside frontends for user estimates.\n *\n * @param amounts an array of token amounts to deposit or withdrawal,\n * corresponding to pooledTokens. The amount should be in each\n * pooled token's native precision. If a token charges a fee on transfers,\n * use the amount that gets transferred after the fee.\n * @param deposit whether this is a deposit or a withdrawal\n * @return token amount the user will receive\n */\n function calculateTokenAmount(uint256[] calldata amounts, bool deposit)\n external\n view\n returns (uint256)\n {\n return SWAP.calculateTokenAmount(amounts, deposit);\n }\n\n /**\n * @notice A simple method to calculate amount of each underlying\n * tokens that is returned upon burning given amount of LP tokens\n * @param amount the amount of LP tokens that would be burned on withdrawal\n * @return array of token balances that the user will receive\n */\n function calculateRemoveLiquidity(uint256 amount)\n external\n view\n returns (uint256[] memory)\n {\n return SWAP.calculateRemoveLiquidity(amount);\n }\n\n /**\n * @notice Calculate the amount of underlying token available to withdraw\n * when withdrawing via only single token\n * @param tokenAmount the amount of LP token to burn\n * @param tokenIndex index of which token will be withdrawn\n * @return availableTokenAmount calculated amount of underlying token\n * available to withdraw\n */\n function calculateRemoveLiquidityOneToken(\n uint256 tokenAmount,\n uint8 tokenIndex\n ) external view returns (uint256 availableTokenAmount) {\n return SWAP.calculateRemoveLiquidityOneToken(tokenAmount, tokenIndex);\n }\n}\n" + }, + "contracts/amm/interfaces/IWETH9.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.4.0;\n\ninterface IWETH9 {\n function name() external view returns (string memory);\n\n function symbol() external view returns (string memory);\n\n function decimals() external view returns (uint8);\n\n function balanceOf(address) external view returns (uint256);\n\n function allowance(address, address) external view returns (uint256);\n\n receive() external payable;\n\n function deposit() external payable;\n\n function withdraw(uint256 wad) external;\n\n function totalSupply() external view returns (uint256);\n\n function approve(address guy, uint256 wad) external returns (bool);\n\n function transfer(address dst, uint256 wad) external returns (bool);\n\n function transferFrom(\n address src,\n address dst,\n uint256 wad\n ) external returns (bool);\n}\n" + }, + "contracts/amm/helper/BaseSwapDeposit.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.6.12;\n\nimport \"@openzeppelin/contracts/math/SafeMath.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/SafeERC20.sol\";\nimport \"../interfaces/ISwap.sol\";\nimport \"@openzeppelin/contracts/utils/ReentrancyGuard.sol\";\n\ncontract BaseSwapDeposit is ReentrancyGuard {\n using SafeERC20 for IERC20;\n using SafeMath for uint256;\n\n ISwap public baseSwap;\n IERC20[] public baseTokens;\n\n uint256 constant MAX_UINT256 = 2**256 - 1;\n\n constructor(ISwap _baseSwap) public {\n baseSwap = _baseSwap;\n // Check and approve base level tokens to be deposited to the base Swap contract\n {\n uint8 i;\n for (; i < 32; i++) {\n try _baseSwap.getToken(i) returns (IERC20 token) {\n baseTokens.push(token);\n token.safeApprove(address(_baseSwap), MAX_UINT256);\n } catch {\n break;\n }\n }\n require(i > 1, \"baseSwap must have at least 2 tokens\");\n }\n }\n\n // Mutative functions\n\n /**\n * @notice Swap two underlying tokens using the meta pool and the base pool\n * @param tokenIndexFrom the token the user wants to swap from\n * @param tokenIndexTo the token the user wants to swap to\n * @param dx the amount of tokens the user wants to swap from\n * @param minDy the min amount the user would like to receive, or revert.\n * @param deadline latest timestamp to accept this transaction\n */\n function swap(\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx,\n uint256 minDy,\n uint256 deadline\n ) external nonReentrant returns (uint256) {\n baseTokens[tokenIndexFrom].safeTransferFrom(msg.sender, address(this), dx);\n uint256 tokenToAmount =\n baseSwap.swap(\n tokenIndexFrom,\n tokenIndexTo,\n dx,\n minDy,\n deadline\n );\n baseTokens[tokenIndexTo].safeTransfer(msg.sender, tokenToAmount);\n return tokenToAmount;\n }\n\n /**\n * @notice Calculate amount of tokens you receive on swap\n * @param tokenIndexFrom the token the user wants to sell\n * @param tokenIndexTo the token the user wants to buy\n * @param dx the amount of tokens the user wants to sell. If the token charges\n * a fee on transfers, use the amount that gets transferred after the fee.\n * @return amount of tokens the user will receive\n */\n function calculateSwap(\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx\n ) external view returns (uint256) {\n return\n baseSwap.calculateSwap(tokenIndexFrom, tokenIndexTo, dx);\n }\n\n /**\n * @notice Returns the address of the pooled token at given index. Reverts if tokenIndex is out of range.\n * @param index the index of the token\n * @return address of the token at given index\n */\n function getToken(uint256 index) external view returns (IERC20) {\n require(index < baseTokens.length, \"index out of range\");\n return baseTokens[index];\n }\n\n}" + }, + "@openzeppelin/contracts/utils/ReentrancyGuard.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <0.8.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 () internal {\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" + }, + "contracts/amm/AaveSwapWrapper.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.6.12;\n\nimport \"@openzeppelin/contracts/math/SafeMath.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/SafeERC20.sol\";\nimport \"./Swap.sol\";\n\ninterface ILendingPool {\n /**\n * @dev Deposits an `amount` of underlying asset into the reserve, receiving in return overlying aTokens.\n * - E.g. User deposits 100 USDC and gets in return 100 aUSDC\n * @param asset The address of the underlying asset to deposit\n * @param amount The amount to be deposited\n * @param onBehalfOf The address that will receive the aTokens, same as msg.sender if the user\n * wants to receive them on his own wallet, or a different address if the beneficiary of aTokens\n * is a different wallet\n * @param referralCode Code used to register the integrator originating the operation, for potential rewards.\n * 0 if the action is executed directly by the user, without any middle-man\n **/\n function deposit(\n address asset,\n uint256 amount,\n address onBehalfOf,\n uint16 referralCode\n ) external;\n\n /**\n * @dev Withdraws an `amount` of underlying asset from the reserve, burning the equivalent aTokens owned\n * E.g. User has 100 aUSDC, calls withdraw() and receives 100 USDC, burning the 100 aUSDC\n * @param asset The address of the underlying asset to withdraw\n * @param amount The underlying amount to be withdrawn\n * - Send the value type(uint256).max in order to withdraw the whole aToken balance\n * @param to Address that will receive the underlying, same as msg.sender if the user\n * wants to receive it on his own wallet, or a different address if the beneficiary is a\n * different wallet\n * @return The final amount withdrawn\n **/\n function withdraw(\n address asset,\n uint256 amount,\n address to\n ) external returns (uint256);\n}\n\n/**\n * @title AaveSwapWrapper\n * @notice A wrapper contract for interacting with aTokens\n */\ncontract AaveSwapWrapper {\n using SafeERC20 for IERC20;\n using SafeMath for uint256;\n mapping(uint8 => bool) private isUnderlyingIndex;\n\n // constants\n uint8 private constant MAX_UINT8 = 2**8 - 1;\n uint256 private constant MAX_UINT256 = 2**256 - 1;\n\n // immutables\n Swap public immutable SWAP;\n LPToken public immutable LP_TOKEN;\n address public immutable OWNER;\n IERC20[] public POOLED_TOKENS;\n IERC20[] public UNDERLYING_TOKENS;\n ILendingPool public LENDING_POOL;\n\n constructor(\n Swap swap,\n IERC20[] memory underlyingTokens,\n address lendingPool,\n address owner\n ) public {\n (, , , , , , LPToken lpToken) = swap.swapStorage();\n for (uint8 i = 0; i < MAX_UINT8; i++) {\n try swap.getToken(i) returns (IERC20 token) {\n POOLED_TOKENS.push(token);\n // Approve pooled tokens to be used by Swap\n token.approve(address(swap), MAX_UINT256);\n } catch {\n break;\n }\n }\n\n for (uint8 i = 0; i < POOLED_TOKENS.length; i++) {\n if (POOLED_TOKENS[i] == underlyingTokens[i]) {\n isUnderlyingIndex[i] = true;\n } else {\n isUnderlyingIndex[i] = false;\n underlyingTokens[i].approve(lendingPool, MAX_UINT256);\n }\n }\n\n // Set immutable variables\n SWAP = swap;\n LP_TOKEN = lpToken;\n OWNER = owner;\n UNDERLYING_TOKENS = underlyingTokens;\n LENDING_POOL = ILendingPool(lendingPool);\n\n // Approve LPToken to be used by Swap\n lpToken.approve(address(swap), MAX_UINT256);\n }\n\n /**\n * @notice Add liquidity to the pool with the given amounts of tokens.\n * @param amounts the amounts of each token to add, in their native precision\n * @param minToMint the minimum LP tokens adding this amount of liquidity\n * should mint, otherwise revert. Handy for front-running mitigation\n * @param deadline latest timestamp to accept this transaction\n * @return amount of LP token user minted and received\n */\n function addLiquidity(\n uint256[] memory amounts,\n uint256 minToMint,\n uint256 deadline\n ) external returns (uint256) {\n // Go through amounts array and transfer respective tokens to this contract.\n for (uint8 i = 0; i < amounts.length; i++) {\n uint256 amount = amounts[i];\n if (amount > 0) {\n UNDERLYING_TOKENS[i].safeTransferFrom(\n msg.sender,\n address(this),\n amount\n );\n if (isUnderlyingIndex[i] == false) {\n LENDING_POOL.deposit(\n address(UNDERLYING_TOKENS[i]),\n amount,\n address(this),\n 0\n );\n }\n }\n }\n\n // Add the assets to the pool\n uint256 lpTokenAmount = SWAP.addLiquidity(amounts, minToMint, deadline);\n // Send the LPToken to msg.sender\n IERC20(address(LP_TOKEN)).safeTransfer(msg.sender, lpTokenAmount);\n return lpTokenAmount;\n }\n\n /**\n * @notice Burn LP tokens to remove liquidity from the pool.\n * @dev Liquidity can always be removed, even when the pool is paused. Caller\n * will receive ETH instead of WETH9.\n * @param amount the amount of LP tokens to burn\n * @param minAmounts the minimum amounts of each token in the pool\n * acceptable for this burn. Useful as a front-running mitigation\n * @param deadline latest timestamp to accept this transaction\n * @return amounts of tokens user received\n */\n function removeLiquidity(\n uint256 amount,\n uint256[] calldata minAmounts,\n uint256 deadline\n ) external returns (uint256[] memory) {\n // Transfer LPToken from msg.sender to this contract.\n IERC20(address(LP_TOKEN)).safeTransferFrom(\n msg.sender,\n address(this),\n amount\n );\n // Remove liquidity\n uint256[] memory amounts = SWAP.removeLiquidity(\n amount,\n minAmounts,\n deadline\n );\n // Send the tokens back to the user\n for (uint8 i = 0; i < amounts.length; i++) {\n if (isUnderlyingIndex[i] == true) {\n UNDERLYING_TOKENS[i].safeTransfer(msg.sender, amounts[i]);\n } else {\n LENDING_POOL.withdraw(\n address(UNDERLYING_TOKENS[i]),\n amounts[i],\n msg.sender\n );\n // underlyingTokens[i].safeTransfer(msg.sender, amounts[i]);\n }\n }\n return amounts;\n }\n\n /**\n * @notice Remove liquidity from the pool all in one token.\n * @dev Caller will receive ETH instead of WETH9.\n * @param tokenAmount the amount of the token you want to receive\n * @param tokenIndex the index of the token you want to receive\n * @param minAmount the minimum amount to withdraw, otherwise revert\n * @param deadline latest timestamp to accept this transaction\n * @return amount of chosen token user received\n */\n function removeLiquidityOneToken(\n uint256 tokenAmount,\n uint8 tokenIndex,\n uint256 minAmount,\n uint256 deadline\n ) external returns (uint256) {\n // Transfer LPToken from msg.sender to this contract.\n IERC20(address(LP_TOKEN)).safeTransferFrom(\n msg.sender,\n address(this),\n tokenAmount\n );\n // Withdraw via single token\n uint256 amount = SWAP.removeLiquidityOneToken(\n tokenAmount,\n tokenIndex,\n minAmount,\n deadline\n );\n // Transfer the token to msg.sender accordingly\n if (isUnderlyingIndex[tokenIndex] == true) {\n UNDERLYING_TOKENS[tokenIndex].safeTransfer(msg.sender, amount);\n } else {\n LENDING_POOL.withdraw(\n address(UNDERLYING_TOKENS[tokenIndex]),\n amount,\n msg.sender\n );\n }\n return amount;\n }\n\n /**\n * @notice Swap two tokens using the underlying pool. If tokenIndexFrom\n * represents WETH9 in the pool, the caller must set msg.value equal to dx.\n * If the user is swapping to WETH9 in the pool, the user will receive ETH instead.\n * @param tokenIndexFrom the token the user wants to swap from\n * @param tokenIndexTo the token the user wants to swap to\n * @param dx the amount of tokens the user wants to swap from\n * @param minDy the min amount the user would like to receive, or revert.\n * @param deadline latest timestamp to accept this transaction\n */\n function swap(\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx,\n uint256 minDy,\n uint256 deadline\n ) external returns (uint256) {\n // Transfer tokens from msg.sender to this contract\n UNDERLYING_TOKENS[tokenIndexFrom].safeTransferFrom(\n msg.sender,\n address(this),\n dx\n );\n if (isUnderlyingIndex[tokenIndexFrom] == false) {\n LENDING_POOL.deposit(\n address(UNDERLYING_TOKENS[tokenIndexFrom]),\n dx,\n address(this),\n 0\n );\n }\n // Execute swap\n uint256 dy = SWAP.swap(\n tokenIndexFrom,\n tokenIndexTo,\n dx,\n minDy,\n deadline\n );\n // Transfer the swapped tokens to msg.sender\n if (isUnderlyingIndex[tokenIndexTo] == false) {\n LENDING_POOL.withdraw(\n address(UNDERLYING_TOKENS[tokenIndexTo]),\n dy,\n msg.sender\n );\n } else {\n UNDERLYING_TOKENS[tokenIndexTo].safeTransfer(msg.sender, dy);\n }\n return dy;\n }\n\n /**\n * @notice Rescues any of the ETH, the pooled tokens, or the LPToken that may be stuck\n * in this contract. Only the OWNER can call this function.\n */\n function rescue() external {\n require(msg.sender == OWNER, \"CALLED_BY_NON_OWNER\");\n IERC20[] memory tokens = POOLED_TOKENS;\n for (uint256 i = 0; i < tokens.length; i++) {\n tokens[i].safeTransfer(\n msg.sender,\n tokens[i].balanceOf(address(this))\n );\n }\n\n for (uint256 i = 0; i < UNDERLYING_TOKENS.length; i++) {\n UNDERLYING_TOKENS[i].safeTransfer(\n msg.sender,\n UNDERLYING_TOKENS[i].balanceOf(address(this))\n );\n }\n\n IERC20 lpToken_ = IERC20(address(LP_TOKEN));\n lpToken_.safeTransfer(msg.sender, lpToken_.balanceOf(address(this)));\n }\n\n // VIEW FUNCTIONS\n\n /**\n * @notice Calculate amount of tokens you receive on swap\n * @param tokenIndexFrom the token the user wants to sell\n * @param tokenIndexTo the token the user wants to buy\n * @param dx the amount of tokens the user wants to sell. If the token charges\n * a fee on transfers, use the amount that gets transferred after the fee.\n * @return amount of tokens the user will receive\n */\n function calculateSwap(\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx\n ) external view virtual returns (uint256) {\n return SWAP.calculateSwap(tokenIndexFrom, tokenIndexTo, dx);\n }\n\n /**\n * @notice A simple method to calculate prices from deposits or\n * withdrawals, excluding fees but including slippage. This is\n * helpful as an input into the various \"min\" parameters on calls\n * to fight front-running\n *\n * @dev This shouldn't be used outside frontends for user estimates.\n *\n * @param amounts an array of token amounts to deposit or withdrawal,\n * corresponding to pooledTokens. The amount should be in each\n * pooled token's native precision. If a token charges a fee on transfers,\n * use the amount that gets transferred after the fee.\n * @param deposit whether this is a deposit or a withdrawal\n * @return token amount the user will receive\n */\n function calculateTokenAmount(uint256[] calldata amounts, bool deposit)\n external\n view\n returns (uint256)\n {\n return SWAP.calculateTokenAmount(amounts, deposit);\n }\n\n /**\n * @notice A simple method to calculate amount of each underlying\n * tokens that is returned upon burning given amount of LP tokens\n * @param amount the amount of LP tokens that would be burned on withdrawal\n * @return array of token balances that the user will receive\n */\n function calculateRemoveLiquidity(uint256 amount)\n external\n view\n returns (uint256[] memory)\n {\n return SWAP.calculateRemoveLiquidity(amount);\n }\n\n /**\n * @notice Calculate the amount of underlying token available to withdraw\n * when withdrawing via only single token\n * @param tokenAmount the amount of LP token to burn\n * @param tokenIndex index of which token will be withdrawn\n * @return availableTokenAmount calculated amount of underlying token\n * available to withdraw\n */\n function calculateRemoveLiquidityOneToken(\n uint256 tokenAmount,\n uint8 tokenIndex\n ) external view returns (uint256 availableTokenAmount) {\n return SWAP.calculateRemoveLiquidityOneToken(tokenAmount, tokenIndex);\n }\n\n /**\n * @notice Return address of the pooled token at given index. Reverts if tokenIndex is out of range.\n * @param index the index of the token\n * @return address of the token at given index\n */\n function getToken(uint8 index) public view virtual returns (IERC20) {\n if (index < UNDERLYING_TOKENS.length) {\n return UNDERLYING_TOKENS[index];\n } else {\n revert();\n }\n }\n}\n" + }, + "contracts/bridge/testing/NodeEnv.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.6.12;\npragma experimental ABIEncoderV2;\n\nimport '@openzeppelin/contracts/access/AccessControl.sol';\nimport \"../utils/EnumerableStringMap.sol\";\n\n/**\n * @title NodeEnv contract\n * @author Synapse Authors\n * @notice This contract implements a key-value store for storing variables on which synapse nodes must coordinate\n * methods are purposely arbitrary to allow these fields to be defined in synapse improvement proposals.\n * @notice This token is used for configuring different tokens on the bridge and mapping them across chains.\n**/\ncontract NodeEnv is AccessControl {\n using EnumerableStringMap for EnumerableStringMap.StringToStringMap;\n // BRIDGEMANAGER_ROLE owns the bridge. They are the only user that can call setters on this contract\n bytes32 public constant BRIDGEMANAGER_ROLE = keccak256('BRIDGEMANAGER_ROLE');\n // _config stores the config\n EnumerableStringMap.StringToStringMap private _config; // key is tokenAddress,chainID\n\n // ConfigUpdate is emitted when the config is updated by the user\n event ConfigUpdate(\n string key\n );\n\n constructor() public {\n _setupRole(DEFAULT_ADMIN_ROLE, msg.sender);\n _setupRole(BRIDGEMANAGER_ROLE, msg.sender);\n }\n\n /**\n * @notice get the length of the config\n *\n * @dev this is useful for enumerating through all keys in the env\n */\n function keyCount()\n external\n view\n returns (uint256){\n return _config.length();\n }\n\n /**\n * @notice gets the key/value pair by it's index\n *\n * Requirements:\n *\n * - `index` must be strictly less than {length}.\n */\n function keyValueByIndex(uint256 index) external view returns(string memory, string memory){\n return _config.at(index);\n }\n\n /**\n * @notice gets the value associated with the key\n */\n function get(string calldata _key) external view returns(string memory){\n string memory key = _key;\n return _config.get(key);\n }\n\n /**\n * @notice sets the key\n *\n * @dev caller must have bridge manager role\n */\n function set(string calldata _key, string calldata _value) external returns(bool) {\n require(\n hasRole(BRIDGEMANAGER_ROLE, msg.sender),\n 'Caller is not Bridge Manager'\n );\n string memory key = _key;\n string memory value = _value;\n\n return _config.set(key, value);\n }\n}" + }, + "contracts/bridge/utils/EnumerableStringMap.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.6.12;\n\nimport \"@openzeppelin/contracts/utils/EnumerableSet.sol\";\n\n/**\n * @title EnumerableStringMap\n * @dev Library for managing an enumerable variant of Solidity's\n * https://solidity.readthedocs.io/en/latest/types.html#mapping-types[`mapping`]\n * type.\n *\n * Maps have the following properties:\n *\n * - Entries are added, removed, and checked for existence in constant time\n * (O(1)).\n * - Entries are enumerated in O(n). No guarantees are made on the ordering.\n *\n * this isn't a terribly gas efficient implementation because it emphasizes usability over gas efficiency\n * by allowing arbitrary length string memorys. If Gettetrs/Setters are going to be used frequently in contracts\n * consider using the OpenZeppeling Bytes32 implementation\n *\n * this also differs from the OpenZeppelin implementation by keccac256 hashing the string memorys\n * so we can use enumerable bytes32 set\n */\nlibrary EnumerableStringMap {\n using EnumerableSet for EnumerableSet.Bytes32Set;\n\n // To implement this library for multiple types with as little code\n // repetition as possible, we write it in terms of a generic Map type with\n // bytes32 keys and values.\n // The Map implementation uses private functions, and user-facing\n // implementations (such as Uint256ToAddressMap) are just wrappers around\n // the underlying Map.\n // This means that we can only create new EnumerableMaps for types that fit\n // in bytes32.\n\n struct Map {\n // Storage of keys as a set\n EnumerableSet.Bytes32Set _keys;\n // Mapping of keys to resulting values to allow key lookup in the set\n mapping(bytes32 => string) _hashKeyMap;\n // values\n mapping(bytes32 => string) _values;\n }\n\n /**\n * @dev Adds a key-value pair to a map, or updates the value for an existing\n * key. O(1).\n *\n * Returns true if the key was added to the map, that is if it was not\n * already present.\n */\n function _set(\n Map storage map,\n string memory key,\n string memory value\n ) private returns (bool) {\n bytes32 keyHash = keccak256(abi.encodePacked(key));\n map._values[keyHash] = value;\n map._hashKeyMap[keyHash] = key;\n return map._keys.add(keyHash);\n }\n\n /**\n * @dev Removes a key-value pair from a map. O(1).\n *\n * Returns true if the key was removed from the map, that is if it was present.\n */\n function _remove(Map storage map, bytes32 keyHash) private returns (bool) {\n delete map._values[keyHash];\n delete map._hashKeyMap[keyHash];\n return map._keys.remove(keyHash);\n }\n\n /**\n * @dev Returns true if the key is in the map. O(1).\n */\n function _contains(Map storage map, bytes32 keyHash) private view returns (bool) {\n return map._keys.contains(keyHash);\n }\n\n /**\n * @dev Returns the number of key-value pairs in the map. O(1).\n */\n function _length(Map storage map) private view returns (uint256) {\n return map._keys.length();\n }\n\n /**\n * @dev Returns the key-value pair stored at position `index` in the map. O(1).\n *\n * Note that there are no guarantees on the ordering of entries inside the\n * array, and it may change when more entries are added or removed.\n *\n * Requirements:\n *\n * - `index` must be strictly less than {length}.\n */\n function _at(Map storage map, uint256 index) private view returns (string memory, string memory) {\n bytes32 keyHash = map._keys.at(index);\n return (map._hashKeyMap[keyHash], map._values[keyHash]);\n }\n\n /**\n * @dev Tries to returns the value associated with `key`. O(1).\n * Does not revert if `key` is not in the map.\n */\n function _tryGet(Map storage map, bytes32 keyHash) private view returns (bool, string memory) {\n string memory value = map._values[keyHash];\n if (keccak256(bytes(value)) == keccak256(bytes(\"\"))) {\n return (_contains(map, keyHash), \"\");\n } else {\n return (true, value);\n }\n }\n\n /**\n * @dev Returns the value associated with `key`. O(1).\n *\n * Requirements:\n *\n * - `key` must be in the map.\n */\n function _get(Map storage map, bytes32 keyHash) private view returns (string memory) {\n string memory value = map._values[keyHash];\n require(_contains(map, keyHash), \"EnumerableMap: nonexistent key\");\n return value;\n }\n\n // StringToStringMap\n struct StringToStringMap {\n Map _inner;\n }\n\n /**\n * @dev Adds a key-value pair to a map, or updates the value for an existing\n * key. O(1).\n *\n * Returns true if the key was added to the map, that is if it was not\n * already present.\n */\n function set(\n StringToStringMap storage map,\n string memory key,\n string memory value\n ) internal returns (bool) {\n return _set(map._inner, key, value);\n }\n\n /**\n * @dev Removes a value from a set. O(1).\n *\n * Returns true if the key was removed from the map, that is if it was present.\n */\n function remove(StringToStringMap storage map, string memory key) internal returns (bool) {\n return _remove(map._inner, keccak256(abi.encodePacked(key)));\n }\n\n /**\n * @dev Returns true if the key is in the map. O(1).\n */\n function contains(StringToStringMap storage map, string memory key) internal view returns (bool) {\n return _contains(map._inner, keccak256(abi.encodePacked(key)));\n }\n\n /**\n * @dev Returns the number of elements in the map. O(1).\n */\n function length(StringToStringMap storage map) internal view returns (uint256) {\n return _length(map._inner);\n }\n\n /**\n * @dev Returns the element stored at position `index` in the set. O(1).\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(StringToStringMap storage map, uint256 index) internal view returns (string memory, string memory) {\n return _at(map._inner, index);\n }\n\n /**\n * @dev Tries to returns the value associated with `key`. O(1).\n * Does not revert if `key` is not in the map.\n *\n * _Available since v3.4._\n */\n function tryGet(StringToStringMap storage map, uint256 key) internal view returns (bool, string memory) {\n (bool success, string memory value) = _tryGet(map._inner, bytes32(key));\n return (success, value);\n }\n\n /**\n * @dev Returns the value associated with `key`. O(1).\n *\n * Requirements:\n *\n * - `key` must be in the map.\n */\n function get(StringToStringMap storage map, string memory key) internal view returns (string memory) {\n return _get(map._inner, keccak256(abi.encodePacked(key)));\n }\n}" + }, + "contracts/bridge/PoolConfig.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.6.12;\npragma experimental ABIEncoderV2;\n\nimport \"@openzeppelin/contracts/access/AccessControl.sol\";\n\ncontract PoolConfig is AccessControl {\n bytes32 public constant BRIDGEMANAGER_ROLE =\n keccak256(\"BRIDGEMANAGER_ROLE\");\n mapping(address => mapping(uint256 => Pool)) private _pool; // key is tokenAddress,chainID\n\n struct Pool {\n address tokenAddress;\n uint256 chainId;\n address poolAddress;\n bool metaswap;\n }\n\n constructor() public {\n _setupRole(DEFAULT_ADMIN_ROLE, msg.sender);\n _setupRole(BRIDGEMANAGER_ROLE, msg.sender);\n }\n\n function getPoolConfig(address tokenAddress, uint256 chainID)\n external\n view\n returns (Pool memory)\n {\n return _pool[tokenAddress][chainID];\n }\n\n function setPoolConfig(\n address tokenAddress,\n uint256 chainID,\n address poolAddress,\n bool metaswap\n ) external returns (Pool memory) {\n require(\n hasRole(BRIDGEMANAGER_ROLE, msg.sender),\n \"Caller is not Bridge Manager\"\n );\n Pool memory newPool = Pool(\n tokenAddress,\n chainID,\n poolAddress,\n metaswap\n );\n _pool[tokenAddress][chainID] = newPool;\n return newPool;\n }\n}\n" + }, + "contracts/bridge/BridgeConfigV3.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.6.12;\npragma experimental ABIEncoderV2;\n\nimport \"@openzeppelin/contracts/access/AccessControl.sol\";\nimport \"@openzeppelin/contracts/math/SafeMath.sol\";\n\n/**\n * @title BridgeConfig contract\n * @notice This token is used for configuring different tokens on the bridge and mapping them across chains.\n **/\n\ncontract BridgeConfigV3 is AccessControl {\n using SafeMath for uint256;\n bytes32 public constant BRIDGEMANAGER_ROLE =\n keccak256(\"BRIDGEMANAGER_ROLE\");\n bytes32[] private _allTokenIDs;\n mapping(bytes32 => Token[]) private _allTokens; // key is tokenID\n mapping(uint256 => mapping(string => bytes32)) private _tokenIDMap; // key is chainID,tokenAddress\n mapping(bytes32 => mapping(uint256 => Token)) private _tokens; // key is tokenID,chainID\n mapping(address => mapping(uint256 => Pool)) private _pool; // key is tokenAddress,chainID\n mapping(uint256 => uint256) private _maxGasPrice; // key is tokenID,chainID\n uint256 public constant bridgeConfigVersion = 3;\n\n // the denominator used to calculate fees. For example, an\n // LP fee might be something like tradeAmount.mul(fee).div(FEE_DENOMINATOR)\n uint256 private constant FEE_DENOMINATOR = 10**10;\n\n // this struct must be initialized using setTokenConfig for each token that directly interacts with the bridge\n struct Token {\n uint256 chainId;\n string tokenAddress;\n uint8 tokenDecimals;\n uint256 maxSwap;\n uint256 minSwap;\n uint256 swapFee;\n uint256 maxSwapFee;\n uint256 minSwapFee;\n bool hasUnderlying;\n bool isUnderlying;\n }\n\n struct Pool {\n address tokenAddress;\n uint256 chainId;\n address poolAddress;\n bool metaswap;\n }\n\n constructor() public {\n _setupRole(DEFAULT_ADMIN_ROLE, msg.sender);\n }\n\n /**\n * @notice Returns a list of all existing token IDs converted to strings\n */\n function getAllTokenIDs() public view returns (string[] memory result) {\n uint256 length = _allTokenIDs.length;\n result = new string[](length);\n for (uint256 i = 0; i < length; ++i) {\n result[i] = toString(_allTokenIDs[i]);\n }\n }\n\n function _getTokenID(string memory tokenAddress, uint256 chainID)\n internal\n view\n returns (string memory)\n {\n return toString(_tokenIDMap[chainID][tokenAddress]);\n }\n\n function getTokenID(string memory tokenAddress, uint256 chainID)\n public\n view\n returns (string memory)\n {\n return _getTokenID(_toLower(tokenAddress), chainID);\n }\n\n /**\n * @notice Returns the token ID (string) of the cross-chain token inputted\n * @param tokenAddress address of token to get ID for\n * @param chainID chainID of which to get token ID for\n */\n function getTokenID(address tokenAddress, uint256 chainID)\n public\n view\n returns (string memory)\n {\n return _getTokenID(_toLower(toString(tokenAddress)), chainID);\n }\n\n /**\n * @notice Returns the full token config struct\n * @param tokenID String input of the token ID for the token\n * @param chainID Chain ID of which token address + config to get\n */\n function getToken(string memory tokenID, uint256 chainID)\n public\n view\n returns (Token memory token)\n {\n return _tokens[toBytes32(tokenID)][chainID];\n }\n\n /**\n * @notice Returns the full token config struct\n * @param tokenID String input of the token ID for the token\n * @param chainID Chain ID of which token address + config to get\n */\n function getTokenByID(string memory tokenID, uint256 chainID)\n public\n view\n returns (Token memory token)\n {\n return _tokens[toBytes32(tokenID)][chainID];\n }\n\n /**\n * @notice Returns token config struct, given an address and chainID\n * @param tokenAddress Matches the token ID by using a combo of address + chain ID\n * @param chainID Chain ID of which token to get config for\n */\n function getTokenByAddress(string memory tokenAddress, uint256 chainID)\n public\n view\n returns (Token memory token)\n {\n return _tokens[_tokenIDMap[chainID][_toLower(tokenAddress)]][chainID];\n }\n\n function getTokenByEVMAddress(address tokenAddress, uint256 chainID)\n public\n view\n returns (Token memory token)\n {\n return\n _tokens[_tokenIDMap[chainID][_toLower(toString(tokenAddress))]][\n chainID\n ];\n }\n\n /**\n * @notice Returns true if the token has an underlying token -- meaning the token is deposited into the bridge\n * @param tokenID String to check if it is a withdraw/underlying token\n */\n function hasUnderlyingToken(string memory tokenID)\n public\n view\n returns (bool)\n {\n bytes32 bytesTokenID = toBytes32(tokenID);\n Token[] memory _mcTokens = _allTokens[bytesTokenID];\n for (uint256 i = 0; i < _mcTokens.length; ++i) {\n if (_mcTokens[i].hasUnderlying) {\n return true;\n }\n }\n return false;\n }\n\n /**\n * @notice Returns which token is the underlying token to withdraw\n * @param tokenID string token ID\n */\n function getUnderlyingToken(string memory tokenID)\n public\n view\n returns (Token memory token)\n {\n bytes32 bytesTokenID = toBytes32(tokenID);\n Token[] memory _mcTokens = _allTokens[bytesTokenID];\n for (uint256 i = 0; i < _mcTokens.length; ++i) {\n if (_mcTokens[i].isUnderlying) {\n return _mcTokens[i];\n }\n }\n }\n\n /**\n @notice Public function returning if token ID exists given a string\n */\n function isTokenIDExist(string memory tokenID) public view returns (bool) {\n return _isTokenIDExist(toBytes32(tokenID));\n }\n\n /**\n @notice Internal function returning if token ID exists given bytes32 version of the ID\n */\n function _isTokenIDExist(bytes32 tokenID) internal view returns (bool) {\n for (uint256 i = 0; i < _allTokenIDs.length; ++i) {\n if (_allTokenIDs[i] == tokenID) {\n return true;\n }\n }\n return false;\n }\n\n /**\n * @notice Internal function which handles logic of setting token ID and dealing with mappings\n * @param tokenID bytes32 version of ID\n * @param chainID which chain to set the token config for\n * @param tokenToAdd Token object to set the mapping to\n */\n function _setTokenConfig(\n bytes32 tokenID,\n uint256 chainID,\n Token memory tokenToAdd\n ) internal returns (bool) {\n _tokens[tokenID][chainID] = tokenToAdd;\n if (!_isTokenIDExist(tokenID)) {\n _allTokenIDs.push(tokenID);\n }\n\n Token[] storage _mcTokens = _allTokens[tokenID];\n for (uint256 i = 0; i < _mcTokens.length; ++i) {\n if (_mcTokens[i].chainId == chainID) {\n string memory oldToken = _mcTokens[i].tokenAddress;\n if (!compareStrings(tokenToAdd.tokenAddress, oldToken)) {\n _mcTokens[i].tokenAddress = tokenToAdd.tokenAddress;\n _tokenIDMap[chainID][oldToken] = keccak256(\"\");\n _tokenIDMap[chainID][tokenToAdd.tokenAddress] = tokenID;\n }\n }\n }\n _mcTokens.push(tokenToAdd);\n _tokenIDMap[chainID][tokenToAdd.tokenAddress] = tokenID;\n return true;\n }\n\n /**\n * @notice Main write function of this contract - Handles creating the struct and passing it to the internal logic function\n * @param tokenID string ID to set the token config object form\n * @param chainID chain ID to use for the token config object\n * @param tokenAddress token address of the token on the given chain\n * @param tokenDecimals decimals of token\n * @param maxSwap maximum amount of token allowed to be transferred at once - in native token decimals\n * @param minSwap minimum amount of token needed to be transferred at once - in native token decimals\n * @param swapFee percent based swap fee -- 10e6 == 10bps\n * @param maxSwapFee max swap fee to be charged - in native token decimals\n * @param minSwapFee min swap fee to be charged - in native token decimals - especially useful for mainnet ETH\n * @param hasUnderlying bool which represents whether this is a global mint token or one to withdraw()\n * @param isUnderlying bool which represents if this token is the one to withdraw on the given chain\n */\n function setTokenConfig(\n string calldata tokenID,\n uint256 chainID,\n address tokenAddress,\n uint8 tokenDecimals,\n uint256 maxSwap,\n uint256 minSwap,\n uint256 swapFee,\n uint256 maxSwapFee,\n uint256 minSwapFee,\n bool hasUnderlying,\n bool isUnderlying\n ) public returns (bool) {\n require(hasRole(BRIDGEMANAGER_ROLE, msg.sender));\n return\n setTokenConfig(\n tokenID,\n chainID,\n toString(tokenAddress),\n tokenDecimals,\n maxSwap,\n minSwap,\n swapFee,\n maxSwapFee,\n minSwapFee,\n hasUnderlying,\n isUnderlying\n );\n }\n\n /**\n * @notice Main write function of this contract - Handles creating the struct and passing it to the internal logic function\n * @param tokenID string ID to set the token config object form\n * @param chainID chain ID to use for the token config object\n * @param tokenAddress token address of the token on the given chain\n * @param tokenDecimals decimals of token\n * @param maxSwap maximum amount of token allowed to be transferred at once - in native token decimals\n * @param minSwap minimum amount of token needed to be transferred at once - in native token decimals\n * @param swapFee percent based swap fee -- 10e6 == 10bps\n * @param maxSwapFee max swap fee to be charged - in native token decimals\n * @param minSwapFee min swap fee to be charged - in native token decimals - especially useful for mainnet ETH\n * @param hasUnderlying bool which represents whether this is a global mint token or one to withdraw()\n * @param isUnderlying bool which represents if this token is the one to withdraw on the given chain\n */\n function setTokenConfig(\n string calldata tokenID,\n uint256 chainID,\n string memory tokenAddress,\n uint8 tokenDecimals,\n uint256 maxSwap,\n uint256 minSwap,\n uint256 swapFee,\n uint256 maxSwapFee,\n uint256 minSwapFee,\n bool hasUnderlying,\n bool isUnderlying\n ) public returns (bool) {\n require(hasRole(BRIDGEMANAGER_ROLE, msg.sender));\n Token memory tokenToAdd;\n tokenToAdd.tokenAddress = _toLower(tokenAddress);\n tokenToAdd.tokenDecimals = tokenDecimals;\n tokenToAdd.maxSwap = maxSwap;\n tokenToAdd.minSwap = minSwap;\n tokenToAdd.swapFee = swapFee;\n tokenToAdd.maxSwapFee = maxSwapFee;\n tokenToAdd.minSwapFee = minSwapFee;\n tokenToAdd.hasUnderlying = hasUnderlying;\n tokenToAdd.isUnderlying = isUnderlying;\n tokenToAdd.chainId = chainID;\n\n return _setTokenConfig(toBytes32(tokenID), chainID, tokenToAdd);\n }\n\n function _calculateSwapFee(\n string memory tokenAddress,\n uint256 chainID,\n uint256 amount\n ) internal view returns (uint256) {\n Token memory token = _tokens[_tokenIDMap[chainID][tokenAddress]][\n chainID\n ];\n uint256 calculatedSwapFee = amount.mul(token.swapFee).div(\n FEE_DENOMINATOR\n );\n if (\n calculatedSwapFee > token.minSwapFee &&\n calculatedSwapFee < token.maxSwapFee\n ) {\n return calculatedSwapFee;\n } else if (calculatedSwapFee > token.maxSwapFee) {\n return token.maxSwapFee;\n } else {\n return token.minSwapFee;\n }\n }\n\n /**\n * @notice Calculates bridge swap fee based on the destination chain's token transfer.\n * @dev This means the fee should be calculated based on the chain that the nodes emit a tx on\n * @param tokenAddress address of the destination token to query token config for\n * @param chainID destination chain ID to query the token config for\n * @param amount in native token decimals\n * @return Fee calculated in token decimals\n */\n function calculateSwapFee(\n string memory tokenAddress,\n uint256 chainID,\n uint256 amount\n ) external view returns (uint256) {\n return _calculateSwapFee(_toLower(tokenAddress), chainID, amount);\n }\n\n /**\n * @notice Calculates bridge swap fee based on the destination chain's token transfer.\n * @dev This means the fee should be calculated based on the chain that the nodes emit a tx on\n * @param tokenAddress address of the destination token to query token config for\n * @param chainID destination chain ID to query the token config for\n * @param amount in native token decimals\n * @return Fee calculated in token decimals\n */\n function calculateSwapFee(\n address tokenAddress,\n uint256 chainID,\n uint256 amount\n ) external view returns (uint256) {\n return\n _calculateSwapFee(\n _toLower(toString(tokenAddress)),\n chainID,\n amount\n );\n }\n\n // GAS PRICING\n\n /**\n * @notice sets the max gas price for a chain\n */\n function setMaxGasPrice(uint256 chainID, uint256 maxPrice) public {\n require(hasRole(BRIDGEMANAGER_ROLE, msg.sender));\n _maxGasPrice[chainID] = maxPrice;\n }\n\n /**\n * @notice gets the max gas price for a chain\n */\n function getMaxGasPrice(uint256 chainID) public view returns (uint256) {\n return _maxGasPrice[chainID];\n }\n\n // POOL CONFIG\n\n function getPoolConfig(address tokenAddress, uint256 chainID)\n external\n view\n returns (Pool memory)\n {\n return _pool[tokenAddress][chainID];\n }\n\n function setPoolConfig(\n address tokenAddress,\n uint256 chainID,\n address poolAddress,\n bool metaswap\n ) external returns (Pool memory) {\n require(\n hasRole(BRIDGEMANAGER_ROLE, msg.sender),\n \"Caller is not Bridge Manager\"\n );\n Pool memory newPool = Pool(\n tokenAddress,\n chainID,\n poolAddress,\n metaswap\n );\n _pool[tokenAddress][chainID] = newPool;\n return newPool;\n }\n\n // UTILITY FUNCTIONS\n\n function toString(bytes32 data) internal pure returns (string memory) {\n uint8 i = 0;\n while (i < 32 && data[i] != 0) {\n ++i;\n }\n bytes memory bs = new bytes(i);\n for (uint8 j = 0; j < i; ++j) {\n bs[j] = data[j];\n }\n return string(bs);\n }\n\n // toBytes32 converts a string to a bytes 32\n function toBytes32(string memory str)\n internal\n pure\n returns (bytes32 result)\n {\n require(bytes(str).length <= 32);\n assembly {\n result := mload(add(str, 32))\n }\n }\n\n function toString(address x) internal pure returns (string memory) {\n bytes memory s = new bytes(40);\n for (uint256 i = 0; i < 20; i++) {\n bytes1 b = bytes1(uint8(uint256(uint160(x)) / (2**(8 * (19 - i)))));\n bytes1 hi = bytes1(uint8(b) / 16);\n bytes1 lo = bytes1(uint8(b) - 16 * uint8(hi));\n s[2 * i] = char(hi);\n s[2 * i + 1] = char(lo);\n }\n\n string memory addrPrefix = \"0x\";\n\n return concat(addrPrefix, string(s));\n }\n\n function concat(string memory _x, string memory _y)\n internal\n pure\n returns (string memory)\n {\n bytes memory _xBytes = bytes(_x);\n bytes memory _yBytes = bytes(_y);\n\n string memory _tmpValue = new string(_xBytes.length + _yBytes.length);\n bytes memory _newValue = bytes(_tmpValue);\n\n uint256 i;\n uint256 j;\n\n for (i = 0; i < _xBytes.length; i++) {\n _newValue[j++] = _xBytes[i];\n }\n\n for (i = 0; i < _yBytes.length; i++) {\n _newValue[j++] = _yBytes[i];\n }\n\n return string(_newValue);\n }\n\n function char(bytes1 b) internal pure returns (bytes1 c) {\n if (uint8(b) < 10) {\n c = bytes1(uint8(b) + 0x30);\n } else {\n c = bytes1(uint8(b) + 0x57);\n }\n }\n\n function compareStrings(string memory a, string memory b)\n internal\n pure\n returns (bool)\n {\n return (keccak256(abi.encodePacked((a))) ==\n keccak256(abi.encodePacked((b))));\n }\n\n function _toLower(string memory str) internal pure returns (string memory) {\n bytes memory bStr = bytes(str);\n bytes memory bLower = new bytes(bStr.length);\n for (uint256 i = 0; i < bStr.length; i++) {\n // Uppercase character...\n if ((uint8(bStr[i]) >= 65) && (uint8(bStr[i]) <= 90)) {\n // So we add 32 to make it lowercase\n bLower[i] = bytes1(uint8(bStr[i]) + 32);\n } else {\n bLower[i] = bStr[i];\n }\n }\n return string(bLower);\n }\n}\n" + }, + "contracts/bridge/wrappers/GMXWrapper.sol": { + "content": "// SPDX-License-Identifier: MIT\n\nimport '@openzeppelin/contracts/math/SafeMath.sol';\n\npragma solidity 0.6.12;\n\ninterface IGMX {\n function burn(address _account, uint256 _amount) external;\n function balanceOf(address account) external view returns (uint256);\n function mint(address _account, uint256 _amount) external;\n}\n\ncontract GMXWrapper {\n using SafeMath for uint256;\n\n address constant public gmx = 0x62edc0692BD897D2295872a9FFCac5425011c661;\n address constant public bridge = 0xC05e61d0E7a63D27546389B7aD62FdFf5A91aACE;\n\n function transfer(address _recipient, uint256 _amount) external returns (bool) {\n require(msg.sender == bridge);\n _transfer(msg.sender, _recipient, _amount);\n return true;\n }\n\n function _transfer(address _sender, address _recipient, uint256 _amount) private {\n require(_sender != address(0), \"BaseToken: transfer from the zero address\");\n require(_recipient != address(0), \"BaseToken: transfer to the zero address\");\n IGMX(gmx).burn(_sender, _amount);\n IGMX(gmx).mint(_recipient, _amount);\n }\n\n function mint(address _addr, uint256 _amount) external {\n require(msg.sender == bridge);\n uint256 preMint = IGMX(gmx).balanceOf(_addr);\n IGMX(gmx).mint(_addr, _amount);\n uint256 postMint = IGMX(gmx).balanceOf(_addr);\n require(preMint.add(_amount) == postMint, \"Mint incomplete\");\n }\n\n function burnFrom(address _addr, uint256 _amount) external {\n require(msg.sender == bridge);\n uint256 preBurn = IGMX(gmx).balanceOf(_addr);\n IGMX(gmx).burn(_addr, _amount);\n uint256 postBurn = IGMX(gmx).balanceOf(_addr);\n require(postBurn.add(_amount) == preBurn, \"Burn incomplete\");\n }\n}" + } + }, + "settings": { + "optimizer": { + "enabled": true, + "runs": 10000 + }, + "outputSelection": { + "*": { + "*": [ + "abi", + "evm.bytecode", + "evm.deployedBytecode", + "evm.methodIdentifiers", + "metadata", + "devdoc", + "userdoc", + "storageLayout", + "evm.gasEstimates", + "devdoc", + "userdoc" + ], + "": [ + "ast" + ] + } + }, + "metadata": { + "useLiteralContent": true + } + } +} \ No newline at end of file diff --git a/deployments/dfk/solcInputs/d9ddc44152056b9c2865111aa614cbcf.json b/deployments/dfk/solcInputs/d9ddc44152056b9c2865111aa614cbcf.json new file mode 100644 index 000000000..9265701b0 --- /dev/null +++ b/deployments/dfk/solcInputs/d9ddc44152056b9c2865111aa614cbcf.json @@ -0,0 +1,302 @@ +{ + "language": "Solidity", + "sources": { + "contracts/amm/AaveSwap.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.6.12;\n\nimport \"./Swap.sol\";\n\n/**\n * @title AaveSwap - A StableSwap implementation in solidity, integrated with Aave.\n * @notice This contract is responsible for custody of closely pegged assets (eg. group of stablecoins)\n * and automatic market making system. Users become an LP (Liquidity Provider) by depositing their tokens\n * in desired ratios for an exchange of the pool token that represents their share of the pool.\n * Users can burn pool tokens and withdraw their share of token(s).\n *\n * Each time a swap between the pooled tokens happens, a set fee incurs which effectively gets\n * distributed to the LPs.\n *\n * In case of emergencies, admin can pause additional deposits, swaps, or single-asset withdraws - which\n * stops the ratio of the tokens in the pool from changing.\n * Users can always withdraw their tokens via multi-asset withdraws.\n *\n * @dev Most of the logic is stored as a library `SwapUtils` for the sake of reducing contract's\n * deployment size.\n */\n\ncontract AaveSwap is Swap {\n address internal AAVE_REWARDS;\n address internal AAVE_LENDING_POOL;\n address internal REWARD_TOKEN;\n address internal REWARD_RECEIVER;\n address[] internal AAVE_ASSETS;\n\n /**\n * @notice Initializes this Swap contract with the given parameters.\n * This will also clone a LPToken contract that represents users'\n * LP positions. The owner of LPToken will be this contract - which means\n * only this contract is allowed to mint/burn tokens.\n *\n * @param _pooledTokens an array of ERC20s this pool will accept\n * @param decimals the decimals to use for each pooled token,\n * eg 8 for WBTC. Cannot be larger than POOL_PRECISION_DECIMALS\n * @param lpTokenName the long-form name of the token to be deployed\n * @param lpTokenSymbol the short symbol for the token to be deployed\n * @param _a the amplification coefficient * n * (n - 1). See the\n * StableSwap paper for details\n * @param _fee default swap fee to be initialized with\n * @param _adminFee default adminFee to be initialized with\n * @param lpTokenTargetAddress the address of an existing LPToken contract to use as a target\n */\n function initialize(\n IERC20[] memory _pooledTokens,\n uint8[] memory decimals,\n string memory lpTokenName,\n string memory lpTokenSymbol,\n uint256 _a,\n uint256 _fee,\n uint256 _adminFee,\n address lpTokenTargetAddress\n ) public virtual override initializer {\n Swap.initialize(\n _pooledTokens,\n decimals,\n lpTokenName,\n lpTokenSymbol,\n _a,\n _fee,\n _adminFee,\n lpTokenTargetAddress\n );\n AAVE_REWARDS = 0x01D83Fe6A10D2f2B7AF17034343746188272cAc9;\n AAVE_LENDING_POOL = 0x4F01AeD16D97E3aB5ab2B501154DC9bb0F1A5A2C;\n REWARD_TOKEN = 0xB31f66AA3C1e785363F0875A1B74E27b85FD66c7;\n AAVE_ASSETS = [0x53f7c5869a859F0AeC3D334ee8B4Cf01E3492f21];\n REWARD_RECEIVER = msg.sender;\n }\n\n function setRewardReceiver(address _reward_receiver) external onlyOwner {\n REWARD_RECEIVER = _reward_receiver;\n }\n\n function claimAaveRewards() external {\n AAVE_REWARDS.call(\n abi.encodeWithSignature(\n \"claimRewards(address[],uint256,address)\",\n AAVE_ASSETS,\n type(uint256).max,\n REWARD_RECEIVER\n )\n );\n }\n}\n" + }, + "contracts/amm/Swap.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.6.12;\n\nimport \"@openzeppelin/contracts/math/SafeMath.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/SafeERC20.sol\";\nimport \"@openzeppelin/contracts/proxy/Clones.sol\";\nimport \"@openzeppelin/contracts-upgradeable/utils/ReentrancyGuardUpgradeable.sol\";\nimport \"./OwnerPausableUpgradeable.sol\";\nimport \"./SwapUtils.sol\";\nimport \"./AmplificationUtils.sol\";\n\n/**\n * @title Swap - A StableSwap implementation in solidity.\n * @notice This contract is responsible for custody of closely pegged assets (eg. group of stablecoins)\n * and automatic market making system. Users become an LP (Liquidity Provider) by depositing their tokens\n * in desired ratios for an exchange of the pool token that represents their share of the pool.\n * Users can burn pool tokens and withdraw their share of token(s).\n *\n * Each time a swap between the pooled tokens happens, a set fee incurs which effectively gets\n * distributed to the LPs.\n *\n * In case of emergencies, admin can pause additional deposits, swaps, or single-asset withdraws - which\n * stops the ratio of the tokens in the pool from changing.\n * Users can always withdraw their tokens via multi-asset withdraws.\n *\n * @dev Most of the logic is stored as a library `SwapUtils` for the sake of reducing contract's\n * deployment size.\n */\ncontract Swap is OwnerPausableUpgradeable, ReentrancyGuardUpgradeable {\n using SafeERC20 for IERC20;\n using SafeMath for uint256;\n using SwapUtils for SwapUtils.Swap;\n using AmplificationUtils for SwapUtils.Swap;\n\n // Struct storing data responsible for automatic market maker functionalities. In order to\n // access this data, this contract uses SwapUtils library. For more details, see SwapUtils.sol\n SwapUtils.Swap public swapStorage;\n\n // Maps token address to an index in the pool. Used to prevent duplicate tokens in the pool.\n // getTokenIndex function also relies on this mapping to retrieve token index.\n mapping(address => uint8) private tokenIndexes;\n\n /*** EVENTS ***/\n\n // events replicated from SwapUtils to make the ABI easier for dumb\n // clients\n event TokenSwap(\n address indexed buyer,\n uint256 tokensSold,\n uint256 tokensBought,\n uint128 soldId,\n uint128 boughtId\n );\n event AddLiquidity(\n address indexed provider,\n uint256[] tokenAmounts,\n uint256[] fees,\n uint256 invariant,\n uint256 lpTokenSupply\n );\n event RemoveLiquidity(\n address indexed provider,\n uint256[] tokenAmounts,\n uint256 lpTokenSupply\n );\n event RemoveLiquidityOne(\n address indexed provider,\n uint256 lpTokenAmount,\n uint256 lpTokenSupply,\n uint256 boughtId,\n uint256 tokensBought\n );\n event RemoveLiquidityImbalance(\n address indexed provider,\n uint256[] tokenAmounts,\n uint256[] fees,\n uint256 invariant,\n uint256 lpTokenSupply\n );\n event NewAdminFee(uint256 newAdminFee);\n event NewSwapFee(uint256 newSwapFee);\n event RampA(\n uint256 oldA,\n uint256 newA,\n uint256 initialTime,\n uint256 futureTime\n );\n event StopRampA(uint256 currentA, uint256 time);\n\n /**\n * @notice Initializes this Swap contract with the given parameters.\n * This will also clone a LPToken contract that represents users'\n * LP positions. The owner of LPToken will be this contract - which means\n * only this contract is allowed to mint/burn tokens.\n *\n * @param _pooledTokens an array of ERC20s this pool will accept\n * @param decimals the decimals to use for each pooled token,\n * eg 8 for WBTC. Cannot be larger than POOL_PRECISION_DECIMALS\n * @param lpTokenName the long-form name of the token to be deployed\n * @param lpTokenSymbol the short symbol for the token to be deployed\n * @param _a the amplification coefficient * n * (n - 1). See the\n * StableSwap paper for details\n * @param _fee default swap fee to be initialized with\n * @param _adminFee default adminFee to be initialized with\n * @param lpTokenTargetAddress the address of an existing LPToken contract to use as a target\n */\n function initialize(\n IERC20[] memory _pooledTokens,\n uint8[] memory decimals,\n string memory lpTokenName,\n string memory lpTokenSymbol,\n uint256 _a,\n uint256 _fee,\n uint256 _adminFee,\n address lpTokenTargetAddress\n ) public virtual initializer {\n __OwnerPausable_init();\n __ReentrancyGuard_init();\n // Check _pooledTokens and precisions parameter\n require(_pooledTokens.length > 1, \"_pooledTokens.length <= 1\");\n require(_pooledTokens.length <= 32, \"_pooledTokens.length > 32\");\n require(\n _pooledTokens.length == decimals.length,\n \"_pooledTokens decimals mismatch\"\n );\n\n uint256[] memory precisionMultipliers = new uint256[](decimals.length);\n\n for (uint8 i = 0; i < _pooledTokens.length; i++) {\n if (i > 0) {\n // Check if index is already used. Check if 0th element is a duplicate.\n require(\n tokenIndexes[address(_pooledTokens[i])] == 0 &&\n _pooledTokens[0] != _pooledTokens[i],\n \"Duplicate tokens\"\n );\n }\n require(\n address(_pooledTokens[i]) != address(0),\n \"The 0 address isn't an ERC-20\"\n );\n require(\n decimals[i] <= SwapUtils.POOL_PRECISION_DECIMALS,\n \"Token decimals exceeds max\"\n );\n precisionMultipliers[i] =\n 10 **\n uint256(SwapUtils.POOL_PRECISION_DECIMALS).sub(\n uint256(decimals[i])\n );\n tokenIndexes[address(_pooledTokens[i])] = i;\n }\n\n // Check _a, _fee, _adminFee parameters\n require(_a < AmplificationUtils.MAX_A, \"_a exceeds maximum\");\n require(_fee < SwapUtils.MAX_SWAP_FEE, \"_fee exceeds maximum\");\n require(\n _adminFee < SwapUtils.MAX_ADMIN_FEE,\n \"_adminFee exceeds maximum\"\n );\n\n // Clone and initialize a LPToken contract\n LPToken lpToken = LPToken(Clones.clone(lpTokenTargetAddress));\n require(\n lpToken.initialize(lpTokenName, lpTokenSymbol),\n \"could not init lpToken clone\"\n );\n\n // Initialize swapStorage struct\n swapStorage.lpToken = lpToken;\n swapStorage.pooledTokens = _pooledTokens;\n swapStorage.tokenPrecisionMultipliers = precisionMultipliers;\n swapStorage.balances = new uint256[](_pooledTokens.length);\n swapStorage.initialA = _a.mul(AmplificationUtils.A_PRECISION);\n swapStorage.futureA = _a.mul(AmplificationUtils.A_PRECISION);\n // swapStorage.initialATime = 0;\n // swapStorage.futureATime = 0;\n swapStorage.swapFee = _fee;\n swapStorage.adminFee = _adminFee;\n }\n\n /*** MODIFIERS ***/\n\n /**\n * @notice Modifier to check deadline against current timestamp\n * @param deadline latest timestamp to accept this transaction\n */\n modifier deadlineCheck(uint256 deadline) {\n require(block.timestamp <= deadline, \"Deadline not met\");\n _;\n }\n\n /*** VIEW FUNCTIONS ***/\n\n /**\n * @notice Return A, the amplification coefficient * n * (n - 1)\n * @dev See the StableSwap paper for details\n * @return A parameter\n */\n function getA() external view virtual returns (uint256) {\n return swapStorage.getA();\n }\n\n /**\n * @notice Return A in its raw precision form\n * @dev See the StableSwap paper for details\n * @return A parameter in its raw precision form\n */\n function getAPrecise() external view virtual returns (uint256) {\n return swapStorage.getAPrecise();\n }\n\n /**\n * @notice Return address of the pooled token at given index. Reverts if tokenIndex is out of range.\n * @param index the index of the token\n * @return address of the token at given index\n */\n function getToken(uint8 index) public view virtual returns (IERC20) {\n require(index < swapStorage.pooledTokens.length, \"Out of range\");\n return swapStorage.pooledTokens[index];\n }\n\n /**\n * @notice Return the index of the given token address. Reverts if no matching\n * token is found.\n * @param tokenAddress address of the token\n * @return the index of the given token address\n */\n function getTokenIndex(address tokenAddress)\n public\n view\n virtual\n returns (uint8)\n {\n uint8 index = tokenIndexes[tokenAddress];\n require(\n address(getToken(index)) == tokenAddress,\n \"Token does not exist\"\n );\n return index;\n }\n\n /**\n * @notice Return current balance of the pooled token at given index\n * @param index the index of the token\n * @return current balance of the pooled token at given index with token's native precision\n */\n function getTokenBalance(uint8 index)\n external\n view\n virtual\n returns (uint256)\n {\n require(index < swapStorage.pooledTokens.length, \"Index out of range\");\n return swapStorage.balances[index];\n }\n\n /**\n * @notice Get the virtual price, to help calculate profit\n * @return the virtual price, scaled to the POOL_PRECISION_DECIMALS\n */\n function getVirtualPrice() external view virtual returns (uint256) {\n return swapStorage.getVirtualPrice();\n }\n\n /**\n * @notice Calculate amount of tokens you receive on swap\n * @param tokenIndexFrom the token the user wants to sell\n * @param tokenIndexTo the token the user wants to buy\n * @param dx the amount of tokens the user wants to sell. If the token charges\n * a fee on transfers, use the amount that gets transferred after the fee.\n * @return amount of tokens the user will receive\n */\n function calculateSwap(\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx\n ) external view virtual returns (uint256) {\n return swapStorage.calculateSwap(tokenIndexFrom, tokenIndexTo, dx);\n }\n\n /**\n * @notice A simple method to calculate prices from deposits or\n * withdrawals, excluding fees but including slippage. This is\n * helpful as an input into the various \"min\" parameters on calls\n * to fight front-running\n *\n * @dev This shouldn't be used outside frontends for user estimates.\n *\n * @param amounts an array of token amounts to deposit or withdrawal,\n * corresponding to pooledTokens. The amount should be in each\n * pooled token's native precision. If a token charges a fee on transfers,\n * use the amount that gets transferred after the fee.\n * @param deposit whether this is a deposit or a withdrawal\n * @return token amount the user will receive\n */\n function calculateTokenAmount(uint256[] calldata amounts, bool deposit)\n external\n view\n virtual\n returns (uint256)\n {\n return swapStorage.calculateTokenAmount(amounts, deposit);\n }\n\n /**\n * @notice A simple method to calculate amount of each underlying\n * tokens that is returned upon burning given amount of LP tokens\n * @param amount the amount of LP tokens that would be burned on withdrawal\n * @return array of token balances that the user will receive\n */\n function calculateRemoveLiquidity(uint256 amount)\n external\n view\n virtual\n returns (uint256[] memory)\n {\n return swapStorage.calculateRemoveLiquidity(amount);\n }\n\n /**\n * @notice Calculate the amount of underlying token available to withdraw\n * when withdrawing via only single token\n * @param tokenAmount the amount of LP token to burn\n * @param tokenIndex index of which token will be withdrawn\n * @return availableTokenAmount calculated amount of underlying token\n * available to withdraw\n */\n function calculateRemoveLiquidityOneToken(\n uint256 tokenAmount,\n uint8 tokenIndex\n ) external view virtual returns (uint256 availableTokenAmount) {\n return swapStorage.calculateWithdrawOneToken(tokenAmount, tokenIndex);\n }\n\n /**\n * @notice This function reads the accumulated amount of admin fees of the token with given index\n * @param index Index of the pooled token\n * @return admin's token balance in the token's precision\n */\n function getAdminBalance(uint256 index)\n external\n view\n virtual\n returns (uint256)\n {\n return swapStorage.getAdminBalance(index);\n }\n\n /*** STATE MODIFYING FUNCTIONS ***/\n\n /**\n * @notice Swap two tokens using this pool\n * @param tokenIndexFrom the token the user wants to swap from\n * @param tokenIndexTo the token the user wants to swap to\n * @param dx the amount of tokens the user wants to swap from\n * @param minDy the min amount the user would like to receive, or revert.\n * @param deadline latest timestamp to accept this transaction\n */\n function swap(\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx,\n uint256 minDy,\n uint256 deadline\n )\n external\n virtual\n nonReentrant\n whenNotPaused\n deadlineCheck(deadline)\n returns (uint256)\n {\n return swapStorage.swap(tokenIndexFrom, tokenIndexTo, dx, minDy);\n }\n\n /**\n * @notice Add liquidity to the pool with the given amounts of tokens\n * @param amounts the amounts of each token to add, in their native precision\n * @param minToMint the minimum LP tokens adding this amount of liquidity\n * should mint, otherwise revert. Handy for front-running mitigation\n * @param deadline latest timestamp to accept this transaction\n * @return amount of LP token user minted and received\n */\n function addLiquidity(\n uint256[] calldata amounts,\n uint256 minToMint,\n uint256 deadline\n )\n external\n virtual\n nonReentrant\n whenNotPaused\n deadlineCheck(deadline)\n returns (uint256)\n {\n return swapStorage.addLiquidity(amounts, minToMint);\n }\n\n /**\n * @notice Burn LP tokens to remove liquidity from the pool. Withdraw fee that decays linearly\n * over period of 4 weeks since last deposit will apply.\n * @dev Liquidity can always be removed, even when the pool is paused.\n * @param amount the amount of LP tokens to burn\n * @param minAmounts the minimum amounts of each token in the pool\n * acceptable for this burn. Useful as a front-running mitigation\n * @param deadline latest timestamp to accept this transaction\n * @return amounts of tokens user received\n */\n function removeLiquidity(\n uint256 amount,\n uint256[] calldata minAmounts,\n uint256 deadline\n )\n external\n virtual\n nonReentrant\n deadlineCheck(deadline)\n returns (uint256[] memory)\n {\n return swapStorage.removeLiquidity(amount, minAmounts);\n }\n\n /**\n * @notice Remove liquidity from the pool all in one token. Withdraw fee that decays linearly\n * over period of 4 weeks since last deposit will apply.\n * @param tokenAmount the amount of the token you want to receive\n * @param tokenIndex the index of the token you want to receive\n * @param minAmount the minimum amount to withdraw, otherwise revert\n * @param deadline latest timestamp to accept this transaction\n * @return amount of chosen token user received\n */\n function removeLiquidityOneToken(\n uint256 tokenAmount,\n uint8 tokenIndex,\n uint256 minAmount,\n uint256 deadline\n )\n external\n virtual\n nonReentrant\n whenNotPaused\n deadlineCheck(deadline)\n returns (uint256)\n {\n return\n swapStorage.removeLiquidityOneToken(\n tokenAmount,\n tokenIndex,\n minAmount\n );\n }\n\n /**\n * @notice Remove liquidity from the pool, weighted differently than the\n * pool's current balances. Withdraw fee that decays linearly\n * over period of 4 weeks since last deposit will apply.\n * @param amounts how much of each token to withdraw\n * @param maxBurnAmount the max LP token provider is willing to pay to\n * remove liquidity. Useful as a front-running mitigation.\n * @param deadline latest timestamp to accept this transaction\n * @return amount of LP tokens burned\n */\n function removeLiquidityImbalance(\n uint256[] calldata amounts,\n uint256 maxBurnAmount,\n uint256 deadline\n )\n external\n virtual\n nonReentrant\n whenNotPaused\n deadlineCheck(deadline)\n returns (uint256)\n {\n return swapStorage.removeLiquidityImbalance(amounts, maxBurnAmount);\n }\n\n /*** ADMIN FUNCTIONS ***/\n\n /**\n * @notice Withdraw all admin fees to the contract owner\n */\n function withdrawAdminFees() external onlyOwner {\n swapStorage.withdrawAdminFees(owner());\n }\n\n /**\n * @notice Update the admin fee. Admin fee takes portion of the swap fee.\n * @param newAdminFee new admin fee to be applied on future transactions\n */\n function setAdminFee(uint256 newAdminFee) external onlyOwner {\n swapStorage.setAdminFee(newAdminFee);\n }\n\n /**\n * @notice Update the swap fee to be applied on swaps\n * @param newSwapFee new swap fee to be applied on future transactions\n */\n function setSwapFee(uint256 newSwapFee) external onlyOwner {\n swapStorage.setSwapFee(newSwapFee);\n }\n\n /**\n * @notice Start ramping up or down A parameter towards given futureA and futureTime\n * Checks if the change is too rapid, and commits the new A value only when it falls under\n * the limit range.\n * @param futureA the new A to ramp towards\n * @param futureTime timestamp when the new A should be reached\n */\n function rampA(uint256 futureA, uint256 futureTime) external onlyOwner {\n swapStorage.rampA(futureA, futureTime);\n }\n\n /**\n * @notice Stop ramping A immediately. Reverts if ramp A is already stopped.\n */\n function stopRampA() external onlyOwner {\n swapStorage.stopRampA();\n }\n}\n" + }, + "@openzeppelin/contracts/math/SafeMath.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <0.8.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" + }, + "@openzeppelin/contracts/token/ERC20/SafeERC20.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <0.8.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" + }, + "@openzeppelin/contracts/proxy/Clones.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <0.8.0;\n\n/**\n * @dev https://eips.ethereum.org/EIPS/eip-1167[EIP 1167] is a standard for\n * deploying minimal proxy contracts, also known as \"clones\".\n *\n * > To simply and cheaply clone contract functionality in an immutable way, this standard specifies\n * > a minimal bytecode implementation that delegates all calls to a known, fixed address.\n *\n * The library includes functions to deploy a proxy using either `create` (traditional deployment) or `create2`\n * (salted deterministic deployment). It also includes functions to predict the addresses of clones deployed using the\n * deterministic method.\n *\n * _Available since v3.4._\n */\nlibrary Clones {\n /**\n * @dev Deploys and returns the address of a clone that mimics the behaviour of `master`.\n *\n * This function uses the create opcode, which should never revert.\n */\n function clone(address master) internal returns (address instance) {\n // solhint-disable-next-line no-inline-assembly\n assembly {\n let ptr := mload(0x40)\n mstore(ptr, 0x3d602d80600a3d3981f3363d3d373d3d3d363d73000000000000000000000000)\n mstore(add(ptr, 0x14), shl(0x60, master))\n mstore(add(ptr, 0x28), 0x5af43d82803e903d91602b57fd5bf30000000000000000000000000000000000)\n instance := create(0, ptr, 0x37)\n }\n require(instance != address(0), \"ERC1167: create failed\");\n }\n\n /**\n * @dev Deploys and returns the address of a clone that mimics the behaviour of `master`.\n *\n * This function uses the create2 opcode and a `salt` to deterministically deploy\n * the clone. Using the same `master` and `salt` multiple time will revert, since\n * the clones cannot be deployed twice at the same address.\n */\n function cloneDeterministic(address master, bytes32 salt) internal returns (address instance) {\n // solhint-disable-next-line no-inline-assembly\n assembly {\n let ptr := mload(0x40)\n mstore(ptr, 0x3d602d80600a3d3981f3363d3d373d3d3d363d73000000000000000000000000)\n mstore(add(ptr, 0x14), shl(0x60, master))\n mstore(add(ptr, 0x28), 0x5af43d82803e903d91602b57fd5bf30000000000000000000000000000000000)\n instance := create2(0, ptr, 0x37, salt)\n }\n require(instance != address(0), \"ERC1167: create2 failed\");\n }\n\n /**\n * @dev Computes the address of a clone deployed using {Clones-cloneDeterministic}.\n */\n function predictDeterministicAddress(address master, bytes32 salt, address deployer) internal pure returns (address predicted) {\n // solhint-disable-next-line no-inline-assembly\n assembly {\n let ptr := mload(0x40)\n mstore(ptr, 0x3d602d80600a3d3981f3363d3d373d3d3d363d73000000000000000000000000)\n mstore(add(ptr, 0x14), shl(0x60, master))\n mstore(add(ptr, 0x28), 0x5af43d82803e903d91602b57fd5bf3ff00000000000000000000000000000000)\n mstore(add(ptr, 0x38), shl(0x60, deployer))\n mstore(add(ptr, 0x4c), salt)\n mstore(add(ptr, 0x6c), keccak256(ptr, 0x37))\n predicted := keccak256(add(ptr, 0x37), 0x55)\n }\n }\n\n /**\n * @dev Computes the address of a clone deployed using {Clones-cloneDeterministic}.\n */\n function predictDeterministicAddress(address master, bytes32 salt) internal view returns (address predicted) {\n return predictDeterministicAddress(master, salt, address(this));\n }\n}\n" + }, + "@openzeppelin/contracts-upgradeable/utils/ReentrancyGuardUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <0.8.0;\nimport \"../proxy/Initializable.sol\";\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 ReentrancyGuardUpgradeable is Initializable {\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 function __ReentrancyGuard_init() internal initializer {\n __ReentrancyGuard_init_unchained();\n }\n\n function __ReentrancyGuard_init_unchained() internal initializer {\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 uint256[49] private __gap;\n}\n" + }, + "contracts/amm/OwnerPausableUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.6.12;\n\nimport \"@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol\";\nimport \"@openzeppelin/contracts-upgradeable/utils/PausableUpgradeable.sol\";\n\n/**\n * @title OwnerPausable\n * @notice An ownable contract allows the owner to pause and unpause the\n * contract without a delay.\n * @dev Only methods using the provided modifiers will be paused.\n */\nabstract contract OwnerPausableUpgradeable is\n OwnableUpgradeable,\n PausableUpgradeable\n{\n function __OwnerPausable_init() internal initializer {\n __Context_init_unchained();\n __Ownable_init_unchained();\n __Pausable_init_unchained();\n }\n\n /**\n * @notice Pause the contract. Revert if already paused.\n */\n function pause() external onlyOwner {\n PausableUpgradeable._pause();\n }\n\n /**\n * @notice Unpause the contract. Revert if already unpaused.\n */\n function unpause() external onlyOwner {\n PausableUpgradeable._unpause();\n }\n}\n" + }, + "contracts/amm/SwapUtils.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.6.12;\n\nimport \"@openzeppelin/contracts/math/SafeMath.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/SafeERC20.sol\";\nimport \"./AmplificationUtils.sol\";\nimport \"./LPToken.sol\";\nimport \"./MathUtils.sol\";\n\n/**\n * @title SwapUtils library\n * @notice A library to be used within Swap.sol. Contains functions responsible for custody and AMM functionalities.\n * @dev Contracts relying on this library must initialize SwapUtils.Swap struct then use this library\n * for SwapUtils.Swap struct. Note that this library contains both functions called by users and admins.\n * Admin functions should be protected within contracts using this library.\n */\nlibrary SwapUtils {\n using SafeERC20 for IERC20;\n using SafeMath for uint256;\n using MathUtils for uint256;\n\n /*** EVENTS ***/\n\n event TokenSwap(\n address indexed buyer,\n uint256 tokensSold,\n uint256 tokensBought,\n uint128 soldId,\n uint128 boughtId\n );\n event AddLiquidity(\n address indexed provider,\n uint256[] tokenAmounts,\n uint256[] fees,\n uint256 invariant,\n uint256 lpTokenSupply\n );\n event RemoveLiquidity(\n address indexed provider,\n uint256[] tokenAmounts,\n uint256 lpTokenSupply\n );\n event RemoveLiquidityOne(\n address indexed provider,\n uint256 lpTokenAmount,\n uint256 lpTokenSupply,\n uint256 boughtId,\n uint256 tokensBought\n );\n event RemoveLiquidityImbalance(\n address indexed provider,\n uint256[] tokenAmounts,\n uint256[] fees,\n uint256 invariant,\n uint256 lpTokenSupply\n );\n event NewAdminFee(uint256 newAdminFee);\n event NewSwapFee(uint256 newSwapFee);\n\n struct Swap {\n // variables around the ramp management of A,\n // the amplification coefficient * n * (n - 1)\n // see https://www.curve.fi/stableswap-paper.pdf for details\n uint256 initialA;\n uint256 futureA;\n uint256 initialATime;\n uint256 futureATime;\n // fee calculation\n uint256 swapFee;\n uint256 adminFee;\n LPToken lpToken;\n // contract references for all tokens being pooled\n IERC20[] pooledTokens;\n // multipliers for each pooled token's precision to get to POOL_PRECISION_DECIMALS\n // for example, TBTC has 18 decimals, so the multiplier should be 1. WBTC\n // has 8, so the multiplier should be 10 ** 18 / 10 ** 8 => 10 ** 10\n uint256[] tokenPrecisionMultipliers;\n // the pool balance of each token, in the token's precision\n // the contract's actual token balance might differ\n uint256[] balances;\n }\n\n // Struct storing variables used in calculations in the\n // calculateWithdrawOneTokenDY function to avoid stack too deep errors\n struct CalculateWithdrawOneTokenDYInfo {\n uint256 d0;\n uint256 d1;\n uint256 newY;\n uint256 feePerToken;\n uint256 preciseA;\n }\n\n // Struct storing variables used in calculations in the\n // {add,remove}Liquidity functions to avoid stack too deep errors\n struct ManageLiquidityInfo {\n uint256 d0;\n uint256 d1;\n uint256 d2;\n uint256 preciseA;\n LPToken lpToken;\n uint256 totalSupply;\n uint256[] balances;\n uint256[] multipliers;\n }\n\n // the precision all pools tokens will be converted to\n uint8 public constant POOL_PRECISION_DECIMALS = 18;\n\n // the denominator used to calculate admin and LP fees. For example, an\n // LP fee might be something like tradeAmount.mul(fee).div(FEE_DENOMINATOR)\n uint256 private constant FEE_DENOMINATOR = 10**10;\n\n // Max swap fee is 1% or 100bps of each swap\n uint256 public constant MAX_SWAP_FEE = 10**8;\n\n // Max adminFee is 100% of the swapFee\n // adminFee does not add additional fee on top of swapFee\n // Instead it takes a certain % of the swapFee. Therefore it has no impact on the\n // users but only on the earnings of LPs\n uint256 public constant MAX_ADMIN_FEE = 10**10;\n\n // Constant value used as max loop limit\n uint256 private constant MAX_LOOP_LIMIT = 256;\n\n /*** VIEW & PURE FUNCTIONS ***/\n\n function _getAPrecise(Swap storage self) internal view returns (uint256) {\n return AmplificationUtils._getAPrecise(self);\n }\n\n /**\n * @notice Calculate the dy, the amount of selected token that user receives and\n * the fee of withdrawing in one token\n * @param tokenAmount the amount to withdraw in the pool's precision\n * @param tokenIndex which token will be withdrawn\n * @param self Swap struct to read from\n * @return the amount of token user will receive\n */\n function calculateWithdrawOneToken(\n Swap storage self,\n uint256 tokenAmount,\n uint8 tokenIndex\n ) external view returns (uint256) {\n (uint256 availableTokenAmount, ) = _calculateWithdrawOneToken(\n self,\n tokenAmount,\n tokenIndex,\n self.lpToken.totalSupply()\n );\n return availableTokenAmount;\n }\n\n function _calculateWithdrawOneToken(\n Swap storage self,\n uint256 tokenAmount,\n uint8 tokenIndex,\n uint256 totalSupply\n ) internal view returns (uint256, uint256) {\n uint256 dy;\n uint256 newY;\n uint256 currentY;\n\n (dy, newY, currentY) = calculateWithdrawOneTokenDY(\n self,\n tokenIndex,\n tokenAmount,\n totalSupply\n );\n\n // dy_0 (without fees)\n // dy, dy_0 - dy\n\n uint256 dySwapFee = currentY\n .sub(newY)\n .div(self.tokenPrecisionMultipliers[tokenIndex])\n .sub(dy);\n\n return (dy, dySwapFee);\n }\n\n /**\n * @notice Calculate the dy of withdrawing in one token\n * @param self Swap struct to read from\n * @param tokenIndex which token will be withdrawn\n * @param tokenAmount the amount to withdraw in the pools precision\n * @return the d and the new y after withdrawing one token\n */\n function calculateWithdrawOneTokenDY(\n Swap storage self,\n uint8 tokenIndex,\n uint256 tokenAmount,\n uint256 totalSupply\n )\n internal\n view\n returns (\n uint256,\n uint256,\n uint256\n )\n {\n // Get the current D, then solve the stableswap invariant\n // y_i for D - tokenAmount\n uint256[] memory xp = _xp(self);\n\n require(tokenIndex < xp.length, \"Token index out of range\");\n\n\n CalculateWithdrawOneTokenDYInfo memory v\n = CalculateWithdrawOneTokenDYInfo(0, 0, 0, 0, 0);\n v.preciseA = _getAPrecise(self);\n v.d0 = getD(xp, v.preciseA);\n v.d1 = v.d0.sub(tokenAmount.mul(v.d0).div(totalSupply));\n\n require(tokenAmount <= xp[tokenIndex], \"Withdraw exceeds available\");\n\n v.newY = getYD(v.preciseA, tokenIndex, xp, v.d1);\n\n uint256[] memory xpReduced = new uint256[](xp.length);\n\n v.feePerToken = _feePerToken(self.swapFee, xp.length);\n for (uint256 i = 0; i < xp.length; i++) {\n uint256 xpi = xp[i];\n // if i == tokenIndex, dxExpected = xp[i] * d1 / d0 - newY\n // else dxExpected = xp[i] - (xp[i] * d1 / d0)\n // xpReduced[i] -= dxExpected * fee / FEE_DENOMINATOR\n xpReduced[i] = xpi.sub(\n (\n (i == tokenIndex)\n ? xpi.mul(v.d1).div(v.d0).sub(v.newY)\n : xpi.sub(xpi.mul(v.d1).div(v.d0))\n )\n .mul(v.feePerToken)\n .div(FEE_DENOMINATOR)\n );\n }\n\n uint256 dy = xpReduced[tokenIndex].sub(\n getYD(v.preciseA, tokenIndex, xpReduced, v.d1)\n );\n dy = dy.sub(1).div(self.tokenPrecisionMultipliers[tokenIndex]);\n\n return (dy, v.newY, xp[tokenIndex]);\n }\n\n /**\n * @notice Calculate the price of a token in the pool with given\n * precision-adjusted balances and a particular D.\n *\n * @dev This is accomplished via solving the invariant iteratively.\n * See the StableSwap paper and Curve.fi implementation for further details.\n *\n * x_1**2 + x1 * (sum' - (A*n**n - 1) * D / (A * n**n)) = D ** (n + 1) / (n ** (2 * n) * prod' * A)\n * x_1**2 + b*x_1 = c\n * x_1 = (x_1**2 + c) / (2*x_1 + b)\n *\n * @param a the amplification coefficient * n * (n - 1). See the StableSwap paper for details.\n * @param tokenIndex Index of token we are calculating for.\n * @param xp a precision-adjusted set of pool balances. Array should be\n * the same cardinality as the pool.\n * @param d the stableswap invariant\n * @return the price of the token, in the same precision as in xp\n */\n function getYD(\n uint256 a,\n uint8 tokenIndex,\n uint256[] memory xp,\n uint256 d\n ) internal pure returns (uint256) {\n uint256 numTokens = xp.length;\n require(tokenIndex < numTokens, \"Token not found\");\n\n uint256 c = d;\n uint256 s;\n uint256 nA = a.mul(numTokens);\n\n for (uint256 i = 0; i < numTokens; i++) {\n if (i != tokenIndex) {\n s = s.add(xp[i]);\n c = c.mul(d).div(xp[i].mul(numTokens));\n // If we were to protect the division loss we would have to keep the denominator separate\n // and divide at the end. However this leads to overflow with large numTokens or/and D.\n // c = c * D * D * D * ... overflow!\n }\n }\n c = c.mul(d).mul(AmplificationUtils.A_PRECISION).div(nA.mul(numTokens));\n\n uint256 b = s.add(d.mul(AmplificationUtils.A_PRECISION).div(nA));\n uint256 yPrev;\n uint256 y = d;\n for (uint256 i = 0; i < MAX_LOOP_LIMIT; i++) {\n yPrev = y;\n y = y.mul(y).add(c).div(y.mul(2).add(b).sub(d));\n if (y.within1(yPrev)) {\n return y;\n }\n }\n revert(\"Approximation did not converge\");\n }\n\n /**\n * @notice Get D, the StableSwap invariant, based on a set of balances and a particular A.\n * @param xp a precision-adjusted set of pool balances. Array should be the same cardinality\n * as the pool.\n * @param a the amplification coefficient * n * (n - 1) in A_PRECISION.\n * See the StableSwap paper for details\n * @return the invariant, at the precision of the pool\n */\n function getD(uint256[] memory xp, uint256 a)\n internal\n pure\n returns (uint256)\n {\n uint256 numTokens = xp.length;\n uint256 s;\n for (uint256 i = 0; i < numTokens; i++) {\n s = s.add(xp[i]);\n }\n if (s == 0) {\n return 0;\n }\n\n uint256 prevD;\n uint256 d = s;\n uint256 nA = a.mul(numTokens);\n\n for (uint256 i = 0; i < MAX_LOOP_LIMIT; i++) {\n uint256 dP = d;\n for (uint256 j = 0; j < numTokens; j++) {\n dP = dP.mul(d).div(xp[j].mul(numTokens));\n // If we were to protect the division loss we would have to keep the denominator separate\n // and divide at the end. However this leads to overflow with large numTokens or/and D.\n // dP = dP * D * D * D * ... overflow!\n }\n prevD = d;\n d = nA\n .mul(s)\n .div(AmplificationUtils.A_PRECISION)\n .add(dP.mul(numTokens))\n .mul(d)\n .div(\n nA\n .sub(AmplificationUtils.A_PRECISION)\n .mul(d)\n .div(AmplificationUtils.A_PRECISION)\n .add(numTokens.add(1).mul(dP))\n );\n if (d.within1(prevD)) {\n return d;\n }\n }\n\n // Convergence should occur in 4 loops or less. If this is reached, there may be something wrong\n // with the pool. If this were to occur repeatedly, LPs should withdraw via `removeLiquidity()`\n // function which does not rely on D.\n revert(\"D does not converge\");\n }\n\n /**\n * @notice Given a set of balances and precision multipliers, return the\n * precision-adjusted balances.\n *\n * @param balances an array of token balances, in their native precisions.\n * These should generally correspond with pooled tokens.\n *\n * @param precisionMultipliers an array of multipliers, corresponding to\n * the amounts in the balances array. When multiplied together they\n * should yield amounts at the pool's precision.\n *\n * @return an array of amounts \"scaled\" to the pool's precision\n */\n function _xp(\n uint256[] memory balances,\n uint256[] memory precisionMultipliers\n ) internal pure returns (uint256[] memory) {\n uint256 numTokens = balances.length;\n require(\n numTokens == precisionMultipliers.length,\n \"Balances must match multipliers\"\n );\n uint256[] memory xp = new uint256[](numTokens);\n for (uint256 i = 0; i < numTokens; i++) {\n xp[i] = balances[i].mul(precisionMultipliers[i]);\n }\n return xp;\n }\n\n /**\n * @notice Return the precision-adjusted balances of all tokens in the pool\n * @param self Swap struct to read from\n * @return the pool balances \"scaled\" to the pool's precision, allowing\n * them to be more easily compared.\n */\n function _xp(Swap storage self) internal view returns (uint256[] memory) {\n return _xp(self.balances, self.tokenPrecisionMultipliers);\n }\n\n /**\n * @notice Get the virtual price, to help calculate profit\n * @param self Swap struct to read from\n * @return the virtual price, scaled to precision of POOL_PRECISION_DECIMALS\n */\n function getVirtualPrice(Swap storage self)\n external\n view\n returns (uint256)\n {\n uint256 d = getD(_xp(self), _getAPrecise(self));\n LPToken lpToken = self.lpToken;\n uint256 supply = lpToken.totalSupply();\n if (supply > 0) {\n return d.mul(10**uint256(POOL_PRECISION_DECIMALS)).div(supply);\n }\n return 0;\n }\n\n /**\n * @notice Calculate the new balances of the tokens given the indexes of the token\n * that is swapped from (FROM) and the token that is swapped to (TO).\n * This function is used as a helper function to calculate how much TO token\n * the user should receive on swap.\n *\n * @param preciseA precise form of amplification coefficient\n * @param tokenIndexFrom index of FROM token\n * @param tokenIndexTo index of TO token\n * @param x the new total amount of FROM token\n * @param xp balances of the tokens in the pool\n * @return the amount of TO token that should remain in the pool\n */\n function getY(\n uint256 preciseA,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 x,\n uint256[] memory xp\n ) internal pure returns (uint256) {\n uint256 numTokens = xp.length;\n require(\n tokenIndexFrom != tokenIndexTo,\n \"Can't compare token to itself\"\n );\n require(\n tokenIndexFrom < numTokens && tokenIndexTo < numTokens,\n \"Tokens must be in pool\"\n );\n\n uint256 d = getD(xp, preciseA);\n uint256 c = d;\n uint256 s;\n uint256 nA = numTokens.mul(preciseA);\n\n uint256 _x;\n for (uint256 i = 0; i < numTokens; i++) {\n if (i == tokenIndexFrom) {\n _x = x;\n } else if (i != tokenIndexTo) {\n _x = xp[i];\n } else {\n continue;\n }\n s = s.add(_x);\n c = c.mul(d).div(_x.mul(numTokens));\n // If we were to protect the division loss we would have to keep the denominator separate\n // and divide at the end. However this leads to overflow with large numTokens or/and D.\n // c = c * D * D * D * ... overflow!\n }\n c = c.mul(d).mul(AmplificationUtils.A_PRECISION).div(nA.mul(numTokens));\n uint256 b = s.add(d.mul(AmplificationUtils.A_PRECISION).div(nA));\n uint256 yPrev;\n uint256 y = d;\n\n // iterative approximation\n for (uint256 i = 0; i < MAX_LOOP_LIMIT; i++) {\n yPrev = y;\n y = y.mul(y).add(c).div(y.mul(2).add(b).sub(d));\n if (y.within1(yPrev)) {\n return y;\n }\n }\n revert(\"Approximation did not converge\");\n }\n\n /**\n * @notice Externally calculates a swap between two tokens.\n * @param self Swap struct to read from\n * @param tokenIndexFrom the token to sell\n * @param tokenIndexTo the token to buy\n * @param dx the number of tokens to sell. If the token charges a fee on transfers,\n * use the amount that gets transferred after the fee.\n * @return dy the number of tokens the user will get\n */\n function calculateSwap(\n Swap storage self,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx\n ) external view returns (uint256 dy) {\n (dy, ) = _calculateSwap(\n self,\n tokenIndexFrom,\n tokenIndexTo,\n dx,\n self.balances\n );\n }\n\n /**\n * @notice Internally calculates a swap between two tokens.\n *\n * @dev The caller is expected to transfer the actual amounts (dx and dy)\n * using the token contracts.\n *\n * @param self Swap struct to read from\n * @param tokenIndexFrom the token to sell\n * @param tokenIndexTo the token to buy\n * @param dx the number of tokens to sell. If the token charges a fee on transfers,\n * use the amount that gets transferred after the fee.\n * @return dy the number of tokens the user will get\n * @return dyFee the associated fee\n */\n function _calculateSwap(\n Swap storage self,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx,\n uint256[] memory balances\n ) internal view returns (uint256 dy, uint256 dyFee) {\n uint256[] memory multipliers = self.tokenPrecisionMultipliers;\n uint256[] memory xp = _xp(balances, multipliers);\n require(\n tokenIndexFrom < xp.length && tokenIndexTo < xp.length,\n \"Token index out of range\"\n );\n uint256 x = dx.mul(multipliers[tokenIndexFrom]).add(xp[tokenIndexFrom]);\n uint256 y = getY(\n _getAPrecise(self),\n tokenIndexFrom,\n tokenIndexTo,\n x,\n xp\n );\n dy = xp[tokenIndexTo].sub(y).sub(1);\n dyFee = dy.mul(self.swapFee).div(FEE_DENOMINATOR);\n dy = dy.sub(dyFee).div(multipliers[tokenIndexTo]);\n }\n\n /**\n * @notice A simple method to calculate amount of each underlying\n * tokens that is returned upon burning given amount of\n * LP tokens\n *\n * @param amount the amount of LP tokens that would to be burned on\n * withdrawal\n * @return array of amounts of tokens user will receive\n */\n function calculateRemoveLiquidity(Swap storage self, uint256 amount)\n external\n view\n returns (uint256[] memory)\n {\n return\n _calculateRemoveLiquidity(\n self.balances,\n amount,\n self.lpToken.totalSupply()\n );\n }\n\n function _calculateRemoveLiquidity(\n uint256[] memory balances,\n uint256 amount,\n uint256 totalSupply\n ) internal pure returns (uint256[] memory) {\n require(amount <= totalSupply, \"Cannot exceed total supply\");\n\n uint256[] memory amounts = new uint256[](balances.length);\n\n for (uint256 i = 0; i < balances.length; i++) {\n amounts[i] = balances[i].mul(amount).div(totalSupply);\n }\n return amounts;\n }\n\n /**\n * @notice A simple method to calculate prices from deposits or\n * withdrawals, excluding fees but including slippage. This is\n * helpful as an input into the various \"min\" parameters on calls\n * to fight front-running\n *\n * @dev This shouldn't be used outside frontends for user estimates.\n *\n * @param self Swap struct to read from\n * @param amounts an array of token amounts to deposit or withdrawal,\n * corresponding to pooledTokens. The amount should be in each\n * pooled token's native precision. If a token charges a fee on transfers,\n * use the amount that gets transferred after the fee.\n * @param deposit whether this is a deposit or a withdrawal\n * @return if deposit was true, total amount of lp token that will be minted and if\n * deposit was false, total amount of lp token that will be burned\n */\n function calculateTokenAmount(\n Swap storage self,\n uint256[] calldata amounts,\n bool deposit\n ) external view returns (uint256) {\n uint256 a = _getAPrecise(self);\n uint256[] memory balances = self.balances;\n uint256[] memory multipliers = self.tokenPrecisionMultipliers;\n\n uint256 d0 = getD(_xp(balances, multipliers), a);\n for (uint256 i = 0; i < balances.length; i++) {\n if (deposit) {\n balances[i] = balances[i].add(amounts[i]);\n } else {\n balances[i] = balances[i].sub(\n amounts[i],\n \"Cannot withdraw more than available\"\n );\n }\n }\n uint256 d1 = getD(_xp(balances, multipliers), a);\n uint256 totalSupply = self.lpToken.totalSupply();\n\n if (deposit) {\n return d1.sub(d0).mul(totalSupply).div(d0);\n } else {\n return d0.sub(d1).mul(totalSupply).div(d0);\n }\n }\n\n /**\n * @notice return accumulated amount of admin fees of the token with given index\n * @param self Swap struct to read from\n * @param index Index of the pooled token\n * @return admin balance in the token's precision\n */\n function getAdminBalance(Swap storage self, uint256 index)\n external\n view\n returns (uint256)\n {\n require(index < self.pooledTokens.length, \"Token index out of range\");\n return\n self.pooledTokens[index].balanceOf(address(this)).sub(\n self.balances[index]\n );\n }\n\n /**\n * @notice internal helper function to calculate fee per token multiplier used in\n * swap fee calculations\n * @param swapFee swap fee for the tokens\n * @param numTokens number of tokens pooled\n */\n function _feePerToken(uint256 swapFee, uint256 numTokens)\n internal\n pure\n returns (uint256)\n {\n return swapFee.mul(numTokens).div(numTokens.sub(1).mul(4));\n }\n\n /*** STATE MODIFYING FUNCTIONS ***/\n\n /**\n * @notice swap two tokens in the pool\n * @param self Swap struct to read from and write to\n * @param tokenIndexFrom the token the user wants to sell\n * @param tokenIndexTo the token the user wants to buy\n * @param dx the amount of tokens the user wants to sell\n * @param minDy the min amount the user would like to receive, or revert.\n * @return amount of token user received on swap\n */\n function swap(\n Swap storage self,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx,\n uint256 minDy\n ) external returns (uint256) {\n {\n IERC20 tokenFrom = self.pooledTokens[tokenIndexFrom];\n require(\n dx <= tokenFrom.balanceOf(msg.sender),\n \"Cannot swap more than you own\"\n );\n // Transfer tokens first to see if a fee was charged on transfer\n uint256 beforeBalance = tokenFrom.balanceOf(address(this));\n tokenFrom.safeTransferFrom(msg.sender, address(this), dx);\n\n // Use the actual transferred amount for AMM math\n dx = tokenFrom.balanceOf(address(this)).sub(beforeBalance);\n }\n\n uint256 dy;\n uint256 dyFee;\n uint256[] memory balances = self.balances;\n (dy, dyFee) = _calculateSwap(\n self,\n tokenIndexFrom,\n tokenIndexTo,\n dx,\n balances\n );\n require(dy >= minDy, \"Swap didn't result in min tokens\");\n\n uint256 dyAdminFee = dyFee.mul(self.adminFee).div(FEE_DENOMINATOR).div(\n self.tokenPrecisionMultipliers[tokenIndexTo]\n );\n\n self.balances[tokenIndexFrom] = balances[tokenIndexFrom].add(dx);\n self.balances[tokenIndexTo] = balances[tokenIndexTo].sub(dy).sub(\n dyAdminFee\n );\n\n self.pooledTokens[tokenIndexTo].safeTransfer(msg.sender, dy);\n\n emit TokenSwap(msg.sender, dx, dy, tokenIndexFrom, tokenIndexTo);\n\n return dy;\n }\n\n /**\n * @notice Add liquidity to the pool\n * @param self Swap struct to read from and write to\n * @param amounts the amounts of each token to add, in their native precision\n * @param minToMint the minimum LP tokens adding this amount of liquidity\n * should mint, otherwise revert. Handy for front-running mitigation\n * allowed addresses. If the pool is not in the guarded launch phase, this parameter will be ignored.\n * @return amount of LP token user received\n */\n function addLiquidity(\n Swap storage self,\n uint256[] memory amounts,\n uint256 minToMint\n ) external returns (uint256) {\n IERC20[] memory pooledTokens = self.pooledTokens;\n require(\n amounts.length == pooledTokens.length,\n \"Amounts must match pooled tokens\"\n );\n\n // current state\n ManageLiquidityInfo memory v = ManageLiquidityInfo(\n 0,\n 0,\n 0,\n _getAPrecise(self),\n self.lpToken,\n 0,\n self.balances,\n self.tokenPrecisionMultipliers\n );\n v.totalSupply = v.lpToken.totalSupply();\n\n if (v.totalSupply != 0) {\n v.d0 = getD(_xp(v.balances, v.multipliers), v.preciseA);\n }\n\n uint256[] memory newBalances = new uint256[](pooledTokens.length);\n\n for (uint256 i = 0; i < pooledTokens.length; i++) {\n require(\n v.totalSupply != 0 || amounts[i] > 0,\n \"Must supply all tokens in pool\"\n );\n\n // Transfer tokens first to see if a fee was charged on transfer\n if (amounts[i] != 0) {\n uint256 beforeBalance = pooledTokens[i].balanceOf(\n address(this)\n );\n pooledTokens[i].safeTransferFrom(\n msg.sender,\n address(this),\n amounts[i]\n );\n\n // Update the amounts[] with actual transfer amount\n amounts[i] = pooledTokens[i].balanceOf(address(this)).sub(\n beforeBalance\n );\n }\n\n newBalances[i] = v.balances[i].add(amounts[i]);\n }\n\n // invariant after change\n v.d1 = getD(_xp(newBalances, v.multipliers), v.preciseA);\n require(v.d1 > v.d0, \"D should increase\");\n\n // updated to reflect fees and calculate the user's LP tokens\n v.d2 = v.d1;\n uint256[] memory fees = new uint256[](pooledTokens.length);\n\n if (v.totalSupply != 0) {\n uint256 feePerToken = _feePerToken(\n self.swapFee,\n pooledTokens.length\n );\n for (uint256 i = 0; i < pooledTokens.length; i++) {\n uint256 idealBalance = v.d1.mul(v.balances[i]).div(v.d0);\n fees[i] = feePerToken\n .mul(idealBalance.difference(newBalances[i]))\n .div(FEE_DENOMINATOR);\n self.balances[i] = newBalances[i].sub(\n fees[i].mul(self.adminFee).div(FEE_DENOMINATOR)\n );\n newBalances[i] = newBalances[i].sub(fees[i]);\n }\n v.d2 = getD(_xp(newBalances, v.multipliers), v.preciseA);\n } else {\n // the initial depositor doesn't pay fees\n self.balances = newBalances;\n }\n\n uint256 toMint;\n if (v.totalSupply == 0) {\n toMint = v.d1;\n } else {\n toMint = v.d2.sub(v.d0).mul(v.totalSupply).div(v.d0);\n }\n\n require(toMint >= minToMint, \"Couldn't mint min requested\");\n\n // mint the user's LP tokens\n v.lpToken.mint(msg.sender, toMint);\n\n emit AddLiquidity(\n msg.sender,\n amounts,\n fees,\n v.d1,\n v.totalSupply.add(toMint)\n );\n\n return toMint;\n }\n\n /**\n * @notice Burn LP tokens to remove liquidity from the pool.\n * @dev Liquidity can always be removed, even when the pool is paused.\n * @param self Swap struct to read from and write to\n * @param amount the amount of LP tokens to burn\n * @param minAmounts the minimum amounts of each token in the pool\n * acceptable for this burn. Useful as a front-running mitigation\n * @return amounts of tokens the user received\n */\n function removeLiquidity(\n Swap storage self,\n uint256 amount,\n uint256[] calldata minAmounts\n ) external returns (uint256[] memory) {\n LPToken lpToken = self.lpToken;\n IERC20[] memory pooledTokens = self.pooledTokens;\n require(amount <= lpToken.balanceOf(msg.sender), \">LP.balanceOf\");\n require(\n minAmounts.length == pooledTokens.length,\n \"minAmounts must match poolTokens\"\n );\n\n uint256[] memory balances = self.balances;\n uint256 totalSupply = lpToken.totalSupply();\n\n uint256[] memory amounts = _calculateRemoveLiquidity(\n balances,\n amount,\n totalSupply\n );\n\n for (uint256 i = 0; i < amounts.length; i++) {\n require(amounts[i] >= minAmounts[i], \"amounts[i] < minAmounts[i]\");\n self.balances[i] = balances[i].sub(amounts[i]);\n pooledTokens[i].safeTransfer(msg.sender, amounts[i]);\n }\n\n lpToken.burnFrom(msg.sender, amount);\n\n emit RemoveLiquidity(msg.sender, amounts, totalSupply.sub(amount));\n\n return amounts;\n }\n\n /**\n * @notice Remove liquidity from the pool all in one token.\n * @param self Swap struct to read from and write to\n * @param tokenAmount the amount of the lp tokens to burn\n * @param tokenIndex the index of the token you want to receive\n * @param minAmount the minimum amount to withdraw, otherwise revert\n * @return amount chosen token that user received\n */\n function removeLiquidityOneToken(\n Swap storage self,\n uint256 tokenAmount,\n uint8 tokenIndex,\n uint256 minAmount\n ) external returns (uint256) {\n LPToken lpToken = self.lpToken;\n IERC20[] memory pooledTokens = self.pooledTokens;\n\n require(tokenAmount <= lpToken.balanceOf(msg.sender), \">LP.balanceOf\");\n require(tokenIndex < pooledTokens.length, \"Token not found\");\n\n uint256 totalSupply = lpToken.totalSupply();\n\n (uint256 dy, uint256 dyFee) = _calculateWithdrawOneToken(\n self,\n tokenAmount,\n tokenIndex,\n totalSupply\n );\n\n require(dy >= minAmount, \"dy < minAmount\");\n\n self.balances[tokenIndex] = self.balances[tokenIndex].sub(\n dy.add(dyFee.mul(self.adminFee).div(FEE_DENOMINATOR))\n );\n lpToken.burnFrom(msg.sender, tokenAmount);\n pooledTokens[tokenIndex].safeTransfer(msg.sender, dy);\n\n emit RemoveLiquidityOne(\n msg.sender,\n tokenAmount,\n totalSupply,\n tokenIndex,\n dy\n );\n\n return dy;\n }\n\n /**\n * @notice Remove liquidity from the pool, weighted differently than the\n * pool's current balances.\n *\n * @param self Swap struct to read from and write to\n * @param amounts how much of each token to withdraw\n * @param maxBurnAmount the max LP token provider is willing to pay to\n * remove liquidity. Useful as a front-running mitigation.\n * @return actual amount of LP tokens burned in the withdrawal\n */\n function removeLiquidityImbalance(\n Swap storage self,\n uint256[] memory amounts,\n uint256 maxBurnAmount\n ) public returns (uint256) {\n ManageLiquidityInfo memory v = ManageLiquidityInfo(\n 0,\n 0,\n 0,\n _getAPrecise(self),\n self.lpToken,\n 0,\n self.balances,\n self.tokenPrecisionMultipliers\n );\n v.totalSupply = v.lpToken.totalSupply();\n\n IERC20[] memory pooledTokens = self.pooledTokens;\n\n require(\n amounts.length == pooledTokens.length,\n \"Amounts should match pool tokens\"\n );\n\n require(\n maxBurnAmount <= v.lpToken.balanceOf(msg.sender) &&\n maxBurnAmount != 0,\n \">LP.balanceOf\"\n );\n\n uint256 feePerToken = _feePerToken(self.swapFee, pooledTokens.length);\n uint256[] memory fees = new uint256[](pooledTokens.length);\n {\n uint256[] memory balances1 = new uint256[](pooledTokens.length);\n v.d0 = getD(_xp(v.balances, v.multipliers), v.preciseA);\n for (uint256 i = 0; i < pooledTokens.length; i++) {\n balances1[i] = v.balances[i].sub(\n amounts[i],\n \"Cannot withdraw more than available\"\n );\n }\n v.d1 = getD(_xp(balances1, v.multipliers), v.preciseA);\n\n for (uint256 i = 0; i < pooledTokens.length; i++) {\n uint256 idealBalance = v.d1.mul(v.balances[i]).div(v.d0);\n uint256 difference = idealBalance.difference(balances1[i]);\n fees[i] = feePerToken.mul(difference).div(FEE_DENOMINATOR);\n self.balances[i] = balances1[i].sub(\n fees[i].mul(self.adminFee).div(FEE_DENOMINATOR)\n );\n balances1[i] = balances1[i].sub(fees[i]);\n }\n\n v.d2 = getD(_xp(balances1, v.multipliers), v.preciseA);\n }\n uint256 tokenAmount = v.d0.sub(v.d2).mul(v.totalSupply).div(v.d0);\n require(tokenAmount != 0, \"Burnt amount cannot be zero\");\n tokenAmount = tokenAmount.add(1);\n\n require(tokenAmount <= maxBurnAmount, \"tokenAmount > maxBurnAmount\");\n\n v.lpToken.burnFrom(msg.sender, tokenAmount);\n\n for (uint256 i = 0; i < pooledTokens.length; i++) {\n pooledTokens[i].safeTransfer(msg.sender, amounts[i]);\n }\n\n emit RemoveLiquidityImbalance(\n msg.sender,\n amounts,\n fees,\n v.d1,\n v.totalSupply.sub(tokenAmount)\n );\n\n return tokenAmount;\n }\n\n /**\n * @notice withdraw all admin fees to a given address\n * @param self Swap struct to withdraw fees from\n * @param to Address to send the fees to\n */\n function withdrawAdminFees(Swap storage self, address to) external {\n IERC20[] memory pooledTokens = self.pooledTokens;\n for (uint256 i = 0; i < pooledTokens.length; i++) {\n IERC20 token = pooledTokens[i];\n uint256 balance = token.balanceOf(address(this)).sub(\n self.balances[i]\n );\n if (balance != 0) {\n token.safeTransfer(to, balance);\n }\n }\n }\n\n /**\n * @notice Sets the admin fee\n * @dev adminFee cannot be higher than 100% of the swap fee\n * @param self Swap struct to update\n * @param newAdminFee new admin fee to be applied on future transactions\n */\n function setAdminFee(Swap storage self, uint256 newAdminFee) external {\n require(newAdminFee <= MAX_ADMIN_FEE, \"Fee is too high\");\n self.adminFee = newAdminFee;\n\n emit NewAdminFee(newAdminFee);\n }\n\n /**\n * @notice update the swap fee\n * @dev fee cannot be higher than 1% of each swap\n * @param self Swap struct to update\n * @param newSwapFee new swap fee to be applied on future transactions\n */\n function setSwapFee(Swap storage self, uint256 newSwapFee) external {\n require(newSwapFee <= MAX_SWAP_FEE, \"Fee is too high\");\n self.swapFee = newSwapFee;\n\n emit NewSwapFee(newSwapFee);\n }\n}\n" + }, + "contracts/amm/AmplificationUtils.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.6.12;\n\nimport \"@openzeppelin/contracts/token/ERC20/SafeERC20.sol\";\nimport \"./SwapUtils.sol\";\n\n/**\n * @title AmplificationUtils library\n * @notice A library to calculate and ramp the A parameter of a given `SwapUtils.Swap` struct.\n * This library assumes the struct is fully validated.\n */\nlibrary AmplificationUtils {\n using SafeMath for uint256;\n\n event RampA(\n uint256 oldA,\n uint256 newA,\n uint256 initialTime,\n uint256 futureTime\n );\n event StopRampA(uint256 currentA, uint256 time);\n\n // Constant values used in ramping A calculations\n uint256 public constant A_PRECISION = 100;\n uint256 public constant MAX_A = 10**6;\n uint256 private constant MAX_A_CHANGE = 2;\n uint256 private constant MIN_RAMP_TIME = 7 days;\n\n /**\n * @notice Return A, the amplification coefficient * n * (n - 1)\n * @dev See the StableSwap paper for details\n * @param self Swap struct to read from\n * @return A parameter\n */\n function getA(SwapUtils.Swap storage self) external view returns (uint256) {\n return _getAPrecise(self).div(A_PRECISION);\n }\n\n /**\n * @notice Return A in its raw precision\n * @dev See the StableSwap paper for details\n * @param self Swap struct to read from\n * @return A parameter in its raw precision form\n */\n function getAPrecise(SwapUtils.Swap storage self)\n external\n view\n returns (uint256)\n {\n return _getAPrecise(self);\n }\n\n /**\n * @notice Return A in its raw precision\n * @dev See the StableSwap paper for details\n * @param self Swap struct to read from\n * @return A parameter in its raw precision form\n */\n function _getAPrecise(SwapUtils.Swap storage self)\n internal\n view\n returns (uint256)\n {\n uint256 t1 = self.futureATime; // time when ramp is finished\n uint256 a1 = self.futureA; // final A value when ramp is finished\n\n if (block.timestamp < t1) {\n uint256 t0 = self.initialATime; // time when ramp is started\n uint256 a0 = self.initialA; // initial A value when ramp is started\n if (a1 > a0) {\n // a0 + (a1 - a0) * (block.timestamp - t0) / (t1 - t0)\n return\n a0.add(\n a1.sub(a0).mul(block.timestamp.sub(t0)).div(t1.sub(t0))\n );\n } else {\n // a0 - (a0 - a1) * (block.timestamp - t0) / (t1 - t0)\n return\n a0.sub(\n a0.sub(a1).mul(block.timestamp.sub(t0)).div(t1.sub(t0))\n );\n }\n } else {\n return a1;\n }\n }\n\n /**\n * @notice Start ramping up or down A parameter towards given futureA_ and futureTime_\n * Checks if the change is too rapid, and commits the new A value only when it falls under\n * the limit range.\n * @param self Swap struct to update\n * @param futureA_ the new A to ramp towards\n * @param futureTime_ timestamp when the new A should be reached\n */\n function rampA(\n SwapUtils.Swap storage self,\n uint256 futureA_,\n uint256 futureTime_\n ) external {\n require(\n block.timestamp >= self.initialATime.add(1 days),\n \"Wait 1 day before starting ramp\"\n );\n require(\n futureTime_ >= block.timestamp.add(MIN_RAMP_TIME),\n \"Insufficient ramp time\"\n );\n require(\n futureA_ > 0 && futureA_ < MAX_A,\n \"futureA_ must be > 0 and < MAX_A\"\n );\n\n uint256 initialAPrecise = _getAPrecise(self);\n uint256 futureAPrecise = futureA_.mul(A_PRECISION);\n\n if (futureAPrecise < initialAPrecise) {\n require(\n futureAPrecise.mul(MAX_A_CHANGE) >= initialAPrecise,\n \"futureA_ is too small\"\n );\n } else {\n require(\n futureAPrecise <= initialAPrecise.mul(MAX_A_CHANGE),\n \"futureA_ is too large\"\n );\n }\n\n self.initialA = initialAPrecise;\n self.futureA = futureAPrecise;\n self.initialATime = block.timestamp;\n self.futureATime = futureTime_;\n\n emit RampA(\n initialAPrecise,\n futureAPrecise,\n block.timestamp,\n futureTime_\n );\n }\n\n /**\n * @notice Stops ramping A immediately. Once this function is called, rampA()\n * cannot be called for another 24 hours\n * @param self Swap struct to update\n */\n function stopRampA(SwapUtils.Swap storage self) external {\n require(self.futureATime > block.timestamp, \"Ramp is already stopped\");\n\n uint256 currentA = _getAPrecise(self);\n self.initialA = currentA;\n self.futureA = currentA;\n self.initialATime = block.timestamp;\n self.futureATime = block.timestamp;\n\n emit StopRampA(currentA, block.timestamp);\n }\n}\n" + }, + "@openzeppelin/contracts/token/ERC20/IERC20.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <0.8.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" + }, + "@openzeppelin/contracts/utils/Address.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.2 <0.8.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" + }, + "@openzeppelin/contracts-upgradeable/proxy/Initializable.sol": { + "content": "// SPDX-License-Identifier: MIT\n\n// solhint-disable-next-line compiler-version\npragma solidity >=0.4.24 <0.8.0;\n\nimport \"../utils/AddressUpgradeable.sol\";\n\n/**\n * @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed\n * behind a proxy. Since a proxied contract can't have a constructor, it's common to move constructor logic to an\n * external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer\n * function so it can only be called once. The {initializer} modifier provided by this contract will have this effect.\n *\n * TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as\n * possible by providing the encoded function call as the `_data` argument to {UpgradeableProxy-constructor}.\n *\n * CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure\n * that all initializers are idempotent. This is not verified automatically as constructors are by Solidity.\n */\nabstract contract Initializable {\n\n /**\n * @dev Indicates that the contract has been initialized.\n */\n bool private _initialized;\n\n /**\n * @dev Indicates that the contract is in the process of being initialized.\n */\n bool private _initializing;\n\n /**\n * @dev Modifier to protect an initializer function from being invoked twice.\n */\n modifier initializer() {\n require(_initializing || _isConstructor() || !_initialized, \"Initializable: contract is already initialized\");\n\n bool isTopLevelCall = !_initializing;\n if (isTopLevelCall) {\n _initializing = true;\n _initialized = true;\n }\n\n _;\n\n if (isTopLevelCall) {\n _initializing = false;\n }\n }\n\n /// @dev Returns true if and only if the function is running in the constructor\n function _isConstructor() private view returns (bool) {\n return !AddressUpgradeable.isContract(address(this));\n }\n}\n" + }, + "@openzeppelin/contracts-upgradeable/utils/AddressUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.2 <0.8.0;\n\n/**\n * @dev Collection of functions related to the address type\n */\nlibrary AddressUpgradeable {\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 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" + }, + "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <0.8.0;\n\nimport \"../utils/ContextUpgradeable.sol\";\nimport \"../proxy/Initializable.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 OwnableUpgradeable is Initializable, ContextUpgradeable {\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 function __Ownable_init() internal initializer {\n __Context_init_unchained();\n __Ownable_init_unchained();\n }\n\n function __Ownable_init_unchained() internal initializer {\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 uint256[49] private __gap;\n}\n" + }, + "@openzeppelin/contracts-upgradeable/utils/PausableUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <0.8.0;\n\nimport \"./ContextUpgradeable.sol\";\nimport \"../proxy/Initializable.sol\";\n\n/**\n * @dev Contract module which allows children to implement an emergency stop\n * mechanism that can be triggered by an authorized account.\n *\n * This module is used through inheritance. It will make available the\n * modifiers `whenNotPaused` and `whenPaused`, which can be applied to\n * the functions of your contract. Note that they will not be pausable by\n * simply including this module, only once the modifiers are put in place.\n */\nabstract contract PausableUpgradeable is Initializable, ContextUpgradeable {\n /**\n * @dev Emitted when the pause is triggered by `account`.\n */\n event Paused(address account);\n\n /**\n * @dev Emitted when the pause is lifted by `account`.\n */\n event Unpaused(address account);\n\n bool private _paused;\n\n /**\n * @dev Initializes the contract in unpaused state.\n */\n function __Pausable_init() internal initializer {\n __Context_init_unchained();\n __Pausable_init_unchained();\n }\n\n function __Pausable_init_unchained() internal initializer {\n _paused = false;\n }\n\n /**\n * @dev Returns true if the contract is paused, and false otherwise.\n */\n function paused() public view virtual returns (bool) {\n return _paused;\n }\n\n /**\n * @dev Modifier to make a function callable only when the contract is not paused.\n *\n * Requirements:\n *\n * - The contract must not be paused.\n */\n modifier whenNotPaused() {\n require(!paused(), \"Pausable: paused\");\n _;\n }\n\n /**\n * @dev Modifier to make a function callable only when the contract is paused.\n *\n * Requirements:\n *\n * - The contract must be paused.\n */\n modifier whenPaused() {\n require(paused(), \"Pausable: not paused\");\n _;\n }\n\n /**\n * @dev Triggers stopped state.\n *\n * Requirements:\n *\n * - The contract must not be paused.\n */\n function _pause() internal virtual whenNotPaused {\n _paused = true;\n emit Paused(_msgSender());\n }\n\n /**\n * @dev Returns to normal state.\n *\n * Requirements:\n *\n * - The contract must be paused.\n */\n function _unpause() internal virtual whenPaused {\n _paused = false;\n emit Unpaused(_msgSender());\n }\n uint256[49] private __gap;\n}\n" + }, + "@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <0.8.0;\nimport \"../proxy/Initializable.sol\";\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 ContextUpgradeable is Initializable {\n function __Context_init() internal initializer {\n __Context_init_unchained();\n }\n\n function __Context_init_unchained() internal initializer {\n }\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 uint256[50] private __gap;\n}\n" + }, + "contracts/amm/LPToken.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.6.12;\n\nimport \"@openzeppelin/contracts-upgradeable/token/ERC20/ERC20BurnableUpgradeable.sol\";\nimport \"@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol\";\nimport \"./interfaces/ISwap.sol\";\n\n/**\n * @title Liquidity Provider Token\n * @notice This token is an ERC20 detailed token with added capability to be minted by the owner.\n * It is used to represent user's shares when providing liquidity to swap contracts.\n * @dev Only Swap contracts should initialize and own LPToken contracts.\n */\ncontract LPToken is ERC20BurnableUpgradeable, OwnableUpgradeable {\n using SafeMathUpgradeable for uint256;\n\n /**\n * @notice Initializes this LPToken contract with the given name and symbol\n * @dev The caller of this function will become the owner. A Swap contract should call this\n * in its initializer function.\n * @param name name of this token\n * @param symbol symbol of this token\n */\n function initialize(string memory name, string memory symbol)\n external\n initializer\n returns (bool)\n {\n __Context_init_unchained();\n __ERC20_init_unchained(name, symbol);\n __Ownable_init_unchained();\n return true;\n }\n\n /**\n * @notice Mints the given amount of LPToken to the recipient.\n * @dev only owner can call this mint function\n * @param recipient address of account to receive the tokens\n * @param amount amount of tokens to mint\n */\n function mint(address recipient, uint256 amount) external onlyOwner {\n require(amount != 0, \"LPToken: cannot mint 0\");\n _mint(recipient, amount);\n }\n\n /**\n * @dev Overrides ERC20._beforeTokenTransfer() which get called on every transfers including\n * minting and burning. * This assumes the owner is set to a Swap contract's address.\n */\n function _beforeTokenTransfer(\n address from,\n address to,\n uint256 amount\n ) internal virtual override(ERC20Upgradeable) {\n super._beforeTokenTransfer(from, to, amount);\n require(to != address(this), \"LPToken: cannot send to itself\");\n }\n}\n" + }, + "contracts/amm/MathUtils.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.6.12;\n\nimport \"@openzeppelin/contracts/math/SafeMath.sol\";\n\n/**\n * @title MathUtils library\n * @notice A library to be used in conjunction with SafeMath. Contains functions for calculating\n * differences between two uint256.\n */\nlibrary MathUtils {\n /**\n * @notice Compares a and b and returns true if the difference between a and b\n * is less than 1 or equal to each other.\n * @param a uint256 to compare with\n * @param b uint256 to compare with\n * @return True if the difference between a and b is less than 1 or equal,\n * otherwise return false\n */\n function within1(uint256 a, uint256 b) internal pure returns (bool) {\n return (difference(a, b) <= 1);\n }\n\n /**\n * @notice Calculates absolute difference between a and b\n * @param a uint256 to compare with\n * @param b uint256 to compare with\n * @return Difference between a and b\n */\n function difference(uint256 a, uint256 b) internal pure returns (uint256) {\n if (a > b) {\n return a - b;\n }\n return b - a;\n }\n}\n" + }, + "@openzeppelin/contracts-upgradeable/token/ERC20/ERC20BurnableUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <0.8.0;\n\nimport \"../../utils/ContextUpgradeable.sol\";\nimport \"./ERC20Upgradeable.sol\";\nimport \"../../proxy/Initializable.sol\";\n\n/**\n * @dev Extension of {ERC20} that allows token holders to destroy both their own\n * tokens and those that they have an allowance for, in a way that can be\n * recognized off-chain (via event analysis).\n */\nabstract contract ERC20BurnableUpgradeable is Initializable, ContextUpgradeable, ERC20Upgradeable {\n function __ERC20Burnable_init() internal initializer {\n __Context_init_unchained();\n __ERC20Burnable_init_unchained();\n }\n\n function __ERC20Burnable_init_unchained() internal initializer {\n }\n using SafeMathUpgradeable for uint256;\n\n /**\n * @dev Destroys `amount` tokens from the caller.\n *\n * See {ERC20-_burn}.\n */\n function burn(uint256 amount) public virtual {\n _burn(_msgSender(), amount);\n }\n\n /**\n * @dev Destroys `amount` tokens from `account`, deducting from the caller's\n * allowance.\n *\n * See {ERC20-_burn} and {ERC20-allowance}.\n *\n * Requirements:\n *\n * - the caller must have allowance for ``accounts``'s tokens of at least\n * `amount`.\n */\n function burnFrom(address account, uint256 amount) public virtual {\n uint256 decreasedAllowance = allowance(account, _msgSender()).sub(amount, \"ERC20: burn amount exceeds allowance\");\n\n _approve(account, _msgSender(), decreasedAllowance);\n _burn(account, amount);\n }\n uint256[50] private __gap;\n}\n" + }, + "contracts/amm/interfaces/ISwap.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.6.12;\n\nimport \"@openzeppelin/contracts/token/ERC20/ERC20.sol\";\n\ninterface ISwap {\n // pool data view functions\n function getA() external view returns (uint256);\n\n function getToken(uint8 index) external view returns (IERC20);\n\n function getTokenIndex(address tokenAddress) external view returns (uint8);\n\n function getTokenBalance(uint8 index) external view returns (uint256);\n\n function getVirtualPrice() external view returns (uint256);\n\n // min return calculation functions\n function calculateSwap(\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx\n ) external view returns (uint256);\n\n function calculateTokenAmount(uint256[] calldata amounts, bool deposit)\n external\n view\n returns (uint256);\n\n function calculateRemoveLiquidity(uint256 amount)\n external\n view\n returns (uint256[] memory);\n\n function calculateRemoveLiquidityOneToken(\n uint256 tokenAmount,\n uint8 tokenIndex\n ) external view returns (uint256 availableTokenAmount);\n\n // state modifying functions\n function initialize(\n IERC20[] memory pooledTokens,\n uint8[] memory decimals,\n string memory lpTokenName,\n string memory lpTokenSymbol,\n uint256 a,\n uint256 fee,\n uint256 adminFee,\n address lpTokenTargetAddress\n ) external;\n\n function swap(\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx,\n uint256 minDy,\n uint256 deadline\n ) external returns (uint256);\n\n function addLiquidity(\n uint256[] calldata amounts,\n uint256 minToMint,\n uint256 deadline\n ) external returns (uint256);\n\n function removeLiquidity(\n uint256 amount,\n uint256[] calldata minAmounts,\n uint256 deadline\n ) external returns (uint256[] memory);\n\n function removeLiquidityOneToken(\n uint256 tokenAmount,\n uint8 tokenIndex,\n uint256 minAmount,\n uint256 deadline\n ) external returns (uint256);\n\n function removeLiquidityImbalance(\n uint256[] calldata amounts,\n uint256 maxBurnAmount,\n uint256 deadline\n ) external returns (uint256);\n}\n" + }, + "@openzeppelin/contracts-upgradeable/token/ERC20/ERC20Upgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <0.8.0;\n\nimport \"../../utils/ContextUpgradeable.sol\";\nimport \"./IERC20Upgradeable.sol\";\nimport \"../../math/SafeMathUpgradeable.sol\";\nimport \"../../proxy/Initializable.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 ERC20Upgradeable is Initializable, ContextUpgradeable, IERC20Upgradeable {\n using SafeMathUpgradeable 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 function __ERC20_init(string memory name_, string memory symbol_) internal initializer {\n __Context_init_unchained();\n __ERC20_init_unchained(name_, symbol_);\n }\n\n function __ERC20_init_unchained(string memory name_, string memory symbol_) internal initializer {\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 uint256[44] private __gap;\n}\n" + }, + "@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <0.8.0;\n\n/**\n * @dev Interface of the ERC20 standard as defined in the EIP.\n */\ninterface IERC20Upgradeable {\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" + }, + "@openzeppelin/contracts-upgradeable/math/SafeMathUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <0.8.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 SafeMathUpgradeable {\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" + }, + "@openzeppelin/contracts/token/ERC20/ERC20.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <0.8.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_) public {\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" + }, + "@openzeppelin/contracts/utils/Context.sol": { + "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" + }, + "contracts/amm/SwapFlashLoan.sol": { + "content": "// SPDX-License-Identifier: MIT WITH AGPL-3.0-only\n\npragma solidity 0.6.12;\n\nimport \"./Swap.sol\";\nimport \"./interfaces/IFlashLoanReceiver.sol\";\n\n/**\n * @title Swap - A StableSwap implementation in solidity.\n * @notice This contract is responsible for custody of closely pegged assets (eg. group of stablecoins)\n * and automatic market making system. Users become an LP (Liquidity Provider) by depositing their tokens\n * in desired ratios for an exchange of the pool token that represents their share of the pool.\n * Users can burn pool tokens and withdraw their share of token(s).\n *\n * Each time a swap between the pooled tokens happens, a set fee incurs which effectively gets\n * distributed to the LPs.\n *\n * In case of emergencies, admin can pause additional deposits, swaps, or single-asset withdraws - which\n * stops the ratio of the tokens in the pool from changing.\n * Users can always withdraw their tokens via multi-asset withdraws.\n *\n * @dev Most of the logic is stored as a library `SwapUtils` for the sake of reducing contract's\n * deployment size.\n */\ncontract SwapFlashLoan is Swap {\n // Total fee that is charged on all flashloans in BPS. Borrowers must repay the amount plus the flash loan fee.\n // This fee is split between the protocol and the pool.\n uint256 public flashLoanFeeBPS;\n // Share of the flash loan fee that goes to the protocol in BPS. A portion of each flash loan fee is allocated\n // to the protocol rather than the pool.\n uint256 public protocolFeeShareBPS;\n // Max BPS for limiting flash loan fee settings.\n uint256 public constant MAX_BPS = 10000;\n\n /*** EVENTS ***/\n event FlashLoan(\n address indexed receiver,\n uint8 tokenIndex,\n uint256 amount,\n uint256 amountFee,\n uint256 protocolFee\n );\n\n /**\n * @notice Initializes this Swap contract with the given parameters.\n * This will also clone a LPToken contract that represents users'\n * LP positions. The owner of LPToken will be this contract - which means\n * only this contract is allowed to mint/burn tokens.\n *\n * @param _pooledTokens an array of ERC20s this pool will accept\n * @param decimals the decimals to use for each pooled token,\n * eg 8 for WBTC. Cannot be larger than POOL_PRECISION_DECIMALS\n * @param lpTokenName the long-form name of the token to be deployed\n * @param lpTokenSymbol the short symbol for the token to be deployed\n * @param _a the amplification coefficient * n * (n - 1). See the\n * StableSwap paper for details\n * @param _fee default swap fee to be initialized with\n * @param _adminFee default adminFee to be initialized with\n * @param lpTokenTargetAddress the address of an existing LPToken contract to use as a target\n */\n function initialize(\n IERC20[] memory _pooledTokens,\n uint8[] memory decimals,\n string memory lpTokenName,\n string memory lpTokenSymbol,\n uint256 _a,\n uint256 _fee,\n uint256 _adminFee,\n address lpTokenTargetAddress\n ) public virtual override initializer {\n Swap.initialize(\n _pooledTokens,\n decimals,\n lpTokenName,\n lpTokenSymbol,\n _a,\n _fee,\n _adminFee,\n lpTokenTargetAddress\n );\n flashLoanFeeBPS = 8; // 8 bps\n protocolFeeShareBPS = 0; // 0 bps\n }\n\n /*** STATE MODIFYING FUNCTIONS ***/\n\n /**\n * @notice Borrow the specified token from this pool for this transaction only. This function will call\n * `IFlashLoanReceiver(receiver).executeOperation` and the `receiver` must return the full amount of the token\n * and the associated fee by the end of the callback transaction. If the conditions are not met, this call\n * is reverted.\n * @param receiver the address of the receiver of the token. This address must implement the IFlashLoanReceiver\n * interface and the callback function `executeOperation`.\n * @param token the protocol fee in bps to be applied on the total flash loan fee\n * @param amount the total amount to borrow in this transaction\n * @param params optional data to pass along to the callback function\n */\n function flashLoan(\n address receiver,\n IERC20 token,\n uint256 amount,\n bytes memory params\n ) external nonReentrant {\n uint8 tokenIndex = getTokenIndex(address(token));\n uint256 availableLiquidityBefore = token.balanceOf(address(this));\n uint256 protocolBalanceBefore = availableLiquidityBefore.sub(\n swapStorage.balances[tokenIndex]\n );\n require(\n amount > 0 && availableLiquidityBefore >= amount,\n \"invalid amount\"\n );\n\n // Calculate the additional amount of tokens the pool should end up with\n uint256 amountFee = amount.mul(flashLoanFeeBPS).div(10000);\n // Calculate the portion of the fee that will go to the protocol\n uint256 protocolFee = amountFee.mul(protocolFeeShareBPS).div(10000);\n require(amountFee > 0, \"amount is small for a flashLoan\");\n\n // Transfer the requested amount of tokens\n token.safeTransfer(receiver, amount);\n\n // Execute callback function on receiver\n IFlashLoanReceiver(receiver).executeOperation(\n address(this),\n address(token),\n amount,\n amountFee,\n params\n );\n\n uint256 availableLiquidityAfter = token.balanceOf(address(this));\n require(\n availableLiquidityAfter >= availableLiquidityBefore.add(amountFee),\n \"flashLoan fee is not met\"\n );\n\n swapStorage.balances[tokenIndex] = availableLiquidityAfter\n .sub(protocolBalanceBefore)\n .sub(protocolFee);\n emit FlashLoan(receiver, tokenIndex, amount, amountFee, protocolFee);\n }\n\n /*** ADMIN FUNCTIONS ***/\n\n /**\n * @notice Updates the flash loan fee parameters. This function can only be called by the owner.\n * @param newFlashLoanFeeBPS the total fee in bps to be applied on future flash loans\n * @param newProtocolFeeShareBPS the protocol fee in bps to be applied on the total flash loan fee\n */\n function setFlashLoanFees(\n uint256 newFlashLoanFeeBPS,\n uint256 newProtocolFeeShareBPS\n ) external onlyOwner {\n require(\n newFlashLoanFeeBPS > 0 &&\n newFlashLoanFeeBPS <= MAX_BPS &&\n newProtocolFeeShareBPS <= MAX_BPS,\n \"fees are not in valid range\"\n );\n flashLoanFeeBPS = newFlashLoanFeeBPS;\n protocolFeeShareBPS = newProtocolFeeShareBPS;\n }\n}\n" + }, + "contracts/amm/interfaces/IFlashLoanReceiver.sol": { + "content": "// SPDX-License-Identifier: AGPL-3.0-only\n\npragma solidity 0.6.12;\n\n/**\n * @title IFlashLoanReceiver interface\n * @notice Interface for the Nerve fee IFlashLoanReceiver. Modified from Aave's IFlashLoanReceiver interface.\n * https://github.com/aave/aave-protocol/blob/4b4545fb583fd4f400507b10f3c3114f45b8a037/contracts/flashloan/interfaces/IFlashLoanReceiver.sol\n * @author Aave\n * @dev implement this interface to develop a flashloan-compatible flashLoanReceiver contract\n **/\ninterface IFlashLoanReceiver {\n function executeOperation(\n address pool,\n address token,\n uint256 amount,\n uint256 fee,\n bytes calldata params\n ) external;\n}\n" + }, + "contracts/amm/helper/FlashLoanBorrowerExample.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.6.12;\n\nimport \"@openzeppelin/contracts/math/SafeMath.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/SafeERC20.sol\";\nimport \"../interfaces/IFlashLoanReceiver.sol\";\nimport \"../interfaces/ISwapFlashLoan.sol\";\nimport \"hardhat/console.sol\";\n\ncontract FlashLoanBorrowerExample is IFlashLoanReceiver {\n using SafeMath for uint256;\n\n // Typical executeOperation function should do the 3 following actions\n // 1. Check if the flashLoan was successful\n // 2. Do actions with the borrowed tokens\n // 3. Repay the debt to the `pool`\n function executeOperation(\n address pool,\n address token,\n uint256 amount,\n uint256 fee,\n bytes calldata params\n ) external override {\n // 1. Check if the flashLoan was valid\n require(\n IERC20(token).balanceOf(address(this)) >= amount,\n \"flashloan is broken?\"\n );\n\n // 2. Do actions with the borrowed token\n bytes32 paramsHash = keccak256(params);\n if (paramsHash == keccak256(bytes(\"dontRepayDebt\"))) {\n return;\n } else if (paramsHash == keccak256(bytes(\"reentrancy_addLiquidity\"))) {\n ISwapFlashLoan(pool).addLiquidity(\n new uint256[](0),\n 0,\n block.timestamp\n );\n } else if (paramsHash == keccak256(bytes(\"reentrancy_swap\"))) {\n ISwapFlashLoan(pool).swap(1, 0, 1e6, 0, now);\n } else if (\n paramsHash == keccak256(bytes(\"reentrancy_removeLiquidity\"))\n ) {\n ISwapFlashLoan(pool).removeLiquidity(1e18, new uint256[](0), now);\n } else if (\n paramsHash == keccak256(bytes(\"reentrancy_removeLiquidityOneToken\"))\n ) {\n ISwapFlashLoan(pool).removeLiquidityOneToken(1e18, 0, 1e18, now);\n }\n\n // 3. Payback debt\n uint256 totalDebt = amount.add(fee);\n IERC20(token).transfer(pool, totalDebt);\n }\n\n function flashLoan(\n ISwapFlashLoan swap,\n IERC20 token,\n uint256 amount,\n bytes memory params\n ) external {\n swap.flashLoan(address(this), token, amount, params);\n }\n}\n" + }, + "contracts/amm/interfaces/ISwapFlashLoan.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.6.12;\n\nimport \"./ISwap.sol\";\n\ninterface ISwapFlashLoan is ISwap {\n function flashLoan(\n address receiver,\n IERC20 token,\n uint256 amount,\n bytes memory params\n ) external;\n}\n" + }, + "hardhat/console.sol": { + "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" + }, + "contracts/amm/helper/test/TestSwapReturnValues.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.6.12;\n\nimport \"../../interfaces/ISwap.sol\";\nimport \"hardhat/console.sol\";\n\ncontract TestSwapReturnValues {\n using SafeMath for uint256;\n\n ISwap public swap;\n IERC20 public lpToken;\n uint8 public n;\n\n uint256 public constant MAX_INT = 2**256 - 1;\n\n constructor(\n ISwap swapContract,\n IERC20 lpTokenContract,\n uint8 numOfTokens\n ) public {\n swap = swapContract;\n lpToken = lpTokenContract;\n n = numOfTokens;\n\n // Pre-approve tokens\n for (uint8 i; i < n; i++) {\n swap.getToken(i).approve(address(swap), MAX_INT);\n }\n lpToken.approve(address(swap), MAX_INT);\n }\n\n function test_swap(\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx,\n uint256 minDy\n ) public {\n uint256 balanceBefore =\n swap.getToken(tokenIndexTo).balanceOf(address(this));\n uint256 returnValue =\n swap.swap(tokenIndexFrom, tokenIndexTo, dx, minDy, block.timestamp);\n uint256 balanceAfter =\n swap.getToken(tokenIndexTo).balanceOf(address(this));\n\n console.log(\n \"swap: Expected %s, got %s\",\n balanceAfter.sub(balanceBefore),\n returnValue\n );\n\n require(\n returnValue == balanceAfter.sub(balanceBefore),\n \"swap()'s return value does not match received amount\"\n );\n }\n\n function test_addLiquidity(uint256[] calldata amounts, uint256 minToMint)\n public\n {\n uint256 balanceBefore = lpToken.balanceOf(address(this));\n uint256 returnValue = swap.addLiquidity(amounts, minToMint, MAX_INT);\n uint256 balanceAfter = lpToken.balanceOf(address(this));\n\n console.log(\n \"addLiquidity: Expected %s, got %s\",\n balanceAfter.sub(balanceBefore),\n returnValue\n );\n\n require(\n returnValue == balanceAfter.sub(balanceBefore),\n \"addLiquidity()'s return value does not match minted amount\"\n );\n }\n\n function test_removeLiquidity(uint256 amount, uint256[] memory minAmounts)\n public\n {\n uint256[] memory balanceBefore = new uint256[](n);\n uint256[] memory balanceAfter = new uint256[](n);\n\n for (uint8 i = 0; i < n; i++) {\n balanceBefore[i] = swap.getToken(i).balanceOf(address(this));\n }\n\n uint256[] memory returnValue =\n swap.removeLiquidity(amount, minAmounts, MAX_INT);\n\n for (uint8 i = 0; i < n; i++) {\n balanceAfter[i] = swap.getToken(i).balanceOf(address(this));\n console.log(\n \"removeLiquidity: Expected %s, got %s\",\n balanceAfter[i].sub(balanceBefore[i]),\n returnValue[i]\n );\n require(\n balanceAfter[i].sub(balanceBefore[i]) == returnValue[i],\n \"removeLiquidity()'s return value does not match received amounts of tokens\"\n );\n }\n }\n\n function test_removeLiquidityImbalance(\n uint256[] calldata amounts,\n uint256 maxBurnAmount\n ) public {\n uint256 balanceBefore = lpToken.balanceOf(address(this));\n uint256 returnValue =\n swap.removeLiquidityImbalance(amounts, maxBurnAmount, MAX_INT);\n uint256 balanceAfter = lpToken.balanceOf(address(this));\n\n console.log(\n \"removeLiquidityImbalance: Expected %s, got %s\",\n balanceBefore.sub(balanceAfter),\n returnValue\n );\n\n require(\n returnValue == balanceBefore.sub(balanceAfter),\n \"removeLiquidityImbalance()'s return value does not match burned lpToken amount\"\n );\n }\n\n function test_removeLiquidityOneToken(\n uint256 tokenAmount,\n uint8 tokenIndex,\n uint256 minAmount\n ) public {\n uint256 balanceBefore =\n swap.getToken(tokenIndex).balanceOf(address(this));\n uint256 returnValue =\n swap.removeLiquidityOneToken(\n tokenAmount,\n tokenIndex,\n minAmount,\n MAX_INT\n );\n uint256 balanceAfter =\n swap.getToken(tokenIndex).balanceOf(address(this));\n\n console.log(\n \"removeLiquidityOneToken: Expected %s, got %s\",\n balanceAfter.sub(balanceBefore),\n returnValue\n );\n\n require(\n returnValue == balanceAfter.sub(balanceBefore),\n \"removeLiquidityOneToken()'s return value does not match received token amount\"\n );\n }\n}\n" + }, + "contracts/amm/SwapDeployer.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.6.12;\n\nimport \"@openzeppelin/contracts/access/Ownable.sol\";\nimport \"@openzeppelin/contracts/proxy/Clones.sol\";\nimport \"./interfaces/ISwap.sol\";\n\ncontract SwapDeployer is Ownable {\n event NewSwapPool(\n address indexed deployer,\n address swapAddress,\n IERC20[] pooledTokens\n );\n\n constructor() public Ownable() {}\n\n function deploy(\n address swapAddress,\n IERC20[] memory _pooledTokens,\n uint8[] memory decimals,\n string memory lpTokenName,\n string memory lpTokenSymbol,\n uint256 _a,\n uint256 _fee,\n uint256 _adminFee,\n address lpTokenTargetAddress\n ) external returns (address) {\n address swapClone = Clones.clone(swapAddress);\n ISwap(swapClone).initialize(\n _pooledTokens,\n decimals,\n lpTokenName,\n lpTokenSymbol,\n _a,\n _fee,\n _adminFee,\n lpTokenTargetAddress\n );\n Ownable(swapClone).transferOwnership(owner());\n emit NewSwapPool(msg.sender, swapClone, _pooledTokens);\n return swapClone;\n }\n}\n" + }, + "@openzeppelin/contracts/access/Ownable.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <0.8.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 () internal {\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" + }, + "contracts/bridge/SynapseERC20Factory.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.6.12;\n\nimport \"@openzeppelin/contracts/access/Ownable.sol\";\nimport \"@openzeppelin/contracts/proxy/Clones.sol\";\nimport \"./interfaces/ISynapseERC20.sol\";\n\ncontract SynapseERC20Factory {\n constructor() public {}\n\n event SynapseERC20Created(address contractAddress);\n\n /**\n * @notice Deploys a new node\n * @param synapseERC20Address address of the synapseERC20Address contract to initialize with\n * @param name Token name\n * @param symbol Token symbol\n * @param decimals Token name\n * @param owner admin address to be initialized with\n * @return Address of the newest node management contract created\n **/\n function deploy(\n address synapseERC20Address,\n string memory name,\n string memory symbol,\n uint8 decimals,\n address owner\n ) external returns (address) {\n address synERC20Clone = Clones.clone(synapseERC20Address);\n ISynapseERC20(synERC20Clone).initialize(name, symbol, decimals, owner);\n\n emit SynapseERC20Created(synERC20Clone);\n\n return synERC20Clone;\n }\n}\n" + }, + "contracts/bridge/interfaces/ISynapseERC20.sol": { + "content": "// SPDX-License-Identifier: MIT\n\n\npragma solidity 0.6.12;\n\ninterface ISynapseERC20 { \n function initialize(\n string memory _name, string memory _symbol, uint8 _decimals, address owner) external;\n\n function mint(address to, uint256 amount) external;\n}\n\n" + }, + "contracts/bridge/mocks/JewelTokenMock.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.6.12;\n\nimport \"@openzeppelin/contracts/token/ERC20/ERC20.sol\";\nimport \"@openzeppelin/contracts/access/Ownable.sol\";\nimport \"./Authorizable.sol\";\n\nimport \"./IProfiles.sol\";\n\n/**\n * @author DefiKingdoms\n * @title JewelToken\n */\ncontract JewelToken is ERC20, Ownable, Authorizable {\n uint256 private _cap;\n uint256 private _totalLock;\n uint256 public lockFromBlock;\n uint256 public lockToBlock;\n uint256 public manualMintLimit;\n uint256 public manualMinted = 0;\n address public miner;\n IProfiles public profilesContract;\n uint64 public profileAgeReq = 0;\n\n mapping(address => uint256) private _locks;\n mapping(address => uint256) private _lastUnlockBlock;\n\n // Max transfer amount rate in basis points. Default is 100% of total\n // supply, and it can't be less than 0.5% of the supply.\n uint16 public maxTransferAmountRate = 10000;\n\n // Addresses that are excluded from anti-whale checking.\n mapping(address => bool) private _excludedFromAntiWhale;\n\n // Events.\n event MaxTransferAmountRateUpdated(uint256 previousRate, uint256 newRate);\n event Lock(address indexed to, uint256 value);\n event Unlock(address indexed to, uint256 value);\n\n // Modifiers.\n\n /**\n * @dev Ensures that the anti-whale rules are enforced.\n */\n modifier antiWhale(address sender, address recipient, uint256 amount) {\n if (maxTransferAmount() > 0) {\n if (\n _excludedFromAntiWhale[sender] == false\n && _excludedFromAntiWhale[recipient] == false\n ) {\n require(amount <= maxTransferAmount(), \"antiWhale: Transfer amount exceeds the maxTransferAmount\");\n }\n }\n _;\n }\n\n /**\n * @dev Ensures that the recipient has a profile.\n */\n modifier onlyProfile(address sender, address recipient) {\n if (profileAgeReq > 0) {\n if (\n _excludedFromAntiWhale[recipient] == false\n ) {\n // Get the profile of the recipient, and check the age.\n uint64 _created = 0;\n (, , , _created, , , ) = profilesContract.getProfileByAddress(recipient);\n require(_created > 0 && ((block.timestamp - _created) > profileAgeReq), \"profile not old enough\");\n }\n }\n _;\n }\n\n constructor(\n string memory _name,\n string memory _symbol,\n uint256 cap_,\n uint256 _manualMintLimit,\n uint256 _lockFromBlock,\n uint256 _lockToBlock\n ) public ERC20(_name, _symbol) {\n _cap = cap_;\n manualMintLimit = _manualMintLimit;\n lockFromBlock = _lockFromBlock;\n lockToBlock = _lockToBlock;\n\n _excludedFromAntiWhale[msg.sender] = true;\n _excludedFromAntiWhale[address(0)] = true;\n _excludedFromAntiWhale[address(this)] = true;\n }\n\n /**\n * @dev Returns the cap on the token's total supply.\n */\n function cap() public view returns (uint256) {\n return _cap;\n }\n\n /**\n * @dev Updates the total cap.\n */\n function capUpdate(uint256 _newCap) public onlyAuthorized {\n _cap = _newCap;\n }\n\n /// @dev Sets the profiles contract.\n function setProfiles(address _profilesAddress) public onlyAuthorized returns (bool success) {\n IProfiles candidateContract = IProfiles(_profilesAddress);\n\n // Verify that it is an actual contract.\n require(candidateContract.heroesNftContract() != address(0), \"invalid\");\n\n // Set it.\n profilesContract = candidateContract;\n return true;\n }\n\n /// @dev Sets the profiles age requirement.\n function setProfileAgeReq(uint64 _age) public onlyAuthorized returns (bool success) {\n // Set it.\n profileAgeReq = _age;\n return true;\n }\n\n // Update the lockFromBlock\n function lockFromUpdate(uint256 _newLockFrom) public onlyAuthorized {\n lockFromBlock = _newLockFrom;\n }\n\n // Update the lockToBlock\n function lockToUpdate(uint256 _newLockTo) public onlyAuthorized {\n lockToBlock = _newLockTo;\n }\n\n function unlockedSupply() public view returns (uint256) {\n return totalSupply().sub(_totalLock);\n }\n\n function lockedSupply() public view returns (uint256) {\n return totalLock();\n }\n\n function circulatingSupply() public view returns (uint256) {\n return totalSupply();\n }\n\n function totalLock() public view returns (uint256) {\n return _totalLock;\n }\n\n /**\n * @dev See {ERC20-_beforeTokenTransfer}.\n *\n * Requirements:\n *\n * - minted tokens must not cause the total supply to go over the cap.\n */\n function _beforeTokenTransfer(\n address from,\n address to,\n uint256 amount\n ) internal virtual override {\n super._beforeTokenTransfer(from, to, amount);\n\n if (from == address(0)) {\n // When minting tokens\n require(\n totalSupply().add(amount) <= _cap,\n \"ERC20Capped: cap exceeded\"\n );\n }\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(\n address sender,\n address recipient,\n uint256 amount\n ) internal virtual override\n antiWhale(sender, recipient, amount)\n onlyProfile(sender, recipient) {\n super._transfer(sender, recipient, amount);\n _moveDelegates(_delegates[sender], _delegates[recipient], amount);\n }\n\n /// @notice Creates `_amount` token to `_to`. Must only be called by the owner (MasterGardener).\n function mint(address _to, uint256 _amount) public onlyOwner {\n _mint(_to, _amount);\n _moveDelegates(address(0), _delegates[_to], _amount);\n }\n\n function manualMint(address _to, uint256 _amount) public onlyAuthorized {\n require(manualMinted < manualMintLimit, \"ERC20: manualMinted greater than manualMintLimit\");\n _mint(_to, _amount);\n _moveDelegates(address(0), _delegates[_to], _amount);\n manualMinted = manualMinted.add(_amount);\n }\n\n function totalBalanceOf(address _holder) public view returns (uint256) {\n return _locks[_holder].add(balanceOf(_holder));\n }\n\n function lockOf(address _holder) public view returns (uint256) {\n return _locks[_holder];\n }\n\n function lastUnlockBlock(address _holder) public view returns (uint256) {\n return _lastUnlockBlock[_holder];\n }\n\n function lock(address _holder, uint256 _amount) public onlyAuthorized {\n require(_holder != address(0), \"Cannot lock to the zero address\");\n require(\n _amount <= balanceOf(_holder),\n \"Lock amount over balance\"\n );\n\n _transfer(_holder, address(this), _amount);\n\n _locks[_holder] = _locks[_holder].add(_amount);\n _totalLock = _totalLock.add(_amount);\n if (_lastUnlockBlock[_holder] < lockFromBlock) {\n _lastUnlockBlock[_holder] = lockFromBlock;\n }\n emit Lock(_holder, _amount);\n }\n\n function canUnlockAmount(address _holder) public view returns (uint256) {\n if (block.number < lockFromBlock) {\n return 0;\n } else if (block.number >= lockToBlock) {\n return _locks[_holder];\n } else {\n uint256 releaseBlock = block.number.sub(_lastUnlockBlock[_holder]);\n uint256 numberLockBlock =\n lockToBlock.sub(_lastUnlockBlock[_holder]);\n return _locks[_holder].mul(releaseBlock).div(numberLockBlock);\n }\n }\n\n // Unlocks some locked tokens immediately.\n function unlockForUser(address account, uint256 amount) public onlyAuthorized {\n // First we need to unlock all tokens the address is eligible for.\n uint256 pendingLocked = canUnlockAmount(account);\n if (pendingLocked > 0) {\n _unlock(account, pendingLocked);\n }\n\n // Now that that's done, we can unlock the extra amount passed in.\n _unlock(account, amount);\n }\n\n function unlock() public {\n uint256 amount = canUnlockAmount(msg.sender);\n _unlock(msg.sender, amount);\n }\n\n function _unlock(address holder, uint256 amount) internal {\n require(_locks[holder] > 0, \"Insufficient locked tokens\");\n\n // Make sure they aren't trying to unlock more than they have locked.\n if (amount > _locks[holder]) {\n amount = _locks[holder];\n }\n\n // If the amount is greater than the total balance, set it to max.\n if (amount > balanceOf(address(this))) {\n amount = balanceOf(address(this));\n }\n _transfer(address(this), holder, amount);\n _locks[holder] = _locks[holder].sub(amount);\n _lastUnlockBlock[holder] = block.number;\n _totalLock = _totalLock.sub(amount);\n\n emit Unlock(holder, amount);\n }\n\n // This function is for dev address migrate all balance to a multi sig address\n function transferAll(address _to) public {\n _locks[_to] = _locks[_to].add(_locks[msg.sender]);\n\n if (_lastUnlockBlock[_to] < lockFromBlock) {\n _lastUnlockBlock[_to] = lockFromBlock;\n }\n\n if (_lastUnlockBlock[_to] < _lastUnlockBlock[msg.sender]) {\n _lastUnlockBlock[_to] = _lastUnlockBlock[msg.sender];\n }\n\n _locks[msg.sender] = 0;\n _lastUnlockBlock[msg.sender] = 0;\n\n _transfer(msg.sender, _to, balanceOf(msg.sender));\n }\n\n // Copied and modified from YAM code:\n // https://github.com/yam-finance/yam-protocol/blob/master/contracts/token/YAMGovernanceStorage.sol\n // https://github.com/yam-finance/yam-protocol/blob/master/contracts/token/YAMGovernance.sol\n // Which is copied and modified from COMPOUND:\n // https://github.com/compound-finance/compound-protocol/blob/master/contracts/Governance/Comp.sol\n\n /// @dev A record of each accounts delegate\n mapping(address => address) internal _delegates;\n\n /// @notice A checkpoint for marking number of votes from a given block\n struct Checkpoint {\n uint32 fromBlock;\n uint256 votes;\n }\n\n /// @notice A record of votes checkpoints for each account, by index\n mapping(address => mapping(uint32 => Checkpoint)) public checkpoints;\n\n /// @notice The number of checkpoints for each account\n mapping(address => uint32) public numCheckpoints;\n\n /// @notice The EIP-712 typehash for the contract's domain\n bytes32 public constant DOMAIN_TYPEHASH =\n keccak256(\n \"EIP712Domain(string name,uint256 chainId,address verifyingContract)\"\n );\n\n /// @notice The EIP-712 typehash for the delegation struct used by the contract\n bytes32 public constant DELEGATION_TYPEHASH =\n keccak256(\"Delegation(address delegatee,uint256 nonce,uint256 expiry)\");\n\n /// @notice A record of states for signing / validating signatures\n mapping(address => uint256) public nonces;\n\n /// @notice An event thats emitted when an account changes its delegate\n event DelegateChanged(\n address indexed delegator,\n address indexed fromDelegate,\n address indexed toDelegate\n );\n\n /// @notice An event thats emitted when a delegate account's vote balance changes\n event DelegateVotesChanged(\n address indexed delegate,\n uint256 previousBalance,\n uint256 newBalance\n );\n\n /**\n * @notice Delegate votes from `msg.sender` to `delegatee`\n * @param delegator The address to get delegatee for\n */\n function delegates(address delegator) external view returns (address) {\n return _delegates[delegator];\n }\n\n /**\n * @notice Delegate votes from `msg.sender` to `delegatee`\n * @param delegatee The address to delegate votes to\n */\n function delegate(address delegatee) external {\n return _delegate(msg.sender, delegatee);\n }\n\n /**\n * @notice Delegates votes from signatory to `delegatee`\n * @param delegatee The address to delegate votes to\n * @param nonce The contract state required to match the signature\n * @param expiry The time at which to expire the signature\n * @param v The recovery byte of the signature\n * @param r Half of the ECDSA signature pair\n * @param s Half of the ECDSA signature pair\n */\n function delegateBySig(\n address delegatee,\n uint256 nonce,\n uint256 expiry,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) external {\n bytes32 domainSeparator =\n keccak256(\n abi.encode(\n DOMAIN_TYPEHASH,\n keccak256(bytes(name())),\n getChainId(),\n address(this)\n )\n );\n\n bytes32 structHash =\n keccak256(\n abi.encode(DELEGATION_TYPEHASH, delegatee, nonce, expiry)\n );\n\n bytes32 digest =\n keccak256(\n abi.encodePacked(\"\\x19\\x01\", domainSeparator, structHash)\n );\n\n address signatory = ecrecover(digest, v, r, s);\n require(\n signatory != address(0),\n \"JewelToken::delegateBySig: invalid signature\"\n );\n require(\n nonce == nonces[signatory]++,\n \"JewelToken::delegateBySig: invalid nonce\"\n );\n require(now <= expiry, \"JewelToken::delegateBySig: signature expired\");\n return _delegate(signatory, delegatee);\n }\n\n /**\n * @notice Gets the current votes balance for `account`\n * @param account The address to get votes balance\n * @return The number of current votes for `account`\n */\n function getCurrentVotes(address account) external view returns (uint256) {\n uint32 nCheckpoints = numCheckpoints[account];\n return\n nCheckpoints > 0 ? checkpoints[account][nCheckpoints - 1].votes : 0;\n }\n\n /**\n * @notice Determine the prior number of votes for an account as of a block number\n * @dev Block number must be a finalized block or else this function will revert to prevent misinformation.\n * @param account The address of the account to check\n * @param blockNumber The block number to get the vote balance at\n * @return The number of votes the account had as of the given block\n */\n function getPriorVotes(address account, uint256 blockNumber)\n external\n view\n returns (uint256)\n {\n require(\n blockNumber < block.number,\n \"JewelToken::getPriorVotes: not yet determined\"\n );\n\n uint32 nCheckpoints = numCheckpoints[account];\n if (nCheckpoints == 0) {\n return 0;\n }\n\n // First check most recent balance\n if (checkpoints[account][nCheckpoints - 1].fromBlock <= blockNumber) {\n return checkpoints[account][nCheckpoints - 1].votes;\n }\n\n // Next check implicit zero balance\n if (checkpoints[account][0].fromBlock > blockNumber) {\n return 0;\n }\n\n uint32 lower = 0;\n uint32 upper = nCheckpoints - 1;\n while (upper > lower) {\n uint32 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\n Checkpoint memory cp = checkpoints[account][center];\n if (cp.fromBlock == blockNumber) {\n return cp.votes;\n } else if (cp.fromBlock < blockNumber) {\n lower = center;\n } else {\n upper = center - 1;\n }\n }\n return checkpoints[account][lower].votes;\n }\n\n function _delegate(address delegator, address delegatee) internal {\n address currentDelegate = _delegates[delegator];\n uint256 delegatorBalance = balanceOf(delegator);\n _delegates[delegator] = delegatee;\n\n emit DelegateChanged(delegator, currentDelegate, delegatee);\n\n _moveDelegates(currentDelegate, delegatee, delegatorBalance);\n }\n\n function _moveDelegates(\n address srcRep,\n address dstRep,\n uint256 amount\n ) internal {\n if (srcRep != dstRep && amount > 0) {\n if (srcRep != address(0)) {\n // decrease old representative\n uint32 srcRepNum = numCheckpoints[srcRep];\n uint256 srcRepOld =\n srcRepNum > 0\n ? checkpoints[srcRep][srcRepNum - 1].votes\n : 0;\n uint256 srcRepNew = srcRepOld.sub(amount);\n _writeCheckpoint(srcRep, srcRepNum, srcRepOld, srcRepNew);\n }\n\n if (dstRep != address(0)) {\n // increase new representative\n uint32 dstRepNum = numCheckpoints[dstRep];\n uint256 dstRepOld =\n dstRepNum > 0\n ? checkpoints[dstRep][dstRepNum - 1].votes\n : 0;\n uint256 dstRepNew = dstRepOld.add(amount);\n _writeCheckpoint(dstRep, dstRepNum, dstRepOld, dstRepNew);\n }\n }\n }\n\n function _writeCheckpoint(\n address delegatee,\n uint32 nCheckpoints,\n uint256 oldVotes,\n uint256 newVotes\n ) internal {\n uint32 blockNumber =\n safe32(\n block.number,\n \"JewelToken::_writeCheckpoint: block number exceeds 32 bits\"\n );\n\n if (\n nCheckpoints > 0 &&\n checkpoints[delegatee][nCheckpoints - 1].fromBlock == blockNumber\n ) {\n checkpoints[delegatee][nCheckpoints - 1].votes = newVotes;\n } else {\n checkpoints[delegatee][nCheckpoints] = Checkpoint(\n blockNumber,\n newVotes\n );\n numCheckpoints[delegatee] = nCheckpoints + 1;\n }\n\n emit DelegateVotesChanged(delegatee, oldVotes, newVotes);\n }\n\n function safe32(uint256 n, string memory errorMessage)\n internal\n pure\n returns (uint32)\n {\n require(n < 2**32, errorMessage);\n return uint32(n);\n }\n\n function getChainId() internal pure returns (uint256) {\n uint256 chainId;\n assembly {\n chainId := chainid()\n }\n return chainId;\n }\n\n /**\n * @dev Update the max transfer amount rate.\n */\n function updateMaxTransferAmountRate(uint16 _maxTransferAmountRate) public onlyAuthorized {\n require(_maxTransferAmountRate <= 10000, \"updateMaxTransferAmountRate: Max transfer amount rate must not exceed the maximum rate.\");\n require(_maxTransferAmountRate >= 50, \"updateMaxTransferAmountRate: Max transfer amount rate must be more than 0.005.\");\n emit MaxTransferAmountRateUpdated(maxTransferAmountRate, _maxTransferAmountRate);\n maxTransferAmountRate = _maxTransferAmountRate;\n }\n\n /**\n * @dev Calculates the max transfer amount.\n */\n function maxTransferAmount() public view returns (uint256) {\n return totalSupply().mul(maxTransferAmountRate).div(10000);\n }\n\n /**\n * @dev Sets an address as excluded or not from the anti-whale checking.\n */\n function setExcludedFromAntiWhale(address _account, bool _excluded) public onlyAuthorized {\n _excludedFromAntiWhale[_account] = _excluded;\n }\n}" + }, + "contracts/bridge/mocks/Authorizable.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.6.12;\n\nimport \"@openzeppelin/contracts/access/Ownable.sol\";\n\ncontract Authorizable is Ownable {\n mapping(address => bool) public authorized;\n\n modifier onlyAuthorized() {\n require(authorized[msg.sender] || owner() == msg.sender, \"caller is not authorized\");\n _;\n }\n\n function addAuthorized(address _toAdd) public onlyOwner {\n authorized[_toAdd] = true;\n }\n\n function removeAuthorized(address _toRemove) public onlyOwner {\n require(_toRemove != msg.sender);\n authorized[_toRemove] = false;\n }\n}" + }, + "contracts/bridge/mocks/IProfiles.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.6.12;\n\ninterface IProfiles {\n function DEFAULT_ADMIN_ROLE ( ) external view returns ( bytes32 );\n function MODERATOR_ROLE ( ) external view returns ( bytes32 );\n function POINTS_ROLE ( ) external view returns ( bytes32 );\n function addPoints ( address _address, uint256 _points ) external returns ( bool success );\n function addressToIndex ( address ) external view returns ( uint256 );\n function addresses ( uint256 ) external view returns ( address );\n function changeHeroPic ( uint256 profileId, uint256 _heroId ) external returns ( bool success );\n function changeName ( uint256 profileId, string memory _name ) external returns ( bool success );\n function changePic ( uint256 profileId, uint8 _picId ) external returns ( bool success );\n function createProfile ( string memory _name, uint8 _picId ) external returns ( bool success );\n function getAddressByName ( string memory name ) external view returns ( address profileAddress );\n function getProfileByAddress ( address profileAddress ) external view returns ( uint256 _id, address _owner, string memory _name, uint64 _created, uint8 _picId, uint256 _heroId, uint256 _points );\n function getProfileByName ( string memory name ) external view returns ( uint256 _id, address _owner, string memory _name, uint64 _created, uint8 _picId, uint256 _heroId, uint256 _points );\n function getProfileCount ( ) external view returns ( uint256 count );\n function getRoleAdmin ( bytes32 role ) external view returns ( bytes32 );\n function grantRole ( bytes32 role, address account ) external;\n function hasRole ( bytes32 role, address account ) external view returns ( bool );\n function heroesNftContract ( ) external view returns ( address );\n function initialize ( ) external;\n function nameTaken ( string memory name ) external view returns ( bool taken );\n function nameToIndex ( string memory ) external view returns ( uint256 );\n function points ( uint256 ) external view returns ( uint256 );\n function profileExists ( address profileAddress ) external view returns ( bool exists );\n function profiles ( uint256 ) external view returns ( uint256 id, address owner, string memory name, uint64 created, uint8 picId, uint256 heroId, bool set );\n function renounceRole ( bytes32 role, address account ) external;\n function revokeRole ( bytes32 role, address account ) external;\n function setHeroes ( address _address ) external returns ( bool success );\n function setNameLengths ( uint8 _min, uint8 _max ) external returns ( bool success );\n function setPicMax ( uint8 _max ) external returns ( bool success );\n function supportsInterface ( bytes4 interfaceId ) external view returns ( bool );\n}" + }, + "@openzeppelin/contracts/drafts/ERC20Permit.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.5 <0.8.0;\n\nimport \"../token/ERC20/ERC20.sol\";\nimport \"./IERC20Permit.sol\";\nimport \"../cryptography/ECDSA.sol\";\nimport \"../utils/Counters.sol\";\nimport \"./EIP712.sol\";\n\n/**\n * @dev Implementation of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in\n * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612].\n *\n * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by\n * presenting a message signed by the account. By not relying on `{IERC20-approve}`, the token holder account doesn't\n * need to send a transaction, and thus is not required to hold Ether at all.\n *\n * _Available since v3.4._\n */\nabstract contract ERC20Permit is ERC20, IERC20Permit, EIP712 {\n using Counters for Counters.Counter;\n\n mapping (address => Counters.Counter) private _nonces;\n\n // solhint-disable-next-line var-name-mixedcase\n bytes32 private immutable _PERMIT_TYPEHASH = keccak256(\"Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)\");\n\n /**\n * @dev Initializes the {EIP712} domain separator using the `name` parameter, and setting `version` to `\"1\"`.\n *\n * It's a good idea to use the same `name` that is defined as the ERC20 token name.\n */\n constructor(string memory name) internal EIP712(name, \"1\") {\n }\n\n /**\n * @dev See {IERC20Permit-permit}.\n */\n function permit(address owner, address spender, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s) public virtual override {\n // solhint-disable-next-line not-rely-on-time\n require(block.timestamp <= deadline, \"ERC20Permit: expired deadline\");\n\n bytes32 structHash = keccak256(\n abi.encode(\n _PERMIT_TYPEHASH,\n owner,\n spender,\n value,\n _nonces[owner].current(),\n deadline\n )\n );\n\n bytes32 hash = _hashTypedDataV4(structHash);\n\n address signer = ECDSA.recover(hash, v, r, s);\n require(signer == owner, \"ERC20Permit: invalid signature\");\n\n _nonces[owner].increment();\n _approve(owner, spender, value);\n }\n\n /**\n * @dev See {IERC20Permit-nonces}.\n */\n function nonces(address owner) public view override returns (uint256) {\n return _nonces[owner].current();\n }\n\n /**\n * @dev See {IERC20Permit-DOMAIN_SEPARATOR}.\n */\n // solhint-disable-next-line func-name-mixedcase\n function DOMAIN_SEPARATOR() external view override returns (bytes32) {\n return _domainSeparatorV4();\n }\n}\n" + }, + "@openzeppelin/contracts/drafts/IERC20Permit.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <0.8.0;\n\n/**\n * @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in\n * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612].\n *\n * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by\n * presenting a message signed by the account. By not relying on `{IERC20-approve}`, the token holder account doesn't\n * need to send a transaction, and thus is not required to hold Ether at all.\n */\ninterface IERC20Permit {\n /**\n * @dev Sets `value` as the allowance of `spender` over `owner`'s tokens,\n * given `owner`'s signed approval.\n *\n * IMPORTANT: The same issues {IERC20-approve} has related to transaction\n * ordering also apply here.\n *\n * Emits an {Approval} event.\n *\n * Requirements:\n *\n * - `spender` cannot be the zero address.\n * - `deadline` must be a timestamp in the future.\n * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner`\n * over the EIP712-formatted function arguments.\n * - the signature must use ``owner``'s current nonce (see {nonces}).\n *\n * For more information on the signature format, see the\n * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP\n * section].\n */\n function permit(address owner, address spender, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s) external;\n\n /**\n * @dev Returns the current nonce for `owner`. This value must be\n * included whenever a signature is generated for {permit}.\n *\n * Every successful call to {permit} increases ``owner``'s nonce by one. This\n * prevents a signature from being used multiple times.\n */\n function nonces(address owner) external view returns (uint256);\n\n /**\n * @dev Returns the domain separator used in the encoding of the signature for `permit`, as defined by {EIP712}.\n */\n // solhint-disable-next-line func-name-mixedcase\n function DOMAIN_SEPARATOR() external view returns (bytes32);\n}\n" + }, + "@openzeppelin/contracts/cryptography/ECDSA.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <0.8.0;\n\n/**\n * @dev Elliptic Curve Digital Signature Algorithm (ECDSA) operations.\n *\n * These functions can be used to verify that a message was signed by the holder\n * of the private keys of a given address.\n */\nlibrary ECDSA {\n /**\n * @dev Returns the address that signed a hashed message (`hash`) with\n * `signature`. This address can then be used for verification purposes.\n *\n * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:\n * this function rejects them by requiring the `s` value to be in the lower\n * half order, and the `v` value to be either 27 or 28.\n *\n * IMPORTANT: `hash` _must_ be the result of a hash operation for the\n * verification to be secure: it is possible to craft signatures that\n * recover to arbitrary addresses for non-hashed data. A safe way to ensure\n * this is by receiving a hash of the original message (which may otherwise\n * be too long), and then calling {toEthSignedMessageHash} on it.\n */\n function recover(bytes32 hash, bytes memory signature) internal pure returns (address) {\n // Check the signature length\n if (signature.length != 65) {\n revert(\"ECDSA: invalid signature length\");\n }\n\n // Divide the signature in r, s and v variables\n bytes32 r;\n bytes32 s;\n uint8 v;\n\n // ecrecover takes the signature parameters, and the only way to get them\n // currently is to use assembly.\n // solhint-disable-next-line no-inline-assembly\n assembly {\n r := mload(add(signature, 0x20))\n s := mload(add(signature, 0x40))\n v := byte(0, mload(add(signature, 0x60)))\n }\n\n return recover(hash, v, r, s);\n }\n\n /**\n * @dev Overload of {ECDSA-recover-bytes32-bytes-} that receives the `v`,\n * `r` and `s` signature fields separately.\n */\n function recover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) internal pure returns (address) {\n // EIP-2 still allows signature malleability for ecrecover(). Remove this possibility and make the signature\n // unique. Appendix F in the Ethereum Yellow paper (https://ethereum.github.io/yellowpaper/paper.pdf), defines\n // the valid range for s in (281): 0 < s < secp256k1n ÷ 2 + 1, and for v in (282): v ∈ {27, 28}. Most\n // signatures from current libraries generate a unique signature with an s-value in the lower half order.\n //\n // If your library generates malleable signatures, such as s-values in the upper range, calculate a new s-value\n // with 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 - s1 and flip v from 27 to 28 or\n // vice versa. If your library also generates signatures with 0/1 for v instead 27/28, add 27 to v to accept\n // these malleable signatures as well.\n require(uint256(s) <= 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0, \"ECDSA: invalid signature 's' value\");\n require(v == 27 || v == 28, \"ECDSA: invalid signature 'v' value\");\n\n // If the signature is valid (and not malleable), return the signer address\n address signer = ecrecover(hash, v, r, s);\n require(signer != address(0), \"ECDSA: invalid signature\");\n\n return signer;\n }\n\n /**\n * @dev Returns an Ethereum Signed Message, created from a `hash`. This\n * replicates the behavior of the\n * https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_sign[`eth_sign`]\n * JSON-RPC method.\n *\n * See {recover}.\n */\n function toEthSignedMessageHash(bytes32 hash) internal pure returns (bytes32) {\n // 32 is the length in bytes of hash,\n // enforced by the type signature above\n return keccak256(abi.encodePacked(\"\\x19Ethereum Signed Message:\\n32\", hash));\n }\n}\n" + }, + "@openzeppelin/contracts/utils/Counters.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <0.8.0;\n\nimport \"../math/SafeMath.sol\";\n\n/**\n * @title Counters\n * @author Matt Condon (@shrugs)\n * @dev Provides counters that can only be incremented or decremented by one. This can be used e.g. to track the number\n * of elements in a mapping, issuing ERC721 ids, or counting request ids.\n *\n * Include with `using Counters for Counters.Counter;`\n * Since it is not possible to overflow a 256 bit integer with increments of one, `increment` can skip the {SafeMath}\n * overflow check, thereby saving gas. This does assume however correct usage, in that the underlying `_value` is never\n * directly accessed.\n */\nlibrary Counters {\n using SafeMath for uint256;\n\n struct Counter {\n // This variable should never be directly accessed by users of the library: interactions must be restricted to\n // the library's function. As of Solidity v0.5.2, this cannot be enforced, though there is a proposal to add\n // this feature: see https://github.com/ethereum/solidity/issues/4637\n uint256 _value; // default: 0\n }\n\n function current(Counter storage counter) internal view returns (uint256) {\n return counter._value;\n }\n\n function increment(Counter storage counter) internal {\n // The {SafeMath} overflow check can be skipped here, see the comment at the top\n counter._value += 1;\n }\n\n function decrement(Counter storage counter) internal {\n counter._value = counter._value.sub(1);\n }\n}\n" + }, + "@openzeppelin/contracts/drafts/EIP712.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <0.8.0;\n\n/**\n * @dev https://eips.ethereum.org/EIPS/eip-712[EIP 712] is a standard for hashing and signing of typed structured data.\n *\n * The encoding specified in the EIP is very generic, and such a generic implementation in Solidity is not feasible,\n * thus this contract does not implement the encoding itself. Protocols need to implement the type-specific encoding\n * they need in their contracts using a combination of `abi.encode` and `keccak256`.\n *\n * This contract implements the EIP 712 domain separator ({_domainSeparatorV4}) that is used as part of the encoding\n * scheme, and the final step of the encoding to obtain the message digest that is then signed via ECDSA\n * ({_hashTypedDataV4}).\n *\n * The implementation of the domain separator was designed to be as efficient as possible while still properly updating\n * the chain id to protect against replay attacks on an eventual fork of the chain.\n *\n * NOTE: This contract implements the version of the encoding known as \"v4\", as implemented by the JSON RPC method\n * https://docs.metamask.io/guide/signing-data.html[`eth_signTypedDataV4` in MetaMask].\n *\n * _Available since v3.4._\n */\nabstract contract EIP712 {\n /* solhint-disable var-name-mixedcase */\n // Cache the domain separator as an immutable value, but also store the chain id that it corresponds to, in order to\n // invalidate the cached domain separator if the chain id changes.\n bytes32 private immutable _CACHED_DOMAIN_SEPARATOR;\n uint256 private immutable _CACHED_CHAIN_ID;\n\n bytes32 private immutable _HASHED_NAME;\n bytes32 private immutable _HASHED_VERSION;\n bytes32 private immutable _TYPE_HASH;\n /* solhint-enable var-name-mixedcase */\n\n /**\n * @dev Initializes the domain separator and parameter caches.\n *\n * The meaning of `name` and `version` is specified in\n * https://eips.ethereum.org/EIPS/eip-712#definition-of-domainseparator[EIP 712]:\n *\n * - `name`: the user readable name of the signing domain, i.e. the name of the DApp or the protocol.\n * - `version`: the current major version of the signing domain.\n *\n * NOTE: These parameters cannot be changed except through a xref:learn::upgrading-smart-contracts.adoc[smart\n * contract upgrade].\n */\n constructor(string memory name, string memory version) internal {\n bytes32 hashedName = keccak256(bytes(name));\n bytes32 hashedVersion = keccak256(bytes(version));\n bytes32 typeHash = keccak256(\"EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)\");\n _HASHED_NAME = hashedName;\n _HASHED_VERSION = hashedVersion;\n _CACHED_CHAIN_ID = _getChainId();\n _CACHED_DOMAIN_SEPARATOR = _buildDomainSeparator(typeHash, hashedName, hashedVersion);\n _TYPE_HASH = typeHash;\n }\n\n /**\n * @dev Returns the domain separator for the current chain.\n */\n function _domainSeparatorV4() internal view virtual returns (bytes32) {\n if (_getChainId() == _CACHED_CHAIN_ID) {\n return _CACHED_DOMAIN_SEPARATOR;\n } else {\n return _buildDomainSeparator(_TYPE_HASH, _HASHED_NAME, _HASHED_VERSION);\n }\n }\n\n function _buildDomainSeparator(bytes32 typeHash, bytes32 name, bytes32 version) private view returns (bytes32) {\n return keccak256(\n abi.encode(\n typeHash,\n name,\n version,\n _getChainId(),\n address(this)\n )\n );\n }\n\n /**\n * @dev Given an already https://eips.ethereum.org/EIPS/eip-712#definition-of-hashstruct[hashed struct], this\n * function returns the hash of the fully encoded EIP712 message for this domain.\n *\n * This hash can be used together with {ECDSA-recover} to obtain the signer of a message. For example:\n *\n * ```solidity\n * bytes32 digest = _hashTypedDataV4(keccak256(abi.encode(\n * keccak256(\"Mail(address to,string contents)\"),\n * mailTo,\n * keccak256(bytes(mailContents))\n * )));\n * address signer = ECDSA.recover(digest, signature);\n * ```\n */\n function _hashTypedDataV4(bytes32 structHash) internal view virtual returns (bytes32) {\n return keccak256(abi.encodePacked(\"\\x19\\x01\", _domainSeparatorV4(), structHash));\n }\n\n function _getChainId() private view returns (uint256 chainId) {\n this; // silence state mutability warning without generating bytecode - see https://github.com/ethereum/solidity/issues/2691\n // solhint-disable-next-line no-inline-assembly\n assembly {\n chainId := chainid()\n }\n }\n}\n" + }, + "contracts/bridge/wrappers/MigratorBridgeZap.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.6.12;\n\nimport '@openzeppelin/contracts/token/ERC20/IERC20.sol';\nimport '@openzeppelin/contracts/token/ERC20/SafeERC20.sol';\nimport '@openzeppelin/contracts/math/SafeMath.sol';\n\nimport '../interfaces/ISynapseBridge.sol';\nimport '../interfaces/IERC20Migrator.sol';\n\ncontract MigratorBridgeZap {\n using SafeERC20 for IERC20;\n using SafeMath for uint256;\n \n ISynapseBridge constant synapseBridge = ISynapseBridge(0xd123f70AE324d34A9E76b67a27bf77593bA8749f);\n IERC20Migrator constant erc20Migrator = IERC20Migrator(0xf0284FB86adA5E4D82555C529677eEA3B2C3E022); \n IERC20 constant legacyToken = IERC20(0x42F6f551ae042cBe50C739158b4f0CAC0Edb9096);\n IERC20 constant newToken = IERC20(0xa4080f1778e69467E905B8d6F72f6e441f9e9484);\n uint256 constant MAX_UINT256 = 2**256 - 1;\n\n constructor() public {\n legacyToken.safeApprove(address(erc20Migrator), MAX_UINT256);\n newToken.safeApprove(address(synapseBridge), MAX_UINT256);\n }\n\n function migrate(uint256 amount) external {\n legacyToken.safeTransferFrom(msg.sender, address(this), amount);\n erc20Migrator.migrate(amount);\n newToken.safeTransfer(msg.sender, amount.mul(5).div(2));\n }\n\n function migrateAndBridge(uint256 amount, address to, uint256 chainId) external {\n legacyToken.safeTransferFrom(msg.sender, address(this), amount);\n erc20Migrator.migrate(amount);\n synapseBridge.redeem(to, chainId, newToken, amount.mul(5).div(2));\n }\n}" + }, + "contracts/bridge/interfaces/ISynapseBridge.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.6.12;\n\nimport '@openzeppelin/contracts/token/ERC20/SafeERC20.sol';\nimport '@openzeppelin/contracts/token/ERC20/ERC20Burnable.sol';\n\ninterface ISynapseBridge {\n using SafeERC20 for IERC20;\n\n function deposit(\n address to,\n uint256 chainId,\n IERC20 token,\n uint256 amount\n ) external;\n\n function depositAndSwap(\n address to,\n uint256 chainId,\n IERC20 token,\n uint256 amount,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 minDy,\n uint256 deadline\n ) external;\n\n function redeem(\n address to,\n uint256 chainId,\n IERC20 token,\n uint256 amount\n ) external;\n\n\n function redeemv2(\n bytes32 to,\n uint256 chainId,\n IERC20 token,\n uint256 amount\n ) external;\n\n\n function redeemAndSwap(\n address to,\n uint256 chainId,\n IERC20 token,\n uint256 amount,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 minDy,\n uint256 deadline\n ) external;\n\n function redeemAndRemove(\n address to,\n uint256 chainId,\n IERC20 token,\n uint256 amount,\n uint8 liqTokenIndex,\n uint256 liqMinAmount,\n uint256 liqDeadline\n ) external;\n}\n" + }, + "contracts/bridge/interfaces/IERC20Migrator.sol": { + "content": "// SPDX-License-Identifier: MIT\n\n\npragma solidity 0.6.12;\n\ninterface IERC20Migrator { \n function migrate(uint256 amount) external;\n}\n\n" + }, + "@openzeppelin/contracts/token/ERC20/ERC20Burnable.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <0.8.0;\n\nimport \"../../utils/Context.sol\";\nimport \"./ERC20.sol\";\n\n/**\n * @dev Extension of {ERC20} that allows token holders to destroy both their own\n * tokens and those that they have an allowance for, in a way that can be\n * recognized off-chain (via event analysis).\n */\nabstract contract ERC20Burnable is Context, ERC20 {\n using SafeMath for uint256;\n\n /**\n * @dev Destroys `amount` tokens from the caller.\n *\n * See {ERC20-_burn}.\n */\n function burn(uint256 amount) public virtual {\n _burn(_msgSender(), amount);\n }\n\n /**\n * @dev Destroys `amount` tokens from `account`, deducting from the caller's\n * allowance.\n *\n * See {ERC20-_burn} and {ERC20-allowance}.\n *\n * Requirements:\n *\n * - the caller must have allowance for ``accounts``'s tokens of at least\n * `amount`.\n */\n function burnFrom(address account, uint256 amount) public virtual {\n uint256 decreasedAllowance = allowance(account, _msgSender()).sub(amount, \"ERC20: burn amount exceeds allowance\");\n\n _approve(account, _msgSender(), decreasedAllowance);\n _burn(account, amount);\n }\n}\n" + }, + "contracts/bridge/wrappers/MoonriverBridgeZap.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.6.12;\n\nimport \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/SafeERC20.sol\";\nimport \"../interfaces/ISwap.sol\";\nimport \"../interfaces/ISynapseBridge.sol\";\nimport \"../interfaces/IWETH9.sol\";\n\ninterface IFrax {\n function exchangeCanonicalForOld(address bridge_token_address, uint256 token_amount) external returns (uint256);\n}\n\ncontract MoonriverBridgeZap {\n using SafeERC20 for IERC20;\n\n ISynapseBridge synapseBridge;\n address payable public immutable WETH_ADDRESS;\n IFrax private constant CANOLICAL_FRAX = IFrax(0x1A93B23281CC1CDE4C4741353F3064709A16197d);\n IERC20 private constant SYN_FRAX = IERC20(0xE96AC70907ffF3Efee79f502C985A7A21Bce407d);\n\n mapping(address => address) public swapMap;\n mapping(address => IERC20[]) public swapTokensMap;\n\n uint256 constant MAX_UINT256 = 2**256 - 1;\n\n constructor(\n address payable _wethAddress,\n address _swapOne,\n address tokenOne,\n address _swapTwo,\n address tokenTwo,\n ISynapseBridge _synapseBridge\n ) public {\n WETH_ADDRESS = _wethAddress;\n synapseBridge = _synapseBridge;\n swapMap[tokenOne] = _swapOne;\n swapMap[tokenTwo] = _swapTwo;\n IERC20(_wethAddress).safeIncreaseAllowance(address(_synapseBridge), MAX_UINT256);\n if (address(_swapOne) != address(0)) {\n {\n uint8 i;\n for (; i < 32; i++) {\n try ISwap(_swapOne).getToken(i) returns (\n IERC20 token\n ) {\n swapTokensMap[_swapOne].push(token);\n token.safeApprove(address(_swapOne), MAX_UINT256);\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n } catch {\n break;\n }\n }\n require(i > 1, \"swap must have at least 2 tokens\");\n }\n }\n if (address(_swapTwo) != address(0)) {\n {\n uint8 i;\n for (; i < 32; i++) {\n try ISwap(_swapTwo).getToken(i) returns (\n IERC20 token\n ) {\n swapTokensMap[_swapTwo].push(token);\n token.safeApprove(address(_swapTwo), MAX_UINT256);\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n } catch {\n break;\n }\n }\n require(i > 1, \"swap must have at least 2 tokens\");\n }\n }\n }\n\n /**\n * @notice Calculate amount of tokens you receive on swap\n * @param tokenIndexFrom the token the user wants to sell\n * @param tokenIndexTo the token the user wants to buy\n * @param dx the amount of tokens the user wants to sell. If the token charges\n * a fee on transfers, use the amount that gets transferred after the fee.\n * @return amount of tokens the user will receive\n */\n function calculateSwap(\n IERC20 token,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx\n ) external view virtual returns (uint256) {\n ISwap swap = ISwap(\n swapMap[address(token)]\n );\n return swap.calculateSwap(tokenIndexFrom, tokenIndexTo, dx);\n }\n\n function swapAndRedeem(\n address to,\n uint256 chainId,\n IERC20 token,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx,\n uint256 minDy,\n uint256 deadline\n ) external {\n ISwap swap = ISwap(swapMap[address(token)]);\n require(address(swap) != address(0), \"Swap is 0x00\");\n IERC20[] memory tokens = swapTokensMap[address(swap)];\n tokens[tokenIndexFrom].safeTransferFrom(\n msg.sender,\n address(this),\n dx\n );\n // swap\n\n uint256 swappedAmount = swap.swap(\n tokenIndexFrom,\n tokenIndexTo,\n dx,\n minDy,\n deadline\n );\n // deposit into bridge, gets nUSD\n if (\n token.allowance(address(this), address(synapseBridge)) <\n swappedAmount\n ) {\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n }\n synapseBridge.redeem(to, chainId, token, swappedAmount);\n }\n\n function swapAndRedeemAndSwap(\n address to,\n uint256 chainId,\n IERC20 token,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx,\n uint256 minDy,\n uint256 deadline,\n uint8 swapTokenIndexFrom,\n uint8 swapTokenIndexTo,\n uint256 swapMinDy,\n uint256 swapDeadline\n ) external {\n require(\n address(swapMap[address(token)]) != address(0),\n \"Swap is 0x00\"\n );\n IERC20[] memory tokens = swapTokensMap[\n swapMap[address(token)]\n ];\n tokens[tokenIndexFrom].safeTransferFrom(\n msg.sender,\n address(this),\n dx\n );\n // swap\n\n uint256 swappedAmount = ISwap(swapMap[address(token)]).swap(tokenIndexFrom, tokenIndexTo, dx, minDy, deadline);\n // deposit into bridge, gets nUSD\n if (\n token.allowance(address(this), address(synapseBridge)) <\n swappedAmount\n ) {\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n }\n synapseBridge.redeemAndSwap(\n to,\n chainId,\n token,\n swappedAmount,\n swapTokenIndexFrom,\n swapTokenIndexTo,\n swapMinDy,\n swapDeadline\n );\n }\n\n function swapAndRedeemAndRemove(\n address to,\n uint256 chainId,\n IERC20 token,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx,\n uint256 minDy,\n uint256 deadline,\n uint8 liqTokenIndex,\n uint256 liqMinAmount,\n uint256 liqDeadline\n ) external {\n ISwap swap = ISwap(swapMap[address(token)]);\n require(address(swap) != address(0), \"Swap is 0x00\");\n IERC20[] memory tokens = swapTokensMap[address(swap)];\n tokens[tokenIndexFrom].safeTransferFrom(\n msg.sender,\n address(this),\n dx\n );\n // swap\n\n uint256 swappedAmount = swap.swap(\n tokenIndexFrom,\n tokenIndexTo,\n dx,\n minDy,\n deadline\n );\n // deposit into bridge, gets nUSD\n if (\n token.allowance(address(this), address(synapseBridge)) <\n swappedAmount\n ) {\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n }\n synapseBridge.redeemAndRemove(\n to,\n chainId,\n token,\n swappedAmount,\n liqTokenIndex,\n liqMinAmount,\n liqDeadline\n );\n }\n\n /**\n * @notice wraps SynapseBridge redeem()\n * @param to address on other chain to redeem underlying assets to\n * @param chainId which underlying chain to bridge assets onto\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n **/\n function redeem(\n address to,\n uint256 chainId,\n IERC20 token,\n uint256 amount\n ) external {\n token.safeTransferFrom(msg.sender, address(this), amount);\n if (address(token) == address(CANOLICAL_FRAX)) {\n uint256 swappedAmount = CANOLICAL_FRAX.exchangeCanonicalForOld(address(SYN_FRAX), amount);\n if (SYN_FRAX.allowance(address(this), address(synapseBridge)) < amount) {\n SYN_FRAX.safeApprove(address(synapseBridge), MAX_UINT256);\n }\n synapseBridge.redeem(to, chainId, SYN_FRAX, swappedAmount);\n } else {\n if (token.allowance(address(this), address(synapseBridge)) < amount) {\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n }\n synapseBridge.redeem(to, chainId, token, amount);\n }\n }\n\n /**\n * @notice Wraps SynapseBridge redeemv2() function\n * @param to address on other chain to bridge assets to\n * @param chainId which chain to bridge assets onto\n * @param token ERC20 compatible token to redeem into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n **/\n function redeemv2(\n bytes32 to,\n uint256 chainId,\n IERC20 token,\n uint256 amount\n ) external {\n token.safeTransferFrom(msg.sender, address(this), amount);\n\n if (token.allowance(address(this), address(synapseBridge)) < amount) {\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n }\n synapseBridge.redeemv2(to, chainId, token, amount);\n }\n\n /**\n * @notice wraps SynapseBridge redeem()\n * @param to address on other chain to redeem underlying assets to\n * @param chainId which underlying chain to bridge assets onto\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n **/\n function deposit(\n address to,\n uint256 chainId,\n IERC20 token,\n uint256 amount\n ) external {\n token.safeTransferFrom(msg.sender, address(this), amount);\n if (token.allowance(address(this), address(synapseBridge)) < amount) {\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n }\n synapseBridge.deposit(to, chainId, token, amount);\n }\n\n /**\n * @notice Wraps SynapseBridge deposit() function to make it compatible w/ ETH -> WETH conversions\n * @param to address on other chain to bridge assets to\n * @param chainId which chain to bridge assets onto\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n **/\n function depositETH(\n address to,\n uint256 chainId,\n uint256 amount\n ) external payable {\n require(msg.value > 0 && msg.value == amount, 'INCORRECT MSG VALUE');\n IWETH9(WETH_ADDRESS).deposit{value: msg.value}();\n synapseBridge.deposit(to, chainId, IERC20(WETH_ADDRESS), amount);\n }\n\n\n\n function swapETHAndRedeem(\n address to,\n uint256 chainId,\n IERC20 token,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx,\n uint256 minDy,\n uint256 deadline\n ) external payable {\n require(WETH_ADDRESS != address(0), \"WETH 0\");\n require(msg.value > 0 && msg.value == dx, \"INCORRECT MSG VALUE\");\n ISwap swap = ISwap(swapMap[address(token)]);\n require(address(swap) != address(0), \"Swap is 0x00\");\n IWETH9(WETH_ADDRESS).deposit{value: msg.value}();\n\n // swap\n uint256 swappedAmount = swap.swap(\n tokenIndexFrom,\n tokenIndexTo,\n dx,\n minDy,\n deadline\n );\n synapseBridge.redeem(to, chainId, token, swappedAmount);\n }\n\n /**\n * @notice Wraps redeemAndSwap on SynapseBridge.sol\n * Relays to nodes that (typically) a wrapped synAsset ERC20 token has been burned and the underlying needs to be redeeemed on the native chain. This function indicates to the nodes that they should attempt to redeem the LP token for the underlying assets (E.g \"swap\" out of the LP token)\n * @param to address on other chain to redeem underlying assets to\n * @param chainId which underlying chain to bridge assets onto\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n * @param tokenIndexFrom the token the user wants to swap from\n * @param tokenIndexTo the token the user wants to swap to\n * @param minDy the min amount the user would like to receive, or revert to only minting the SynERC20 token crosschain.\n * @param deadline latest timestamp to accept this transaction\n **/\n function redeemAndSwap(\n address to,\n uint256 chainId,\n IERC20 token,\n uint256 amount,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 minDy,\n uint256 deadline\n ) external {\n token.safeTransferFrom(msg.sender, address(this), amount);\n if (token.allowance(address(this), address(synapseBridge)) < amount) {\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n }\n synapseBridge.redeemAndSwap(\n to,\n chainId,\n token,\n amount,\n tokenIndexFrom,\n tokenIndexTo,\n minDy,\n deadline\n );\n }\n\n /**\n * @notice Wraps redeemAndRemove on SynapseBridge\n * Relays to nodes that (typically) a wrapped synAsset ERC20 token has been burned and the underlying needs to be redeeemed on the native chain. This function indicates to the nodes that they should attempt to redeem the LP token for the underlying assets (E.g \"swap\" out of the LP token)\n * @param to address on other chain to redeem underlying assets to\n * @param chainId which underlying chain to bridge assets onto\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount of (typically) LP token to pass to the nodes to attempt to removeLiquidity() with to redeem for the underlying assets of the LP token\n * @param liqTokenIndex Specifies which of the underlying LP assets the nodes should attempt to redeem for\n * @param liqMinAmount Specifies the minimum amount of the underlying asset needed for the nodes to execute the redeem/swap\n * @param liqDeadline Specificies the deadline that the nodes are allowed to try to redeem/swap the LP token\n **/\n function redeemAndRemove(\n address to,\n uint256 chainId,\n IERC20 token,\n uint256 amount,\n uint8 liqTokenIndex,\n uint256 liqMinAmount,\n uint256 liqDeadline\n ) external {\n token.safeTransferFrom(msg.sender, address(this), amount);\n if (token.allowance(address(this), address(synapseBridge)) < amount) {\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n }\n synapseBridge.redeemAndRemove(\n to,\n chainId,\n token,\n amount,\n liqTokenIndex,\n liqMinAmount,\n liqDeadline\n );\n }\n}\n" + }, + "contracts/bridge/interfaces/ISwap.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.6.12;\n\nimport '@openzeppelin/contracts/token/ERC20/ERC20.sol';\n\ninterface ISwap {\n // pool data view functions\n function getA() external view returns (uint256);\n\n function getToken(uint8 index) external view returns (IERC20);\n\n function getTokenIndex(address tokenAddress) external view returns (uint8);\n\n function getTokenBalance(uint8 index) external view returns (uint256);\n\n function getVirtualPrice() external view returns (uint256);\n\n // min return calculation functions\n function calculateSwap(\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx\n ) external view returns (uint256);\n\n function calculateTokenAmount(uint256[] calldata amounts, bool deposit)\n external\n view\n returns (uint256);\n\n function calculateRemoveLiquidity(uint256 amount)\n external\n view\n returns (uint256[] memory);\n\n function calculateRemoveLiquidityOneToken(\n uint256 tokenAmount,\n uint8 tokenIndex\n ) external view returns (uint256 availableTokenAmount);\n\n // state modifying functions\n function initialize(\n IERC20[] memory pooledTokens,\n uint8[] memory decimals,\n string memory lpTokenName,\n string memory lpTokenSymbol,\n uint256 a,\n uint256 fee,\n uint256 adminFee,\n address lpTokenTargetAddress\n ) external;\n\n function swap(\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx,\n uint256 minDy,\n uint256 deadline\n ) external returns (uint256);\n\n function addLiquidity(\n uint256[] calldata amounts,\n uint256 minToMint,\n uint256 deadline\n ) external returns (uint256);\n\n function removeLiquidity(\n uint256 amount,\n uint256[] calldata minAmounts,\n uint256 deadline\n ) external returns (uint256[] memory);\n\n function removeLiquidityOneToken(\n uint256 tokenAmount,\n uint8 tokenIndex,\n uint256 minAmount,\n uint256 deadline\n ) external returns (uint256);\n\n function removeLiquidityImbalance(\n uint256[] calldata amounts,\n uint256 maxBurnAmount,\n uint256 deadline\n ) external returns (uint256);\n}\n" + }, + "contracts/bridge/interfaces/IWETH9.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.4.0;\n\ninterface IWETH9 {\n function name() external view returns (string memory);\n\n function symbol() external view returns (string memory);\n\n function decimals() external view returns (uint8);\n\n function balanceOf(address) external view returns (uint256);\n\n function allowance(address, address) external view returns (uint256);\n\n receive() external payable;\n\n function deposit() external payable;\n\n function withdraw(uint256 wad) external;\n\n function totalSupply() external view returns (uint256);\n\n function approve(address guy, uint256 wad) external returns (bool);\n\n function transfer(address dst, uint256 wad) external returns (bool);\n\n function transferFrom(\n address src,\n address dst,\n uint256 wad\n ) external returns (bool);\n}" + }, + "contracts/bridge/wrappers/L2BridgeZap.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.6.12;\n\nimport \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/SafeERC20.sol\";\nimport \"../interfaces/ISwap.sol\";\nimport \"../interfaces/ISynapseBridge.sol\";\nimport \"../interfaces/IWETH9.sol\";\n\ncontract L2BridgeZap {\n using SafeERC20 for IERC20;\n\n ISynapseBridge synapseBridge;\n address payable public immutable WETH_ADDRESS;\n\n mapping(address => address) public swapMap;\n mapping(address => IERC20[]) public swapTokensMap;\n\n uint256 constant MAX_UINT256 = 2**256 - 1;\n\n constructor(\n address payable _wethAddress,\n address _swapOne,\n address tokenOne,\n address _swapTwo,\n address tokenTwo,\n ISynapseBridge _synapseBridge\n ) public {\n WETH_ADDRESS = _wethAddress;\n synapseBridge = _synapseBridge;\n swapMap[tokenOne] = _swapOne;\n swapMap[tokenTwo] = _swapTwo;\n if (_wethAddress != address(0)) {\n IERC20(_wethAddress).safeIncreaseAllowance(address(_synapseBridge), MAX_UINT256);\n }\n if (address(_swapOne) != address(0)) {\n {\n uint8 i;\n for (; i < 32; i++) {\n try ISwap(_swapOne).getToken(i) returns (\n IERC20 token\n ) {\n swapTokensMap[_swapOne].push(token);\n token.safeApprove(address(_swapOne), MAX_UINT256);\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n } catch {\n break;\n }\n }\n require(i > 1, \"swap must have at least 2 tokens\");\n }\n }\n if (address(_swapTwo) != address(0)) {\n {\n uint8 i;\n for (; i < 32; i++) {\n try ISwap(_swapTwo).getToken(i) returns (\n IERC20 token\n ) {\n swapTokensMap[_swapTwo].push(token);\n token.safeApprove(address(_swapTwo), MAX_UINT256);\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n } catch {\n break;\n }\n }\n require(i > 1, \"swap must have at least 2 tokens\");\n }\n }\n }\n\n /**\n * @notice Calculate amount of tokens you receive on swap\n * @param tokenIndexFrom the token the user wants to sell\n * @param tokenIndexTo the token the user wants to buy\n * @param dx the amount of tokens the user wants to sell. If the token charges\n * a fee on transfers, use the amount that gets transferred after the fee.\n * @return amount of tokens the user will receive\n */\n function calculateSwap(\n IERC20 token,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx\n ) external view virtual returns (uint256) {\n ISwap swap = ISwap(\n swapMap[address(token)]\n );\n return swap.calculateSwap(tokenIndexFrom, tokenIndexTo, dx);\n }\n\n function swapAndRedeem(\n address to,\n uint256 chainId,\n IERC20 token,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx,\n uint256 minDy,\n uint256 deadline\n ) external {\n ISwap swap = ISwap(swapMap[address(token)]);\n require(address(swap) != address(0), \"Swap is 0x00\");\n IERC20[] memory tokens = swapTokensMap[address(swap)];\n tokens[tokenIndexFrom].safeTransferFrom(\n msg.sender,\n address(this),\n dx\n );\n // swap\n\n uint256 swappedAmount = swap.swap(\n tokenIndexFrom,\n tokenIndexTo,\n dx,\n minDy,\n deadline\n );\n // deposit into bridge, gets nUSD\n if (\n token.allowance(address(this), address(synapseBridge)) <\n swappedAmount\n ) {\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n }\n synapseBridge.redeem(to, chainId, token, swappedAmount);\n }\n\n function swapAndRedeemAndSwap(\n address to,\n uint256 chainId,\n IERC20 token,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx,\n uint256 minDy,\n uint256 deadline,\n uint8 swapTokenIndexFrom,\n uint8 swapTokenIndexTo,\n uint256 swapMinDy,\n uint256 swapDeadline\n ) external {\n require(\n address(swapMap[address(token)]) != address(0),\n \"Swap is 0x00\"\n );\n IERC20[] memory tokens = swapTokensMap[\n swapMap[address(token)]\n ];\n tokens[tokenIndexFrom].safeTransferFrom(\n msg.sender,\n address(this),\n dx\n );\n // swap\n\n uint256 swappedAmount = ISwap(swapMap[address(token)]).swap(tokenIndexFrom, tokenIndexTo, dx, minDy, deadline);\n // deposit into bridge, gets nUSD\n if (\n token.allowance(address(this), address(synapseBridge)) <\n swappedAmount\n ) {\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n }\n synapseBridge.redeemAndSwap(\n to,\n chainId,\n token,\n swappedAmount,\n swapTokenIndexFrom,\n swapTokenIndexTo,\n swapMinDy,\n swapDeadline\n );\n }\n\n function swapAndRedeemAndRemove(\n address to,\n uint256 chainId,\n IERC20 token,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx,\n uint256 minDy,\n uint256 deadline,\n uint8 liqTokenIndex,\n uint256 liqMinAmount,\n uint256 liqDeadline\n ) external {\n ISwap swap = ISwap(swapMap[address(token)]);\n require(address(swap) != address(0), \"Swap is 0x00\");\n IERC20[] memory tokens = swapTokensMap[address(swap)];\n tokens[tokenIndexFrom].safeTransferFrom(\n msg.sender,\n address(this),\n dx\n );\n // swap\n\n uint256 swappedAmount = swap.swap(\n tokenIndexFrom,\n tokenIndexTo,\n dx,\n minDy,\n deadline\n );\n // deposit into bridge, gets nUSD\n if (\n token.allowance(address(this), address(synapseBridge)) <\n swappedAmount\n ) {\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n }\n synapseBridge.redeemAndRemove(\n to,\n chainId,\n token,\n swappedAmount,\n liqTokenIndex,\n liqMinAmount,\n liqDeadline\n );\n }\n\n /**\n * @notice wraps SynapseBridge redeem()\n * @param to address on other chain to redeem underlying assets to\n * @param chainId which underlying chain to bridge assets onto\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n **/\n function redeem(\n address to,\n uint256 chainId,\n IERC20 token,\n uint256 amount\n ) external {\n token.safeTransferFrom(msg.sender, address(this), amount);\n if (token.allowance(address(this), address(synapseBridge)) < amount) {\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n }\n synapseBridge.redeem(to, chainId, token, amount);\n }\n\n /**\n * @notice wraps SynapseBridge redeem()\n * @param to address on other chain to redeem underlying assets to\n * @param chainId which underlying chain to bridge assets onto\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n **/\n function deposit(\n address to,\n uint256 chainId,\n IERC20 token,\n uint256 amount\n ) external {\n token.safeTransferFrom(msg.sender, address(this), amount);\n if (token.allowance(address(this), address(synapseBridge)) < amount) {\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n }\n synapseBridge.deposit(to, chainId, token, amount);\n }\n\n /**\n * @notice Wraps SynapseBridge deposit() function to make it compatible w/ ETH -> WETH conversions\n * @param to address on other chain to bridge assets to\n * @param chainId which chain to bridge assets onto\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n **/\n function depositETH(\n address to,\n uint256 chainId,\n uint256 amount\n ) external payable {\n require(msg.value > 0 && msg.value == amount, 'INCORRECT MSG VALUE');\n IWETH9(WETH_ADDRESS).deposit{value: msg.value}();\n synapseBridge.deposit(to, chainId, IERC20(WETH_ADDRESS), amount);\n }\n\n\n function swapETHAndRedeem(\n address to,\n uint256 chainId,\n IERC20 token,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx,\n uint256 minDy,\n uint256 deadline\n ) external payable {\n require(WETH_ADDRESS != address(0), \"WETH 0\");\n require(msg.value > 0 && msg.value == dx, \"INCORRECT MSG VALUE\");\n ISwap swap = ISwap(swapMap[address(token)]);\n require(address(swap) != address(0), \"Swap is 0x00\");\n IWETH9(WETH_ADDRESS).deposit{value: msg.value}();\n\n // swap\n uint256 swappedAmount = swap.swap(\n tokenIndexFrom,\n tokenIndexTo,\n dx,\n minDy,\n deadline\n );\n synapseBridge.redeem(to, chainId, token, swappedAmount);\n }\n\n\n function swapETHAndRedeemAndSwap(\n address to,\n uint256 chainId,\n IERC20 token,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx,\n uint256 minDy,\n uint256 deadline,\n uint8 swapTokenIndexFrom,\n uint8 swapTokenIndexTo,\n uint256 swapMinDy,\n uint256 swapDeadline\n ) external payable {\n require(WETH_ADDRESS != address(0), \"WETH 0\");\n require(msg.value > 0 && msg.value == dx, \"INCORRECT MSG VALUE\");\n ISwap swap = ISwap(swapMap[address(token)]);\n require(address(swap) != address(0), \"Swap is 0x00\");\n IWETH9(WETH_ADDRESS).deposit{value: msg.value}();\n\n // swap\n uint256 swappedAmount = swap.swap(\n tokenIndexFrom,\n tokenIndexTo,\n dx,\n minDy,\n deadline\n );\n synapseBridge.redeemAndSwap(to, chainId, token, swappedAmount,swapTokenIndexFrom,\n swapTokenIndexTo,\n swapMinDy,\n swapDeadline);\n }\n\n\n /**\n * @notice Wraps redeemAndSwap on SynapseBridge.sol\n * Relays to nodes that (typically) a wrapped synAsset ERC20 token has been burned and the underlying needs to be redeeemed on the native chain. This function indicates to the nodes that they should attempt to redeem the LP token for the underlying assets (E.g \"swap\" out of the LP token)\n * @param to address on other chain to redeem underlying assets to\n * @param chainId which underlying chain to bridge assets onto\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n * @param tokenIndexFrom the token the user wants to swap from\n * @param tokenIndexTo the token the user wants to swap to\n * @param minDy the min amount the user would like to receive, or revert to only minting the SynERC20 token crosschain.\n * @param deadline latest timestamp to accept this transaction\n **/\n function redeemAndSwap(\n address to,\n uint256 chainId,\n IERC20 token,\n uint256 amount,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 minDy,\n uint256 deadline\n ) external {\n token.safeTransferFrom(msg.sender, address(this), amount);\n if (token.allowance(address(this), address(synapseBridge)) < amount) {\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n }\n synapseBridge.redeemAndSwap(\n to,\n chainId,\n token,\n amount,\n tokenIndexFrom,\n tokenIndexTo,\n minDy,\n deadline\n );\n }\n\n /**\n * @notice Wraps redeemAndRemove on SynapseBridge\n * Relays to nodes that (typically) a wrapped synAsset ERC20 token has been burned and the underlying needs to be redeeemed on the native chain. This function indicates to the nodes that they should attempt to redeem the LP token for the underlying assets (E.g \"swap\" out of the LP token)\n * @param to address on other chain to redeem underlying assets to\n * @param chainId which underlying chain to bridge assets onto\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount of (typically) LP token to pass to the nodes to attempt to removeLiquidity() with to redeem for the underlying assets of the LP token\n * @param liqTokenIndex Specifies which of the underlying LP assets the nodes should attempt to redeem for\n * @param liqMinAmount Specifies the minimum amount of the underlying asset needed for the nodes to execute the redeem/swap\n * @param liqDeadline Specificies the deadline that the nodes are allowed to try to redeem/swap the LP token\n **/\n function redeemAndRemove(\n address to,\n uint256 chainId,\n IERC20 token,\n uint256 amount,\n uint8 liqTokenIndex,\n uint256 liqMinAmount,\n uint256 liqDeadline\n ) external {\n token.safeTransferFrom(msg.sender, address(this), amount);\n if (token.allowance(address(this), address(synapseBridge)) < amount) {\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n }\n synapseBridge.redeemAndRemove(\n to,\n chainId,\n token,\n amount,\n liqTokenIndex,\n liqMinAmount,\n liqDeadline\n );\n }\n\n /**\n * @notice Wraps SynapseBridge redeemv2() function\n * @param to address on other chain to bridge assets to\n * @param chainId which chain to bridge assets onto\n * @param token ERC20 compatible token to redeem into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n **/\n function redeemv2(\n bytes32 to,\n uint256 chainId,\n IERC20 token,\n uint256 amount\n ) external {\n token.safeTransferFrom(msg.sender, address(this), amount);\n\n if (token.allowance(address(this), address(synapseBridge)) < amount) {\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n }\n synapseBridge.redeemv2(to, chainId, token, amount);\n }\n}\n" + }, + "contracts/bridge/wrappers/L1BridgeZap.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.6.12;\n\nimport '@openzeppelin/contracts/token/ERC20/IERC20.sol';\nimport '@openzeppelin/contracts/token/ERC20/SafeERC20.sol';\nimport '../interfaces/ISwap.sol';\nimport '../interfaces/ISynapseBridge.sol';\nimport \"../interfaces/IWETH9.sol\";\n\n\n/**\n * @title L1BridgeZap\n * @notice This contract is responsible for handling user Zaps into the SynapseBridge contract, through the Synapse Swap contracts. It does so\n * It does so by combining the action of addLiquidity() to the base swap pool, and then calling either deposit() or depositAndSwap() on the bridge.\n * This is done in hopes of automating portions of the bridge user experience to users, while keeping the SynapseBridge contract logic small.\n *\n * @dev This contract should be deployed with a base Swap.sol address and a SynapseBridge.sol address, otherwise, it will not function.\n */\ncontract L1BridgeZap {\n using SafeERC20 for IERC20;\n\n uint256 constant MAX_UINT256 = 2**256 - 1;\n \n ISwap baseSwap;\n ISynapseBridge synapseBridge;\n IERC20[] public baseTokens;\n address payable public immutable WETH_ADDRESS;\n \n\n /**\n * @notice Constructs the contract, approves each token inside of baseSwap to be used by baseSwap (needed for addLiquidity())\n */\n constructor(address payable _wethAddress, ISwap _baseSwap, ISynapseBridge _synapseBridge) public {\n WETH_ADDRESS = _wethAddress;\n baseSwap = _baseSwap;\n synapseBridge = _synapseBridge;\n IERC20(_wethAddress).safeIncreaseAllowance(address(_synapseBridge), MAX_UINT256);\n {\n uint8 i;\n for (; i < 32; i++) {\n try _baseSwap.getToken(i) returns (IERC20 token) {\n baseTokens.push(token);\n token.safeIncreaseAllowance(address(_baseSwap), MAX_UINT256);\n } catch {\n break;\n }\n }\n require(i > 1, 'baseSwap must have at least 2 tokens');\n }\n }\n \n /**\n * @notice Wraps SynapseBridge deposit() function to make it compatible w/ ETH -> WETH conversions\n * @param to address on other chain to bridge assets to\n * @param chainId which chain to bridge assets onto\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n **/\n function depositETH(\n address to,\n uint256 chainId,\n uint256 amount\n ) external payable {\n require(msg.value > 0 && msg.value == amount, 'INCORRECT MSG VALUE');\n IWETH9(WETH_ADDRESS).deposit{value: msg.value}();\n synapseBridge.deposit(to, chainId, IERC20(WETH_ADDRESS), amount);\n }\n\n /**\n * @notice Wraps SynapseBridge depositAndSwap() function to make it compatible w/ ETH -> WETH conversions\n * @param to address on other chain to bridge assets to\n * @param chainId which chain to bridge assets onto\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n * @param tokenIndexFrom the token the user wants to swap from\n * @param tokenIndexTo the token the user wants to swap to\n * @param minDy the min amount the user would like to receive, or revert to only minting the SynERC20 token crosschain.\n * @param deadline latest timestamp to accept this transaction\n **/\n function depositETHAndSwap(\n address to,\n uint256 chainId,\n uint256 amount,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 minDy,\n uint256 deadline\n ) external payable {\n require(msg.value > 0 && msg.value == amount, 'INCORRECT MSG VALUE');\n IWETH9(WETH_ADDRESS).deposit{value: msg.value}();\n synapseBridge.depositAndSwap(to, chainId, IERC20(WETH_ADDRESS), amount, tokenIndexFrom, tokenIndexTo, minDy, deadline);\n }\n\n\n /**\n * @notice A simple method to calculate prices from deposits or\n * withdrawals, excluding fees but including slippage. This is\n * helpful as an input into the various \"min\" parameters on calls\n * to fight front-running\n *\n * @dev This shouldn't be used outside frontends for user estimates.\n *\n * @param amounts an array of token amounts to deposit or withdrawal,\n * corresponding to pooledTokens. The amount should be in each\n * pooled token's native precision.\n * @param deposit whether this is a deposit or a withdrawal\n * @return token amount the user will receive\n */\n function calculateTokenAmount(uint256[] calldata amounts, bool deposit)\n external\n view\n virtual\n returns (uint256)\n {\n return baseSwap.calculateTokenAmount(amounts, deposit);\n }\n\n /**\n * @notice Calculate the amount of underlying token available to withdraw\n * when withdrawing via only single token\n * @param tokenAmount the amount of LP token to burn\n * @param tokenIndex index of which token will be withdrawn\n * @return availableTokenAmount calculated amount of underlying token\n * available to withdraw\n */\n function calculateRemoveLiquidityOneToken(\n uint256 tokenAmount,\n uint8 tokenIndex\n ) external view virtual returns (uint256 availableTokenAmount) {\n return baseSwap.calculateRemoveLiquidityOneToken(tokenAmount, tokenIndex);\n }\n\n\n /**\n * @notice Combines adding liquidity to the given Swap, and calls deposit() on the bridge using that LP token\n * @param to address on other chain to bridge assets to\n * @param chainId which chain to bridge assets onto\n * @param token ERC20 compatible token to deposit into the bridge\n * @param liquidityAmounts the amounts of each token to add, in their native precision\n * @param minToMint the minimum LP tokens adding this amount of liquidity\n * should mint, otherwise revert. Handy for front-running mitigation\n * @param deadline latest timestamp to accept this transaction\n **/\n function zapAndDeposit(\n address to,\n uint256 chainId,\n IERC20 token,\n uint256[] calldata liquidityAmounts,\n uint256 minToMint,\n uint256 deadline\n ) external {\n // add liquidity\n for (uint256 i = 0; i < baseTokens.length; i++) {\n if (liquidityAmounts[i] != 0) {\n baseTokens[i].safeTransferFrom(\n msg.sender,\n address(this),\n liquidityAmounts[i]\n );\n }\n }\n\n uint256 liqAdded = baseSwap.addLiquidity(\n liquidityAmounts,\n minToMint,\n deadline\n );\n // deposit into bridge, gets nUSD\n if (token.allowance(address(this), address(synapseBridge)) < liqAdded) {\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n }\n synapseBridge.deposit(to, chainId, token, liqAdded);\n }\n\n /**\n * @notice Combines adding liquidity to the given Swap, and calls depositAndSwap() on the bridge using that LP token\n * @param to address on other chain to bridge assets to\n * @param chainId which chain to bridge assets onto\n * @param token ERC20 compatible token to deposit into the bridge\n * @param liquidityAmounts the amounts of each token to add, in their native precision\n * @param minToMint the minimum LP tokens adding this amount of liquidity\n * should mint, otherwise revert. Handy for front-running mitigation\n * @param liqDeadline latest timestamp to accept this transaction\n * @param tokenIndexFrom the token the user wants to swap from\n * @param tokenIndexTo the token the user wants to swap to\n * @param minDy the min amount the user would like to receive, or revert to only minting the SynERC20 token crosschain.\n * @param swapDeadline latest timestamp to accept this transaction\n **/\n function zapAndDepositAndSwap(\n address to,\n uint256 chainId,\n IERC20 token,\n uint256[] calldata liquidityAmounts,\n uint256 minToMint,\n uint256 liqDeadline,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 minDy,\n uint256 swapDeadline\n ) external {\n // add liquidity\n for (uint256 i = 0; i < baseTokens.length; i++) {\n if (liquidityAmounts[i] != 0) {\n baseTokens[i].safeTransferFrom(\n msg.sender,\n address(this),\n liquidityAmounts[i]\n );\n }\n }\n\n uint256 liqAdded = baseSwap.addLiquidity(\n liquidityAmounts,\n minToMint,\n liqDeadline\n );\n // deposit into bridge, bridge attemps to swap into desired asset\n if (token.allowance(address(this), address(synapseBridge)) < liqAdded) {\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n }\n synapseBridge.depositAndSwap(\n to,\n chainId,\n token,\n liqAdded,\n tokenIndexFrom,\n tokenIndexTo,\n minDy,\n swapDeadline\n );\n }\n\n /**\n * @notice Wraps SynapseBridge deposit() function\n * @param to address on other chain to bridge assets to\n * @param chainId which chain to bridge assets onto\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n **/\n function deposit(\n address to,\n uint256 chainId,\n IERC20 token,\n uint256 amount\n ) external {\n token.safeTransferFrom(msg.sender, address(this), amount);\n\n if (token.allowance(address(this), address(synapseBridge)) < amount) {\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n }\n synapseBridge.deposit(to, chainId, token, amount);\n }\n \n /**\n * @notice Wraps SynapseBridge depositAndSwap() function\n * @param to address on other chain to bridge assets to\n * @param chainId which chain to bridge assets onto\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n * @param tokenIndexFrom the token the user wants to swap from\n * @param tokenIndexTo the token the user wants to swap to\n * @param minDy the min amount the user would like to receive, or revert to only minting the SynERC20 token crosschain.\n * @param deadline latest timestamp to accept this transaction\n **/\n function depositAndSwap(\n address to,\n uint256 chainId,\n IERC20 token,\n uint256 amount,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 minDy,\n uint256 deadline\n ) external {\n token.safeTransferFrom(msg.sender, address(this), amount);\n \n if (token.allowance(address(this), address(synapseBridge)) < amount) {\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n }\n synapseBridge.depositAndSwap(to, chainId, token, amount, tokenIndexFrom, tokenIndexTo, minDy, deadline);\n }\n\n\n /**\n * @notice Wraps SynapseBridge redeem() function\n * @param to address on other chain to bridge assets to\n * @param chainId which chain to bridge assets onto\n * @param token ERC20 compatible token to redeem into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n **/\n function redeem(\n address to,\n uint256 chainId,\n IERC20 token,\n uint256 amount\n ) external {\n token.safeTransferFrom(msg.sender, address(this), amount);\n\n if (token.allowance(address(this), address(synapseBridge)) < amount) {\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n }\n synapseBridge.redeem(to, chainId, token, amount);\n }\n\n /**\n * @notice Wraps SynapseBridge redeemv2() function\n * @param to address on other chain to bridge assets to\n * @param chainId which chain to bridge assets onto\n * @param token ERC20 compatible token to redeem into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n **/\n function redeemv2(\n bytes32 to,\n uint256 chainId,\n IERC20 token,\n uint256 amount\n ) external {\n token.safeTransferFrom(msg.sender, address(this), amount);\n\n if (token.allowance(address(this), address(synapseBridge)) < amount) {\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n }\n synapseBridge.redeemv2(to, chainId, token, amount);\n }\n\n}\n" + }, + "contracts/bridge/wrappers/HarmonyBridgeZap.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.6.12;\n\nimport \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/SafeERC20.sol\";\nimport \"../interfaces/ISwap.sol\";\nimport \"../interfaces/ISynapseBridge.sol\";\nimport \"../interfaces/IWETH9.sol\";\n\ninterface IFrax {\n function exchangeCanonicalForOld(address bridge_token_address, uint256 token_amount) external returns (uint256);\n}\n\ncontract HarmonyBridgeZap {\n using SafeERC20 for IERC20;\n\n ISynapseBridge synapseBridge;\n address payable public immutable WETH_ADDRESS;\n IFrax private constant CANOLICAL_FRAX = IFrax(0xFa7191D292d5633f702B0bd7E3E3BcCC0e633200);\n IERC20 private constant SYN_FRAX = IERC20(0x1852F70512298d56e9c8FDd905e02581E04ddb2a);\n\n mapping(address => address) public swapMap;\n mapping(address => IERC20[]) public swapTokensMap;\n\n uint256 constant MAX_UINT256 = 2**256 - 1;\n\n constructor(\n address payable _wethAddress,\n address _swapOne,\n address tokenOne,\n address _swapTwo,\n address tokenTwo,\n ISynapseBridge _synapseBridge\n ) public {\n WETH_ADDRESS = _wethAddress;\n synapseBridge = _synapseBridge;\n swapMap[tokenOne] = _swapOne;\n swapMap[tokenTwo] = _swapTwo;\n\n if (address(_swapOne) != address(0)) {\n {\n uint8 i;\n for (; i < 32; i++) {\n try ISwap(_swapOne).getToken(i) returns (\n IERC20 token\n ) {\n swapTokensMap[_swapOne].push(token);\n token.safeApprove(address(_swapOne), MAX_UINT256);\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n } catch {\n break;\n }\n }\n require(i > 1, \"swap must have at least 2 tokens\");\n }\n }\n if (address(_swapTwo) != address(0)) {\n {\n uint8 i;\n for (; i < 32; i++) {\n try ISwap(_swapTwo).getToken(i) returns (\n IERC20 token\n ) {\n swapTokensMap[_swapTwo].push(token);\n token.safeApprove(address(_swapTwo), MAX_UINT256);\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n } catch {\n break;\n }\n }\n require(i > 1, \"swap must have at least 2 tokens\");\n }\n }\n }\n\n /**\n * @notice Calculate amount of tokens you receive on swap\n * @param tokenIndexFrom the token the user wants to sell\n * @param tokenIndexTo the token the user wants to buy\n * @param dx the amount of tokens the user wants to sell. If the token charges\n * a fee on transfers, use the amount that gets transferred after the fee.\n * @return amount of tokens the user will receive\n */\n function calculateSwap(\n IERC20 token,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx\n ) external view virtual returns (uint256) {\n ISwap swap = ISwap(\n swapMap[address(token)]\n );\n return swap.calculateSwap(tokenIndexFrom, tokenIndexTo, dx);\n }\n\n function swapAndRedeem(\n address to,\n uint256 chainId,\n IERC20 token,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx,\n uint256 minDy,\n uint256 deadline\n ) external {\n ISwap swap = ISwap(swapMap[address(token)]);\n require(address(swap) != address(0), \"Swap is 0x00\");\n IERC20[] memory tokens = swapTokensMap[address(swap)];\n tokens[tokenIndexFrom].safeTransferFrom(\n msg.sender,\n address(this),\n dx\n );\n // swap\n\n uint256 swappedAmount = swap.swap(\n tokenIndexFrom,\n tokenIndexTo,\n dx,\n minDy,\n deadline\n );\n // deposit into bridge, gets nUSD\n if (\n token.allowance(address(this), address(synapseBridge)) <\n swappedAmount\n ) {\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n }\n synapseBridge.redeem(to, chainId, token, swappedAmount);\n }\n\n function swapAndRedeemAndSwap(\n address to,\n uint256 chainId,\n IERC20 token,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx,\n uint256 minDy,\n uint256 deadline,\n uint8 swapTokenIndexFrom,\n uint8 swapTokenIndexTo,\n uint256 swapMinDy,\n uint256 swapDeadline\n ) external {\n require(\n address(swapMap[address(token)]) != address(0),\n \"Swap is 0x00\"\n );\n IERC20[] memory tokens = swapTokensMap[\n swapMap[address(token)]\n ];\n tokens[tokenIndexFrom].safeTransferFrom(\n msg.sender,\n address(this),\n dx\n );\n // swap\n\n uint256 swappedAmount = ISwap(swapMap[address(token)]).swap(tokenIndexFrom, tokenIndexTo, dx, minDy, deadline);\n // deposit into bridge, gets nUSD\n if (\n token.allowance(address(this), address(synapseBridge)) <\n swappedAmount\n ) {\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n }\n synapseBridge.redeemAndSwap(\n to,\n chainId,\n token,\n swappedAmount,\n swapTokenIndexFrom,\n swapTokenIndexTo,\n swapMinDy,\n swapDeadline\n );\n }\n\n function swapAndRedeemAndRemove(\n address to,\n uint256 chainId,\n IERC20 token,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx,\n uint256 minDy,\n uint256 deadline,\n uint8 liqTokenIndex,\n uint256 liqMinAmount,\n uint256 liqDeadline\n ) external {\n ISwap swap = ISwap(swapMap[address(token)]);\n require(address(swap) != address(0), \"Swap is 0x00\");\n IERC20[] memory tokens = swapTokensMap[address(swap)];\n tokens[tokenIndexFrom].safeTransferFrom(\n msg.sender,\n address(this),\n dx\n );\n // swap\n\n uint256 swappedAmount = swap.swap(\n tokenIndexFrom,\n tokenIndexTo,\n dx,\n minDy,\n deadline\n );\n // deposit into bridge, gets nUSD\n if (\n token.allowance(address(this), address(synapseBridge)) <\n swappedAmount\n ) {\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n }\n synapseBridge.redeemAndRemove(\n to,\n chainId,\n token,\n swappedAmount,\n liqTokenIndex,\n liqMinAmount,\n liqDeadline\n );\n }\n\n /**\n * @notice wraps SynapseBridge redeem()\n * @param to address on other chain to redeem underlying assets to\n * @param chainId which underlying chain to bridge assets onto\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n **/\n function redeem(\n address to,\n uint256 chainId,\n IERC20 token,\n uint256 amount\n ) external {\n token.safeTransferFrom(msg.sender, address(this), amount);\n if (address(token) == address(CANOLICAL_FRAX)) {\n uint256 swappedAmount = CANOLICAL_FRAX.exchangeCanonicalForOld(address(SYN_FRAX), amount);\n if (SYN_FRAX.allowance(address(this), address(synapseBridge)) < amount) {\n SYN_FRAX.safeApprove(address(synapseBridge), MAX_UINT256);\n }\n synapseBridge.redeem(to, chainId, SYN_FRAX, swappedAmount);\n } else {\n if (token.allowance(address(this), address(synapseBridge)) < amount) {\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n }\n synapseBridge.redeem(to, chainId, token, amount);\n }\n \n }\n\n /**\n * @notice Wraps SynapseBridge redeemv2() function\n * @param to address on other chain to bridge assets to\n * @param chainId which chain to bridge assets onto\n * @param token ERC20 compatible token to redeem into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n **/\n function redeemv2(\n bytes32 to,\n uint256 chainId,\n IERC20 token,\n uint256 amount\n ) external {\n token.safeTransferFrom(msg.sender, address(this), amount);\n\n if (token.allowance(address(this), address(synapseBridge)) < amount) {\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n }\n synapseBridge.redeemv2(to, chainId, token, amount);\n }\n\n /**\n * @notice wraps SynapseBridge redeem()\n * @param to address on other chain to redeem underlying assets to\n * @param chainId which underlying chain to bridge assets onto\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n **/\n function deposit(\n address to,\n uint256 chainId,\n IERC20 token,\n uint256 amount\n ) external {\n token.safeTransferFrom(msg.sender, address(this), amount);\n if (token.allowance(address(this), address(synapseBridge)) < amount) {\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n }\n synapseBridge.deposit(to, chainId, token, amount);\n }\n\n function swapETHAndRedeem(\n address to,\n uint256 chainId,\n IERC20 token,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx,\n uint256 minDy,\n uint256 deadline\n ) external payable {\n require(WETH_ADDRESS != address(0), \"WETH 0\");\n require(msg.value > 0 && msg.value == dx, \"INCORRECT MSG VALUE\");\n ISwap swap = ISwap(swapMap[address(token)]);\n require(address(swap) != address(0), \"Swap is 0x00\");\n IWETH9(WETH_ADDRESS).deposit{value: msg.value}();\n\n // swap\n uint256 swappedAmount = swap.swap(\n tokenIndexFrom,\n tokenIndexTo,\n dx,\n minDy,\n deadline\n );\n synapseBridge.redeem(to, chainId, token, swappedAmount);\n }\n\n /**\n * @notice Wraps redeemAndSwap on SynapseBridge.sol\n * Relays to nodes that (typically) a wrapped synAsset ERC20 token has been burned and the underlying needs to be redeeemed on the native chain. This function indicates to the nodes that they should attempt to redeem the LP token for the underlying assets (E.g \"swap\" out of the LP token)\n * @param to address on other chain to redeem underlying assets to\n * @param chainId which underlying chain to bridge assets onto\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n * @param tokenIndexFrom the token the user wants to swap from\n * @param tokenIndexTo the token the user wants to swap to\n * @param minDy the min amount the user would like to receive, or revert to only minting the SynERC20 token crosschain.\n * @param deadline latest timestamp to accept this transaction\n **/\n function redeemAndSwap(\n address to,\n uint256 chainId,\n IERC20 token,\n uint256 amount,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 minDy,\n uint256 deadline\n ) external {\n token.safeTransferFrom(msg.sender, address(this), amount);\n if (token.allowance(address(this), address(synapseBridge)) < amount) {\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n }\n synapseBridge.redeemAndSwap(\n to,\n chainId,\n token,\n amount,\n tokenIndexFrom,\n tokenIndexTo,\n minDy,\n deadline\n );\n }\n\n /**\n * @notice Wraps redeemAndRemove on SynapseBridge\n * Relays to nodes that (typically) a wrapped synAsset ERC20 token has been burned and the underlying needs to be redeeemed on the native chain. This function indicates to the nodes that they should attempt to redeem the LP token for the underlying assets (E.g \"swap\" out of the LP token)\n * @param to address on other chain to redeem underlying assets to\n * @param chainId which underlying chain to bridge assets onto\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount of (typically) LP token to pass to the nodes to attempt to removeLiquidity() with to redeem for the underlying assets of the LP token\n * @param liqTokenIndex Specifies which of the underlying LP assets the nodes should attempt to redeem for\n * @param liqMinAmount Specifies the minimum amount of the underlying asset needed for the nodes to execute the redeem/swap\n * @param liqDeadline Specificies the deadline that the nodes are allowed to try to redeem/swap the LP token\n **/\n function redeemAndRemove(\n address to,\n uint256 chainId,\n IERC20 token,\n uint256 amount,\n uint8 liqTokenIndex,\n uint256 liqMinAmount,\n uint256 liqDeadline\n ) external {\n token.safeTransferFrom(msg.sender, address(this), amount);\n if (token.allowance(address(this), address(synapseBridge)) < amount) {\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n }\n synapseBridge.redeemAndRemove(\n to,\n chainId,\n token,\n amount,\n liqTokenIndex,\n liqMinAmount,\n liqDeadline\n );\n }\n}\n" + }, + "contracts/bridge/SynapseBridge.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.6.12;\n\nimport \"@openzeppelin/contracts-upgradeable/proxy/Initializable.sol\";\nimport \"@openzeppelin/contracts-upgradeable/access/AccessControlUpgradeable.sol\";\nimport \"@openzeppelin/contracts-upgradeable/utils/ReentrancyGuardUpgradeable.sol\";\nimport \"@openzeppelin/contracts-upgradeable/utils/PausableUpgradeable.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/SafeERC20.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/ERC20Burnable.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport \"@openzeppelin/contracts/math/SafeMath.sol\";\n\nimport \"./interfaces/ISwap.sol\";\nimport \"./interfaces/IWETH9.sol\";\n\ninterface IERC20Mintable is IERC20 {\n function mint(address to, uint256 amount) external;\n}\n\ncontract SynapseBridge is\n Initializable,\n AccessControlUpgradeable,\n ReentrancyGuardUpgradeable,\n PausableUpgradeable\n{\n using SafeERC20 for IERC20;\n using SafeERC20 for IERC20Mintable;\n using SafeMath for uint256;\n\n bytes32 public constant NODEGROUP_ROLE = keccak256(\"NODEGROUP_ROLE\");\n bytes32 public constant GOVERNANCE_ROLE = keccak256(\"GOVERNANCE_ROLE\");\n\n mapping(address => uint256) private fees;\n\n uint256 public startBlockNumber;\n uint256 public constant bridgeVersion = 6;\n uint256 public chainGasAmount;\n address payable public WETH_ADDRESS;\n\n mapping(bytes32 => bool) private kappaMap;\n\n receive() external payable {}\n\n function initialize() external initializer {\n startBlockNumber = block.number;\n _setupRole(DEFAULT_ADMIN_ROLE, msg.sender);\n __AccessControl_init();\n }\n\n function setChainGasAmount(uint256 amount) external {\n require(hasRole(GOVERNANCE_ROLE, msg.sender), \"Not governance\");\n chainGasAmount = amount;\n }\n\n function setWethAddress(address payable _wethAddress) external {\n require(hasRole(DEFAULT_ADMIN_ROLE, msg.sender), \"Not admin\");\n WETH_ADDRESS = _wethAddress;\n }\n\n function addKappas(bytes32[] calldata kappas) external {\n require(hasRole(GOVERNANCE_ROLE, msg.sender), \"Not governance\");\n for (uint256 i = 0; i < kappas.length; ++i) {\n kappaMap[kappas[i]] = true;\n }\n }\n\n event TokenDeposit(\n address indexed to,\n uint256 chainId,\n IERC20 token,\n uint256 amount\n );\n event TokenRedeem(\n address indexed to,\n uint256 chainId,\n IERC20 token,\n uint256 amount\n );\n event TokenWithdraw(\n address indexed to,\n IERC20 token,\n uint256 amount,\n uint256 fee,\n bytes32 indexed kappa\n );\n event TokenMint(\n address indexed to,\n IERC20Mintable token,\n uint256 amount,\n uint256 fee,\n bytes32 indexed kappa\n );\n event TokenDepositAndSwap(\n address indexed to,\n uint256 chainId,\n IERC20 token,\n uint256 amount,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 minDy,\n uint256 deadline\n );\n event TokenMintAndSwap(\n address indexed to,\n IERC20Mintable token,\n uint256 amount,\n uint256 fee,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 minDy,\n uint256 deadline,\n bool swapSuccess,\n bytes32 indexed kappa\n );\n event TokenRedeemAndSwap(\n address indexed to,\n uint256 chainId,\n IERC20 token,\n uint256 amount,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 minDy,\n uint256 deadline\n );\n event TokenRedeemAndRemove(\n address indexed to,\n uint256 chainId,\n IERC20 token,\n uint256 amount,\n uint8 swapTokenIndex,\n uint256 swapMinAmount,\n uint256 swapDeadline\n );\n event TokenWithdrawAndRemove(\n address indexed to,\n IERC20 token,\n uint256 amount,\n uint256 fee,\n uint8 swapTokenIndex,\n uint256 swapMinAmount,\n uint256 swapDeadline,\n bool swapSuccess,\n bytes32 indexed kappa\n );\n\n // v2 events\n event TokenRedeemV2(\n bytes32 indexed to,\n uint256 chainId,\n IERC20 token,\n uint256 amount\n );\n\n // VIEW FUNCTIONS ***/\n function getFeeBalance(address tokenAddress)\n external\n view\n returns (uint256)\n {\n return fees[tokenAddress];\n }\n\n function kappaExists(bytes32 kappa) external view returns (bool) {\n return kappaMap[kappa];\n }\n\n // FEE FUNCTIONS ***/\n /**\n * * @notice withdraw specified ERC20 token fees to a given address\n * * @param token ERC20 token in which fees acccumulated to transfer\n * * @param to Address to send the fees to\n */\n function withdrawFees(IERC20 token, address to) external whenNotPaused {\n require(hasRole(GOVERNANCE_ROLE, msg.sender), \"Not governance\");\n require(to != address(0), \"Address is 0x000\");\n if (fees[address(token)] != 0) {\n token.safeTransfer(to, fees[address(token)]);\n fees[address(token)] = 0;\n }\n }\n\n // PAUSABLE FUNCTIONS ***/\n function pause() external {\n require(hasRole(GOVERNANCE_ROLE, msg.sender), \"Not governance\");\n _pause();\n }\n\n function unpause() external {\n require(hasRole(GOVERNANCE_ROLE, msg.sender), \"Not governance\");\n _unpause();\n }\n\n /**\n * @notice Relays to nodes to transfers an ERC20 token cross-chain\n * @param to address on other chain to bridge assets to\n * @param chainId which chain to bridge assets onto\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n **/\n function deposit(\n address to,\n uint256 chainId,\n IERC20 token,\n uint256 amount\n ) external nonReentrant whenNotPaused {\n emit TokenDeposit(to, chainId, token, amount);\n token.safeTransferFrom(msg.sender, address(this), amount);\n }\n\n /**\n * @notice Relays to nodes that (typically) a wrapped synAsset ERC20 token has been burned and the underlying needs to be redeeemed on the native chain\n * @param to address on other chain to redeem underlying assets to\n * @param chainId which underlying chain to bridge assets onto\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n **/\n function redeem(\n address to,\n uint256 chainId,\n ERC20Burnable token,\n uint256 amount\n ) external nonReentrant whenNotPaused {\n emit TokenRedeem(to, chainId, token, amount);\n token.burnFrom(msg.sender, amount);\n }\n\n /**\n * @notice Function to be called by the node group to withdraw the underlying assets from the contract\n * @param to address on chain to send underlying assets to\n * @param token ERC20 compatible token to withdraw from the bridge\n * @param amount Amount in native token decimals to withdraw\n * @param fee Amount in native token decimals to save to the contract as fees\n * @param kappa kappa\n **/\n function withdraw(\n address to,\n IERC20 token,\n uint256 amount,\n uint256 fee,\n bytes32 kappa\n ) external nonReentrant whenNotPaused {\n require(\n hasRole(NODEGROUP_ROLE, msg.sender),\n \"Caller is not a node group\"\n );\n require(amount > fee, \"Amount must be greater than fee\");\n require(!kappaMap[kappa], \"Kappa is already present\");\n kappaMap[kappa] = true;\n fees[address(token)] = fees[address(token)].add(fee);\n if (address(token) == WETH_ADDRESS && WETH_ADDRESS != address(0)) {\n IWETH9(WETH_ADDRESS).withdraw(amount.sub(fee));\n (bool success, ) = to.call{value: amount.sub(fee)}(\"\");\n require(success, \"ETH_TRANSFER_FAILED\");\n emit TokenWithdraw(to, token, amount, fee, kappa);\n } else {\n emit TokenWithdraw(to, token, amount, fee, kappa);\n token.safeTransfer(to, amount.sub(fee));\n }\n }\n\n /**\n * @notice Nodes call this function to mint a SynERC20 (or any asset that the bridge is given minter access to). This is called by the nodes after a TokenDeposit event is emitted.\n * @dev This means the SynapseBridge.sol contract must have minter access to the token attempting to be minted\n * @param to address on other chain to redeem underlying assets to\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain post-fees\n * @param fee Amount in native token decimals to save to the contract as fees\n * @param kappa kappa\n **/\n function mint(\n address payable to,\n IERC20Mintable token,\n uint256 amount,\n uint256 fee,\n bytes32 kappa\n ) external nonReentrant whenNotPaused {\n require(\n hasRole(NODEGROUP_ROLE, msg.sender),\n \"Caller is not a node group\"\n );\n require(amount > fee, \"Amount must be greater than fee\");\n require(!kappaMap[kappa], \"Kappa is already present\");\n kappaMap[kappa] = true;\n fees[address(token)] = fees[address(token)].add(fee);\n emit TokenMint(to, token, amount.sub(fee), fee, kappa);\n token.mint(address(this), amount);\n IERC20(token).safeTransfer(to, amount.sub(fee));\n if (chainGasAmount != 0 && address(this).balance > chainGasAmount) {\n to.call.value(chainGasAmount)(\"\");\n }\n }\n\n /**\n * @notice Relays to nodes to both transfer an ERC20 token cross-chain, and then have the nodes execute a swap through a liquidity pool on behalf of the user.\n * @param to address on other chain to bridge assets to\n * @param chainId which chain to bridge assets onto\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n * @param tokenIndexFrom the token the user wants to swap from\n * @param tokenIndexTo the token the user wants to swap to\n * @param minDy the min amount the user would like to receive, or revert to only minting the SynERC20 token crosschain.\n * @param deadline latest timestamp to accept this transaction\n **/\n function depositAndSwap(\n address to,\n uint256 chainId,\n IERC20 token,\n uint256 amount,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 minDy,\n uint256 deadline\n ) external nonReentrant whenNotPaused {\n emit TokenDepositAndSwap(\n to,\n chainId,\n token,\n amount,\n tokenIndexFrom,\n tokenIndexTo,\n minDy,\n deadline\n );\n token.safeTransferFrom(msg.sender, address(this), amount);\n }\n\n /**\n * @notice Relays to nodes that (typically) a wrapped synAsset ERC20 token has been burned and the underlying needs to be redeeemed on the native chain. This function indicates to the nodes that they should attempt to redeem the LP token for the underlying assets (E.g \"swap\" out of the LP token)\n * @param to address on other chain to redeem underlying assets to\n * @param chainId which underlying chain to bridge assets onto\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n * @param tokenIndexFrom the token the user wants to swap from\n * @param tokenIndexTo the token the user wants to swap to\n * @param minDy the min amount the user would like to receive, or revert to only minting the SynERC20 token crosschain.\n * @param deadline latest timestamp to accept this transaction\n **/\n function redeemAndSwap(\n address to,\n uint256 chainId,\n ERC20Burnable token,\n uint256 amount,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 minDy,\n uint256 deadline\n ) external nonReentrant whenNotPaused {\n emit TokenRedeemAndSwap(\n to,\n chainId,\n token,\n amount,\n tokenIndexFrom,\n tokenIndexTo,\n minDy,\n deadline\n );\n token.burnFrom(msg.sender, amount);\n }\n\n /**\n * @notice Relays to nodes that (typically) a wrapped synAsset ERC20 token has been burned and the underlying needs to be redeeemed on the native chain. This function indicates to the nodes that they should attempt to redeem the LP token for the underlying assets (E.g \"swap\" out of the LP token)\n * @param to address on other chain to redeem underlying assets to\n * @param chainId which underlying chain to bridge assets onto\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n * @param swapTokenIndex Specifies which of the underlying LP assets the nodes should attempt to redeem for\n * @param swapMinAmount Specifies the minimum amount of the underlying asset needed for the nodes to execute the redeem/swap\n * @param swapDeadline Specificies the deadline that the nodes are allowed to try to redeem/swap the LP token\n **/\n function redeemAndRemove(\n address to,\n uint256 chainId,\n ERC20Burnable token,\n uint256 amount,\n uint8 swapTokenIndex,\n uint256 swapMinAmount,\n uint256 swapDeadline\n ) external nonReentrant whenNotPaused {\n emit TokenRedeemAndRemove(\n to,\n chainId,\n token,\n amount,\n swapTokenIndex,\n swapMinAmount,\n swapDeadline\n );\n token.burnFrom(msg.sender, amount);\n }\n\n /**\n * @notice Nodes call this function to mint a SynERC20 (or any asset that the bridge is given minter access to), and then attempt to swap the SynERC20 into the desired destination asset. This is called by the nodes after a TokenDepositAndSwap event is emitted.\n * @dev This means the BridgeDeposit.sol contract must have minter access to the token attempting to be minted\n * @param to address on other chain to redeem underlying assets to\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain post-fees\n * @param fee Amount in native token decimals to save to the contract as fees\n * @param pool Destination chain's pool to use to swap SynERC20 -> Asset. The nodes determine this by using PoolConfig.sol.\n * @param tokenIndexFrom Index of the SynERC20 asset in the pool\n * @param tokenIndexTo Index of the desired final asset\n * @param minDy Minumum amount (in final asset decimals) that must be swapped for, otherwise the user will receive the SynERC20.\n * @param deadline Epoch time of the deadline that the swap is allowed to be executed.\n * @param kappa kappa\n **/\n function mintAndSwap(\n address payable to,\n IERC20Mintable token,\n uint256 amount,\n uint256 fee,\n ISwap pool,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 minDy,\n uint256 deadline,\n bytes32 kappa\n ) external nonReentrant whenNotPaused {\n require(\n hasRole(NODEGROUP_ROLE, msg.sender),\n \"Caller is not a node group\"\n );\n require(amount > fee, \"Amount must be greater than fee\");\n require(!kappaMap[kappa], \"Kappa is already present\");\n kappaMap[kappa] = true;\n fees[address(token)] = fees[address(token)].add(fee);\n // Transfer gas airdrop\n if (chainGasAmount != 0 && address(this).balance > chainGasAmount) {\n to.call.value(chainGasAmount)(\"\");\n }\n // first check to make sure more will be given than min amount required\n uint256 expectedOutput = ISwap(pool).calculateSwap(\n tokenIndexFrom,\n tokenIndexTo,\n amount.sub(fee)\n );\n\n if (expectedOutput >= minDy) {\n // proceed with swap\n token.mint(address(this), amount);\n token.safeIncreaseAllowance(address(pool), amount);\n try\n ISwap(pool).swap(\n tokenIndexFrom,\n tokenIndexTo,\n amount.sub(fee),\n minDy,\n deadline\n )\n returns (uint256 finalSwappedAmount) {\n // Swap succeeded, transfer swapped asset\n IERC20 swappedTokenTo = ISwap(pool).getToken(tokenIndexTo);\n if (\n address(swappedTokenTo) == WETH_ADDRESS &&\n WETH_ADDRESS != address(0)\n ) {\n IWETH9(WETH_ADDRESS).withdraw(finalSwappedAmount);\n (bool success, ) = to.call{value: finalSwappedAmount}(\"\");\n require(success, \"ETH_TRANSFER_FAILED\");\n emit TokenMintAndSwap(\n to,\n token,\n finalSwappedAmount,\n fee,\n tokenIndexFrom,\n tokenIndexTo,\n minDy,\n deadline,\n true,\n kappa\n );\n } else {\n swappedTokenTo.safeTransfer(to, finalSwappedAmount);\n emit TokenMintAndSwap(\n to,\n token,\n finalSwappedAmount,\n fee,\n tokenIndexFrom,\n tokenIndexTo,\n minDy,\n deadline,\n true,\n kappa\n );\n }\n } catch {\n IERC20(token).safeTransfer(to, amount.sub(fee));\n emit TokenMintAndSwap(\n to,\n token,\n amount.sub(fee),\n fee,\n tokenIndexFrom,\n tokenIndexTo,\n minDy,\n deadline,\n false,\n kappa\n );\n }\n } else {\n token.mint(address(this), amount);\n IERC20(token).safeTransfer(to, amount.sub(fee));\n emit TokenMintAndSwap(\n to,\n token,\n amount.sub(fee),\n fee,\n tokenIndexFrom,\n tokenIndexTo,\n minDy,\n deadline,\n false,\n kappa\n );\n }\n }\n\n /**\n * @notice Function to be called by the node group to withdraw the underlying assets from the contract\n * @param to address on chain to send underlying assets to\n * @param token ERC20 compatible token to withdraw from the bridge\n * @param amount Amount in native token decimals to withdraw\n * @param fee Amount in native token decimals to save to the contract as fees\n * @param pool Destination chain's pool to use to swap SynERC20 -> Asset. The nodes determine this by using PoolConfig.sol.\n * @param swapTokenIndex Specifies which of the underlying LP assets the nodes should attempt to redeem for\n * @param swapMinAmount Specifies the minimum amount of the underlying asset needed for the nodes to execute the redeem/swap\n * @param swapDeadline Specificies the deadline that the nodes are allowed to try to redeem/swap the LP token\n * @param kappa kappa\n **/\n function withdrawAndRemove(\n address to,\n IERC20 token,\n uint256 amount,\n uint256 fee,\n ISwap pool,\n uint8 swapTokenIndex,\n uint256 swapMinAmount,\n uint256 swapDeadline,\n bytes32 kappa\n ) external nonReentrant whenNotPaused {\n require(\n hasRole(NODEGROUP_ROLE, msg.sender),\n \"Caller is not a node group\"\n );\n require(amount > fee, \"Amount must be greater than fee\");\n require(!kappaMap[kappa], \"Kappa is already present\");\n kappaMap[kappa] = true;\n fees[address(token)] = fees[address(token)].add(fee);\n // first check to make sure more will be given than min amount required\n uint256 expectedOutput = ISwap(pool).calculateRemoveLiquidityOneToken(\n amount.sub(fee),\n swapTokenIndex\n );\n\n if (expectedOutput >= swapMinAmount) {\n token.safeIncreaseAllowance(address(pool), amount.sub(fee));\n try\n ISwap(pool).removeLiquidityOneToken(\n amount.sub(fee),\n swapTokenIndex,\n swapMinAmount,\n swapDeadline\n )\n returns (uint256 finalSwappedAmount) {\n // Swap succeeded, transfer swapped asset\n IERC20 swappedTokenTo = ISwap(pool).getToken(swapTokenIndex);\n swappedTokenTo.safeTransfer(to, finalSwappedAmount);\n emit TokenWithdrawAndRemove(\n to,\n token,\n finalSwappedAmount,\n fee,\n swapTokenIndex,\n swapMinAmount,\n swapDeadline,\n true,\n kappa\n );\n } catch {\n IERC20(token).safeTransfer(to, amount.sub(fee));\n emit TokenWithdrawAndRemove(\n to,\n token,\n amount.sub(fee),\n fee,\n swapTokenIndex,\n swapMinAmount,\n swapDeadline,\n false,\n kappa\n );\n }\n } else {\n token.safeTransfer(to, amount.sub(fee));\n emit TokenWithdrawAndRemove(\n to,\n token,\n amount.sub(fee),\n fee,\n swapTokenIndex,\n swapMinAmount,\n swapDeadline,\n false,\n kappa\n );\n }\n }\n\n // BRIDGE FUNCTIONS TO HANDLE DIFF ADDRESSES\n /**\n * @notice Relays to nodes that (typically) a wrapped synAsset ERC20 token has been burned and the underlying needs to be redeeemed on the native chain\n * @param to address on other chain to redeem underlying assets to\n * @param chainId which underlying chain to bridge assets onto\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n **/\n function redeemV2(\n bytes32 to,\n uint256 chainId,\n ERC20Burnable token,\n uint256 amount\n ) external nonReentrant whenNotPaused {\n emit TokenRedeemV2(to, chainId, token, amount);\n token.burnFrom(msg.sender, amount);\n }\n}\n" + }, + "@openzeppelin/contracts-upgradeable/access/AccessControlUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <0.8.0;\n\nimport \"../utils/EnumerableSetUpgradeable.sol\";\nimport \"../utils/AddressUpgradeable.sol\";\nimport \"../utils/ContextUpgradeable.sol\";\nimport \"../proxy/Initializable.sol\";\n\n/**\n * @dev Contract module that allows children to implement role-based access\n * control mechanisms.\n *\n * Roles are referred to by their `bytes32` identifier. These should be exposed\n * in the external API and be unique. The best way to achieve this is by\n * using `public constant` hash digests:\n *\n * ```\n * bytes32 public constant MY_ROLE = keccak256(\"MY_ROLE\");\n * ```\n *\n * Roles can be used to represent a set of permissions. To restrict access to a\n * function call, use {hasRole}:\n *\n * ```\n * function foo() public {\n * require(hasRole(MY_ROLE, msg.sender));\n * ...\n * }\n * ```\n *\n * Roles can be granted and revoked dynamically via the {grantRole} and\n * {revokeRole} functions. Each role has an associated admin role, and only\n * accounts that have a role's admin role can call {grantRole} and {revokeRole}.\n *\n * By default, the admin role for all roles is `DEFAULT_ADMIN_ROLE`, which means\n * that only accounts with this role will be able to grant or revoke other\n * roles. More complex role relationships can be created by using\n * {_setRoleAdmin}.\n *\n * WARNING: The `DEFAULT_ADMIN_ROLE` is also its own admin: it has permission to\n * grant and revoke this role. Extra precautions should be taken to secure\n * accounts that have been granted it.\n */\nabstract contract AccessControlUpgradeable is Initializable, ContextUpgradeable {\n function __AccessControl_init() internal initializer {\n __Context_init_unchained();\n __AccessControl_init_unchained();\n }\n\n function __AccessControl_init_unchained() internal initializer {\n }\n using EnumerableSetUpgradeable for EnumerableSetUpgradeable.AddressSet;\n using AddressUpgradeable for address;\n\n struct RoleData {\n EnumerableSetUpgradeable.AddressSet members;\n bytes32 adminRole;\n }\n\n mapping (bytes32 => RoleData) private _roles;\n\n bytes32 public constant DEFAULT_ADMIN_ROLE = 0x00;\n\n /**\n * @dev Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole`\n *\n * `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite\n * {RoleAdminChanged} not being emitted signaling this.\n *\n * _Available since v3.1._\n */\n event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole);\n\n /**\n * @dev Emitted when `account` is granted `role`.\n *\n * `sender` is the account that originated the contract call, an admin role\n * bearer except when using {_setupRole}.\n */\n event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender);\n\n /**\n * @dev Emitted when `account` is revoked `role`.\n *\n * `sender` is the account that originated the contract call:\n * - if using `revokeRole`, it is the admin role bearer\n * - if using `renounceRole`, it is the role bearer (i.e. `account`)\n */\n event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender);\n\n /**\n * @dev Returns `true` if `account` has been granted `role`.\n */\n function hasRole(bytes32 role, address account) public view returns (bool) {\n return _roles[role].members.contains(account);\n }\n\n /**\n * @dev Returns the number of accounts that have `role`. Can be used\n * together with {getRoleMember} to enumerate all bearers of a role.\n */\n function getRoleMemberCount(bytes32 role) public view returns (uint256) {\n return _roles[role].members.length();\n }\n\n /**\n * @dev Returns one of the accounts that have `role`. `index` must be a\n * value between 0 and {getRoleMemberCount}, non-inclusive.\n *\n * Role bearers are not sorted in any particular way, and their ordering may\n * change at any point.\n *\n * WARNING: When using {getRoleMember} and {getRoleMemberCount}, make sure\n * you perform all queries on the same block. See the following\n * https://forum.openzeppelin.com/t/iterating-over-elements-on-enumerableset-in-openzeppelin-contracts/2296[forum post]\n * for more information.\n */\n function getRoleMember(bytes32 role, uint256 index) public view returns (address) {\n return _roles[role].members.at(index);\n }\n\n /**\n * @dev Returns the admin role that controls `role`. See {grantRole} and\n * {revokeRole}.\n *\n * To change a role's admin, use {_setRoleAdmin}.\n */\n function getRoleAdmin(bytes32 role) public view returns (bytes32) {\n return _roles[role].adminRole;\n }\n\n /**\n * @dev Grants `role` to `account`.\n *\n * If `account` had not been already granted `role`, emits a {RoleGranted}\n * event.\n *\n * Requirements:\n *\n * - the caller must have ``role``'s admin role.\n */\n function grantRole(bytes32 role, address account) public virtual {\n require(hasRole(_roles[role].adminRole, _msgSender()), \"AccessControl: sender must be an admin to grant\");\n\n _grantRole(role, account);\n }\n\n /**\n * @dev Revokes `role` from `account`.\n *\n * If `account` had been granted `role`, emits a {RoleRevoked} event.\n *\n * Requirements:\n *\n * - the caller must have ``role``'s admin role.\n */\n function revokeRole(bytes32 role, address account) public virtual {\n require(hasRole(_roles[role].adminRole, _msgSender()), \"AccessControl: sender must be an admin to revoke\");\n\n _revokeRole(role, account);\n }\n\n /**\n * @dev Revokes `role` from the calling account.\n *\n * Roles are often managed via {grantRole} and {revokeRole}: this function's\n * purpose is to provide a mechanism for accounts to lose their privileges\n * if they are compromised (such as when a trusted device is misplaced).\n *\n * If the calling account had been granted `role`, emits a {RoleRevoked}\n * event.\n *\n * Requirements:\n *\n * - the caller must be `account`.\n */\n function renounceRole(bytes32 role, address account) public virtual {\n require(account == _msgSender(), \"AccessControl: can only renounce roles for self\");\n\n _revokeRole(role, account);\n }\n\n /**\n * @dev Grants `role` to `account`.\n *\n * If `account` had not been already granted `role`, emits a {RoleGranted}\n * event. Note that unlike {grantRole}, this function doesn't perform any\n * checks on the calling account.\n *\n * [WARNING]\n * ====\n * This function should only be called from the constructor when setting\n * up the initial roles for the system.\n *\n * Using this function in any other way is effectively circumventing the admin\n * system imposed by {AccessControl}.\n * ====\n */\n function _setupRole(bytes32 role, address account) internal virtual {\n _grantRole(role, account);\n }\n\n /**\n * @dev Sets `adminRole` as ``role``'s admin role.\n *\n * Emits a {RoleAdminChanged} event.\n */\n function _setRoleAdmin(bytes32 role, bytes32 adminRole) internal virtual {\n emit RoleAdminChanged(role, _roles[role].adminRole, adminRole);\n _roles[role].adminRole = adminRole;\n }\n\n function _grantRole(bytes32 role, address account) private {\n if (_roles[role].members.add(account)) {\n emit RoleGranted(role, account, _msgSender());\n }\n }\n\n function _revokeRole(bytes32 role, address account) private {\n if (_roles[role].members.remove(account)) {\n emit RoleRevoked(role, account, _msgSender());\n }\n }\n uint256[49] private __gap;\n}\n" + }, + "@openzeppelin/contracts-upgradeable/utils/EnumerableSetUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <0.8.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 EnumerableSetUpgradeable {\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" + }, + "contracts/bridge/testing/SynapseToken.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity >=0.6.0 <0.8.0;\n\n\nimport \"@openzeppelin/contracts/token/ERC20/ERC20.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/ERC20Burnable.sol\";\nimport \"@openzeppelin/contracts/access/AccessControl.sol\";\nimport \"@openzeppelin/contracts/drafts/ERC20Permit.sol\";\n\ncontract Synapse is ERC20, ERC20Burnable, AccessControl, ERC20Permit {\n bytes32 public constant MINTER_ROLE = keccak256(\"MINTER_ROLE\");\n\n constructor() public ERC20(\"Synapse\", \"SYN\") ERC20Permit(\"Synapse\") {\n _setupRole(DEFAULT_ADMIN_ROLE, msg.sender);\n _setupRole(MINTER_ROLE, msg.sender);\n }\n\n function mint(address to, uint256 amount) external {\n require(hasRole(MINTER_ROLE, msg.sender));\n _mint(to, amount);\n }\n}" + }, + "@openzeppelin/contracts/access/AccessControl.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <0.8.0;\n\nimport \"../utils/EnumerableSet.sol\";\nimport \"../utils/Address.sol\";\nimport \"../utils/Context.sol\";\n\n/**\n * @dev Contract module that allows children to implement role-based access\n * control mechanisms.\n *\n * Roles are referred to by their `bytes32` identifier. These should be exposed\n * in the external API and be unique. The best way to achieve this is by\n * using `public constant` hash digests:\n *\n * ```\n * bytes32 public constant MY_ROLE = keccak256(\"MY_ROLE\");\n * ```\n *\n * Roles can be used to represent a set of permissions. To restrict access to a\n * function call, use {hasRole}:\n *\n * ```\n * function foo() public {\n * require(hasRole(MY_ROLE, msg.sender));\n * ...\n * }\n * ```\n *\n * Roles can be granted and revoked dynamically via the {grantRole} and\n * {revokeRole} functions. Each role has an associated admin role, and only\n * accounts that have a role's admin role can call {grantRole} and {revokeRole}.\n *\n * By default, the admin role for all roles is `DEFAULT_ADMIN_ROLE`, which means\n * that only accounts with this role will be able to grant or revoke other\n * roles. More complex role relationships can be created by using\n * {_setRoleAdmin}.\n *\n * WARNING: The `DEFAULT_ADMIN_ROLE` is also its own admin: it has permission to\n * grant and revoke this role. Extra precautions should be taken to secure\n * accounts that have been granted it.\n */\nabstract contract AccessControl is Context {\n using EnumerableSet for EnumerableSet.AddressSet;\n using Address for address;\n\n struct RoleData {\n EnumerableSet.AddressSet members;\n bytes32 adminRole;\n }\n\n mapping (bytes32 => RoleData) private _roles;\n\n bytes32 public constant DEFAULT_ADMIN_ROLE = 0x00;\n\n /**\n * @dev Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole`\n *\n * `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite\n * {RoleAdminChanged} not being emitted signaling this.\n *\n * _Available since v3.1._\n */\n event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole);\n\n /**\n * @dev Emitted when `account` is granted `role`.\n *\n * `sender` is the account that originated the contract call, an admin role\n * bearer except when using {_setupRole}.\n */\n event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender);\n\n /**\n * @dev Emitted when `account` is revoked `role`.\n *\n * `sender` is the account that originated the contract call:\n * - if using `revokeRole`, it is the admin role bearer\n * - if using `renounceRole`, it is the role bearer (i.e. `account`)\n */\n event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender);\n\n /**\n * @dev Returns `true` if `account` has been granted `role`.\n */\n function hasRole(bytes32 role, address account) public view returns (bool) {\n return _roles[role].members.contains(account);\n }\n\n /**\n * @dev Returns the number of accounts that have `role`. Can be used\n * together with {getRoleMember} to enumerate all bearers of a role.\n */\n function getRoleMemberCount(bytes32 role) public view returns (uint256) {\n return _roles[role].members.length();\n }\n\n /**\n * @dev Returns one of the accounts that have `role`. `index` must be a\n * value between 0 and {getRoleMemberCount}, non-inclusive.\n *\n * Role bearers are not sorted in any particular way, and their ordering may\n * change at any point.\n *\n * WARNING: When using {getRoleMember} and {getRoleMemberCount}, make sure\n * you perform all queries on the same block. See the following\n * https://forum.openzeppelin.com/t/iterating-over-elements-on-enumerableset-in-openzeppelin-contracts/2296[forum post]\n * for more information.\n */\n function getRoleMember(bytes32 role, uint256 index) public view returns (address) {\n return _roles[role].members.at(index);\n }\n\n /**\n * @dev Returns the admin role that controls `role`. See {grantRole} and\n * {revokeRole}.\n *\n * To change a role's admin, use {_setRoleAdmin}.\n */\n function getRoleAdmin(bytes32 role) public view returns (bytes32) {\n return _roles[role].adminRole;\n }\n\n /**\n * @dev Grants `role` to `account`.\n *\n * If `account` had not been already granted `role`, emits a {RoleGranted}\n * event.\n *\n * Requirements:\n *\n * - the caller must have ``role``'s admin role.\n */\n function grantRole(bytes32 role, address account) public virtual {\n require(hasRole(_roles[role].adminRole, _msgSender()), \"AccessControl: sender must be an admin to grant\");\n\n _grantRole(role, account);\n }\n\n /**\n * @dev Revokes `role` from `account`.\n *\n * If `account` had been granted `role`, emits a {RoleRevoked} event.\n *\n * Requirements:\n *\n * - the caller must have ``role``'s admin role.\n */\n function revokeRole(bytes32 role, address account) public virtual {\n require(hasRole(_roles[role].adminRole, _msgSender()), \"AccessControl: sender must be an admin to revoke\");\n\n _revokeRole(role, account);\n }\n\n /**\n * @dev Revokes `role` from the calling account.\n *\n * Roles are often managed via {grantRole} and {revokeRole}: this function's\n * purpose is to provide a mechanism for accounts to lose their privileges\n * if they are compromised (such as when a trusted device is misplaced).\n *\n * If the calling account had been granted `role`, emits a {RoleRevoked}\n * event.\n *\n * Requirements:\n *\n * - the caller must be `account`.\n */\n function renounceRole(bytes32 role, address account) public virtual {\n require(account == _msgSender(), \"AccessControl: can only renounce roles for self\");\n\n _revokeRole(role, account);\n }\n\n /**\n * @dev Grants `role` to `account`.\n *\n * If `account` had not been already granted `role`, emits a {RoleGranted}\n * event. Note that unlike {grantRole}, this function doesn't perform any\n * checks on the calling account.\n *\n * [WARNING]\n * ====\n * This function should only be called from the constructor when setting\n * up the initial roles for the system.\n *\n * Using this function in any other way is effectively circumventing the admin\n * system imposed by {AccessControl}.\n * ====\n */\n function _setupRole(bytes32 role, address account) internal virtual {\n _grantRole(role, account);\n }\n\n /**\n * @dev Sets `adminRole` as ``role``'s admin role.\n *\n * Emits a {RoleAdminChanged} event.\n */\n function _setRoleAdmin(bytes32 role, bytes32 adminRole) internal virtual {\n emit RoleAdminChanged(role, _roles[role].adminRole, adminRole);\n _roles[role].adminRole = adminRole;\n }\n\n function _grantRole(bytes32 role, address account) private {\n if (_roles[role].members.add(account)) {\n emit RoleGranted(role, account, _msgSender());\n }\n }\n\n function _revokeRole(bytes32 role, address account) private {\n if (_roles[role].members.remove(account)) {\n emit RoleRevoked(role, account, _msgSender());\n }\n }\n}\n" + }, + "@openzeppelin/contracts/utils/EnumerableSet.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <0.8.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" + }, + "contracts/bridge/testing/NodeEnv.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.6.12;\npragma experimental ABIEncoderV2;\n\nimport '@openzeppelin/contracts/access/AccessControl.sol';\nimport \"../utils/EnumerableStringMap.sol\";\n\n/**\n * @title NodeEnv contract\n * @author Synapse Authors\n * @notice This contract implements a key-value store for storing variables on which synapse nodes must coordinate\n * methods are purposely arbitrary to allow these fields to be defined in synapse improvement proposals.\n * @notice This token is used for configuring different tokens on the bridge and mapping them across chains.\n**/\ncontract NodeEnv is AccessControl {\n using EnumerableStringMap for EnumerableStringMap.StringToStringMap;\n // BRIDGEMANAGER_ROLE owns the bridge. They are the only user that can call setters on this contract\n bytes32 public constant BRIDGEMANAGER_ROLE = keccak256('BRIDGEMANAGER_ROLE');\n // _config stores the config\n EnumerableStringMap.StringToStringMap private _config; // key is tokenAddress,chainID\n\n // ConfigUpdate is emitted when the config is updated by the user\n event ConfigUpdate(\n string key\n );\n\n constructor() public {\n _setupRole(DEFAULT_ADMIN_ROLE, msg.sender);\n _setupRole(BRIDGEMANAGER_ROLE, msg.sender);\n }\n\n /**\n * @notice get the length of the config\n *\n * @dev this is useful for enumerating through all keys in the env\n */\n function keyCount()\n external\n view\n returns (uint256){\n return _config.length();\n }\n\n /**\n * @notice gets the key/value pair by it's index\n *\n * Requirements:\n *\n * - `index` must be strictly less than {length}.\n */\n function keyValueByIndex(uint256 index) external view returns(string memory, string memory){\n return _config.at(index);\n }\n\n /**\n * @notice gets the value associated with the key\n */\n function get(string calldata _key) external view returns(string memory){\n string memory key = _key;\n return _config.get(key);\n }\n\n /**\n * @notice sets the key\n *\n * @dev caller must have bridge manager role\n */\n function set(string calldata _key, string calldata _value) external returns(bool) {\n require(\n hasRole(BRIDGEMANAGER_ROLE, msg.sender),\n 'Caller is not Bridge Manager'\n );\n string memory key = _key;\n string memory value = _value;\n\n return _config.set(key, value);\n }\n}" + }, + "contracts/bridge/utils/EnumerableStringMap.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.6.12;\n\nimport \"@openzeppelin/contracts/utils/EnumerableSet.sol\";\n\n/**\n * @title EnumerableStringMap\n * @dev Library for managing an enumerable variant of Solidity's\n * https://solidity.readthedocs.io/en/latest/types.html#mapping-types[`mapping`]\n * type.\n *\n * Maps have the following properties:\n *\n * - Entries are added, removed, and checked for existence in constant time\n * (O(1)).\n * - Entries are enumerated in O(n). No guarantees are made on the ordering.\n *\n * this isn't a terribly gas efficient implementation because it emphasizes usability over gas efficiency\n * by allowing arbitrary length string memorys. If Gettetrs/Setters are going to be used frequently in contracts\n * consider using the OpenZeppeling Bytes32 implementation\n *\n * this also differs from the OpenZeppelin implementation by keccac256 hashing the string memorys\n * so we can use enumerable bytes32 set\n */\nlibrary EnumerableStringMap {\n using EnumerableSet for EnumerableSet.Bytes32Set;\n\n // To implement this library for multiple types with as little code\n // repetition as possible, we write it in terms of a generic Map type with\n // bytes32 keys and values.\n // The Map implementation uses private functions, and user-facing\n // implementations (such as Uint256ToAddressMap) are just wrappers around\n // the underlying Map.\n // This means that we can only create new EnumerableMaps for types that fit\n // in bytes32.\n\n struct Map {\n // Storage of keys as a set\n EnumerableSet.Bytes32Set _keys;\n // Mapping of keys to resulting values to allow key lookup in the set\n mapping(bytes32 => string) _hashKeyMap;\n // values\n mapping(bytes32 => string) _values;\n }\n\n /**\n * @dev Adds a key-value pair to a map, or updates the value for an existing\n * key. O(1).\n *\n * Returns true if the key was added to the map, that is if it was not\n * already present.\n */\n function _set(\n Map storage map,\n string memory key,\n string memory value\n ) private returns (bool) {\n bytes32 keyHash = keccak256(abi.encodePacked(key));\n map._values[keyHash] = value;\n map._hashKeyMap[keyHash] = key;\n return map._keys.add(keyHash);\n }\n\n /**\n * @dev Removes a key-value pair from a map. O(1).\n *\n * Returns true if the key was removed from the map, that is if it was present.\n */\n function _remove(Map storage map, bytes32 keyHash) private returns (bool) {\n delete map._values[keyHash];\n delete map._hashKeyMap[keyHash];\n return map._keys.remove(keyHash);\n }\n\n /**\n * @dev Returns true if the key is in the map. O(1).\n */\n function _contains(Map storage map, bytes32 keyHash) private view returns (bool) {\n return map._keys.contains(keyHash);\n }\n\n /**\n * @dev Returns the number of key-value pairs in the map. O(1).\n */\n function _length(Map storage map) private view returns (uint256) {\n return map._keys.length();\n }\n\n /**\n * @dev Returns the key-value pair stored at position `index` in the map. O(1).\n *\n * Note that there are no guarantees on the ordering of entries inside the\n * array, and it may change when more entries are added or removed.\n *\n * Requirements:\n *\n * - `index` must be strictly less than {length}.\n */\n function _at(Map storage map, uint256 index) private view returns (string memory, string memory) {\n bytes32 keyHash = map._keys.at(index);\n return (map._hashKeyMap[keyHash], map._values[keyHash]);\n }\n\n /**\n * @dev Tries to returns the value associated with `key`. O(1).\n * Does not revert if `key` is not in the map.\n */\n function _tryGet(Map storage map, bytes32 keyHash) private view returns (bool, string memory) {\n string memory value = map._values[keyHash];\n if (keccak256(bytes(value)) == keccak256(bytes(\"\"))) {\n return (_contains(map, keyHash), \"\");\n } else {\n return (true, value);\n }\n }\n\n /**\n * @dev Returns the value associated with `key`. O(1).\n *\n * Requirements:\n *\n * - `key` must be in the map.\n */\n function _get(Map storage map, bytes32 keyHash) private view returns (string memory) {\n string memory value = map._values[keyHash];\n require(_contains(map, keyHash), \"EnumerableMap: nonexistent key\");\n return value;\n }\n\n // StringToStringMap\n struct StringToStringMap {\n Map _inner;\n }\n\n /**\n * @dev Adds a key-value pair to a map, or updates the value for an existing\n * key. O(1).\n *\n * Returns true if the key was added to the map, that is if it was not\n * already present.\n */\n function set(\n StringToStringMap storage map,\n string memory key,\n string memory value\n ) internal returns (bool) {\n return _set(map._inner, key, value);\n }\n\n /**\n * @dev Removes a value from a set. O(1).\n *\n * Returns true if the key was removed from the map, that is if it was present.\n */\n function remove(StringToStringMap storage map, string memory key) internal returns (bool) {\n return _remove(map._inner, keccak256(abi.encodePacked(key)));\n }\n\n /**\n * @dev Returns true if the key is in the map. O(1).\n */\n function contains(StringToStringMap storage map, string memory key) internal view returns (bool) {\n return _contains(map._inner, keccak256(abi.encodePacked(key)));\n }\n\n /**\n * @dev Returns the number of elements in the map. O(1).\n */\n function length(StringToStringMap storage map) internal view returns (uint256) {\n return _length(map._inner);\n }\n\n /**\n * @dev Returns the element stored at position `index` in the set. O(1).\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(StringToStringMap storage map, uint256 index) internal view returns (string memory, string memory) {\n return _at(map._inner, index);\n }\n\n /**\n * @dev Tries to returns the value associated with `key`. O(1).\n * Does not revert if `key` is not in the map.\n *\n * _Available since v3.4._\n */\n function tryGet(StringToStringMap storage map, uint256 key) internal view returns (bool, string memory) {\n (bool success, string memory value) = _tryGet(map._inner, bytes32(key));\n return (success, value);\n }\n\n /**\n * @dev Returns the value associated with `key`. O(1).\n *\n * Requirements:\n *\n * - `key` must be in the map.\n */\n function get(StringToStringMap storage map, string memory key) internal view returns (string memory) {\n return _get(map._inner, keccak256(abi.encodePacked(key)));\n }\n}" + }, + "contracts/bridge/PoolConfig.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.6.12;\npragma experimental ABIEncoderV2;\n\nimport \"@openzeppelin/contracts/access/AccessControl.sol\";\n\ncontract PoolConfig is AccessControl {\n bytes32 public constant BRIDGEMANAGER_ROLE =\n keccak256(\"BRIDGEMANAGER_ROLE\");\n mapping(address => mapping(uint256 => Pool)) private _pool; // key is tokenAddress,chainID\n\n struct Pool {\n address tokenAddress;\n uint256 chainId;\n address poolAddress;\n bool metaswap;\n }\n\n constructor() public {\n _setupRole(DEFAULT_ADMIN_ROLE, msg.sender);\n _setupRole(BRIDGEMANAGER_ROLE, msg.sender);\n }\n\n function getPoolConfig(address tokenAddress, uint256 chainID)\n external\n view\n returns (Pool memory)\n {\n return _pool[tokenAddress][chainID];\n }\n\n function setPoolConfig(\n address tokenAddress,\n uint256 chainID,\n address poolAddress,\n bool metaswap\n ) external returns (Pool memory) {\n require(\n hasRole(BRIDGEMANAGER_ROLE, msg.sender),\n \"Caller is not Bridge Manager\"\n );\n Pool memory newPool = Pool(\n tokenAddress,\n chainID,\n poolAddress,\n metaswap\n );\n _pool[tokenAddress][chainID] = newPool;\n return newPool;\n }\n}\n" + }, + "contracts/bridge/BridgeConfigV3.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.6.12;\npragma experimental ABIEncoderV2;\n\nimport \"@openzeppelin/contracts/access/AccessControl.sol\";\nimport \"@openzeppelin/contracts/math/SafeMath.sol\";\n\n/**\n * @title BridgeConfig contract\n * @notice This token is used for configuring different tokens on the bridge and mapping them across chains.\n **/\n\ncontract BridgeConfigV3 is AccessControl {\n using SafeMath for uint256;\n bytes32 public constant BRIDGEMANAGER_ROLE =\n keccak256(\"BRIDGEMANAGER_ROLE\");\n bytes32[] private _allTokenIDs;\n mapping(bytes32 => Token[]) private _allTokens; // key is tokenID\n mapping(uint256 => mapping(string => bytes32)) private _tokenIDMap; // key is chainID,tokenAddress\n mapping(bytes32 => mapping(uint256 => Token)) private _tokens; // key is tokenID,chainID\n mapping(address => mapping(uint256 => Pool)) private _pool; // key is tokenAddress,chainID\n mapping(uint256 => uint256) private _maxGasPrice; // key is tokenID,chainID\n uint256 public constant bridgeConfigVersion = 3;\n\n // the denominator used to calculate fees. For example, an\n // LP fee might be something like tradeAmount.mul(fee).div(FEE_DENOMINATOR)\n uint256 private constant FEE_DENOMINATOR = 10**10;\n\n // this struct must be initialized using setTokenConfig for each token that directly interacts with the bridge\n struct Token {\n uint256 chainId;\n string tokenAddress;\n uint8 tokenDecimals;\n uint256 maxSwap;\n uint256 minSwap;\n uint256 swapFee;\n uint256 maxSwapFee;\n uint256 minSwapFee;\n bool hasUnderlying;\n bool isUnderlying;\n }\n\n struct Pool {\n address tokenAddress;\n uint256 chainId;\n address poolAddress;\n bool metaswap;\n }\n\n constructor() public {\n _setupRole(DEFAULT_ADMIN_ROLE, msg.sender);\n }\n\n /**\n * @notice Returns a list of all existing token IDs converted to strings\n */\n function getAllTokenIDs() public view returns (string[] memory result) {\n uint256 length = _allTokenIDs.length;\n result = new string[](length);\n for (uint256 i = 0; i < length; ++i) {\n result[i] = toString(_allTokenIDs[i]);\n }\n }\n\n function _getTokenID(string memory tokenAddress, uint256 chainID)\n internal\n view\n returns (string memory)\n {\n return toString(_tokenIDMap[chainID][tokenAddress]);\n }\n\n function getTokenID(string memory tokenAddress, uint256 chainID)\n public\n view\n returns (string memory)\n {\n return _getTokenID(_toLower(tokenAddress), chainID);\n }\n\n /**\n * @notice Returns the token ID (string) of the cross-chain token inputted\n * @param tokenAddress address of token to get ID for\n * @param chainID chainID of which to get token ID for\n */\n function getTokenID(address tokenAddress, uint256 chainID)\n public\n view\n returns (string memory)\n {\n return _getTokenID(_toLower(toString(tokenAddress)), chainID);\n }\n\n /**\n * @notice Returns the full token config struct\n * @param tokenID String input of the token ID for the token\n * @param chainID Chain ID of which token address + config to get\n */\n function getToken(string memory tokenID, uint256 chainID)\n public\n view\n returns (Token memory token)\n {\n return _tokens[toBytes32(tokenID)][chainID];\n }\n\n /**\n * @notice Returns the full token config struct\n * @param tokenID String input of the token ID for the token\n * @param chainID Chain ID of which token address + config to get\n */\n function getTokenByID(string memory tokenID, uint256 chainID)\n public\n view\n returns (Token memory token)\n {\n return _tokens[toBytes32(tokenID)][chainID];\n }\n\n /**\n * @notice Returns token config struct, given an address and chainID\n * @param tokenAddress Matches the token ID by using a combo of address + chain ID\n * @param chainID Chain ID of which token to get config for\n */\n function getTokenByAddress(string memory tokenAddress, uint256 chainID)\n public\n view\n returns (Token memory token)\n {\n return _tokens[_tokenIDMap[chainID][_toLower(tokenAddress)]][chainID];\n }\n\n function getTokenByEVMAddress(address tokenAddress, uint256 chainID)\n public\n view\n returns (Token memory token)\n {\n return\n _tokens[_tokenIDMap[chainID][_toLower(toString(tokenAddress))]][\n chainID\n ];\n }\n\n /**\n * @notice Returns true if the token has an underlying token -- meaning the token is deposited into the bridge\n * @param tokenID String to check if it is a withdraw/underlying token\n */\n function hasUnderlyingToken(string memory tokenID)\n public\n view\n returns (bool)\n {\n bytes32 bytesTokenID = toBytes32(tokenID);\n Token[] memory _mcTokens = _allTokens[bytesTokenID];\n for (uint256 i = 0; i < _mcTokens.length; ++i) {\n if (_mcTokens[i].hasUnderlying) {\n return true;\n }\n }\n return false;\n }\n\n /**\n * @notice Returns which token is the underlying token to withdraw\n * @param tokenID string token ID\n */\n function getUnderlyingToken(string memory tokenID)\n public\n view\n returns (Token memory token)\n {\n bytes32 bytesTokenID = toBytes32(tokenID);\n Token[] memory _mcTokens = _allTokens[bytesTokenID];\n for (uint256 i = 0; i < _mcTokens.length; ++i) {\n if (_mcTokens[i].isUnderlying) {\n return _mcTokens[i];\n }\n }\n }\n\n /**\n @notice Public function returning if token ID exists given a string\n */\n function isTokenIDExist(string memory tokenID) public view returns (bool) {\n return _isTokenIDExist(toBytes32(tokenID));\n }\n\n /**\n @notice Internal function returning if token ID exists given bytes32 version of the ID\n */\n function _isTokenIDExist(bytes32 tokenID) internal view returns (bool) {\n for (uint256 i = 0; i < _allTokenIDs.length; ++i) {\n if (_allTokenIDs[i] == tokenID) {\n return true;\n }\n }\n return false;\n }\n\n /**\n * @notice Internal function which handles logic of setting token ID and dealing with mappings\n * @param tokenID bytes32 version of ID\n * @param chainID which chain to set the token config for\n * @param tokenToAdd Token object to set the mapping to\n */\n function _setTokenConfig(\n bytes32 tokenID,\n uint256 chainID,\n Token memory tokenToAdd\n ) internal returns (bool) {\n _tokens[tokenID][chainID] = tokenToAdd;\n if (!_isTokenIDExist(tokenID)) {\n _allTokenIDs.push(tokenID);\n }\n\n Token[] storage _mcTokens = _allTokens[tokenID];\n for (uint256 i = 0; i < _mcTokens.length; ++i) {\n if (_mcTokens[i].chainId == chainID) {\n string memory oldToken = _mcTokens[i].tokenAddress;\n if (!compareStrings(tokenToAdd.tokenAddress, oldToken)) {\n _mcTokens[i].tokenAddress = tokenToAdd.tokenAddress;\n _tokenIDMap[chainID][oldToken] = keccak256(\"\");\n _tokenIDMap[chainID][tokenToAdd.tokenAddress] = tokenID;\n }\n }\n }\n _mcTokens.push(tokenToAdd);\n _tokenIDMap[chainID][tokenToAdd.tokenAddress] = tokenID;\n return true;\n }\n\n /**\n * @notice Main write function of this contract - Handles creating the struct and passing it to the internal logic function\n * @param tokenID string ID to set the token config object form\n * @param chainID chain ID to use for the token config object\n * @param tokenAddress token address of the token on the given chain\n * @param tokenDecimals decimals of token\n * @param maxSwap maximum amount of token allowed to be transferred at once - in native token decimals\n * @param minSwap minimum amount of token needed to be transferred at once - in native token decimals\n * @param swapFee percent based swap fee -- 10e6 == 10bps\n * @param maxSwapFee max swap fee to be charged - in native token decimals\n * @param minSwapFee min swap fee to be charged - in native token decimals - especially useful for mainnet ETH\n * @param hasUnderlying bool which represents whether this is a global mint token or one to withdraw()\n * @param isUnderlying bool which represents if this token is the one to withdraw on the given chain\n */\n function setTokenConfig(\n string calldata tokenID,\n uint256 chainID,\n address tokenAddress,\n uint8 tokenDecimals,\n uint256 maxSwap,\n uint256 minSwap,\n uint256 swapFee,\n uint256 maxSwapFee,\n uint256 minSwapFee,\n bool hasUnderlying,\n bool isUnderlying\n ) public returns (bool) {\n require(hasRole(BRIDGEMANAGER_ROLE, msg.sender));\n return\n setTokenConfig(\n tokenID,\n chainID,\n toString(tokenAddress),\n tokenDecimals,\n maxSwap,\n minSwap,\n swapFee,\n maxSwapFee,\n minSwapFee,\n hasUnderlying,\n isUnderlying\n );\n }\n\n /**\n * @notice Main write function of this contract - Handles creating the struct and passing it to the internal logic function\n * @param tokenID string ID to set the token config object form\n * @param chainID chain ID to use for the token config object\n * @param tokenAddress token address of the token on the given chain\n * @param tokenDecimals decimals of token\n * @param maxSwap maximum amount of token allowed to be transferred at once - in native token decimals\n * @param minSwap minimum amount of token needed to be transferred at once - in native token decimals\n * @param swapFee percent based swap fee -- 10e6 == 10bps\n * @param maxSwapFee max swap fee to be charged - in native token decimals\n * @param minSwapFee min swap fee to be charged - in native token decimals - especially useful for mainnet ETH\n * @param hasUnderlying bool which represents whether this is a global mint token or one to withdraw()\n * @param isUnderlying bool which represents if this token is the one to withdraw on the given chain\n */\n function setTokenConfig(\n string calldata tokenID,\n uint256 chainID,\n string memory tokenAddress,\n uint8 tokenDecimals,\n uint256 maxSwap,\n uint256 minSwap,\n uint256 swapFee,\n uint256 maxSwapFee,\n uint256 minSwapFee,\n bool hasUnderlying,\n bool isUnderlying\n ) public returns (bool) {\n require(hasRole(BRIDGEMANAGER_ROLE, msg.sender));\n Token memory tokenToAdd;\n tokenToAdd.tokenAddress = _toLower(tokenAddress);\n tokenToAdd.tokenDecimals = tokenDecimals;\n tokenToAdd.maxSwap = maxSwap;\n tokenToAdd.minSwap = minSwap;\n tokenToAdd.swapFee = swapFee;\n tokenToAdd.maxSwapFee = maxSwapFee;\n tokenToAdd.minSwapFee = minSwapFee;\n tokenToAdd.hasUnderlying = hasUnderlying;\n tokenToAdd.isUnderlying = isUnderlying;\n tokenToAdd.chainId = chainID;\n\n return _setTokenConfig(toBytes32(tokenID), chainID, tokenToAdd);\n }\n\n function _calculateSwapFee(\n string memory tokenAddress,\n uint256 chainID,\n uint256 amount\n ) internal view returns (uint256) {\n Token memory token = _tokens[_tokenIDMap[chainID][tokenAddress]][\n chainID\n ];\n uint256 calculatedSwapFee = amount.mul(token.swapFee).div(\n FEE_DENOMINATOR\n );\n if (\n calculatedSwapFee > token.minSwapFee &&\n calculatedSwapFee < token.maxSwapFee\n ) {\n return calculatedSwapFee;\n } else if (calculatedSwapFee > token.maxSwapFee) {\n return token.maxSwapFee;\n } else {\n return token.minSwapFee;\n }\n }\n\n /**\n * @notice Calculates bridge swap fee based on the destination chain's token transfer.\n * @dev This means the fee should be calculated based on the chain that the nodes emit a tx on\n * @param tokenAddress address of the destination token to query token config for\n * @param chainID destination chain ID to query the token config for\n * @param amount in native token decimals\n * @return Fee calculated in token decimals\n */\n function calculateSwapFee(\n string memory tokenAddress,\n uint256 chainID,\n uint256 amount\n ) external view returns (uint256) {\n return _calculateSwapFee(_toLower(tokenAddress), chainID, amount);\n }\n\n /**\n * @notice Calculates bridge swap fee based on the destination chain's token transfer.\n * @dev This means the fee should be calculated based on the chain that the nodes emit a tx on\n * @param tokenAddress address of the destination token to query token config for\n * @param chainID destination chain ID to query the token config for\n * @param amount in native token decimals\n * @return Fee calculated in token decimals\n */\n function calculateSwapFee(\n address tokenAddress,\n uint256 chainID,\n uint256 amount\n ) external view returns (uint256) {\n return\n _calculateSwapFee(\n _toLower(toString(tokenAddress)),\n chainID,\n amount\n );\n }\n\n // GAS PRICING\n\n /**\n * @notice sets the max gas price for a chain\n */\n function setMaxGasPrice(uint256 chainID, uint256 maxPrice) public {\n require(hasRole(BRIDGEMANAGER_ROLE, msg.sender));\n _maxGasPrice[chainID] = maxPrice;\n }\n\n /**\n * @notice gets the max gas price for a chain\n */\n function getMaxGasPrice(uint256 chainID) public view returns (uint256) {\n return _maxGasPrice[chainID];\n }\n\n // POOL CONFIG\n\n function getPoolConfig(address tokenAddress, uint256 chainID)\n external\n view\n returns (Pool memory)\n {\n return _pool[tokenAddress][chainID];\n }\n\n function setPoolConfig(\n address tokenAddress,\n uint256 chainID,\n address poolAddress,\n bool metaswap\n ) external returns (Pool memory) {\n require(\n hasRole(BRIDGEMANAGER_ROLE, msg.sender),\n \"Caller is not Bridge Manager\"\n );\n Pool memory newPool = Pool(\n tokenAddress,\n chainID,\n poolAddress,\n metaswap\n );\n _pool[tokenAddress][chainID] = newPool;\n return newPool;\n }\n\n // UTILITY FUNCTIONS\n\n function toString(bytes32 data) internal pure returns (string memory) {\n uint8 i = 0;\n while (i < 32 && data[i] != 0) {\n ++i;\n }\n bytes memory bs = new bytes(i);\n for (uint8 j = 0; j < i; ++j) {\n bs[j] = data[j];\n }\n return string(bs);\n }\n\n // toBytes32 converts a string to a bytes 32\n function toBytes32(string memory str)\n internal\n pure\n returns (bytes32 result)\n {\n require(bytes(str).length <= 32);\n assembly {\n result := mload(add(str, 32))\n }\n }\n\n function toString(address x) internal pure returns (string memory) {\n bytes memory s = new bytes(40);\n for (uint256 i = 0; i < 20; i++) {\n bytes1 b = bytes1(uint8(uint256(uint160(x)) / (2**(8 * (19 - i)))));\n bytes1 hi = bytes1(uint8(b) / 16);\n bytes1 lo = bytes1(uint8(b) - 16 * uint8(hi));\n s[2 * i] = char(hi);\n s[2 * i + 1] = char(lo);\n }\n\n string memory addrPrefix = \"0x\";\n\n return concat(addrPrefix, string(s));\n }\n\n function concat(string memory _x, string memory _y)\n internal\n pure\n returns (string memory)\n {\n bytes memory _xBytes = bytes(_x);\n bytes memory _yBytes = bytes(_y);\n\n string memory _tmpValue = new string(_xBytes.length + _yBytes.length);\n bytes memory _newValue = bytes(_tmpValue);\n\n uint256 i;\n uint256 j;\n\n for (i = 0; i < _xBytes.length; i++) {\n _newValue[j++] = _xBytes[i];\n }\n\n for (i = 0; i < _yBytes.length; i++) {\n _newValue[j++] = _yBytes[i];\n }\n\n return string(_newValue);\n }\n\n function char(bytes1 b) internal pure returns (bytes1 c) {\n if (uint8(b) < 10) {\n c = bytes1(uint8(b) + 0x30);\n } else {\n c = bytes1(uint8(b) + 0x57);\n }\n }\n\n function compareStrings(string memory a, string memory b)\n internal\n pure\n returns (bool)\n {\n return (keccak256(abi.encodePacked((a))) ==\n keccak256(abi.encodePacked((b))));\n }\n\n function _toLower(string memory str) internal pure returns (string memory) {\n bytes memory bStr = bytes(str);\n bytes memory bLower = new bytes(bStr.length);\n for (uint256 i = 0; i < bStr.length; i++) {\n // Uppercase character...\n if ((uint8(bStr[i]) >= 65) && (uint8(bStr[i]) <= 90)) {\n // So we add 32 to make it lowercase\n bLower[i] = bytes1(uint8(bStr[i]) + 32);\n } else {\n bLower[i] = bStr[i];\n }\n }\n return string(bLower);\n }\n}\n" + }, + "contracts/bridge/MoonriverSynapseBridge.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.6.12;\n\nimport \"@openzeppelin/contracts-upgradeable/proxy/Initializable.sol\";\nimport \"@openzeppelin/contracts-upgradeable/access/AccessControlUpgradeable.sol\";\nimport \"@openzeppelin/contracts-upgradeable/utils/ReentrancyGuardUpgradeable.sol\";\nimport \"@openzeppelin/contracts-upgradeable/utils/PausableUpgradeable.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/SafeERC20.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/ERC20Burnable.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport \"@openzeppelin/contracts/math/SafeMath.sol\";\n\nimport \"./interfaces/ISwap.sol\";\nimport \"./interfaces/IWETH9.sol\";\n\ninterface IERC20Mintable is IERC20 {\n function mint(address to, uint256 amount) external;\n}\n\ninterface IFrax {\n function exchangeOldForCanonical(\n address bridge_token_address,\n uint256 token_amount\n ) external returns (uint256);\n}\n\ncontract MRSynapseBridge is\n Initializable,\n AccessControlUpgradeable,\n ReentrancyGuardUpgradeable,\n PausableUpgradeable\n{\n using SafeERC20 for IERC20;\n using SafeERC20 for IERC20Mintable;\n using SafeMath for uint256;\n\n bytes32 public constant NODEGROUP_ROLE = keccak256(\"NODEGROUP_ROLE\");\n bytes32 public constant GOVERNANCE_ROLE = keccak256(\"GOVERNANCE_ROLE\");\n\n mapping(address => uint256) private fees;\n\n uint256 public startBlockNumber;\n uint256 public constant bridgeVersion = 6;\n uint256 public chainGasAmount;\n address payable public WETH_ADDRESS;\n\n mapping(bytes32 => bool) private kappaMap;\n\n receive() external payable {}\n\n function initialize() external initializer {\n startBlockNumber = block.number;\n _setupRole(DEFAULT_ADMIN_ROLE, msg.sender);\n __AccessControl_init();\n }\n\n function setChainGasAmount(uint256 amount) external {\n require(hasRole(GOVERNANCE_ROLE, msg.sender), \"Not governance\");\n chainGasAmount = amount;\n }\n\n function setWethAddress(address payable _wethAddress) external {\n require(hasRole(DEFAULT_ADMIN_ROLE, msg.sender), \"Not admin\");\n WETH_ADDRESS = _wethAddress;\n }\n\n function addKappas(bytes32[] calldata kappas) external {\n require(hasRole(GOVERNANCE_ROLE, msg.sender), \"Not governance\");\n for (uint256 i = 0; i < kappas.length; ++i) {\n kappaMap[kappas[i]] = true;\n }\n }\n\n event TokenDeposit(\n address indexed to,\n uint256 chainId,\n IERC20 token,\n uint256 amount\n );\n event TokenRedeem(\n address indexed to,\n uint256 chainId,\n IERC20 token,\n uint256 amount\n );\n event TokenWithdraw(\n address indexed to,\n IERC20 token,\n uint256 amount,\n uint256 fee,\n bytes32 indexed kappa\n );\n event TokenMint(\n address indexed to,\n IERC20Mintable token,\n uint256 amount,\n uint256 fee,\n bytes32 indexed kappa\n );\n event TokenDepositAndSwap(\n address indexed to,\n uint256 chainId,\n IERC20 token,\n uint256 amount,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 minDy,\n uint256 deadline\n );\n event TokenMintAndSwap(\n address indexed to,\n IERC20Mintable token,\n uint256 amount,\n uint256 fee,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 minDy,\n uint256 deadline,\n bool swapSuccess,\n bytes32 indexed kappa\n );\n event TokenRedeemAndSwap(\n address indexed to,\n uint256 chainId,\n IERC20 token,\n uint256 amount,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 minDy,\n uint256 deadline\n );\n event TokenRedeemAndRemove(\n address indexed to,\n uint256 chainId,\n IERC20 token,\n uint256 amount,\n uint8 swapTokenIndex,\n uint256 swapMinAmount,\n uint256 swapDeadline\n );\n event TokenWithdrawAndRemove(\n address indexed to,\n IERC20 token,\n uint256 amount,\n uint256 fee,\n uint8 swapTokenIndex,\n uint256 swapMinAmount,\n uint256 swapDeadline,\n bool swapSuccess,\n bytes32 indexed kappa\n );\n\n // v2 events\n event TokenRedeemV2(\n bytes32 indexed to,\n uint256 chainId,\n IERC20 token,\n uint256 amount\n );\n\n // VIEW FUNCTIONS ***/\n function getFeeBalance(address tokenAddress)\n external\n view\n returns (uint256)\n {\n return fees[tokenAddress];\n }\n\n function kappaExists(bytes32 kappa) external view returns (bool) {\n return kappaMap[kappa];\n }\n\n // FEE FUNCTIONS ***/\n /**\n * * @notice withdraw specified ERC20 token fees to a given address\n * * @param token ERC20 token in which fees acccumulated to transfer\n * * @param to Address to send the fees to\n */\n function withdrawFees(IERC20 token, address to) external whenNotPaused {\n require(hasRole(GOVERNANCE_ROLE, msg.sender), \"Not governance\");\n require(to != address(0), \"Address is 0x000\");\n if (fees[address(token)] != 0) {\n token.safeTransfer(to, fees[address(token)]);\n fees[address(token)] = 0;\n }\n }\n\n // PAUSABLE FUNCTIONS ***/\n function pause() external {\n require(hasRole(GOVERNANCE_ROLE, msg.sender), \"Not governance\");\n _pause();\n }\n\n function unpause() external {\n require(hasRole(GOVERNANCE_ROLE, msg.sender), \"Not governance\");\n _unpause();\n }\n\n /**\n * @notice Relays to nodes to transfers an ERC20 token cross-chain\n * @param to address on other chain to bridge assets to\n * @param chainId which chain to bridge assets onto\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n **/\n function deposit(\n address to,\n uint256 chainId,\n IERC20 token,\n uint256 amount\n ) external nonReentrant whenNotPaused {\n emit TokenDeposit(to, chainId, token, amount);\n token.safeTransferFrom(msg.sender, address(this), amount);\n }\n\n /**\n * @notice Relays to nodes that (typically) a wrapped synAsset ERC20 token has been burned and the underlying needs to be redeeemed on the native chain\n * @param to address on other chain to redeem underlying assets to\n * @param chainId which underlying chain to bridge assets onto\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n **/\n function redeem(\n address to,\n uint256 chainId,\n ERC20Burnable token,\n uint256 amount\n ) external nonReentrant whenNotPaused {\n emit TokenRedeem(to, chainId, token, amount);\n token.burnFrom(msg.sender, amount);\n }\n\n /**\n * @notice Function to be called by the node group to withdraw the underlying assets from the contract\n * @param to address on chain to send underlying assets to\n * @param token ERC20 compatible token to withdraw from the bridge\n * @param amount Amount in native token decimals to withdraw\n * @param fee Amount in native token decimals to save to the contract as fees\n * @param kappa kappa\n **/\n function withdraw(\n address to,\n IERC20 token,\n uint256 amount,\n uint256 fee,\n bytes32 kappa\n ) external nonReentrant whenNotPaused {\n require(\n hasRole(NODEGROUP_ROLE, msg.sender),\n \"Caller is not a node group\"\n );\n require(amount > fee, \"Amount must be greater than fee\");\n require(!kappaMap[kappa], \"Kappa is already present\");\n kappaMap[kappa] = true;\n fees[address(token)] = fees[address(token)].add(fee);\n if (address(token) == WETH_ADDRESS && WETH_ADDRESS != address(0)) {\n IWETH9(WETH_ADDRESS).withdraw(amount.sub(fee));\n (bool success, ) = to.call{value: amount.sub(fee)}(\"\");\n require(success, \"ETH_TRANSFER_FAILED\");\n emit TokenWithdraw(to, token, amount, fee, kappa);\n } else {\n emit TokenWithdraw(to, token, amount, fee, kappa);\n token.safeTransfer(to, amount.sub(fee));\n }\n }\n\n /**\n * @notice Nodes call this function to mint a SynERC20 (or any asset that the bridge is given minter access to). This is called by the nodes after a TokenDeposit event is emitted.\n * @dev This means the SynapseBridge.sol contract must have minter access to the token attempting to be minted\n * @param to address on other chain to redeem underlying assets to\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain post-fees\n * @param fee Amount in native token decimals to save to the contract as fees\n * @param kappa kappa\n **/\n function mint(\n address payable to,\n IERC20Mintable token,\n uint256 amount,\n uint256 fee,\n bytes32 kappa\n ) external nonReentrant whenNotPaused {\n require(\n hasRole(NODEGROUP_ROLE, msg.sender),\n \"Caller is not a node group\"\n );\n require(amount > fee, \"Amount must be greater than fee\");\n require(!kappaMap[kappa], \"Kappa is already present\");\n kappaMap[kappa] = true;\n fees[address(token)] = fees[address(token)].add(fee);\n emit TokenMint(to, token, amount.sub(fee), fee, kappa);\n token.mint(address(this), amount);\n // checks if synFRAX\n if (address(token) == 0xE96AC70907ffF3Efee79f502C985A7A21Bce407d) {\n token.safeIncreaseAllowance(\n 0x1A93B23281CC1CDE4C4741353F3064709A16197d,\n amount.sub(fee)\n );\n try\n IFrax(0x1A93B23281CC1CDE4C4741353F3064709A16197d)\n .exchangeOldForCanonical(address(token), amount.sub(fee))\n returns (uint256 canolical_tokens_out) {\n IERC20(0x1A93B23281CC1CDE4C4741353F3064709A16197d).safeTransfer(\n to,\n canolical_tokens_out\n );\n } catch {\n IERC20(token).safeTransfer(to, amount.sub(fee));\n }\n } else {\n IERC20(token).safeTransfer(to, amount.sub(fee));\n }\n if (chainGasAmount != 0 && address(this).balance > chainGasAmount) {\n to.call.value(chainGasAmount)(\"\");\n }\n }\n\n /**\n * @notice Relays to nodes to both transfer an ERC20 token cross-chain, and then have the nodes execute a swap through a liquidity pool on behalf of the user.\n * @param to address on other chain to bridge assets to\n * @param chainId which chain to bridge assets onto\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n * @param tokenIndexFrom the token the user wants to swap from\n * @param tokenIndexTo the token the user wants to swap to\n * @param minDy the min amount the user would like to receive, or revert to only minting the SynERC20 token crosschain.\n * @param deadline latest timestamp to accept this transaction\n **/\n function depositAndSwap(\n address to,\n uint256 chainId,\n IERC20 token,\n uint256 amount,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 minDy,\n uint256 deadline\n ) external nonReentrant whenNotPaused {\n emit TokenDepositAndSwap(\n to,\n chainId,\n token,\n amount,\n tokenIndexFrom,\n tokenIndexTo,\n minDy,\n deadline\n );\n token.safeTransferFrom(msg.sender, address(this), amount);\n }\n\n /**\n * @notice Relays to nodes that (typically) a wrapped synAsset ERC20 token has been burned and the underlying needs to be redeeemed on the native chain. This function indicates to the nodes that they should attempt to redeem the LP token for the underlying assets (E.g \"swap\" out of the LP token)\n * @param to address on other chain to redeem underlying assets to\n * @param chainId which underlying chain to bridge assets onto\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n * @param tokenIndexFrom the token the user wants to swap from\n * @param tokenIndexTo the token the user wants to swap to\n * @param minDy the min amount the user would like to receive, or revert to only minting the SynERC20 token crosschain.\n * @param deadline latest timestamp to accept this transaction\n **/\n function redeemAndSwap(\n address to,\n uint256 chainId,\n ERC20Burnable token,\n uint256 amount,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 minDy,\n uint256 deadline\n ) external nonReentrant whenNotPaused {\n emit TokenRedeemAndSwap(\n to,\n chainId,\n token,\n amount,\n tokenIndexFrom,\n tokenIndexTo,\n minDy,\n deadline\n );\n token.burnFrom(msg.sender, amount);\n }\n\n /**\n * @notice Relays to nodes that (typically) a wrapped synAsset ERC20 token has been burned and the underlying needs to be redeeemed on the native chain. This function indicates to the nodes that they should attempt to redeem the LP token for the underlying assets (E.g \"swap\" out of the LP token)\n * @param to address on other chain to redeem underlying assets to\n * @param chainId which underlying chain to bridge assets onto\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n * @param swapTokenIndex Specifies which of the underlying LP assets the nodes should attempt to redeem for\n * @param swapMinAmount Specifies the minimum amount of the underlying asset needed for the nodes to execute the redeem/swap\n * @param swapDeadline Specificies the deadline that the nodes are allowed to try to redeem/swap the LP token\n **/\n function redeemAndRemove(\n address to,\n uint256 chainId,\n ERC20Burnable token,\n uint256 amount,\n uint8 swapTokenIndex,\n uint256 swapMinAmount,\n uint256 swapDeadline\n ) external nonReentrant whenNotPaused {\n emit TokenRedeemAndRemove(\n to,\n chainId,\n token,\n amount,\n swapTokenIndex,\n swapMinAmount,\n swapDeadline\n );\n token.burnFrom(msg.sender, amount);\n }\n\n /**\n * @notice Nodes call this function to mint a SynERC20 (or any asset that the bridge is given minter access to), and then attempt to swap the SynERC20 into the desired destination asset. This is called by the nodes after a TokenDepositAndSwap event is emitted.\n * @dev This means the BridgeDeposit.sol contract must have minter access to the token attempting to be minted\n * @param to address on other chain to redeem underlying assets to\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain post-fees\n * @param fee Amount in native token decimals to save to the contract as fees\n * @param pool Destination chain's pool to use to swap SynERC20 -> Asset. The nodes determine this by using PoolConfig.sol.\n * @param tokenIndexFrom Index of the SynERC20 asset in the pool\n * @param tokenIndexTo Index of the desired final asset\n * @param minDy Minumum amount (in final asset decimals) that must be swapped for, otherwise the user will receive the SynERC20.\n * @param deadline Epoch time of the deadline that the swap is allowed to be executed.\n * @param kappa kappa\n **/\n function mintAndSwap(\n address payable to,\n IERC20Mintable token,\n uint256 amount,\n uint256 fee,\n ISwap pool,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 minDy,\n uint256 deadline,\n bytes32 kappa\n ) external nonReentrant whenNotPaused {\n require(\n hasRole(NODEGROUP_ROLE, msg.sender),\n \"Caller is not a node group\"\n );\n require(amount > fee, \"Amount must be greater than fee\");\n require(!kappaMap[kappa], \"Kappa is already present\");\n kappaMap[kappa] = true;\n fees[address(token)] = fees[address(token)].add(fee);\n // Transfer gas airdrop\n if (chainGasAmount != 0 && address(this).balance > chainGasAmount) {\n to.call.value(chainGasAmount)(\"\");\n }\n // first check to make sure more will be given than min amount required\n uint256 expectedOutput = ISwap(pool).calculateSwap(\n tokenIndexFrom,\n tokenIndexTo,\n amount.sub(fee)\n );\n\n if (expectedOutput >= minDy) {\n // proceed with swap\n token.mint(address(this), amount);\n token.safeIncreaseAllowance(address(pool), amount);\n try\n ISwap(pool).swap(\n tokenIndexFrom,\n tokenIndexTo,\n amount.sub(fee),\n minDy,\n deadline\n )\n returns (uint256 finalSwappedAmount) {\n // Swap succeeded, transfer swapped asset\n IERC20 swappedTokenTo = ISwap(pool).getToken(tokenIndexTo);\n if (\n address(swappedTokenTo) == WETH_ADDRESS &&\n WETH_ADDRESS != address(0)\n ) {\n IWETH9(WETH_ADDRESS).withdraw(finalSwappedAmount);\n (bool success, ) = to.call{value: finalSwappedAmount}(\"\");\n require(success, \"ETH_TRANSFER_FAILED\");\n emit TokenMintAndSwap(\n to,\n token,\n finalSwappedAmount,\n fee,\n tokenIndexFrom,\n tokenIndexTo,\n minDy,\n deadline,\n true,\n kappa\n );\n } else {\n swappedTokenTo.safeTransfer(to, finalSwappedAmount);\n emit TokenMintAndSwap(\n to,\n token,\n finalSwappedAmount,\n fee,\n tokenIndexFrom,\n tokenIndexTo,\n minDy,\n deadline,\n true,\n kappa\n );\n }\n } catch {\n IERC20(token).safeTransfer(to, amount.sub(fee));\n emit TokenMintAndSwap(\n to,\n token,\n amount.sub(fee),\n fee,\n tokenIndexFrom,\n tokenIndexTo,\n minDy,\n deadline,\n false,\n kappa\n );\n }\n } else {\n token.mint(address(this), amount);\n IERC20(token).safeTransfer(to, amount.sub(fee));\n emit TokenMintAndSwap(\n to,\n token,\n amount.sub(fee),\n fee,\n tokenIndexFrom,\n tokenIndexTo,\n minDy,\n deadline,\n false,\n kappa\n );\n }\n }\n\n /**\n * @notice Function to be called by the node group to withdraw the underlying assets from the contract\n * @param to address on chain to send underlying assets to\n * @param token ERC20 compatible token to withdraw from the bridge\n * @param amount Amount in native token decimals to withdraw\n * @param fee Amount in native token decimals to save to the contract as fees\n * @param pool Destination chain's pool to use to swap SynERC20 -> Asset. The nodes determine this by using PoolConfig.sol.\n * @param swapTokenIndex Specifies which of the underlying LP assets the nodes should attempt to redeem for\n * @param swapMinAmount Specifies the minimum amount of the underlying asset needed for the nodes to execute the redeem/swap\n * @param swapDeadline Specificies the deadline that the nodes are allowed to try to redeem/swap the LP token\n * @param kappa kappa\n **/\n function withdrawAndRemove(\n address to,\n IERC20 token,\n uint256 amount,\n uint256 fee,\n ISwap pool,\n uint8 swapTokenIndex,\n uint256 swapMinAmount,\n uint256 swapDeadline,\n bytes32 kappa\n ) external nonReentrant whenNotPaused {\n require(\n hasRole(NODEGROUP_ROLE, msg.sender),\n \"Caller is not a node group\"\n );\n require(amount > fee, \"Amount must be greater than fee\");\n require(!kappaMap[kappa], \"Kappa is already present\");\n kappaMap[kappa] = true;\n fees[address(token)] = fees[address(token)].add(fee);\n // first check to make sure more will be given than min amount required\n uint256 expectedOutput = ISwap(pool).calculateRemoveLiquidityOneToken(\n amount.sub(fee),\n swapTokenIndex\n );\n\n if (expectedOutput >= swapMinAmount) {\n token.safeIncreaseAllowance(address(pool), amount.sub(fee));\n try\n ISwap(pool).removeLiquidityOneToken(\n amount.sub(fee),\n swapTokenIndex,\n swapMinAmount,\n swapDeadline\n )\n returns (uint256 finalSwappedAmount) {\n // Swap succeeded, transfer swapped asset\n IERC20 swappedTokenTo = ISwap(pool).getToken(swapTokenIndex);\n swappedTokenTo.safeTransfer(to, finalSwappedAmount);\n emit TokenWithdrawAndRemove(\n to,\n token,\n finalSwappedAmount,\n fee,\n swapTokenIndex,\n swapMinAmount,\n swapDeadline,\n true,\n kappa\n );\n } catch {\n IERC20(token).safeTransfer(to, amount.sub(fee));\n emit TokenWithdrawAndRemove(\n to,\n token,\n amount.sub(fee),\n fee,\n swapTokenIndex,\n swapMinAmount,\n swapDeadline,\n false,\n kappa\n );\n }\n } else {\n token.safeTransfer(to, amount.sub(fee));\n emit TokenWithdrawAndRemove(\n to,\n token,\n amount.sub(fee),\n fee,\n swapTokenIndex,\n swapMinAmount,\n swapDeadline,\n false,\n kappa\n );\n }\n }\n\n // BRIDGE FUNCTIONS TO HANDLE DIFF ADDRESSES\n /**\n * @notice Relays to nodes that (typically) a wrapped synAsset ERC20 token has been burned and the underlying needs to be redeeemed on the native chain\n * @param to address on other chain to redeem underlying assets to\n * @param chainId which underlying chain to bridge assets onto\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n **/\n function redeemV2(\n bytes32 to,\n uint256 chainId,\n ERC20Burnable token,\n uint256 amount\n ) external nonReentrant whenNotPaused {\n emit TokenRedeemV2(to, chainId, token, amount);\n token.burnFrom(msg.sender, amount);\n }\n}\n" + }, + "contracts/bridge/HarmonySynapseBridge.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.6.12;\n\nimport \"@openzeppelin/contracts-upgradeable/proxy/Initializable.sol\";\nimport \"@openzeppelin/contracts-upgradeable/access/AccessControlUpgradeable.sol\";\nimport \"@openzeppelin/contracts-upgradeable/utils/ReentrancyGuardUpgradeable.sol\";\nimport \"@openzeppelin/contracts-upgradeable/utils/PausableUpgradeable.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/SafeERC20.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/ERC20Burnable.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport \"@openzeppelin/contracts/math/SafeMath.sol\";\n\nimport \"./interfaces/ISwap.sol\";\nimport \"./interfaces/IWETH9.sol\";\n\ninterface IERC20Mintable is IERC20 {\n function mint(address to, uint256 amount) external;\n}\n\ninterface IFrax {\n function exchangeOldForCanonical(\n address bridge_token_address,\n uint256 token_amount\n ) external returns (uint256);\n}\n\ncontract HarmonySynapseBridge is\n Initializable,\n AccessControlUpgradeable,\n ReentrancyGuardUpgradeable,\n PausableUpgradeable\n{\n using SafeERC20 for IERC20;\n using SafeERC20 for IERC20Mintable;\n using SafeMath for uint256;\n\n bytes32 public constant NODEGROUP_ROLE = keccak256(\"NODEGROUP_ROLE\");\n bytes32 public constant GOVERNANCE_ROLE = keccak256(\"GOVERNANCE_ROLE\");\n\n mapping(address => uint256) private fees;\n\n uint256 public startBlockNumber;\n uint256 public constant bridgeVersion = 6;\n uint256 public chainGasAmount;\n address payable public WETH_ADDRESS;\n\n mapping(bytes32 => bool) private kappaMap;\n\n receive() external payable {}\n\n function initialize() external initializer {\n startBlockNumber = block.number;\n _setupRole(DEFAULT_ADMIN_ROLE, msg.sender);\n __AccessControl_init();\n }\n\n function setChainGasAmount(uint256 amount) external {\n require(hasRole(GOVERNANCE_ROLE, msg.sender), \"Not governance\");\n chainGasAmount = amount;\n }\n\n function setWethAddress(address payable _wethAddress) external {\n require(hasRole(DEFAULT_ADMIN_ROLE, msg.sender), \"Not admin\");\n WETH_ADDRESS = _wethAddress;\n }\n\n function addKappas(bytes32[] calldata kappas) external {\n require(hasRole(GOVERNANCE_ROLE, msg.sender), \"Not governance\");\n for (uint256 i = 0; i < kappas.length; ++i) {\n kappaMap[kappas[i]] = true;\n }\n }\n\n event TokenDeposit(\n address indexed to,\n uint256 chainId,\n IERC20 token,\n uint256 amount\n );\n event TokenRedeem(\n address indexed to,\n uint256 chainId,\n IERC20 token,\n uint256 amount\n );\n event TokenWithdraw(\n address indexed to,\n IERC20 token,\n uint256 amount,\n uint256 fee,\n bytes32 indexed kappa\n );\n event TokenMint(\n address indexed to,\n IERC20Mintable token,\n uint256 amount,\n uint256 fee,\n bytes32 indexed kappa\n );\n event TokenDepositAndSwap(\n address indexed to,\n uint256 chainId,\n IERC20 token,\n uint256 amount,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 minDy,\n uint256 deadline\n );\n event TokenMintAndSwap(\n address indexed to,\n IERC20Mintable token,\n uint256 amount,\n uint256 fee,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 minDy,\n uint256 deadline,\n bool swapSuccess,\n bytes32 indexed kappa\n );\n event TokenRedeemAndSwap(\n address indexed to,\n uint256 chainId,\n IERC20 token,\n uint256 amount,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 minDy,\n uint256 deadline\n );\n event TokenRedeemAndRemove(\n address indexed to,\n uint256 chainId,\n IERC20 token,\n uint256 amount,\n uint8 swapTokenIndex,\n uint256 swapMinAmount,\n uint256 swapDeadline\n );\n event TokenWithdrawAndRemove(\n address indexed to,\n IERC20 token,\n uint256 amount,\n uint256 fee,\n uint8 swapTokenIndex,\n uint256 swapMinAmount,\n uint256 swapDeadline,\n bool swapSuccess,\n bytes32 indexed kappa\n );\n\n // v2 events\n event TokenRedeemV2(\n bytes32 indexed to,\n uint256 chainId,\n IERC20 token,\n uint256 amount\n );\n\n // VIEW FUNCTIONS ***/\n function getFeeBalance(address tokenAddress)\n external\n view\n returns (uint256)\n {\n return fees[tokenAddress];\n }\n\n function kappaExists(bytes32 kappa) external view returns (bool) {\n return kappaMap[kappa];\n }\n\n // FEE FUNCTIONS ***/\n /**\n * * @notice withdraw specified ERC20 token fees to a given address\n * * @param token ERC20 token in which fees acccumulated to transfer\n * * @param to Address to send the fees to\n */\n function withdrawFees(IERC20 token, address to) external whenNotPaused {\n require(hasRole(GOVERNANCE_ROLE, msg.sender), \"Not governance\");\n require(to != address(0), \"Address is 0x000\");\n if (fees[address(token)] != 0) {\n token.safeTransfer(to, fees[address(token)]);\n fees[address(token)] = 0;\n }\n }\n\n // PAUSABLE FUNCTIONS ***/\n function pause() external {\n require(hasRole(GOVERNANCE_ROLE, msg.sender), \"Not governance\");\n _pause();\n }\n\n function unpause() external {\n require(hasRole(GOVERNANCE_ROLE, msg.sender), \"Not governance\");\n _unpause();\n }\n\n /**\n * @notice Relays to nodes to transfers an ERC20 token cross-chain\n * @param to address on other chain to bridge assets to\n * @param chainId which chain to bridge assets onto\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n **/\n function deposit(\n address to,\n uint256 chainId,\n IERC20 token,\n uint256 amount\n ) external nonReentrant whenNotPaused {\n emit TokenDeposit(to, chainId, token, amount);\n token.safeTransferFrom(msg.sender, address(this), amount);\n }\n\n /**\n * @notice Relays to nodes that (typically) a wrapped synAsset ERC20 token has been burned and the underlying needs to be redeeemed on the native chain\n * @param to address on other chain to redeem underlying assets to\n * @param chainId which underlying chain to bridge assets onto\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n **/\n function redeem(\n address to,\n uint256 chainId,\n ERC20Burnable token,\n uint256 amount\n ) external nonReentrant whenNotPaused {\n emit TokenRedeem(to, chainId, token, amount);\n token.burnFrom(msg.sender, amount);\n }\n\n /**\n * @notice Function to be called by the node group to withdraw the underlying assets from the contract\n * @param to address on chain to send underlying assets to\n * @param token ERC20 compatible token to withdraw from the bridge\n * @param amount Amount in native token decimals to withdraw\n * @param fee Amount in native token decimals to save to the contract as fees\n * @param kappa kappa\n **/\n function withdraw(\n address to,\n IERC20 token,\n uint256 amount,\n uint256 fee,\n bytes32 kappa\n ) external nonReentrant whenNotPaused {\n require(\n hasRole(NODEGROUP_ROLE, msg.sender),\n \"Caller is not a node group\"\n );\n require(amount > fee, \"Amount must be greater than fee\");\n require(!kappaMap[kappa], \"Kappa is already present\");\n kappaMap[kappa] = true;\n fees[address(token)] = fees[address(token)].add(fee);\n if (address(token) == WETH_ADDRESS && WETH_ADDRESS != address(0)) {\n IWETH9(WETH_ADDRESS).withdraw(amount.sub(fee));\n (bool success, ) = to.call{value: amount.sub(fee)}(\"\");\n require(success, \"ETH_TRANSFER_FAILED\");\n emit TokenWithdraw(to, token, amount, fee, kappa);\n } else {\n emit TokenWithdraw(to, token, amount, fee, kappa);\n token.safeTransfer(to, amount.sub(fee));\n }\n }\n\n /**\n * @notice Nodes call this function to mint a SynERC20 (or any asset that the bridge is given minter access to). This is called by the nodes after a TokenDeposit event is emitted.\n * @dev This means the SynapseBridge.sol contract must have minter access to the token attempting to be minted\n * @param to address on other chain to redeem underlying assets to\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain post-fees\n * @param fee Amount in native token decimals to save to the contract as fees\n * @param kappa kappa\n **/\n function mint(\n address payable to,\n IERC20Mintable token,\n uint256 amount,\n uint256 fee,\n bytes32 kappa\n ) external nonReentrant whenNotPaused {\n require(\n hasRole(NODEGROUP_ROLE, msg.sender),\n \"Caller is not a node group\"\n );\n require(amount > fee, \"Amount must be greater than fee\");\n require(!kappaMap[kappa], \"Kappa is already present\");\n kappaMap[kappa] = true;\n fees[address(token)] = fees[address(token)].add(fee);\n emit TokenMint(to, token, amount.sub(fee), fee, kappa);\n token.mint(address(this), amount);\n // checks if synFRAX\n if (address(token) == 0x1852F70512298d56e9c8FDd905e02581E04ddb2a) {\n if (\n token.allowance(\n address(this),\n 0xFa7191D292d5633f702B0bd7E3E3BcCC0e633200\n ) < amount.sub(fee)\n ) {\n token.safeApprove(\n address(0xFa7191D292d5633f702B0bd7E3E3BcCC0e633200),\n 0\n );\n token.safeApprove(\n address(0xFa7191D292d5633f702B0bd7E3E3BcCC0e633200),\n type(uint256).max\n );\n }\n try\n IFrax(0xFa7191D292d5633f702B0bd7E3E3BcCC0e633200)\n .exchangeOldForCanonical(address(token), amount.sub(fee))\n returns (uint256 canolical_tokens_out) {\n IERC20(0xFa7191D292d5633f702B0bd7E3E3BcCC0e633200).safeTransfer(\n to,\n canolical_tokens_out\n );\n } catch {\n IERC20(token).safeTransfer(to, amount.sub(fee));\n }\n } else {\n IERC20(token).safeTransfer(to, amount.sub(fee));\n }\n if (chainGasAmount != 0 && address(this).balance > chainGasAmount) {\n to.call.value(chainGasAmount)(\"\");\n }\n }\n\n /**\n * @notice Relays to nodes to both transfer an ERC20 token cross-chain, and then have the nodes execute a swap through a liquidity pool on behalf of the user.\n * @param to address on other chain to bridge assets to\n * @param chainId which chain to bridge assets onto\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n * @param tokenIndexFrom the token the user wants to swap from\n * @param tokenIndexTo the token the user wants to swap to\n * @param minDy the min amount the user would like to receive, or revert to only minting the SynERC20 token crosschain.\n * @param deadline latest timestamp to accept this transaction\n **/\n function depositAndSwap(\n address to,\n uint256 chainId,\n IERC20 token,\n uint256 amount,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 minDy,\n uint256 deadline\n ) external nonReentrant whenNotPaused {\n emit TokenDepositAndSwap(\n to,\n chainId,\n token,\n amount,\n tokenIndexFrom,\n tokenIndexTo,\n minDy,\n deadline\n );\n token.safeTransferFrom(msg.sender, address(this), amount);\n }\n\n /**\n * @notice Relays to nodes that (typically) a wrapped synAsset ERC20 token has been burned and the underlying needs to be redeeemed on the native chain. This function indicates to the nodes that they should attempt to redeem the LP token for the underlying assets (E.g \"swap\" out of the LP token)\n * @param to address on other chain to redeem underlying assets to\n * @param chainId which underlying chain to bridge assets onto\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n * @param tokenIndexFrom the token the user wants to swap from\n * @param tokenIndexTo the token the user wants to swap to\n * @param minDy the min amount the user would like to receive, or revert to only minting the SynERC20 token crosschain.\n * @param deadline latest timestamp to accept this transaction\n **/\n function redeemAndSwap(\n address to,\n uint256 chainId,\n ERC20Burnable token,\n uint256 amount,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 minDy,\n uint256 deadline\n ) external nonReentrant whenNotPaused {\n emit TokenRedeemAndSwap(\n to,\n chainId,\n token,\n amount,\n tokenIndexFrom,\n tokenIndexTo,\n minDy,\n deadline\n );\n token.burnFrom(msg.sender, amount);\n }\n\n /**\n * @notice Relays to nodes that (typically) a wrapped synAsset ERC20 token has been burned and the underlying needs to be redeeemed on the native chain. This function indicates to the nodes that they should attempt to redeem the LP token for the underlying assets (E.g \"swap\" out of the LP token)\n * @param to address on other chain to redeem underlying assets to\n * @param chainId which underlying chain to bridge assets onto\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n * @param swapTokenIndex Specifies which of the underlying LP assets the nodes should attempt to redeem for\n * @param swapMinAmount Specifies the minimum amount of the underlying asset needed for the nodes to execute the redeem/swap\n * @param swapDeadline Specificies the deadline that the nodes are allowed to try to redeem/swap the LP token\n **/\n function redeemAndRemove(\n address to,\n uint256 chainId,\n ERC20Burnable token,\n uint256 amount,\n uint8 swapTokenIndex,\n uint256 swapMinAmount,\n uint256 swapDeadline\n ) external nonReentrant whenNotPaused {\n emit TokenRedeemAndRemove(\n to,\n chainId,\n token,\n amount,\n swapTokenIndex,\n swapMinAmount,\n swapDeadline\n );\n token.burnFrom(msg.sender, amount);\n }\n\n /**\n * @notice Nodes call this function to mint a SynERC20 (or any asset that the bridge is given minter access to), and then attempt to swap the SynERC20 into the desired destination asset. This is called by the nodes after a TokenDepositAndSwap event is emitted.\n * @dev This means the BridgeDeposit.sol contract must have minter access to the token attempting to be minted\n * @param to address on other chain to redeem underlying assets to\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain post-fees\n * @param fee Amount in native token decimals to save to the contract as fees\n * @param pool Destination chain's pool to use to swap SynERC20 -> Asset. The nodes determine this by using PoolConfig.sol.\n * @param tokenIndexFrom Index of the SynERC20 asset in the pool\n * @param tokenIndexTo Index of the desired final asset\n * @param minDy Minumum amount (in final asset decimals) that must be swapped for, otherwise the user will receive the SynERC20.\n * @param deadline Epoch time of the deadline that the swap is allowed to be executed.\n * @param kappa kappa\n **/\n function mintAndSwap(\n address payable to,\n IERC20Mintable token,\n uint256 amount,\n uint256 fee,\n ISwap pool,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 minDy,\n uint256 deadline,\n bytes32 kappa\n ) external nonReentrant whenNotPaused {\n require(\n hasRole(NODEGROUP_ROLE, msg.sender),\n \"Caller is not a node group\"\n );\n require(amount > fee, \"Amount must be greater than fee\");\n require(!kappaMap[kappa], \"Kappa is already present\");\n kappaMap[kappa] = true;\n fees[address(token)] = fees[address(token)].add(fee);\n // Transfer gas airdrop\n if (chainGasAmount != 0 && address(this).balance > chainGasAmount) {\n to.call.value(chainGasAmount)(\"\");\n }\n // first check to make sure more will be given than min amount required\n uint256 expectedOutput = ISwap(pool).calculateSwap(\n tokenIndexFrom,\n tokenIndexTo,\n amount.sub(fee)\n );\n\n if (expectedOutput >= minDy) {\n // proceed with swap\n token.mint(address(this), amount);\n token.safeIncreaseAllowance(address(pool), amount);\n try\n ISwap(pool).swap(\n tokenIndexFrom,\n tokenIndexTo,\n amount.sub(fee),\n minDy,\n deadline\n )\n returns (uint256 finalSwappedAmount) {\n // Swap succeeded, transfer swapped asset\n IERC20 swappedTokenTo = ISwap(pool).getToken(tokenIndexTo);\n if (\n address(swappedTokenTo) == WETH_ADDRESS &&\n WETH_ADDRESS != address(0)\n ) {\n IWETH9(WETH_ADDRESS).withdraw(finalSwappedAmount);\n (bool success, ) = to.call{value: finalSwappedAmount}(\"\");\n require(success, \"ETH_TRANSFER_FAILED\");\n emit TokenMintAndSwap(\n to,\n token,\n finalSwappedAmount,\n fee,\n tokenIndexFrom,\n tokenIndexTo,\n minDy,\n deadline,\n true,\n kappa\n );\n } else {\n swappedTokenTo.safeTransfer(to, finalSwappedAmount);\n emit TokenMintAndSwap(\n to,\n token,\n finalSwappedAmount,\n fee,\n tokenIndexFrom,\n tokenIndexTo,\n minDy,\n deadline,\n true,\n kappa\n );\n }\n } catch {\n IERC20(token).safeTransfer(to, amount.sub(fee));\n emit TokenMintAndSwap(\n to,\n token,\n amount.sub(fee),\n fee,\n tokenIndexFrom,\n tokenIndexTo,\n minDy,\n deadline,\n false,\n kappa\n );\n }\n } else {\n token.mint(address(this), amount);\n IERC20(token).safeTransfer(to, amount.sub(fee));\n emit TokenMintAndSwap(\n to,\n token,\n amount.sub(fee),\n fee,\n tokenIndexFrom,\n tokenIndexTo,\n minDy,\n deadline,\n false,\n kappa\n );\n }\n }\n\n /**\n * @notice Function to be called by the node group to withdraw the underlying assets from the contract\n * @param to address on chain to send underlying assets to\n * @param token ERC20 compatible token to withdraw from the bridge\n * @param amount Amount in native token decimals to withdraw\n * @param fee Amount in native token decimals to save to the contract as fees\n * @param pool Destination chain's pool to use to swap SynERC20 -> Asset. The nodes determine this by using PoolConfig.sol.\n * @param swapTokenIndex Specifies which of the underlying LP assets the nodes should attempt to redeem for\n * @param swapMinAmount Specifies the minimum amount of the underlying asset needed for the nodes to execute the redeem/swap\n * @param swapDeadline Specificies the deadline that the nodes are allowed to try to redeem/swap the LP token\n * @param kappa kappa\n **/\n function withdrawAndRemove(\n address to,\n IERC20 token,\n uint256 amount,\n uint256 fee,\n ISwap pool,\n uint8 swapTokenIndex,\n uint256 swapMinAmount,\n uint256 swapDeadline,\n bytes32 kappa\n ) external nonReentrant whenNotPaused {\n require(\n hasRole(NODEGROUP_ROLE, msg.sender),\n \"Caller is not a node group\"\n );\n require(amount > fee, \"Amount must be greater than fee\");\n require(!kappaMap[kappa], \"Kappa is already present\");\n kappaMap[kappa] = true;\n fees[address(token)] = fees[address(token)].add(fee);\n // first check to make sure more will be given than min amount required\n uint256 expectedOutput = ISwap(pool).calculateRemoveLiquidityOneToken(\n amount.sub(fee),\n swapTokenIndex\n );\n\n if (expectedOutput >= swapMinAmount) {\n token.safeIncreaseAllowance(address(pool), amount.sub(fee));\n try\n ISwap(pool).removeLiquidityOneToken(\n amount.sub(fee),\n swapTokenIndex,\n swapMinAmount,\n swapDeadline\n )\n returns (uint256 finalSwappedAmount) {\n // Swap succeeded, transfer swapped asset\n IERC20 swappedTokenTo = ISwap(pool).getToken(swapTokenIndex);\n swappedTokenTo.safeTransfer(to, finalSwappedAmount);\n emit TokenWithdrawAndRemove(\n to,\n token,\n finalSwappedAmount,\n fee,\n swapTokenIndex,\n swapMinAmount,\n swapDeadline,\n true,\n kappa\n );\n } catch {\n IERC20(token).safeTransfer(to, amount.sub(fee));\n emit TokenWithdrawAndRemove(\n to,\n token,\n amount.sub(fee),\n fee,\n swapTokenIndex,\n swapMinAmount,\n swapDeadline,\n false,\n kappa\n );\n }\n } else {\n token.safeTransfer(to, amount.sub(fee));\n emit TokenWithdrawAndRemove(\n to,\n token,\n amount.sub(fee),\n fee,\n swapTokenIndex,\n swapMinAmount,\n swapDeadline,\n false,\n kappa\n );\n }\n }\n\n // BRIDGE FUNCTIONS TO HANDLE DIFF ADDRESSES\n /**\n * @notice Relays to nodes that (typically) a wrapped synAsset ERC20 token has been burned and the underlying needs to be redeeemed on the native chain\n * @param to address on other chain to redeem underlying assets to\n * @param chainId which underlying chain to bridge assets onto\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n **/\n function redeemV2(\n bytes32 to,\n uint256 chainId,\n ERC20Burnable token,\n uint256 amount\n ) external nonReentrant whenNotPaused {\n emit TokenRedeemV2(to, chainId, token, amount);\n token.burnFrom(msg.sender, amount);\n }\n}\n" + }, + "@openzeppelin/contracts-upgradeable/drafts/EIP712Upgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <0.8.0;\nimport \"../proxy/Initializable.sol\";\n\n/**\n * @dev https://eips.ethereum.org/EIPS/eip-712[EIP 712] is a standard for hashing and signing of typed structured data.\n *\n * The encoding specified in the EIP is very generic, and such a generic implementation in Solidity is not feasible,\n * thus this contract does not implement the encoding itself. Protocols need to implement the type-specific encoding\n * they need in their contracts using a combination of `abi.encode` and `keccak256`.\n *\n * This contract implements the EIP 712 domain separator ({_domainSeparatorV4}) that is used as part of the encoding\n * scheme, and the final step of the encoding to obtain the message digest that is then signed via ECDSA\n * ({_hashTypedDataV4}).\n *\n * The implementation of the domain separator was designed to be as efficient as possible while still properly updating\n * the chain id to protect against replay attacks on an eventual fork of the chain.\n *\n * NOTE: This contract implements the version of the encoding known as \"v4\", as implemented by the JSON RPC method\n * https://docs.metamask.io/guide/signing-data.html[`eth_signTypedDataV4` in MetaMask].\n *\n * _Available since v3.4._\n */\nabstract contract EIP712Upgradeable is Initializable {\n /* solhint-disable var-name-mixedcase */\n bytes32 private _HASHED_NAME;\n bytes32 private _HASHED_VERSION;\n bytes32 private constant _TYPE_HASH = keccak256(\"EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)\");\n /* solhint-enable var-name-mixedcase */\n\n /**\n * @dev Initializes the domain separator and parameter caches.\n *\n * The meaning of `name` and `version` is specified in\n * https://eips.ethereum.org/EIPS/eip-712#definition-of-domainseparator[EIP 712]:\n *\n * - `name`: the user readable name of the signing domain, i.e. the name of the DApp or the protocol.\n * - `version`: the current major version of the signing domain.\n *\n * NOTE: These parameters cannot be changed except through a xref:learn::upgrading-smart-contracts.adoc[smart\n * contract upgrade].\n */\n function __EIP712_init(string memory name, string memory version) internal initializer {\n __EIP712_init_unchained(name, version);\n }\n\n function __EIP712_init_unchained(string memory name, string memory version) internal initializer {\n bytes32 hashedName = keccak256(bytes(name));\n bytes32 hashedVersion = keccak256(bytes(version));\n _HASHED_NAME = hashedName;\n _HASHED_VERSION = hashedVersion;\n }\n\n /**\n * @dev Returns the domain separator for the current chain.\n */\n function _domainSeparatorV4() internal view returns (bytes32) {\n return _buildDomainSeparator(_TYPE_HASH, _EIP712NameHash(), _EIP712VersionHash());\n }\n\n function _buildDomainSeparator(bytes32 typeHash, bytes32 name, bytes32 version) private view returns (bytes32) {\n return keccak256(\n abi.encode(\n typeHash,\n name,\n version,\n _getChainId(),\n address(this)\n )\n );\n }\n\n /**\n * @dev Given an already https://eips.ethereum.org/EIPS/eip-712#definition-of-hashstruct[hashed struct], this\n * function returns the hash of the fully encoded EIP712 message for this domain.\n *\n * This hash can be used together with {ECDSA-recover} to obtain the signer of a message. For example:\n *\n * ```solidity\n * bytes32 digest = _hashTypedDataV4(keccak256(abi.encode(\n * keccak256(\"Mail(address to,string contents)\"),\n * mailTo,\n * keccak256(bytes(mailContents))\n * )));\n * address signer = ECDSA.recover(digest, signature);\n * ```\n */\n function _hashTypedDataV4(bytes32 structHash) internal view virtual returns (bytes32) {\n return keccak256(abi.encodePacked(\"\\x19\\x01\", _domainSeparatorV4(), structHash));\n }\n\n function _getChainId() private view returns (uint256 chainId) {\n this; // silence state mutability warning without generating bytecode - see https://github.com/ethereum/solidity/issues/2691\n // solhint-disable-next-line no-inline-assembly\n assembly {\n chainId := chainid()\n }\n }\n\n /**\n * @dev The hash of the name parameter for the EIP712 domain.\n *\n * NOTE: This function reads from storage by default, but can be redefined to return a constant value if gas costs\n * are a concern.\n */\n function _EIP712NameHash() internal virtual view returns (bytes32) {\n return _HASHED_NAME;\n }\n\n /**\n * @dev The hash of the version parameter for the EIP712 domain.\n *\n * NOTE: This function reads from storage by default, but can be redefined to return a constant value if gas costs\n * are a concern.\n */\n function _EIP712VersionHash() internal virtual view returns (bytes32) {\n return _HASHED_VERSION;\n }\n uint256[50] private __gap;\n}\n" + }, + "@openzeppelin/contracts-upgradeable/drafts/ERC20PermitUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.5 <0.8.0;\n\nimport \"../token/ERC20/ERC20Upgradeable.sol\";\nimport \"./IERC20PermitUpgradeable.sol\";\nimport \"../cryptography/ECDSAUpgradeable.sol\";\nimport \"../utils/CountersUpgradeable.sol\";\nimport \"./EIP712Upgradeable.sol\";\nimport \"../proxy/Initializable.sol\";\n\n/**\n * @dev Implementation of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in\n * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612].\n *\n * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by\n * presenting a message signed by the account. By not relying on `{IERC20-approve}`, the token holder account doesn't\n * need to send a transaction, and thus is not required to hold Ether at all.\n *\n * _Available since v3.4._\n */\nabstract contract ERC20PermitUpgradeable is Initializable, ERC20Upgradeable, IERC20PermitUpgradeable, EIP712Upgradeable {\n using CountersUpgradeable for CountersUpgradeable.Counter;\n\n mapping (address => CountersUpgradeable.Counter) private _nonces;\n\n // solhint-disable-next-line var-name-mixedcase\n bytes32 private _PERMIT_TYPEHASH;\n\n /**\n * @dev Initializes the {EIP712} domain separator using the `name` parameter, and setting `version` to `\"1\"`.\n *\n * It's a good idea to use the same `name` that is defined as the ERC20 token name.\n */\n function __ERC20Permit_init(string memory name) internal initializer {\n __Context_init_unchained();\n __EIP712_init_unchained(name, \"1\");\n __ERC20Permit_init_unchained(name);\n }\n\n function __ERC20Permit_init_unchained(string memory name) internal initializer {\n _PERMIT_TYPEHASH = keccak256(\"Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)\");\n }\n\n /**\n * @dev See {IERC20Permit-permit}.\n */\n function permit(address owner, address spender, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s) public virtual override {\n // solhint-disable-next-line not-rely-on-time\n require(block.timestamp <= deadline, \"ERC20Permit: expired deadline\");\n\n bytes32 structHash = keccak256(\n abi.encode(\n _PERMIT_TYPEHASH,\n owner,\n spender,\n value,\n _nonces[owner].current(),\n deadline\n )\n );\n\n bytes32 hash = _hashTypedDataV4(structHash);\n\n address signer = ECDSAUpgradeable.recover(hash, v, r, s);\n require(signer == owner, \"ERC20Permit: invalid signature\");\n\n _nonces[owner].increment();\n _approve(owner, spender, value);\n }\n\n /**\n * @dev See {IERC20Permit-nonces}.\n */\n function nonces(address owner) public view override returns (uint256) {\n return _nonces[owner].current();\n }\n\n /**\n * @dev See {IERC20Permit-DOMAIN_SEPARATOR}.\n */\n // solhint-disable-next-line func-name-mixedcase\n function DOMAIN_SEPARATOR() external view override returns (bytes32) {\n return _domainSeparatorV4();\n }\n uint256[49] private __gap;\n}\n" + }, + "@openzeppelin/contracts-upgradeable/drafts/IERC20PermitUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <0.8.0;\n\n/**\n * @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in\n * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612].\n *\n * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by\n * presenting a message signed by the account. By not relying on `{IERC20-approve}`, the token holder account doesn't\n * need to send a transaction, and thus is not required to hold Ether at all.\n */\ninterface IERC20PermitUpgradeable {\n /**\n * @dev Sets `value` as the allowance of `spender` over `owner`'s tokens,\n * given `owner`'s signed approval.\n *\n * IMPORTANT: The same issues {IERC20-approve} has related to transaction\n * ordering also apply here.\n *\n * Emits an {Approval} event.\n *\n * Requirements:\n *\n * - `spender` cannot be the zero address.\n * - `deadline` must be a timestamp in the future.\n * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner`\n * over the EIP712-formatted function arguments.\n * - the signature must use ``owner``'s current nonce (see {nonces}).\n *\n * For more information on the signature format, see the\n * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP\n * section].\n */\n function permit(address owner, address spender, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s) external;\n\n /**\n * @dev Returns the current nonce for `owner`. This value must be\n * included whenever a signature is generated for {permit}.\n *\n * Every successful call to {permit} increases ``owner``'s nonce by one. This\n * prevents a signature from being used multiple times.\n */\n function nonces(address owner) external view returns (uint256);\n\n /**\n * @dev Returns the domain separator used in the encoding of the signature for `permit`, as defined by {EIP712}.\n */\n // solhint-disable-next-line func-name-mixedcase\n function DOMAIN_SEPARATOR() external view returns (bytes32);\n}\n" + }, + "@openzeppelin/contracts-upgradeable/cryptography/ECDSAUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <0.8.0;\n\n/**\n * @dev Elliptic Curve Digital Signature Algorithm (ECDSA) operations.\n *\n * These functions can be used to verify that a message was signed by the holder\n * of the private keys of a given address.\n */\nlibrary ECDSAUpgradeable {\n /**\n * @dev Returns the address that signed a hashed message (`hash`) with\n * `signature`. This address can then be used for verification purposes.\n *\n * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:\n * this function rejects them by requiring the `s` value to be in the lower\n * half order, and the `v` value to be either 27 or 28.\n *\n * IMPORTANT: `hash` _must_ be the result of a hash operation for the\n * verification to be secure: it is possible to craft signatures that\n * recover to arbitrary addresses for non-hashed data. A safe way to ensure\n * this is by receiving a hash of the original message (which may otherwise\n * be too long), and then calling {toEthSignedMessageHash} on it.\n */\n function recover(bytes32 hash, bytes memory signature) internal pure returns (address) {\n // Check the signature length\n if (signature.length != 65) {\n revert(\"ECDSA: invalid signature length\");\n }\n\n // Divide the signature in r, s and v variables\n bytes32 r;\n bytes32 s;\n uint8 v;\n\n // ecrecover takes the signature parameters, and the only way to get them\n // currently is to use assembly.\n // solhint-disable-next-line no-inline-assembly\n assembly {\n r := mload(add(signature, 0x20))\n s := mload(add(signature, 0x40))\n v := byte(0, mload(add(signature, 0x60)))\n }\n\n return recover(hash, v, r, s);\n }\n\n /**\n * @dev Overload of {ECDSA-recover-bytes32-bytes-} that receives the `v`,\n * `r` and `s` signature fields separately.\n */\n function recover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) internal pure returns (address) {\n // EIP-2 still allows signature malleability for ecrecover(). Remove this possibility and make the signature\n // unique. Appendix F in the Ethereum Yellow paper (https://ethereum.github.io/yellowpaper/paper.pdf), defines\n // the valid range for s in (281): 0 < s < secp256k1n ÷ 2 + 1, and for v in (282): v ∈ {27, 28}. Most\n // signatures from current libraries generate a unique signature with an s-value in the lower half order.\n //\n // If your library generates malleable signatures, such as s-values in the upper range, calculate a new s-value\n // with 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 - s1 and flip v from 27 to 28 or\n // vice versa. If your library also generates signatures with 0/1 for v instead 27/28, add 27 to v to accept\n // these malleable signatures as well.\n require(uint256(s) <= 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0, \"ECDSA: invalid signature 's' value\");\n require(v == 27 || v == 28, \"ECDSA: invalid signature 'v' value\");\n\n // If the signature is valid (and not malleable), return the signer address\n address signer = ecrecover(hash, v, r, s);\n require(signer != address(0), \"ECDSA: invalid signature\");\n\n return signer;\n }\n\n /**\n * @dev Returns an Ethereum Signed Message, created from a `hash`. This\n * replicates the behavior of the\n * https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_sign[`eth_sign`]\n * JSON-RPC method.\n *\n * See {recover}.\n */\n function toEthSignedMessageHash(bytes32 hash) internal pure returns (bytes32) {\n // 32 is the length in bytes of hash,\n // enforced by the type signature above\n return keccak256(abi.encodePacked(\"\\x19Ethereum Signed Message:\\n32\", hash));\n }\n}\n" + }, + "@openzeppelin/contracts-upgradeable/utils/CountersUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <0.8.0;\n\nimport \"../math/SafeMathUpgradeable.sol\";\n\n/**\n * @title Counters\n * @author Matt Condon (@shrugs)\n * @dev Provides counters that can only be incremented or decremented by one. This can be used e.g. to track the number\n * of elements in a mapping, issuing ERC721 ids, or counting request ids.\n *\n * Include with `using Counters for Counters.Counter;`\n * Since it is not possible to overflow a 256 bit integer with increments of one, `increment` can skip the {SafeMath}\n * overflow check, thereby saving gas. This does assume however correct usage, in that the underlying `_value` is never\n * directly accessed.\n */\nlibrary CountersUpgradeable {\n using SafeMathUpgradeable for uint256;\n\n struct Counter {\n // This variable should never be directly accessed by users of the library: interactions must be restricted to\n // the library's function. As of Solidity v0.5.2, this cannot be enforced, though there is a proposal to add\n // this feature: see https://github.com/ethereum/solidity/issues/4637\n uint256 _value; // default: 0\n }\n\n function current(Counter storage counter) internal view returns (uint256) {\n return counter._value;\n }\n\n function increment(Counter storage counter) internal {\n // The {SafeMath} overflow check can be skipped here, see the comment at the top\n counter._value += 1;\n }\n\n function decrement(Counter storage counter) internal {\n counter._value = counter._value.sub(1);\n }\n}\n" + }, + "contracts/bridge/SynapseERC20.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.6.12;\n\nimport \"@openzeppelin/contracts-upgradeable/token/ERC20/ERC20Upgradeable.sol\";\nimport \"@openzeppelin/contracts-upgradeable/token/ERC20/ERC20BurnableUpgradeable.sol\";\nimport \"@openzeppelin/contracts-upgradeable/drafts/ERC20PermitUpgradeable.sol\";\nimport \"@openzeppelin/contracts-upgradeable/access/AccessControlUpgradeable.sol\";\nimport \"@openzeppelin/contracts-upgradeable/proxy/Initializable.sol\";\n\ncontract SynapseERC20 is\n Initializable,\n ContextUpgradeable,\n AccessControlUpgradeable,\n ERC20BurnableUpgradeable,\n ERC20PermitUpgradeable\n{\n bytes32 public constant MINTER_ROLE = keccak256(\"MINTER_ROLE\");\n\n /**\n * @notice Initializes this ERC20 contract with the given parameters.\n * @param name Token name\n * @param symbol Token symbol\n * @param decimals Token name\n * @param owner admin address to be initialized with\n */\n function initialize(\n string memory name,\n string memory symbol,\n uint8 decimals,\n address owner\n ) external initializer {\n __Context_init_unchained();\n __AccessControl_init_unchained();\n __ERC20_init_unchained(name, symbol);\n __ERC20Burnable_init_unchained();\n _setupDecimals(decimals);\n __ERC20Permit_init(name);\n _setupRole(DEFAULT_ADMIN_ROLE, owner);\n }\n\n function mint(address to, uint256 amount) external {\n require(hasRole(MINTER_ROLE, msg.sender), \"Not a minter\");\n _mint(to, amount);\n }\n}\n" + }, + "contracts/auxiliary/DummyWethProxy.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.6.12;\nimport \"@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol\";\nimport \"@openzeppelin/contracts-upgradeable/proxy/Initializable.sol\";\n\ninterface IWETH9 {\n function name() external view returns (string memory);\n\n function symbol() external view returns (string memory);\n\n function decimals() external view returns (uint8);\n\n function balanceOf(address) external view returns (uint256);\n\n function allowance(address, address) external view returns (uint256);\n\n receive() external payable;\n\n function deposit() external payable;\n\n function withdraw(uint256 wad) external;\n\n function totalSupply() external view returns (uint256);\n\n function approve(address guy, uint256 wad) external returns (bool);\n\n function transfer(address dst, uint256 wad) external returns (bool);\n\n function transferFrom(\n address src,\n address dst,\n uint256 wad\n ) external returns (bool);\n}\n\ncontract DummyWethProxy is Initializable, OwnableUpgradeable {\n function initialize() external initializer {\n __Ownable_init();\n }\n\n IWETH9 public WETH;\n\n function setWETHAddress(address payable _weth) external onlyOwner {\n WETH = IWETH9(_weth);\n }\n\n function withdrawToSelf(uint256 amount) external {\n WETH.withdraw(amount);\n }\n\n function rescue(uint256 amount) external onlyOwner {\n WETH.transfer(owner(), amount);\n }\n\n receive() external payable {}\n\n fallback() external payable {}\n}\n" + }, + "contracts/amm/helper/test/TestMathUtils.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.6.12;\n\nimport \"../../MathUtils.sol\";\n\ncontract TestMathUtils {\n using MathUtils for uint256;\n\n function difference(uint256 a, uint256 b) public pure returns (uint256) {\n return a.difference(b);\n }\n\n function within1(uint256 a, uint256 b) public pure returns (bool) {\n return a.within1(b);\n }\n}\n" + }, + "contracts/bridge/ERC20Migrator.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.6.12;\n\nimport \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/SafeERC20.sol\";\nimport \"@openzeppelin/contracts/math/SafeMath.sol\";\n\n/**\n * @title ERC20Migrator\n * @dev This contract can be used to migrate an ERC20 token from one\n * contract to another, where each token holder has to opt-in to the migration.\n * To opt-in, users must approve for this contract the number of tokens they\n * want to migrate. Once the allowance is set up, anyone can trigger the\n * migration to the new token contract. In this way, token holders \"turn in\"\n * their old balance and will be minted an equal amount in the new token.\n * The new token contract must be mintable.\n * ```\n */\n\ninterface IERC20Mintable is IERC20 {\n function mint(address to, uint256 amount) external;\n}\n\ncontract ERC20Migrator {\n using SafeERC20 for IERC20;\n using SafeMath for uint256;\n\n // Address of the old token contract\n IERC20 private _legacyToken;\n\n // Address of the new token contract\n IERC20Mintable private _newToken;\n\n /**\n * @param legacyToken address of the old token contract\n */\n constructor(IERC20 legacyToken, IERC20Mintable newToken) public {\n _legacyToken = legacyToken;\n _newToken = newToken;\n }\n\n /**\n * @dev Returns the legacy token that is being migrated.\n */\n function legacyToken() external view returns (IERC20) {\n return _legacyToken;\n }\n\n /**\n * @dev Returns the new token to which we are migrating.\n */\n function newToken() external view returns (IERC20) {\n return _newToken;\n }\n\n /**\n * @dev Transfers part of an account's balance in the old token to this\n * contract, and mints the same amount of new tokens for that account.\n * @param amount amount of tokens to be migrated\n */\n function migrate(uint256 amount) external {\n _legacyToken.safeTransferFrom(msg.sender, address(this), amount);\n uint256 amountToMint = amount.mul(5).div(2);\n _newToken.mint(msg.sender, amountToMint);\n }\n}\n" + }, + "contracts/bridge/ECDSANodeManagement.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.6.12;\n\nimport \"./utils/AddressArrayUtils.sol\";\nimport \"@openzeppelin/contracts/math/SafeMath.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/SafeERC20.sol\";\n\ncontract ECDSANodeManagement {\n using AddressArrayUtils for address[];\n using SafeMath for uint256;\n using SafeERC20 for IERC20;\n\n // Status of the keep.\n // Active means the keep is active.\n // Closed means the keep was closed happily.\n // Terminated means the keep was closed due to misbehavior.\n enum Status {\n Active,\n Closed,\n Terminated\n }\n\n // Address of the keep's owner.\n address public owner;\n\n // List of keep members' addresses.\n address[] public members;\n\n // Minimum number of honest keep members required to produce a signature.\n uint256 public honestThreshold;\n\n // Keep's ECDSA public key serialized to 64-bytes, where X and Y coordinates\n // are padded with zeros to 32-byte each.\n bytes public publicKey;\n\n // The timestamp at which keep has been created and key generation process\n // started.\n uint256 internal keyGenerationStartTimestamp;\n\n // Map stores public key by member addresses. All members should submit the\n // same public key.\n mapping(address => bytes) internal submittedPublicKeys;\n\n // The current status of the keep.\n // If the keep is Active members monitor it and support requests from the\n // keep owner.\n // If the owner decides to close the keep the flag is set to Closed.\n // If the owner seizes member bonds the flag is set to Terminated.\n Status internal status;\n\n // Flags execution of contract initialization.\n bool internal isInitialized;\n\n // Notification that the submitted public key does not match a key submitted\n // by other member. The event contains address of the member who tried to\n // submit a public key and a conflicting public key submitted already by other\n // member.\n event ConflictingPublicKeySubmitted(\n address indexed submittingMember,\n bytes conflictingPublicKey\n );\n\n // Notification that keep's ECDSA public key has been successfully established.\n event PublicKeyPublished(bytes publicKey);\n\n // Notification that the keep was closed by the owner.\n // Members no longer need to support this keep.\n event KeepClosed();\n\n // Notification that the keep has been terminated by the owner.\n // Members no longer need to support this keep.\n event KeepTerminated();\n\n /// @notice Returns keep's ECDSA public key.\n /// @return Keep's ECDSA public key.\n function getPublicKey() external view returns (bytes memory) {\n return publicKey;\n }\n\n /// @notice Submits a public key to the keep.\n /// @dev Public key is published successfully if all members submit the same\n /// value. In case of conflicts with others members submissions it will emit\n /// `ConflictingPublicKeySubmitted` event. When all submitted keys match\n /// it will store the key as keep's public key and emit a `PublicKeyPublished`\n /// event.\n /// @param _publicKey Signer's public key.\n function submitPublicKey(bytes calldata _publicKey) external onlyMember {\n require(\n !hasMemberSubmittedPublicKey(msg.sender),\n \"Member already submitted a public key\"\n );\n\n require(_publicKey.length == 64, \"Public key must be 64 bytes long\");\n\n submittedPublicKeys[msg.sender] = _publicKey;\n\n // Check if public keys submitted by all keep members are the same as\n // the currently submitted one.\n uint256 matchingPublicKeysCount = 0;\n for (uint256 i = 0; i < members.length; i++) {\n if (\n keccak256(submittedPublicKeys[members[i]]) !=\n keccak256(_publicKey)\n ) {\n // Emit an event only if compared member already submitted a value.\n if (hasMemberSubmittedPublicKey(members[i])) {\n emit ConflictingPublicKeySubmitted(\n msg.sender,\n submittedPublicKeys[members[i]]\n );\n }\n } else {\n matchingPublicKeysCount++;\n }\n }\n\n if (matchingPublicKeysCount != members.length) {\n return;\n }\n\n // All submitted signatures match.\n publicKey = _publicKey;\n emit PublicKeyPublished(_publicKey);\n }\n\n /// @notice Gets the owner of the keep.\n /// @return Address of the keep owner.\n function getOwner() external view returns (address) {\n return owner;\n }\n\n /// @notice Gets the timestamp the keep was opened at.\n /// @return Timestamp the keep was opened at.\n function getOpenedTimestamp() external view returns (uint256) {\n return keyGenerationStartTimestamp;\n }\n\n /// @notice Closes keep when owner decides that they no longer need it.\n /// Releases bonds to the keep members.\n /// @dev The function can be called only by the owner of the keep and only\n /// if the keep has not been already closed.\n function closeKeep() public onlyOwner onlyWhenActive {\n markAsClosed();\n }\n\n /// @notice Returns true if the keep is active.\n /// @return true if the keep is active, false otherwise.\n function isActive() public view returns (bool) {\n return status == Status.Active;\n }\n\n /// @notice Returns true if the keep is closed and members no longer support\n /// this keep.\n /// @return true if the keep is closed, false otherwise.\n function isClosed() public view returns (bool) {\n return status == Status.Closed;\n }\n\n /// @notice Returns true if the keep has been terminated.\n /// Keep is terminated when bonds are seized and members no longer support\n /// this keep.\n /// @return true if the keep has been terminated, false otherwise.\n function isTerminated() public view returns (bool) {\n return status == Status.Terminated;\n }\n\n /// @notice Returns members of the keep.\n /// @return List of the keep members' addresses.\n function getMembers() public view returns (address[] memory) {\n return members;\n }\n\n /// @notice Initialization function.\n /// @dev We use clone factory to create new keep. That is why this contract\n /// doesn't have a constructor. We provide keep parameters for each instance\n /// function after cloning instances from the master contract.\n /// Initialization must happen in the same transaction in which the clone is\n /// created.\n /// @param _owner Address of the keep owner.\n /// @param _members Addresses of the keep members.\n /// @param _honestThreshold Minimum number of honest keep members.\n function initialize(\n address _owner,\n address[] memory _members,\n uint256 _honestThreshold\n ) public {\n require(!isInitialized, \"Contract already initialized\");\n require(_owner != address(0));\n owner = _owner;\n members = _members;\n honestThreshold = _honestThreshold;\n\n status = Status.Active;\n isInitialized = true;\n\n /* solium-disable-next-line security/no-block-members*/\n keyGenerationStartTimestamp = block.timestamp;\n }\n\n /// @notice Checks if the member already submitted a public key.\n /// @param _member Address of the member.\n /// @return True if member already submitted a public key, else false.\n function hasMemberSubmittedPublicKey(address _member)\n internal\n view\n returns (bool)\n {\n return submittedPublicKeys[_member].length != 0;\n }\n\n /// @notice Marks the keep as closed.\n /// Keep can be marked as closed only when there is no signing in progress\n /// or the requested signing process has timed out.\n function markAsClosed() internal {\n status = Status.Closed;\n emit KeepClosed();\n }\n\n /// @notice Marks the keep as terminated.\n /// Keep can be marked as terminated only when there is no signing in progress\n /// or the requested signing process has timed out.\n function markAsTerminated() internal {\n status = Status.Terminated;\n emit KeepTerminated();\n }\n\n /// @notice Coverts a public key to an ethereum address.\n /// @param _publicKey Public key provided as 64-bytes concatenation of\n /// X and Y coordinates (32-bytes each).\n /// @return Ethereum address.\n function publicKeyToAddress(bytes memory _publicKey)\n internal\n pure\n returns (address)\n {\n // We hash the public key and then truncate last 20 bytes of the digest\n // which is the ethereum address.\n return address(uint160(uint256(keccak256(_publicKey))));\n }\n\n /// @notice Terminates the keep.\n function terminateKeep() internal {\n markAsTerminated();\n }\n\n /// @notice Checks if the caller is the keep's owner.\n /// @dev Throws an error if called by any account other than owner.\n modifier onlyOwner() {\n require(owner == msg.sender, \"Caller is not the keep owner\");\n _;\n }\n\n /// @notice Checks if the caller is a keep member.\n /// @dev Throws an error if called by any account other than one of the members.\n modifier onlyMember() {\n require(members.contains(msg.sender), \"Caller is not the keep member\");\n _;\n }\n\n /// @notice Checks if the keep is currently active.\n /// @dev Throws an error if called when the keep has been already closed.\n modifier onlyWhenActive() {\n require(isActive(), \"Keep is not active\");\n _;\n }\n}\n" + }, + "contracts/bridge/utils/AddressArrayUtils.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.6.12;\n\nlibrary AddressArrayUtils {\n function contains(address[] memory self, address _address)\n internal\n pure\n returns (bool)\n {\n for (uint256 i = 0; i < self.length; i++) {\n if (_address == self[i]) {\n return true;\n }\n }\n return false;\n }\n}" + }, + "contracts/amm/SwapEthWrapper.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.6.12;\n\nimport \"@openzeppelin/contracts/math/SafeMath.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/SafeERC20.sol\";\nimport \"./Swap.sol\";\nimport \"./interfaces/IWETH9.sol\";\n\n/**\n * @title SwapEthWrapper\n * @notice A wrapper contract for Swap contracts that have WETH as one of the pooled tokens.\n * @author Jongseung Lim (@weeb_mcgee)\n */\ncontract SwapEthWrapper {\n using SafeERC20 for IERC20;\n using SafeMath for uint256;\n\n // constants\n uint8 private constant MAX_UINT8 = 2**8 - 1;\n uint256 private constant MAX_UINT256 = 2**256 - 1;\n\n // immutables\n Swap public immutable SWAP;\n LPToken public immutable LP_TOKEN;\n address payable public immutable WETH_ADDRESS;\n address public immutable OWNER;\n uint8 public immutable WETH_INDEX;\n\n IERC20[] public pooledTokens;\n\n /**\n * @notice Deploys this contract with given WETH9 address and Swap address. It will attempt to\n * fetch information about the given Swap pool. If the Swap pool does not contain WETH9,\n * this call will be reverted. Owner address must be given so that `rescue()` function\n * can be limited.\n * @param wethAddress address to the WETH9 contract\n * @param swap address to the Swap contract that has WETH9 as one of the tokens\n * @param owner address that will be allowed to call `rescue()`\n */\n constructor(\n address payable wethAddress,\n Swap swap,\n address owner\n ) public {\n (, , , , , , LPToken lpToken) = swap.swapStorage();\n uint8 wethIndex = MAX_UINT8;\n\n for (uint8 i = 0; i < MAX_UINT8; i++) {\n try swap.getToken(i) returns (IERC20 token) {\n pooledTokens.push(token);\n if (address(token) == wethAddress) {\n wethIndex = i;\n }\n // Approve pooled tokens to be used by Swap\n token.approve(address(swap), MAX_UINT256);\n } catch {\n break;\n }\n }\n require(wethIndex != MAX_UINT8, \"WETH was not found in the swap pool\");\n\n // Set immutable variables\n WETH_INDEX = wethIndex;\n WETH_ADDRESS = wethAddress;\n SWAP = swap;\n LP_TOKEN = lpToken;\n OWNER = owner;\n\n // Approve LPToken to be used by Swap\n lpToken.approve(address(swap), MAX_UINT256);\n }\n\n /**\n * @notice Add liquidity to the pool with the given amounts of tokens.\n * @dev The msg.value of this call should match the value in amounts array\n * in position of WETH9.\n * @param amounts the amounts of each token to add, in their native precision\n * @param minToMint the minimum LP tokens adding this amount of liquidity\n * should mint, otherwise revert. Handy for front-running mitigation\n * @param deadline latest timestamp to accept this transaction\n * @return amount of LP token user minted and received\n */\n function addLiquidity(\n uint256[] memory amounts,\n uint256 minToMint,\n uint256 deadline\n ) external payable returns (uint256) {\n // If using ETH, deposit them to WETH.\n require(msg.value == amounts[WETH_INDEX], \"INCORRECT_MSG_VALUE\");\n if (msg.value > 0) {\n IWETH9(WETH_ADDRESS).deposit{value: msg.value}();\n }\n // Go through amounts array and transfer respective tokens to this contract.\n for (uint256 i = 0; i < amounts.length; i++) {\n uint256 amount = amounts[i];\n if (i != WETH_INDEX && amount > 0) {\n pooledTokens[i].safeTransferFrom(\n msg.sender,\n address(this),\n amount\n );\n }\n }\n // Add the assets to the pool\n uint256 lpTokenAmount = SWAP.addLiquidity(amounts, minToMint, deadline);\n // Send the LPToken to msg.sender\n IERC20(address(LP_TOKEN)).safeTransfer(msg.sender, lpTokenAmount);\n return lpTokenAmount;\n }\n\n /**\n * @notice Burn LP tokens to remove liquidity from the pool.\n * @dev Liquidity can always be removed, even when the pool is paused. Caller\n * will receive ETH instead of WETH9.\n * @param amount the amount of LP tokens to burn\n * @param minAmounts the minimum amounts of each token in the pool\n * acceptable for this burn. Useful as a front-running mitigation\n * @param deadline latest timestamp to accept this transaction\n * @return amounts of tokens user received\n */\n function removeLiquidity(\n uint256 amount,\n uint256[] calldata minAmounts,\n uint256 deadline\n ) external returns (uint256[] memory) {\n // Transfer LPToken from msg.sender to this contract.\n IERC20(address(LP_TOKEN)).safeTransferFrom(\n msg.sender,\n address(this),\n amount\n );\n // Remove liquidity\n uint256[] memory amounts = SWAP.removeLiquidity(\n amount,\n minAmounts,\n deadline\n );\n // Send the tokens back to the user\n for (uint256 i = 0; i < amounts.length; i++) {\n if (i != WETH_INDEX) {\n pooledTokens[i].safeTransfer(msg.sender, amounts[i]);\n } else {\n IWETH9(WETH_ADDRESS).withdraw(amounts[i]);\n // slither-disable-next-line arbitrary-send\n (bool success, ) = msg.sender.call{value: amounts[i]}(\"\");\n require(success, \"ETH_TRANSFER_FAILED\");\n }\n }\n return amounts;\n }\n\n /**\n * @notice Remove liquidity from the pool all in one token.\n * @dev Caller will receive ETH instead of WETH9.\n * @param tokenAmount the amount of the token you want to receive\n * @param tokenIndex the index of the token you want to receive\n * @param minAmount the minimum amount to withdraw, otherwise revert\n * @param deadline latest timestamp to accept this transaction\n * @return amount of chosen token user received\n */\n function removeLiquidityOneToken(\n uint256 tokenAmount,\n uint8 tokenIndex,\n uint256 minAmount,\n uint256 deadline\n ) external returns (uint256) {\n // Transfer LPToken from msg.sender to this contract.\n IERC20(address(LP_TOKEN)).safeTransferFrom(\n msg.sender,\n address(this),\n tokenAmount\n );\n // Withdraw via single token\n uint256 amount = SWAP.removeLiquidityOneToken(\n tokenAmount,\n tokenIndex,\n minAmount,\n deadline\n );\n // Transfer the token to msg.sender accordingly\n if (tokenIndex != WETH_INDEX) {\n pooledTokens[tokenIndex].safeTransfer(msg.sender, amount);\n } else {\n IWETH9(WETH_ADDRESS).withdraw(amount);\n // slither-disable-next-line arbitrary-send\n (bool success, ) = msg.sender.call{value: amount}(\"\");\n require(success, \"ETH_TRANSFER_FAILED\");\n }\n return amount;\n }\n\n /**\n * @notice Remove liquidity from the pool, weighted differently than the\n * pool's current balances.\n * @dev Caller will receive ETH instead of WETH9.\n * @param amounts how much of each token to withdraw\n * @param maxBurnAmount the max LP token provider is willing to pay to\n * remove liquidity. Useful as a front-running mitigation.\n * @param deadline latest timestamp to accept this transaction\n * @return amount of LP tokens burned\n */\n function removeLiquidityImbalance(\n uint256[] calldata amounts,\n uint256 maxBurnAmount,\n uint256 deadline\n ) external returns (uint256) {\n // Transfer LPToken from msg.sender to this contract.\n IERC20(address(LP_TOKEN)).safeTransferFrom(\n msg.sender,\n address(this),\n maxBurnAmount\n );\n // Withdraw in imbalanced ratio\n uint256 burnedLpTokenAmount = SWAP.removeLiquidityImbalance(\n amounts,\n maxBurnAmount,\n deadline\n );\n // Send the tokens back to the user\n for (uint256 i = 0; i < amounts.length; i++) {\n if (i != WETH_INDEX) {\n pooledTokens[i].safeTransfer(msg.sender, amounts[i]);\n } else {\n IWETH9(WETH_ADDRESS).withdraw(amounts[i]);\n // slither-disable-next-line arbitrary-send\n (bool success, ) = msg.sender.call{value: amounts[i]}(\"\");\n require(success, \"ETH_TRANSFER_FAILED\");\n }\n }\n // Send any extra LP tokens back as well\n uint256 extraLpTokenAmount = maxBurnAmount.sub(burnedLpTokenAmount);\n if (extraLpTokenAmount > 0) {\n IERC20(address(LP_TOKEN)).safeTransfer(\n msg.sender,\n extraLpTokenAmount\n );\n }\n return burnedLpTokenAmount;\n }\n\n /**\n * @notice Swap two tokens using the underlying pool. If tokenIndexFrom\n * represents WETH9 in the pool, the caller must set msg.value equal to dx.\n * If the user is swapping to WETH9 in the pool, the user will receive ETH instead.\n * @param tokenIndexFrom the token the user wants to swap from\n * @param tokenIndexTo the token the user wants to swap to\n * @param dx the amount of tokens the user wants to swap from\n * @param minDy the min amount the user would like to receive, or revert.\n * @param deadline latest timestamp to accept this transaction\n */\n function swap(\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx,\n uint256 minDy,\n uint256 deadline\n ) external payable returns (uint256) {\n // Transfer tokens from msg.sender to this contract\n if (tokenIndexFrom != WETH_INDEX) {\n IERC20(pooledTokens[tokenIndexFrom]).safeTransferFrom(\n msg.sender,\n address(this),\n dx\n );\n } else {\n require(msg.value == dx, \"INCORRECT_MSG_VALUE\");\n IWETH9(WETH_ADDRESS).deposit{value: msg.value}();\n }\n // Execute swap\n uint256 dy = SWAP.swap(\n tokenIndexFrom,\n tokenIndexTo,\n dx,\n minDy,\n deadline\n );\n // Transfer the swapped tokens to msg.sender\n if (tokenIndexTo != WETH_INDEX) {\n IERC20(pooledTokens[tokenIndexTo]).safeTransfer(msg.sender, dy);\n } else {\n IWETH9(WETH_ADDRESS).withdraw(dy);\n // slither-disable-next-line arbitrary-send\n (bool success, ) = msg.sender.call{value: dy}(\"\");\n require(success, \"ETH_TRANSFER_FAILED\");\n }\n return dy;\n }\n\n /**\n * @notice Rescues any of the ETH, the pooled tokens, or the LPToken that may be stuck\n * in this contract. Only the OWNER can call this function.\n */\n function rescue() external {\n require(msg.sender == OWNER, \"CALLED_BY_NON_OWNER\");\n IERC20[] memory tokens = pooledTokens;\n for (uint256 i = 0; i < tokens.length; i++) {\n tokens[i].safeTransfer(\n msg.sender,\n tokens[i].balanceOf(address(this))\n );\n }\n IERC20 lpToken_ = IERC20(address(LP_TOKEN));\n lpToken_.safeTransfer(msg.sender, lpToken_.balanceOf(address(this)));\n // slither-disable-next-line arbitrary-send\n (bool success, ) = msg.sender.call{value: address(this).balance}(\"\");\n require(success, \"ETH_TRANSFER_FAILED\");\n }\n\n receive() external payable {}\n\n // VIEW FUNCTIONS\n\n /**\n * @notice A simple method to calculate prices from deposits or\n * withdrawals, excluding fees but including slippage. This is\n * helpful as an input into the various \"min\" parameters on calls\n * to fight front-running\n *\n * @dev This shouldn't be used outside frontends for user estimates.\n *\n * @param amounts an array of token amounts to deposit or withdrawal,\n * corresponding to pooledTokens. The amount should be in each\n * pooled token's native precision. If a token charges a fee on transfers,\n * use the amount that gets transferred after the fee.\n * @param deposit whether this is a deposit or a withdrawal\n * @return token amount the user will receive\n */\n function calculateTokenAmount(uint256[] calldata amounts, bool deposit)\n external\n view\n returns (uint256)\n {\n return SWAP.calculateTokenAmount(amounts, deposit);\n }\n\n /**\n * @notice A simple method to calculate amount of each underlying\n * tokens that is returned upon burning given amount of LP tokens\n * @param amount the amount of LP tokens that would be burned on withdrawal\n * @return array of token balances that the user will receive\n */\n function calculateRemoveLiquidity(uint256 amount)\n external\n view\n returns (uint256[] memory)\n {\n return SWAP.calculateRemoveLiquidity(amount);\n }\n\n /**\n * @notice Calculate the amount of underlying token available to withdraw\n * when withdrawing via only single token\n * @param tokenAmount the amount of LP token to burn\n * @param tokenIndex index of which token will be withdrawn\n * @return availableTokenAmount calculated amount of underlying token\n * available to withdraw\n */\n function calculateRemoveLiquidityOneToken(\n uint256 tokenAmount,\n uint8 tokenIndex\n ) external view returns (uint256 availableTokenAmount) {\n return SWAP.calculateRemoveLiquidityOneToken(tokenAmount, tokenIndex);\n }\n}\n" + }, + "contracts/amm/interfaces/IWETH9.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.4.0;\n\ninterface IWETH9 {\n function name() external view returns (string memory);\n\n function symbol() external view returns (string memory);\n\n function decimals() external view returns (uint8);\n\n function balanceOf(address) external view returns (uint256);\n\n function allowance(address, address) external view returns (uint256);\n\n receive() external payable;\n\n function deposit() external payable;\n\n function withdraw(uint256 wad) external;\n\n function totalSupply() external view returns (uint256);\n\n function approve(address guy, uint256 wad) external returns (bool);\n\n function transfer(address dst, uint256 wad) external returns (bool);\n\n function transferFrom(\n address src,\n address dst,\n uint256 wad\n ) external returns (bool);\n}\n" + }, + "contracts/amm/helper/BaseSwapDeposit.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.6.12;\n\nimport \"@openzeppelin/contracts/math/SafeMath.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/SafeERC20.sol\";\nimport \"../interfaces/ISwap.sol\";\nimport \"@openzeppelin/contracts/utils/ReentrancyGuard.sol\";\n\ncontract BaseSwapDeposit is ReentrancyGuard {\n using SafeERC20 for IERC20;\n using SafeMath for uint256;\n\n ISwap public baseSwap;\n IERC20[] public baseTokens;\n\n uint256 constant MAX_UINT256 = 2**256 - 1;\n\n constructor(ISwap _baseSwap) public {\n baseSwap = _baseSwap;\n // Check and approve base level tokens to be deposited to the base Swap contract\n {\n uint8 i;\n for (; i < 32; i++) {\n try _baseSwap.getToken(i) returns (IERC20 token) {\n baseTokens.push(token);\n token.safeApprove(address(_baseSwap), MAX_UINT256);\n } catch {\n break;\n }\n }\n require(i > 1, \"baseSwap must have at least 2 tokens\");\n }\n }\n\n // Mutative functions\n\n /**\n * @notice Swap two underlying tokens using the meta pool and the base pool\n * @param tokenIndexFrom the token the user wants to swap from\n * @param tokenIndexTo the token the user wants to swap to\n * @param dx the amount of tokens the user wants to swap from\n * @param minDy the min amount the user would like to receive, or revert.\n * @param deadline latest timestamp to accept this transaction\n */\n function swap(\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx,\n uint256 minDy,\n uint256 deadline\n ) external nonReentrant returns (uint256) {\n baseTokens[tokenIndexFrom].safeTransferFrom(msg.sender, address(this), dx);\n uint256 tokenToAmount =\n baseSwap.swap(\n tokenIndexFrom,\n tokenIndexTo,\n dx,\n minDy,\n deadline\n );\n baseTokens[tokenIndexTo].safeTransfer(msg.sender, tokenToAmount);\n return tokenToAmount;\n }\n\n /**\n * @notice Calculate amount of tokens you receive on swap\n * @param tokenIndexFrom the token the user wants to sell\n * @param tokenIndexTo the token the user wants to buy\n * @param dx the amount of tokens the user wants to sell. If the token charges\n * a fee on transfers, use the amount that gets transferred after the fee.\n * @return amount of tokens the user will receive\n */\n function calculateSwap(\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx\n ) external view returns (uint256) {\n return\n baseSwap.calculateSwap(tokenIndexFrom, tokenIndexTo, dx);\n }\n\n /**\n * @notice Returns the address of the pooled token at given index. Reverts if tokenIndex is out of range.\n * @param index the index of the token\n * @return address of the token at given index\n */\n function getToken(uint256 index) external view returns (IERC20) {\n require(index < baseTokens.length, \"index out of range\");\n return baseTokens[index];\n }\n\n}" + }, + "@openzeppelin/contracts/utils/ReentrancyGuard.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <0.8.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 () internal {\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" + }, + "contracts/amm/AaveSwapWrapper.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.6.12;\n\nimport \"@openzeppelin/contracts/math/SafeMath.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/SafeERC20.sol\";\nimport \"./Swap.sol\";\n\ninterface ILendingPool {\n /**\n * @dev Deposits an `amount` of underlying asset into the reserve, receiving in return overlying aTokens.\n * - E.g. User deposits 100 USDC and gets in return 100 aUSDC\n * @param asset The address of the underlying asset to deposit\n * @param amount The amount to be deposited\n * @param onBehalfOf The address that will receive the aTokens, same as msg.sender if the user\n * wants to receive them on his own wallet, or a different address if the beneficiary of aTokens\n * is a different wallet\n * @param referralCode Code used to register the integrator originating the operation, for potential rewards.\n * 0 if the action is executed directly by the user, without any middle-man\n **/\n function deposit(\n address asset,\n uint256 amount,\n address onBehalfOf,\n uint16 referralCode\n ) external;\n\n /**\n * @dev Withdraws an `amount` of underlying asset from the reserve, burning the equivalent aTokens owned\n * E.g. User has 100 aUSDC, calls withdraw() and receives 100 USDC, burning the 100 aUSDC\n * @param asset The address of the underlying asset to withdraw\n * @param amount The underlying amount to be withdrawn\n * - Send the value type(uint256).max in order to withdraw the whole aToken balance\n * @param to Address that will receive the underlying, same as msg.sender if the user\n * wants to receive it on his own wallet, or a different address if the beneficiary is a\n * different wallet\n * @return The final amount withdrawn\n **/\n function withdraw(\n address asset,\n uint256 amount,\n address to\n ) external returns (uint256);\n}\n\n/**\n * @title AaveSwapWrapper\n * @notice A wrapper contract for interacting with aTokens\n */\ncontract AaveSwapWrapper {\n using SafeERC20 for IERC20;\n using SafeMath for uint256;\n mapping(uint8 => bool) private isUnderlyingIndex;\n\n // constants\n uint8 private constant MAX_UINT8 = 2**8 - 1;\n uint256 private constant MAX_UINT256 = 2**256 - 1;\n\n // immutables\n Swap public immutable SWAP;\n LPToken public immutable LP_TOKEN;\n address public immutable OWNER;\n IERC20[] public POOLED_TOKENS;\n IERC20[] public UNDERLYING_TOKENS;\n ILendingPool public LENDING_POOL;\n\n constructor(\n Swap swap,\n IERC20[] memory underlyingTokens,\n address lendingPool,\n address owner\n ) public {\n (, , , , , , LPToken lpToken) = swap.swapStorage();\n for (uint8 i = 0; i < MAX_UINT8; i++) {\n try swap.getToken(i) returns (IERC20 token) {\n POOLED_TOKENS.push(token);\n // Approve pooled tokens to be used by Swap\n token.approve(address(swap), MAX_UINT256);\n } catch {\n break;\n }\n }\n\n for (uint8 i = 0; i < POOLED_TOKENS.length; i++) {\n if (POOLED_TOKENS[i] == underlyingTokens[i]) {\n isUnderlyingIndex[i] = true;\n } else {\n isUnderlyingIndex[i] = false;\n underlyingTokens[i].approve(lendingPool, MAX_UINT256);\n }\n }\n\n // Set immutable variables\n SWAP = swap;\n LP_TOKEN = lpToken;\n OWNER = owner;\n UNDERLYING_TOKENS = underlyingTokens;\n LENDING_POOL = ILendingPool(lendingPool);\n\n // Approve LPToken to be used by Swap\n lpToken.approve(address(swap), MAX_UINT256);\n }\n\n /**\n * @notice Add liquidity to the pool with the given amounts of tokens.\n * @param amounts the amounts of each token to add, in their native precision\n * @param minToMint the minimum LP tokens adding this amount of liquidity\n * should mint, otherwise revert. Handy for front-running mitigation\n * @param deadline latest timestamp to accept this transaction\n * @return amount of LP token user minted and received\n */\n function addLiquidity(\n uint256[] memory amounts,\n uint256 minToMint,\n uint256 deadline\n ) external returns (uint256) {\n // Go through amounts array and transfer respective tokens to this contract.\n for (uint8 i = 0; i < amounts.length; i++) {\n uint256 amount = amounts[i];\n if (amount > 0) {\n UNDERLYING_TOKENS[i].safeTransferFrom(\n msg.sender,\n address(this),\n amount\n );\n if (isUnderlyingIndex[i] == false) {\n LENDING_POOL.deposit(\n address(UNDERLYING_TOKENS[i]),\n amount,\n address(this),\n 0\n );\n }\n }\n }\n\n // Add the assets to the pool\n uint256 lpTokenAmount = SWAP.addLiquidity(amounts, minToMint, deadline);\n // Send the LPToken to msg.sender\n IERC20(address(LP_TOKEN)).safeTransfer(msg.sender, lpTokenAmount);\n return lpTokenAmount;\n }\n\n /**\n * @notice Burn LP tokens to remove liquidity from the pool.\n * @dev Liquidity can always be removed, even when the pool is paused. Caller\n * will receive ETH instead of WETH9.\n * @param amount the amount of LP tokens to burn\n * @param minAmounts the minimum amounts of each token in the pool\n * acceptable for this burn. Useful as a front-running mitigation\n * @param deadline latest timestamp to accept this transaction\n * @return amounts of tokens user received\n */\n function removeLiquidity(\n uint256 amount,\n uint256[] calldata minAmounts,\n uint256 deadline\n ) external returns (uint256[] memory) {\n // Transfer LPToken from msg.sender to this contract.\n IERC20(address(LP_TOKEN)).safeTransferFrom(\n msg.sender,\n address(this),\n amount\n );\n // Remove liquidity\n uint256[] memory amounts = SWAP.removeLiquidity(\n amount,\n minAmounts,\n deadline\n );\n // Send the tokens back to the user\n for (uint8 i = 0; i < amounts.length; i++) {\n if (isUnderlyingIndex[i] == true) {\n UNDERLYING_TOKENS[i].safeTransfer(msg.sender, amounts[i]);\n } else {\n LENDING_POOL.withdraw(\n address(UNDERLYING_TOKENS[i]),\n amounts[i],\n msg.sender\n );\n // underlyingTokens[i].safeTransfer(msg.sender, amounts[i]);\n }\n }\n return amounts;\n }\n\n /**\n * @notice Remove liquidity from the pool all in one token.\n * @dev Caller will receive ETH instead of WETH9.\n * @param tokenAmount the amount of the token you want to receive\n * @param tokenIndex the index of the token you want to receive\n * @param minAmount the minimum amount to withdraw, otherwise revert\n * @param deadline latest timestamp to accept this transaction\n * @return amount of chosen token user received\n */\n function removeLiquidityOneToken(\n uint256 tokenAmount,\n uint8 tokenIndex,\n uint256 minAmount,\n uint256 deadline\n ) external returns (uint256) {\n // Transfer LPToken from msg.sender to this contract.\n IERC20(address(LP_TOKEN)).safeTransferFrom(\n msg.sender,\n address(this),\n tokenAmount\n );\n // Withdraw via single token\n uint256 amount = SWAP.removeLiquidityOneToken(\n tokenAmount,\n tokenIndex,\n minAmount,\n deadline\n );\n // Transfer the token to msg.sender accordingly\n if (isUnderlyingIndex[tokenIndex] == true) {\n UNDERLYING_TOKENS[tokenIndex].safeTransfer(msg.sender, amount);\n } else {\n LENDING_POOL.withdraw(\n address(UNDERLYING_TOKENS[tokenIndex]),\n amount,\n msg.sender\n );\n }\n return amount;\n }\n\n /**\n * @notice Swap two tokens using the underlying pool. If tokenIndexFrom\n * represents WETH9 in the pool, the caller must set msg.value equal to dx.\n * If the user is swapping to WETH9 in the pool, the user will receive ETH instead.\n * @param tokenIndexFrom the token the user wants to swap from\n * @param tokenIndexTo the token the user wants to swap to\n * @param dx the amount of tokens the user wants to swap from\n * @param minDy the min amount the user would like to receive, or revert.\n * @param deadline latest timestamp to accept this transaction\n */\n function swap(\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx,\n uint256 minDy,\n uint256 deadline\n ) external returns (uint256) {\n // Transfer tokens from msg.sender to this contract\n UNDERLYING_TOKENS[tokenIndexFrom].safeTransferFrom(\n msg.sender,\n address(this),\n dx\n );\n if (isUnderlyingIndex[tokenIndexFrom] == false) {\n LENDING_POOL.deposit(\n address(UNDERLYING_TOKENS[tokenIndexFrom]),\n dx,\n address(this),\n 0\n );\n }\n // Execute swap\n uint256 dy = SWAP.swap(\n tokenIndexFrom,\n tokenIndexTo,\n dx,\n minDy,\n deadline\n );\n // Transfer the swapped tokens to msg.sender\n if (isUnderlyingIndex[tokenIndexTo] == false) {\n LENDING_POOL.withdraw(\n address(UNDERLYING_TOKENS[tokenIndexTo]),\n dy,\n msg.sender\n );\n } else {\n UNDERLYING_TOKENS[tokenIndexTo].safeTransfer(msg.sender, dy);\n }\n return dy;\n }\n\n /**\n * @notice Rescues any of the ETH, the pooled tokens, or the LPToken that may be stuck\n * in this contract. Only the OWNER can call this function.\n */\n function rescue() external {\n require(msg.sender == OWNER, \"CALLED_BY_NON_OWNER\");\n IERC20[] memory tokens = POOLED_TOKENS;\n for (uint256 i = 0; i < tokens.length; i++) {\n tokens[i].safeTransfer(\n msg.sender,\n tokens[i].balanceOf(address(this))\n );\n }\n\n for (uint256 i = 0; i < UNDERLYING_TOKENS.length; i++) {\n UNDERLYING_TOKENS[i].safeTransfer(\n msg.sender,\n UNDERLYING_TOKENS[i].balanceOf(address(this))\n );\n }\n\n IERC20 lpToken_ = IERC20(address(LP_TOKEN));\n lpToken_.safeTransfer(msg.sender, lpToken_.balanceOf(address(this)));\n }\n\n // VIEW FUNCTIONS\n\n /**\n * @notice Calculate amount of tokens you receive on swap\n * @param tokenIndexFrom the token the user wants to sell\n * @param tokenIndexTo the token the user wants to buy\n * @param dx the amount of tokens the user wants to sell. If the token charges\n * a fee on transfers, use the amount that gets transferred after the fee.\n * @return amount of tokens the user will receive\n */\n function calculateSwap(\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx\n ) external view virtual returns (uint256) {\n return SWAP.calculateSwap(tokenIndexFrom, tokenIndexTo, dx);\n }\n\n /**\n * @notice A simple method to calculate prices from deposits or\n * withdrawals, excluding fees but including slippage. This is\n * helpful as an input into the various \"min\" parameters on calls\n * to fight front-running\n *\n * @dev This shouldn't be used outside frontends for user estimates.\n *\n * @param amounts an array of token amounts to deposit or withdrawal,\n * corresponding to pooledTokens. The amount should be in each\n * pooled token's native precision. If a token charges a fee on transfers,\n * use the amount that gets transferred after the fee.\n * @param deposit whether this is a deposit or a withdrawal\n * @return token amount the user will receive\n */\n function calculateTokenAmount(uint256[] calldata amounts, bool deposit)\n external\n view\n returns (uint256)\n {\n return SWAP.calculateTokenAmount(amounts, deposit);\n }\n\n /**\n * @notice A simple method to calculate amount of each underlying\n * tokens that is returned upon burning given amount of LP tokens\n * @param amount the amount of LP tokens that would be burned on withdrawal\n * @return array of token balances that the user will receive\n */\n function calculateRemoveLiquidity(uint256 amount)\n external\n view\n returns (uint256[] memory)\n {\n return SWAP.calculateRemoveLiquidity(amount);\n }\n\n /**\n * @notice Calculate the amount of underlying token available to withdraw\n * when withdrawing via only single token\n * @param tokenAmount the amount of LP token to burn\n * @param tokenIndex index of which token will be withdrawn\n * @return availableTokenAmount calculated amount of underlying token\n * available to withdraw\n */\n function calculateRemoveLiquidityOneToken(\n uint256 tokenAmount,\n uint8 tokenIndex\n ) external view returns (uint256 availableTokenAmount) {\n return SWAP.calculateRemoveLiquidityOneToken(tokenAmount, tokenIndex);\n }\n\n /**\n * @notice Return address of the pooled token at given index. Reverts if tokenIndex is out of range.\n * @param index the index of the token\n * @return address of the token at given index\n */\n function getToken(uint8 index) public view virtual returns (IERC20) {\n if (index < UNDERLYING_TOKENS.length) {\n return UNDERLYING_TOKENS[index];\n } else {\n revert();\n }\n }\n}\n" + }, + "contracts/bridge/wrappers/GMXWrapper.sol": { + "content": "// SPDX-License-Identifier: MIT\n\nimport '@openzeppelin/contracts/math/SafeMath.sol';\n\npragma solidity 0.6.12;\n\ninterface IGMX {\n function burn(address _account, uint256 _amount) external;\n function balanceOf(address account) external view returns (uint256);\n function mint(address _account, uint256 _amount) external;\n}\n\ncontract GMXWrapper {\n using SafeMath for uint256;\n\n address constant public gmx = 0x62edc0692BD897D2295872a9FFCac5425011c661;\n address constant public bridge = 0xC05e61d0E7a63D27546389B7aD62FdFf5A91aACE;\n\n function transfer(address _recipient, uint256 _amount) external returns (bool) {\n require(msg.sender == bridge);\n _transfer(msg.sender, _recipient, _amount);\n return true;\n }\n\n function _transfer(address _sender, address _recipient, uint256 _amount) private {\n require(_sender != address(0), \"BaseToken: transfer from the zero address\");\n require(_recipient != address(0), \"BaseToken: transfer to the zero address\");\n IGMX(gmx).burn(_sender, _amount);\n IGMX(gmx).mint(_recipient, _amount);\n }\n\n function mint(address _addr, uint256 _amount) external {\n require(msg.sender == bridge);\n uint256 preMint = IGMX(gmx).balanceOf(_addr);\n IGMX(gmx).mint(_addr, _amount);\n uint256 postMint = IGMX(gmx).balanceOf(_addr);\n require(preMint.add(_amount) == postMint, \"Mint incomplete\");\n }\n\n function burnFrom(address _addr, uint256 _amount) external {\n require(msg.sender == bridge);\n uint256 preBurn = IGMX(gmx).balanceOf(_addr);\n IGMX(gmx).burn(_addr, _amount);\n uint256 postBurn = IGMX(gmx).balanceOf(_addr);\n require(postBurn.add(_amount) == preBurn, \"Burn incomplete\");\n }\n}" + }, + "contracts/bridge/mocks/ERC20Mock.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.6.12;\n\nimport \"@openzeppelin/contracts/token/ERC20/ERC20.sol\";\n\ncontract ERC20Mock is ERC20 {\n constructor(\n string memory name,\n string memory symbol,\n uint256 supply\n ) public ERC20(name, symbol) {\n _mint(msg.sender, supply);\n }\n\n function mint(address to, uint256 amount) external {\n _mint(to, amount);\n }\n}" + }, + "contracts/bridge/interfaces/IMetaSwapDeposit.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.6.12;\nimport '@openzeppelin/contracts/token/ERC20/ERC20.sol';\n\n/**\n * @title IMetaSwapDeposit interface\n * @notice Interface for the meta swap contract.\n * @dev implement this interface to develop a a factory-patterned ECDSA node management contract\n **/\ninterface IMetaSwapDeposit {\n // min return calculation functions\n function calculateSwap(\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx\n ) external view returns (uint256);\n\n function swap(\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx,\n uint256 minDy,\n uint256 deadline\n ) external returns (uint256);\n\n function getToken(uint256 index) external view returns (IERC20);\n}\n" + }, + "contracts/amm/interfaces/IMetaSwapDeposit.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.6.12;\n\nimport \"@openzeppelin/contracts/token/ERC20/ERC20.sol\";\nimport \"./ISwap.sol\";\nimport \"./IMetaSwap.sol\";\n\ninterface IMetaSwapDeposit {\n function initialize(\n ISwap baseSwap_,\n IMetaSwap metaSwap_,\n IERC20 metaLPToken_\n ) external;\n}\n" + }, + "contracts/amm/interfaces/IMetaSwap.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.6.12;\n\nimport \"@openzeppelin/contracts/token/ERC20/ERC20.sol\";\n\ninterface IMetaSwap {\n // pool data view functions\n function getA() external view returns (uint256);\n\n function getToken(uint8 index) external view returns (IERC20);\n\n function getTokenIndex(address tokenAddress) external view returns (uint8);\n\n function getTokenBalance(uint8 index) external view returns (uint256);\n\n function getVirtualPrice() external view returns (uint256);\n\n function isGuarded() external view returns (bool);\n\n // min return calculation functions\n function calculateSwap(\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx\n ) external view returns (uint256);\n\n function calculateSwapUnderlying(\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx\n ) external view returns (uint256);\n\n function calculateTokenAmount(uint256[] calldata amounts, bool deposit)\n external\n view\n returns (uint256);\n\n function calculateRemoveLiquidity(uint256 amount)\n external\n view\n returns (uint256[] memory);\n\n function calculateRemoveLiquidityOneToken(\n uint256 tokenAmount,\n uint8 tokenIndex\n ) external view returns (uint256 availableTokenAmount);\n\n // state modifying functions\n function initializeMetaSwap(\n IERC20[] memory pooledTokens,\n uint8[] memory decimals,\n string memory lpTokenName,\n string memory lpTokenSymbol,\n uint256 a,\n uint256 fee,\n uint256 adminFee,\n address lpTokenTargetAddress,\n address baseSwap\n ) external;\n\n function swap(\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx,\n uint256 minDy,\n uint256 deadline\n ) external returns (uint256);\n\n function swapUnderlying(\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx,\n uint256 minDy,\n uint256 deadline\n ) external returns (uint256);\n\n function addLiquidity(\n uint256[] calldata amounts,\n uint256 minToMint,\n uint256 deadline\n ) external returns (uint256);\n\n function removeLiquidity(\n uint256 amount,\n uint256[] calldata minAmounts,\n uint256 deadline\n ) external returns (uint256[] memory);\n\n function removeLiquidityOneToken(\n uint256 tokenAmount,\n uint8 tokenIndex,\n uint256 minAmount,\n uint256 deadline\n ) external returns (uint256);\n\n function removeLiquidityImbalance(\n uint256[] calldata amounts,\n uint256 maxBurnAmount,\n uint256 deadline\n ) external returns (uint256);\n\n function swapStorage()\n external\n view\n returns (\n uint256 initialA,\n uint256 futureA,\n uint256 initialATime,\n uint256 futureATime,\n uint256 swapFee,\n uint256 adminFee,\n address lpToken\n );\n}\n" + }, + "contracts/amm/helper/GenericERC20.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.6.12;\n\nimport \"@openzeppelin/contracts/token/ERC20/ERC20.sol\";\nimport \"@openzeppelin/contracts/access/Ownable.sol\";\n\n/**\n * @title Generic ERC20 token\n * @notice This contract simulates a generic ERC20 token that is mintable and burnable.\n */\ncontract GenericERC20 is ERC20, Ownable {\n /**\n * @notice Deploy this contract with given name, symbol, and decimals\n * @dev the caller of this constructor will become the owner of this contract\n * @param name_ name of this token\n * @param symbol_ symbol of this token\n * @param decimals_ number of decimals this token will be based on\n */\n constructor(\n string memory name_,\n string memory symbol_,\n uint8 decimals_\n ) public ERC20(name_, symbol_) {\n _setupDecimals(decimals_);\n }\n\n /**\n * @notice Mints given amount of tokens to recipient\n * @dev only owner can call this mint function\n * @param recipient address of account to receive the tokens\n * @param amount amount of tokens to mint\n */\n function mint(address recipient, uint256 amount) external onlyOwner {\n require(amount != 0, \"amount == 0\");\n _mint(recipient, amount);\n }\n}\n" + }, + "contracts/bridge/ECDSAFactory.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.6.12;\n\nimport \"@openzeppelin/contracts/access/Ownable.sol\";\nimport \"@openzeppelin/contracts/proxy/Clones.sol\";\nimport \"./interfaces/IECDSANodeManagement.sol\";\n\ncontract ECDSAFactory is Ownable {\n event ECDSANodeGroupCreated(\n address indexed keepAddress,\n address[] members,\n address indexed owner,\n uint256 honestThreshold\n );\n\n struct LatestNodeGroup {\n address keepAddress;\n address[] members;\n address owner;\n uint256 honestThreshold;\n }\n\n LatestNodeGroup public latestNodeGroup;\n\n constructor() public Ownable() {}\n\n /// @notice Returns members of the keep.\n /// @return List of the keep members' addresses.\n function getMembers() public view returns (address[] memory) {\n return latestNodeGroup.members;\n }\n\n /**\n @notice Deploys a new node \n @param nodeMgmtAddress address of the ECDSANodeManagement contract to initialize with\n @param owner Owner of the ECDSANodeManagement contract who can determine if the node group is closed or active\n @param members Array of node group members addresses\n @param honestThreshold Number of signers to process a transaction \n @return Address of the newest node management contract created\n **/\n function deploy(\n address nodeMgmtAddress,\n address owner,\n address[] memory members,\n uint256 honestThreshold\n ) external onlyOwner returns (address) {\n address nodeClone = Clones.clone(nodeMgmtAddress);\n IECDSANodeManagement(nodeClone).initialize(\n owner,\n members,\n honestThreshold\n );\n\n latestNodeGroup.keepAddress = nodeClone;\n latestNodeGroup.members = members;\n latestNodeGroup.owner = owner;\n latestNodeGroup.honestThreshold = honestThreshold;\n\n emit ECDSANodeGroupCreated(nodeClone, members, owner, honestThreshold);\n return nodeClone;\n }\n}\n" + }, + "contracts/bridge/interfaces/IECDSANodeManagement.sol": { + "content": "// SPDX-License-Identifier: MIT\n\n\npragma solidity 0.6.12;\n\n/**\n * @title IECDSANodeManagement interface\n * @notice Interface for the ECDSA node management interface.\n * @dev implement this interface to develop a a factory-patterned ECDSA node management contract\n **/\ninterface IECDSANodeManagement { \n function initialize(\n address _owner,\n address[] memory _members,\n uint256 _honestThreshold) external;\n}\n\n" + }, + "contracts/auxiliary/DummyWeth.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.6.12;\nimport \"@openzeppelin/contracts/access/Ownable.sol\";\n\ninterface IWETH9 {\n function name() external view returns (string memory);\n\n function symbol() external view returns (string memory);\n\n function decimals() external view returns (uint8);\n\n function balanceOf(address) external view returns (uint256);\n\n function allowance(address, address) external view returns (uint256);\n\n receive() external payable;\n\n function deposit() external payable;\n\n function withdraw(uint256 wad) external;\n\n function totalSupply() external view returns (uint256);\n\n function approve(address guy, uint256 wad) external returns (bool);\n\n function transfer(address dst, uint256 wad) external returns (bool);\n\n function transferFrom(\n address src,\n address dst,\n uint256 wad\n ) external returns (bool);\n}\n\ncontract DummyWeth is Ownable {\n IWETH9 public WETH;\n\n function setWETHAddress(address payable _weth) external onlyOwner {\n WETH = IWETH9(_weth);\n }\n\n function withdrawToSelf(uint256 amount) external {\n WETH.withdraw(amount);\n }\n\n function rescue(uint256 amount) external onlyOwner {\n WETH.transfer(owner(), amount);\n }\n\n receive() external payable {}\n\n fallback() external payable {}\n}\n" + } + }, + "settings": { + "optimizer": { + "enabled": true, + "runs": 10000 + }, + "outputSelection": { + "*": { + "*": [ + "abi", + "evm.bytecode", + "evm.deployedBytecode", + "evm.methodIdentifiers", + "metadata", + "devdoc", + "userdoc", + "storageLayout", + "evm.gasEstimates" + ], + "": [ + "ast" + ] + } + }, + "metadata": { + "useLiteralContent": true + } + } +} \ No newline at end of file diff --git a/deployments/dfk/solcInputs/f2fd7140f46faca58f086e028b2ac3b2.json b/deployments/dfk/solcInputs/f2fd7140f46faca58f086e028b2ac3b2.json new file mode 100644 index 000000000..e13ea8310 --- /dev/null +++ b/deployments/dfk/solcInputs/f2fd7140f46faca58f086e028b2ac3b2.json @@ -0,0 +1,59 @@ +{ + "language": "Solidity", + "sources": { + "contracts/auxiliary/WETH9.sol": { + "content": "// SPDX-License-Identifier: ISC\n\n/**\n *Submitted for verification at Etherscan.io on 2017-12-12\n */\n\n// Copyright (C) 2015, 2016, 2017 Dapphub\n\n// This program is free software: you can redistribute it and/or modify\n// it under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n\n// You should have received a copy of the GNU General Public License\n// along with this program. If not, see .\n\npragma solidity ^0.4.18;\n\ncontract WETH9 {\n string public name = \"Wrapped Ether\";\n string public symbol = \"WETH\";\n uint8 public decimals = 18;\n\n event Approval(address indexed src, address indexed guy, uint256 wad);\n event Transfer(address indexed src, address indexed dst, uint256 wad);\n event Deposit(address indexed dst, uint256 wad);\n event Withdrawal(address indexed src, uint256 wad);\n\n mapping(address => uint256) public balanceOf;\n mapping(address => mapping(address => uint256)) public allowance;\n\n function() public payable {\n deposit();\n }\n\n function deposit() public payable {\n balanceOf[msg.sender] += msg.value;\n Deposit(msg.sender, msg.value);\n }\n\n function withdraw(uint256 wad) public {\n require(balanceOf[msg.sender] >= wad);\n balanceOf[msg.sender] -= wad;\n (bool success, ) = msg.sender.call.value(wad).gas(200000)();\n require(success, \"Transfer failed\");\n Withdrawal(msg.sender, wad);\n }\n\n function totalSupply() public view returns (uint256) {\n return this.balance;\n }\n\n function approve(address guy, uint256 wad) public returns (bool) {\n allowance[msg.sender][guy] = wad;\n Approval(msg.sender, guy, wad);\n return true;\n }\n\n function transfer(address dst, uint256 wad) public returns (bool) {\n return transferFrom(msg.sender, dst, wad);\n }\n\n function transferFrom(\n address src,\n address dst,\n uint256 wad\n ) public returns (bool) {\n require(balanceOf[src] >= wad);\n\n if (src != msg.sender && allowance[src][msg.sender] != uint256(-1)) {\n require(allowance[src][msg.sender] >= wad);\n allowance[src][msg.sender] -= wad;\n }\n\n balanceOf[src] -= wad;\n balanceOf[dst] += wad;\n\n Transfer(src, dst, wad);\n\n return true;\n }\n}\n\n/*\n GNU GENERAL PUBLIC LICENSE\n Version 3, 29 June 2007\n\n Copyright (C) 2007 Free Software Foundation, Inc. \n Everyone is permitted to copy and distribute verbatim copies\n of this license document, but changing it is not allowed.\n\n Preamble\n\n The GNU General Public License is a free, copyleft license for\nsoftware and other kinds of works.\n\n The licenses for most software and other practical works are designed\nto take away your freedom to share and change the works. By contrast,\nthe GNU General Public License is intended to guarantee your freedom to\nshare and change all versions of a program--to make sure it remains free\nsoftware for all its users. We, the Free Software Foundation, use the\nGNU General Public License for most of our software; it applies also to\nany other work released this way by its authors. You can apply it to\nyour programs, too.\n\n When we speak of free software, we are referring to freedom, not\nprice. Our General Public Licenses are designed to make sure that you\nhave the freedom to distribute copies of free software (and charge for\nthem if you wish), that you receive source code or can get it if you\nwant it, that you can change the software or use pieces of it in new\nfree programs, and that you know you can do these things.\n\n To protect your rights, we need to prevent others from denying you\nthese rights or asking you to surrender the rights. Therefore, you have\ncertain responsibilities if you distribute copies of the software, or if\nyou modify it: responsibilities to respect the freedom of others.\n\n For example, if you distribute copies of such a program, whether\ngratis or for a fee, you must pass on to the recipients the same\nfreedoms that you received. You must make sure that they, too, receive\nor can get the source code. And you must show them these terms so they\nknow their rights.\n\n Developers that use the GNU GPL protect your rights with two steps:\n(1) assert copyright on the software, and (2) offer you this License\ngiving you legal permission to copy, distribute and/or modify it.\n\n For the developers' and authors' protection, the GPL clearly explains\nthat there is no warranty for this free software. For both users' and\nauthors' sake, the GPL requires that modified versions be marked as\nchanged, so that their problems will not be attributed erroneously to\nauthors of previous versions.\n\n Some devices are designed to deny users access to install or run\nmodified versions of the software inside them, although the manufacturer\ncan do so. This is fundamentally incompatible with the aim of\nprotecting users' freedom to change the software. The systematic\npattern of such abuse occurs in the area of products for individuals to\nuse, which is precisely where it is most unacceptable. Therefore, we\nhave designed this version of the GPL to prohibit the practice for those\nproducts. If such problems arise substantially in other domains, we\nstand ready to extend this provision to those domains in future versions\nof the GPL, as needed to protect the freedom of users.\n\n Finally, every program is threatened constantly by software patents.\nStates should not allow patents to restrict development and use of\nsoftware on general-purpose computers, but in those that do, we wish to\navoid the special danger that patents applied to a free program could\nmake it effectively proprietary. To prevent this, the GPL assures that\npatents cannot be used to render the program non-free.\n\n The precise terms and conditions for copying, distribution and\nmodification follow.\n\n TERMS AND CONDITIONS\n\n 0. Definitions.\n\n \"This License\" refers to version 3 of the GNU General Public License.\n\n \"Copyright\" also means copyright-like laws that apply to other kinds of\nworks, such as semiconductor masks.\n\n \"The Program\" refers to any copyrightable work licensed under this\nLicense. Each licensee is addressed as \"you\". \"Licensees\" and\n\"recipients\" may be individuals or organizations.\n\n To \"modify\" a work means to copy from or adapt all or part of the work\nin a fashion requiring copyright permission, other than the making of an\nexact copy. The resulting work is called a \"modified version\" of the\nearlier work or a work \"based on\" the earlier work.\n\n A \"covered work\" means either the unmodified Program or a work based\non the Program.\n\n To \"propagate\" a work means to do anything with it that, without\npermission, would make you directly or secondarily liable for\ninfringement under applicable copyright law, except executing it on a\ncomputer or modifying a private copy. Propagation includes copying,\ndistribution (with or without modification), making available to the\npublic, and in some countries other activities as well.\n\n To \"convey\" a work means any kind of propagation that enables other\nparties to make or receive copies. Mere interaction with a user through\na computer network, with no transfer of a copy, is not conveying.\n\n An interactive user interface displays \"Appropriate Legal Notices\"\nto the extent that it includes a convenient and prominently visible\nfeature that (1) displays an appropriate copyright notice, and (2)\ntells the user that there is no warranty for the work (except to the\nextent that warranties are provided), that licensees may convey the\nwork under this License, and how to view a copy of this License. If\nthe interface presents a list of user commands or options, such as a\nmenu, a prominent item in the list meets this criterion.\n\n 1. Source Code.\n\n The \"source code\" for a work means the preferred form of the work\nfor making modifications to it. \"Object code\" means any non-source\nform of a work.\n\n A \"Standard Interface\" means an interface that either is an official\nstandard defined by a recognized standards body, or, in the case of\ninterfaces specified for a particular programming language, one that\nis widely used among developers working in that language.\n\n The \"System Libraries\" of an executable work include anything, other\nthan the work as a whole, that (a) is included in the normal form of\npackaging a Major Component, but which is not part of that Major\nComponent, and (b) serves only to enable use of the work with that\nMajor Component, or to implement a Standard Interface for which an\nimplementation is available to the public in source code form. A\n\"Major Component\", in this context, means a major essential component\n(kernel, window system, and so on) of the specific operating system\n(if any) on which the executable work runs, or a compiler used to\nproduce the work, or an object code interpreter used to run it.\n\n The \"Corresponding Source\" for a work in object code form means all\nthe source code needed to generate, install, and (for an executable\nwork) run the object code and to modify the work, including scripts to\ncontrol those activities. However, it does not include the work's\nSystem Libraries, or general-purpose tools or generally available free\nprograms which are used unmodified in performing those activities but\nwhich are not part of the work. For example, Corresponding Source\nincludes interface definition files associated with source files for\nthe work, and the source code for shared libraries and dynamically\nlinked subprograms that the work is specifically designed to require,\nsuch as by intimate data communication or control flow between those\nsubprograms and other parts of the work.\n\n The Corresponding Source need not include anything that users\ncan regenerate automatically from other parts of the Corresponding\nSource.\n\n The Corresponding Source for a work in source code form is that\nsame work.\n\n 2. Basic Permissions.\n\n All rights granted under this License are granted for the term of\ncopyright on the Program, and are irrevocable provided the stated\nconditions are met. This License explicitly affirms your unlimited\npermission to run the unmodified Program. The output from running a\ncovered work is covered by this License only if the output, given its\ncontent, constitutes a covered work. This License acknowledges your\nrights of fair use or other equivalent, as provided by copyright law.\n\n You may make, run and propagate covered works that you do not\nconvey, without conditions so long as your license otherwise remains\nin force. You may convey covered works to others for the sole purpose\nof having them make modifications exclusively for you, or provide you\nwith facilities for running those works, provided that you comply with\nthe terms of this License in conveying all material for which you do\nnot control copyright. Those thus making or running the covered works\nfor you must do so exclusively on your behalf, under your direction\nand control, on terms that prohibit them from making any copies of\nyour copyrighted material outside their relationship with you.\n\n Conveying under any other circumstances is permitted solely under\nthe conditions stated below. Sublicensing is not allowed; section 10\nmakes it unnecessary.\n\n 3. Protecting Users' Legal Rights From Anti-Circumvention Law.\n\n No covered work shall be deemed part of an effective technological\nmeasure under any applicable law fulfilling obligations under article\n11 of the WIPO copyright treaty adopted on 20 December 1996, or\nsimilar laws prohibiting or restricting circumvention of such\nmeasures.\n\n When you convey a covered work, you waive any legal power to forbid\ncircumvention of technological measures to the extent such circumvention\nis effected by exercising rights under this License with respect to\nthe covered work, and you disclaim any intention to limit operation or\nmodification of the work as a means of enforcing, against the work's\nusers, your or third parties' legal rights to forbid circumvention of\ntechnological measures.\n\n 4. Conveying Verbatim Copies.\n\n You may convey verbatim copies of the Program's source code as you\nreceive it, in any medium, provided that you conspicuously and\nappropriately publish on each copy an appropriate copyright notice;\nkeep intact all notices stating that this License and any\nnon-permissive terms added in accord with section 7 apply to the code;\nkeep intact all notices of the absence of any warranty; and give all\nrecipients a copy of this License along with the Program.\n\n You may charge any price or no price for each copy that you convey,\nand you may offer support or warranty protection for a fee.\n\n 5. Conveying Modified Source Versions.\n\n You may convey a work based on the Program, or the modifications to\nproduce it from the Program, in the form of source code under the\nterms of section 4, provided that you also meet all of these conditions:\n\n a) The work must carry prominent notices stating that you modified\n it, and giving a relevant date.\n\n b) The work must carry prominent notices stating that it is\n released under this License and any conditions added under section\n 7. This requirement modifies the requirement in section 4 to\n \"keep intact all notices\".\n\n c) You must license the entire work, as a whole, under this\n License to anyone who comes into possession of a copy. This\n License will therefore apply, along with any applicable section 7\n additional terms, to the whole of the work, and all its parts,\n regardless of how they are packaged. This License gives no\n permission to license the work in any other way, but it does not\n invalidate such permission if you have separately received it.\n\n d) If the work has interactive user interfaces, each must display\n Appropriate Legal Notices; however, if the Program has interactive\n interfaces that do not display Appropriate Legal Notices, your\n work need not make them do so.\n\n A compilation of a covered work with other separate and independent\nworks, which are not by their nature extensions of the covered work,\nand which are not combined with it such as to form a larger program,\nin or on a volume of a storage or distribution medium, is called an\n\"aggregate\" if the compilation and its resulting copyright are not\nused to limit the access or legal rights of the compilation's users\nbeyond what the individual works permit. Inclusion of a covered work\nin an aggregate does not cause this License to apply to the other\nparts of the aggregate.\n\n 6. Conveying Non-Source Forms.\n\n You may convey a covered work in object code form under the terms\nof sections 4 and 5, provided that you also convey the\nmachine-readable Corresponding Source under the terms of this License,\nin one of these ways:\n\n a) Convey the object code in, or embodied in, a physical product\n (including a physical distribution medium), accompanied by the\n Corresponding Source fixed on a durable physical medium\n customarily used for software interchange.\n\n b) Convey the object code in, or embodied in, a physical product\n (including a physical distribution medium), accompanied by a\n written offer, valid for at least three years and valid for as\n long as you offer spare parts or customer support for that product\n model, to give anyone who possesses the object code either (1) a\n copy of the Corresponding Source for all the software in the\n product that is covered by this License, on a durable physical\n medium customarily used for software interchange, for a price no\n more than your reasonable cost of physically performing this\n conveying of source, or (2) access to copy the\n Corresponding Source from a network server at no charge.\n\n c) Convey individual copies of the object code with a copy of the\n written offer to provide the Corresponding Source. This\n alternative is allowed only occasionally and noncommercially, and\n only if you received the object code with such an offer, in accord\n with subsection 6b.\n\n d) Convey the object code by offering access from a designated\n place (gratis or for a charge), and offer equivalent access to the\n Corresponding Source in the same way through the same place at no\n further charge. You need not require recipients to copy the\n Corresponding Source along with the object code. If the place to\n copy the object code is a network server, the Corresponding Source\n may be on a different server (operated by you or a third party)\n that supports equivalent copying facilities, provided you maintain\n clear directions next to the object code saying where to find the\n Corresponding Source. Regardless of what server hosts the\n Corresponding Source, you remain obligated to ensure that it is\n available for as long as needed to satisfy these requirements.\n\n e) Convey the object code using peer-to-peer transmission, provided\n you inform other peers where the object code and Corresponding\n Source of the work are being offered to the general public at no\n charge under subsection 6d.\n\n A separable portion of the object code, whose source code is excluded\nfrom the Corresponding Source as a System Library, need not be\nincluded in conveying the object code work.\n\n A \"User Product\" is either (1) a \"consumer product\", which means any\ntangible personal property which is normally used for personal, family,\nor household purposes, or (2) anything designed or sold for incorporation\ninto a dwelling. In determining whether a product is a consumer product,\ndoubtful cases shall be resolved in favor of coverage. For a particular\nproduct received by a particular user, \"normally used\" refers to a\ntypical or common use of that class of product, regardless of the status\nof the particular user or of the way in which the particular user\nactually uses, or expects or is expected to use, the product. A product\nis a consumer product regardless of whether the product has substantial\ncommercial, industrial or non-consumer uses, unless such uses represent\nthe only significant mode of use of the product.\n\n \"Installation Information\" for a User Product means any methods,\nprocedures, authorization keys, or other information required to install\nand execute modified versions of a covered work in that User Product from\na modified version of its Corresponding Source. The information must\nsuffice to ensure that the continued functioning of the modified object\ncode is in no case prevented or interfered with solely because\nmodification has been made.\n\n If you convey an object code work under this section in, or with, or\nspecifically for use in, a User Product, and the conveying occurs as\npart of a transaction in which the right of possession and use of the\nUser Product is transferred to the recipient in perpetuity or for a\nfixed term (regardless of how the transaction is characterized), the\nCorresponding Source conveyed under this section must be accompanied\nby the Installation Information. But this requirement does not apply\nif neither you nor any third party retains the ability to install\nmodified object code on the User Product (for example, the work has\nbeen installed in ROM).\n\n The requirement to provide Installation Information does not include a\nrequirement to continue to provide support service, warranty, or updates\nfor a work that has been modified or installed by the recipient, or for\nthe User Product in which it has been modified or installed. Access to a\nnetwork may be denied when the modification itself materially and\nadversely affects the operation of the network or violates the rules and\nprotocols for communication across the network.\n\n Corresponding Source conveyed, and Installation Information provided,\nin accord with this section must be in a format that is publicly\ndocumented (and with an implementation available to the public in\nsource code form), and must require no special password or key for\nunpacking, reading or copying.\n\n 7. Additional Terms.\n\n \"Additional permissions\" are terms that supplement the terms of this\nLicense by making exceptions from one or more of its conditions.\nAdditional permissions that are applicable to the entire Program shall\nbe treated as though they were included in this License, to the extent\nthat they are valid under applicable law. If additional permissions\napply only to part of the Program, that part may be used separately\nunder those permissions, but the entire Program remains governed by\nthis License without regard to the additional permissions.\n\n When you convey a copy of a covered work, you may at your option\nremove any additional permissions from that copy, or from any part of\nit. (Additional permissions may be written to require their own\nremoval in certain cases when you modify the work.) You may place\nadditional permissions on material, added by you to a covered work,\nfor which you have or can give appropriate copyright permission.\n\n Notwithstanding any other provision of this License, for material you\nadd to a covered work, you may (if authorized by the copyright holders of\nthat material) supplement the terms of this License with terms:\n\n a) Disclaiming warranty or limiting liability differently from the\n terms of sections 15 and 16 of this License; or\n\n b) Requiring preservation of specified reasonable legal notices or\n author attributions in that material or in the Appropriate Legal\n Notices displayed by works containing it; or\n\n c) Prohibiting misrepresentation of the origin of that material, or\n requiring that modified versions of such material be marked in\n reasonable ways as different from the original version; or\n\n d) Limiting the use for publicity purposes of names of licensors or\n authors of the material; or\n\n e) Declining to grant rights under trademark law for use of some\n trade names, trademarks, or service marks; or\n\n f) Requiring indemnification of licensors and authors of that\n material by anyone who conveys the material (or modified versions of\n it) with contractual assumptions of liability to the recipient, for\n any liability that these contractual assumptions directly impose on\n those licensors and authors.\n\n All other non-permissive additional terms are considered \"further\nrestrictions\" within the meaning of section 10. If the Program as you\nreceived it, or any part of it, contains a notice stating that it is\ngoverned by this License along with a term that is a further\nrestriction, you may remove that term. If a license document contains\na further restriction but permits relicensing or conveying under this\nLicense, you may add to a covered work material governed by the terms\nof that license document, provided that the further restriction does\nnot survive such relicensing or conveying.\n\n If you add terms to a covered work in accord with this section, you\nmust place, in the relevant source files, a statement of the\nadditional terms that apply to those files, or a notice indicating\nwhere to find the applicable terms.\n\n Additional terms, permissive or non-permissive, may be stated in the\nform of a separately written license, or stated as exceptions;\nthe above requirements apply either way.\n\n 8. Termination.\n\n You may not propagate or modify a covered work except as expressly\nprovided under this License. Any attempt otherwise to propagate or\nmodify it is void, and will automatically terminate your rights under\nthis License (including any patent licenses granted under the third\nparagraph of section 11).\n\n However, if you cease all violation of this License, then your\nlicense from a particular copyright holder is reinstated (a)\nprovisionally, unless and until the copyright holder explicitly and\nfinally terminates your license, and (b) permanently, if the copyright\nholder fails to notify you of the violation by some reasonable means\nprior to 60 days after the cessation.\n\n Moreover, your license from a particular copyright holder is\nreinstated permanently if the copyright holder notifies you of the\nviolation by some reasonable means, this is the first time you have\nreceived notice of violation of this License (for any work) from that\ncopyright holder, and you cure the violation prior to 30 days after\nyour receipt of the notice.\n\n Termination of your rights under this section does not terminate the\nlicenses of parties who have received copies or rights from you under\nthis License. If your rights have been terminated and not permanently\nreinstated, you do not qualify to receive new licenses for the same\nmaterial under section 10.\n\n 9. Acceptance Not Required for Having Copies.\n\n You are not required to accept this License in order to receive or\nrun a copy of the Program. Ancillary propagation of a covered work\noccurring solely as a consequence of using peer-to-peer transmission\nto receive a copy likewise does not require acceptance. However,\nnothing other than this License grants you permission to propagate or\nmodify any covered work. These actions infringe copyright if you do\nnot accept this License. Therefore, by modifying or propagating a\ncovered work, you indicate your acceptance of this License to do so.\n\n 10. Automatic Licensing of Downstream Recipients.\n\n Each time you convey a covered work, the recipient automatically\nreceives a license from the original licensors, to run, modify and\npropagate that work, subject to this License. You are not responsible\nfor enforcing compliance by third parties with this License.\n\n An \"entity transaction\" is a transaction transferring control of an\norganization, or substantially all assets of one, or subdividing an\norganization, or merging organizations. If propagation of a covered\nwork results from an entity transaction, each party to that\ntransaction who receives a copy of the work also receives whatever\nlicenses to the work the party's predecessor in interest had or could\ngive under the previous paragraph, plus a right to possession of the\nCorresponding Source of the work from the predecessor in interest, if\nthe predecessor has it or can get it with reasonable efforts.\n\n You may not impose any further restrictions on the exercise of the\nrights granted or affirmed under this License. For example, you may\nnot impose a license fee, royalty, or other charge for exercise of\nrights granted under this License, and you may not initiate litigation\n(including a cross-claim or counterclaim in a lawsuit) alleging that\nany patent claim is infringed by making, using, selling, offering for\nsale, or importing the Program or any portion of it.\n\n 11. Patents.\n\n A \"contributor\" is a copyright holder who authorizes use under this\nLicense of the Program or a work on which the Program is based. The\nwork thus licensed is called the contributor's \"contributor version\".\n\n A contributor's \"essential patent claims\" are all patent claims\nowned or controlled by the contributor, whether already acquired or\nhereafter acquired, that would be infringed by some manner, permitted\nby this License, of making, using, or selling its contributor version,\nbut do not include claims that would be infringed only as a\nconsequence of further modification of the contributor version. For\npurposes of this definition, \"control\" includes the right to grant\npatent sublicenses in a manner consistent with the requirements of\nthis License.\n\n Each contributor grants you a non-exclusive, worldwide, royalty-free\npatent license under the contributor's essential patent claims, to\nmake, use, sell, offer for sale, import and otherwise run, modify and\npropagate the contents of its contributor version.\n\n In the following three paragraphs, a \"patent license\" is any express\nagreement or commitment, however denominated, not to enforce a patent\n(such as an express permission to practice a patent or covenant not to\nsue for patent infringement). To \"grant\" such a patent license to a\nparty means to make such an agreement or commitment not to enforce a\npatent against the party.\n\n If you convey a covered work, knowingly relying on a patent license,\nand the Corresponding Source of the work is not available for anyone\nto copy, free of charge and under the terms of this License, through a\npublicly available network server or other readily accessible means,\nthen you must either (1) cause the Corresponding Source to be so\navailable, or (2) arrange to deprive yourself of the benefit of the\npatent license for this particular work, or (3) arrange, in a manner\nconsistent with the requirements of this License, to extend the patent\nlicense to downstream recipients. \"Knowingly relying\" means you have\nactual knowledge that, but for the patent license, your conveying the\ncovered work in a country, or your recipient's use of the covered work\nin a country, would infringe one or more identifiable patents in that\ncountry that you have reason to believe are valid.\n\n If, pursuant to or in connection with a single transaction or\narrangement, you convey, or propagate by procuring conveyance of, a\ncovered work, and grant a patent license to some of the parties\nreceiving the covered work authorizing them to use, propagate, modify\nor convey a specific copy of the covered work, then the patent license\nyou grant is automatically extended to all recipients of the covered\nwork and works based on it.\n\n A patent license is \"discriminatory\" if it does not include within\nthe scope of its coverage, prohibits the exercise of, or is\nconditioned on the non-exercise of one or more of the rights that are\nspecifically granted under this License. You may not convey a covered\nwork if you are a party to an arrangement with a third party that is\nin the business of distributing software, under which you make payment\nto the third party based on the extent of your activity of conveying\nthe work, and under which the third party grants, to any of the\nparties who would receive the covered work from you, a discriminatory\npatent license (a) in connection with copies of the covered work\nconveyed by you (or copies made from those copies), or (b) primarily\nfor and in connection with specific products or compilations that\ncontain the covered work, unless you entered into that arrangement,\nor that patent license was granted, prior to 28 March 2007.\n\n Nothing in this License shall be construed as excluding or limiting\nany implied license or other defenses to infringement that may\notherwise be available to you under applicable patent law.\n\n 12. No Surrender of Others' Freedom.\n\n If conditions are imposed on you (whether by court order, agreement or\notherwise) that contradict the conditions of this License, they do not\nexcuse you from the conditions of this License. If you cannot convey a\ncovered work so as to satisfy simultaneously your obligations under this\nLicense and any other pertinent obligations, then as a consequence you may\nnot convey it at all. For example, if you agree to terms that obligate you\nto collect a royalty for further conveying from those to whom you convey\nthe Program, the only way you could satisfy both those terms and this\nLicense would be to refrain entirely from conveying the Program.\n\n 13. Use with the GNU Affero General Public License.\n\n Notwithstanding any other provision of this License, you have\npermission to link or combine any covered work with a work licensed\nunder version 3 of the GNU Affero General Public License into a single\ncombined work, and to convey the resulting work. The terms of this\nLicense will continue to apply to the part which is the covered work,\nbut the special requirements of the GNU Affero General Public License,\nsection 13, concerning interaction through a network will apply to the\ncombination as such.\n\n 14. Revised Versions of this License.\n\n The Free Software Foundation may publish revised and/or new versions of\nthe GNU General Public License from time to time. Such new versions will\nbe similar in spirit to the present version, but may differ in detail to\naddress new problems or concerns.\n\n Each version is given a distinguishing version number. If the\nProgram specifies that a certain numbered version of the GNU General\nPublic License \"or any later version\" applies to it, you have the\noption of following the terms and conditions either of that numbered\nversion or of any later version published by the Free Software\nFoundation. If the Program does not specify a version number of the\nGNU General Public License, you may choose any version ever published\nby the Free Software Foundation.\n\n If the Program specifies that a proxy can decide which future\nversions of the GNU General Public License can be used, that proxy's\npublic statement of acceptance of a version permanently authorizes you\nto choose that version for the Program.\n\n Later license versions may give you additional or different\npermissions. However, no additional obligations are imposed on any\nauthor or copyright holder as a result of your choosing to follow a\nlater version.\n\n 15. Disclaimer of Warranty.\n\n THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY\nAPPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT\nHOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM \"AS IS\" WITHOUT WARRANTY\nOF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,\nTHE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\nPURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM\nIS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF\nALL NECESSARY SERVICING, REPAIR OR CORRECTION.\n\n 16. Limitation of Liability.\n\n IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING\nWILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS\nTHE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY\nGENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE\nUSE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF\nDATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD\nPARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),\nEVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF\nSUCH DAMAGES.\n\n 17. Interpretation of Sections 15 and 16.\n\n If the disclaimer of warranty and limitation of liability provided\nabove cannot be given local legal effect according to their terms,\nreviewing courts shall apply local law that most closely approximates\nan absolute waiver of all civil liability in connection with the\nProgram, unless a warranty or assumption of liability accompanies a\ncopy of the Program in return for a fee.\n\n END OF TERMS AND CONDITIONS\n\n How to Apply These Terms to Your New Programs\n\n If you develop a new program, and you want it to be of the greatest\npossible use to the public, the best way to achieve this is to make it\nfree software which everyone can redistribute and change under these terms.\n\n To do so, attach the following notices to the program. It is safest\nto attach them to the start of each source file to most effectively\nstate the exclusion of warranty; and each file should have at least\nthe \"copyright\" line and a pointer to where the full notice is found.\n\n \n Copyright (C) \n\n This program is free software: you can redistribute it and/or modify\n it under the terms of the GNU General Public License as published by\n the Free Software Foundation, either version 3 of the License, or\n (at your option) any later version.\n\n This program is distributed in the hope that it will be useful,\n but WITHOUT ANY WARRANTY; without even the implied warranty of\n MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n GNU General Public License for more details.\n\n You should have received a copy of the GNU General Public License\n along with this program. If not, see .\n\nAlso add information on how to contact you by electronic and paper mail.\n\n If the program does terminal interaction, make it output a short\nnotice like this when it starts in an interactive mode:\n\n Copyright (C) \n This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.\n This is free software, and you are welcome to redistribute it\n under certain conditions; type `show c' for details.\n\nThe hypothetical commands `show w' and `show c' should show the appropriate\nparts of the General Public License. Of course, your program's commands\nmight be different; for a GUI interface, you would use an \"about box\".\n\n You should also get your employer (if you work as a programmer) or school,\nif any, to sign a \"copyright disclaimer\" for the program, if necessary.\nFor more information on this, and how to apply and follow the GNU GPL, see\n.\n\n The GNU General Public License does not permit incorporating your program\ninto proprietary programs. If your program is a subroutine library, you\nmay consider it more useful to permit linking proprietary applications with\nthe library. If this is what you want to do, use the GNU Lesser General\nPublic License instead of this License. But first, please read\n.\n\n*/\n" + }, + "contracts/MultisigWallet/contracts/Factory.sol": { + "content": "// SPDX-License-Identifier: ISC\n\npragma solidity ^0.4.15;\n\ncontract Factory {\n\n /*\n * Events\n */\n event ContractInstantiation(address sender, address instantiation);\n\n /*\n * Storage\n */\n mapping(address => bool) public isInstantiation;\n mapping(address => address[]) public instantiations;\n\n /*\n * Public functions\n */\n /// @dev Returns number of instantiations by creator.\n /// @param creator Contract creator.\n /// @return Returns number of instantiations by creator.\n function getInstantiationCount(address creator)\n public\n constant\n returns (uint)\n {\n return instantiations[creator].length;\n }\n\n /*\n * Internal functions\n */\n /// @dev Registers contract in factory registry.\n /// @param instantiation Address of contract instantiation.\n function register(address instantiation)\n internal\n {\n isInstantiation[instantiation] = true;\n instantiations[msg.sender].push(instantiation);\n ContractInstantiation(msg.sender, instantiation);\n }\n}\n" + }, + "contracts/MultisigWallet/contracts/MultiSigWalletWithDailyLimitFactory.sol": { + "content": "// SPDX-License-Identifier: ISC\n\npragma solidity ^0.4.15;\nimport \"./Factory.sol\";\nimport \"./MultiSigWalletWithDailyLimit.sol\";\n\n\n/// @title Multisignature wallet factory for daily limit version - Allows creation of multisig wallet.\n/// @author Stefan George - \ncontract MultiSigWalletWithDailyLimitFactory is Factory {\n\n /*\n * Public functions\n */\n /// @dev Allows verified creation of multisignature wallet.\n /// @param _owners List of initial owners.\n /// @param _required Number of required confirmations.\n /// @param _dailyLimit Amount in wei, which can be withdrawn without confirmations on a daily basis.\n /// @return Returns wallet address.\n function create(address[] _owners, uint _required, uint _dailyLimit)\n public\n returns (address wallet)\n {\n wallet = new MultiSigWalletWithDailyLimit(_owners, _required, _dailyLimit);\n register(wallet);\n }\n}\n" + }, + "contracts/MultisigWallet/contracts/MultiSigWalletWithDailyLimit.sol": { + "content": "// SPDX-License-Identifier: ISC\n\npragma solidity ^0.4.15;\nimport \"./MultiSigWallet.sol\";\n\n\n/// @title Multisignature wallet with daily limit - Allows an owner to withdraw a daily limit without multisig.\n/// @author Stefan George - \ncontract MultiSigWalletWithDailyLimit is MultiSigWallet {\n\n /*\n * Events\n */\n event DailyLimitChange(uint dailyLimit);\n\n /*\n * Storage\n */\n uint public dailyLimit;\n uint public lastDay;\n uint public spentToday;\n\n /*\n * Public functions\n */\n /// @dev Contract constructor sets initial owners, required number of confirmations and daily withdraw limit.\n /// @param _owners List of initial owners.\n /// @param _required Number of required confirmations.\n /// @param _dailyLimit Amount in wei, which can be withdrawn without confirmations on a daily basis.\n function MultiSigWalletWithDailyLimit(address[] _owners, uint _required, uint _dailyLimit)\n public\n MultiSigWallet(_owners, _required)\n {\n dailyLimit = _dailyLimit;\n }\n\n /// @dev Allows to change the daily limit. Transaction has to be sent by wallet.\n /// @param _dailyLimit Amount in wei.\n function changeDailyLimit(uint _dailyLimit)\n public\n onlyWallet\n {\n dailyLimit = _dailyLimit;\n DailyLimitChange(_dailyLimit);\n }\n\n /// @dev Allows anyone to execute a confirmed transaction or ether withdraws until daily limit is reached.\n /// @param transactionId Transaction ID.\n function executeTransaction(uint transactionId)\n public\n ownerExists(msg.sender)\n confirmed(transactionId, msg.sender)\n notExecuted(transactionId)\n {\n Transaction storage txn = transactions[transactionId];\n bool _confirmed = isConfirmed(transactionId);\n if (_confirmed || txn.data.length == 0 && isUnderLimit(txn.value)) {\n txn.executed = true;\n if (!_confirmed)\n spentToday += txn.value;\n if (external_call(txn.destination, txn.value, txn.data.length, txn.data))\n Execution(transactionId);\n else {\n ExecutionFailure(transactionId);\n txn.executed = false;\n if (!_confirmed)\n spentToday -= txn.value;\n }\n }\n }\n\n /*\n * Internal functions\n */\n /// @dev Returns if amount is within daily limit and resets spentToday after one day.\n /// @param amount Amount to withdraw.\n /// @return Returns if amount is under daily limit.\n function isUnderLimit(uint amount)\n internal\n returns (bool)\n {\n if (now > lastDay + 24 hours) {\n lastDay = now;\n spentToday = 0;\n }\n if (spentToday + amount > dailyLimit || spentToday + amount < spentToday)\n return false;\n return true;\n }\n\n /*\n * Web3 call functions\n */\n /// @dev Returns maximum withdraw amount.\n /// @return Returns amount.\n function calcMaxWithdraw()\n public\n constant\n returns (uint)\n {\n if (now > lastDay + 24 hours)\n return dailyLimit;\n if (dailyLimit < spentToday)\n return 0;\n return dailyLimit - spentToday;\n }\n}\n" + }, + "contracts/MultisigWallet/contracts/MultiSigWallet.sol": { + "content": "// SPDX-License-Identifier: ISC\n\npragma solidity ^0.4.15;\n\n\n/// @title Multisignature wallet - Allows multiple parties to agree on transactions before execution.\n/// @author Stefan George - \ncontract MultiSigWallet {\n\n /*\n * Events\n */\n event Confirmation(address indexed sender, uint indexed transactionId);\n event Revocation(address indexed sender, uint indexed transactionId);\n event Submission(uint indexed transactionId);\n event Execution(uint indexed transactionId);\n event ExecutionFailure(uint indexed transactionId);\n event Deposit(address indexed sender, uint value);\n event OwnerAddition(address indexed owner);\n event OwnerRemoval(address indexed owner);\n event RequirementChange(uint required);\n\n /*\n * Constants\n */\n uint constant public MAX_OWNER_COUNT = 50;\n\n /*\n * Storage\n */\n mapping (uint => Transaction) public transactions;\n mapping (uint => mapping (address => bool)) public confirmations;\n mapping (address => bool) public isOwner;\n address[] public owners;\n uint public required;\n uint public transactionCount;\n\n struct Transaction {\n address destination;\n uint value;\n bytes data;\n bool executed;\n }\n\n /*\n * Modifiers\n */\n modifier onlyWallet() {\n require(msg.sender == address(this));\n _;\n }\n\n modifier ownerDoesNotExist(address owner) {\n require(!isOwner[owner]);\n _;\n }\n\n modifier ownerExists(address owner) {\n require(isOwner[owner]);\n _;\n }\n\n modifier transactionExists(uint transactionId) {\n require(transactions[transactionId].destination != 0);\n _;\n }\n\n modifier confirmed(uint transactionId, address owner) {\n require(confirmations[transactionId][owner]);\n _;\n }\n\n modifier notConfirmed(uint transactionId, address owner) {\n require(!confirmations[transactionId][owner]);\n _;\n }\n\n modifier notExecuted(uint transactionId) {\n require(!transactions[transactionId].executed);\n _;\n }\n\n modifier notNull(address _address) {\n require(_address != 0);\n _;\n }\n\n modifier validRequirement(uint ownerCount, uint _required) {\n require(ownerCount <= MAX_OWNER_COUNT\n && _required <= ownerCount\n && _required != 0\n && ownerCount != 0);\n _;\n }\n\n /// @dev Fallback function allows to deposit ether.\n function()\n payable\n {\n if (msg.value > 0)\n Deposit(msg.sender, msg.value);\n }\n\n /*\n * Public functions\n */\n /// @dev Contract constructor sets initial owners and required number of confirmations.\n /// @param _owners List of initial owners.\n /// @param _required Number of required confirmations.\n function MultiSigWallet(address[] _owners, uint _required)\n public\n validRequirement(_owners.length, _required)\n {\n for (uint i=0; i<_owners.length; i++) {\n require(!isOwner[_owners[i]] && _owners[i] != 0);\n isOwner[_owners[i]] = true;\n }\n owners = _owners;\n required = _required;\n }\n\n /// @dev Allows to add a new owner. Transaction has to be sent by wallet.\n /// @param owner Address of new owner.\n function addOwner(address owner)\n public\n onlyWallet\n ownerDoesNotExist(owner)\n notNull(owner)\n validRequirement(owners.length + 1, required)\n {\n isOwner[owner] = true;\n owners.push(owner);\n OwnerAddition(owner);\n }\n\n /// @dev Allows to remove an owner. Transaction has to be sent by wallet.\n /// @param owner Address of owner.\n function removeOwner(address owner)\n public\n onlyWallet\n ownerExists(owner)\n {\n isOwner[owner] = false;\n for (uint i=0; i owners.length)\n changeRequirement(owners.length);\n OwnerRemoval(owner);\n }\n\n /// @dev Allows to replace an owner with a new owner. Transaction has to be sent by wallet.\n /// @param owner Address of owner to be replaced.\n /// @param newOwner Address of new owner.\n function replaceOwner(address owner, address newOwner)\n public\n onlyWallet\n ownerExists(owner)\n ownerDoesNotExist(newOwner)\n {\n for (uint i=0; i\ncontract MultiSigWalletFactory is Factory {\n\n /*\n * Public functions\n */\n /// @dev Allows verified creation of multisignature wallet.\n /// @param _owners List of initial owners.\n /// @param _required Number of required confirmations.\n /// @return Returns wallet address.\n function create(address[] _owners, uint _required)\n public\n returns (address wallet)\n {\n wallet = new MultiSigWallet(_owners, _required);\n register(wallet);\n }\n}\n" + }, + "contracts/MultisigWallet/contracts/Migrations.sol": { + "content": "// SPDX-License-Identifier: ISC\n\npragma solidity ^0.4.15;\n\ncontract Migrations {\n address public owner;\n uint public last_completed_migration;\n\n modifier restricted() {\n if (msg.sender == owner) _;\n }\n\n function Migrations() {\n owner = msg.sender;\n }\n\n function setCompleted(uint completed) restricted {\n last_completed_migration = completed;\n }\n\n function upgrade(address new_address) restricted {\n Migrations upgraded = Migrations(new_address);\n upgraded.setCompleted(last_completed_migration);\n }\n}\n" + }, + "contracts/MultisigWallet/contracts/TestCalls.sol": { + "content": "// SPDX-License-Identifier: ISC\n\npragma solidity ^0.4.15;\n\n\n/// @title Contract for testing low-level calls issued from the multisig wallet\ncontract TestCalls {\n\n\t// msg.data.length of the latest call to \"receive\" methods\n\tuint public lastMsgDataLength;\n\n\t// msg.value of the latest call to \"receive\" methods\n\tuint public lastMsgValue;\n\n\tuint public uint1;\n\tuint public uint2;\n\tbytes public byteArray1;\n\n\tmodifier setMsgFields {\n\t\tlastMsgDataLength = msg.data.length;\n\t\tlastMsgValue = msg.value;\n\t\t_;\n\t}\n\n\tfunction TestCalls() setMsgFields public {\n\t\t// This constructor will be used to test the creation via multisig wallet\n\t}\n\n\tfunction receive1uint(uint a) setMsgFields payable public {\n\t\tuint1 = a;\n\t}\n\n\tfunction receive2uints(uint a, uint b) setMsgFields payable public {\n\t\tuint1 = a;\n\t\tuint2 = b;\n\t}\n\n\tfunction receive1bytes(bytes c) setMsgFields payable public {\n\t\tbyteArray1 = c;\n\t}\n\n\tfunction nonPayable() setMsgFields public {\n\t}\n\n}" + }, + "contracts/MultisigWallet/contracts/TestToken.sol": { + "content": "// SPDX-License-Identifier: ISC\n\npragma solidity ^0.4.15;\n\n\n/// @title Test token contract - Allows testing of token transfers with multisig wallet.\ncontract TestToken {\n\n /*\n * Events\n */\n event Transfer(address indexed from, address indexed to, uint256 value);\n event Approval(address indexed owner, address indexed spender, uint256 value);\n\n /*\n * Constants\n */\n string constant public name = \"Test Token\";\n string constant public symbol = \"TT\";\n uint8 constant public decimals = 1;\n\n /*\n * Storage\n */\n mapping (address => uint256) balances;\n mapping (address => mapping (address => uint256)) allowed;\n uint256 public totalSupply;\n\n /*\n * Public functions\n */\n /// @dev Issues new tokens.\n /// @param _to Address of token receiver.\n /// @param _value Number of tokens to issue.\n function issueTokens(address _to, uint256 _value)\n public\n {\n balances[_to] += _value;\n totalSupply += _value;\n }\n\n /*\n * This modifier is present in some real world token contracts, and due to a solidity\n * bug it was not compatible with multisig wallets\n */\n modifier onlyPayloadSize(uint size) {\n require(msg.data.length == size + 4);\n _;\n }\n\n /// @dev Transfers sender's tokens to a given address. Returns success.\n /// @param _to Address of token receiver.\n /// @param _value Number of tokens to transfer.\n /// @return Returns success of function call.\n function transfer(address _to, uint256 _value) onlyPayloadSize(2 * 32)\n public\n returns (bool success)\n {\n require(balances[msg.sender] >= _value);\n balances[msg.sender] -= _value;\n balances[_to] += _value;\n Transfer(msg.sender, _to, _value);\n return true;\n }\n\n /// @dev Allows allowed third party to transfer tokens from one address to another. Returns success.\n /// @param _from Address from where tokens are withdrawn.\n /// @param _to Address to where tokens are sent.\n /// @param _value Number of tokens to transfer.\n /// @return Returns success of function call.\n function transferFrom(address _from, address _to, uint256 _value)\n public\n returns (bool success)\n {\n require(balances[_from] >= _value && allowed[_from][msg.sender] >= _value);\n balances[_to] += _value;\n balances[_from] -= _value;\n allowed[_from][msg.sender] -= _value;\n Transfer(_from, _to, _value);\n return true;\n }\n\n /// @dev Sets approved amount of tokens for spender. Returns success.\n /// @param _spender Address of allowed account.\n /// @param _value Number of approved tokens.\n /// @return Returns success of function call.\n function approve(address _spender, uint256 _value)\n public\n returns (bool success)\n {\n allowed[msg.sender][_spender] = _value;\n Approval(msg.sender, _spender, _value);\n return true;\n }\n\n /// @dev Returns number of allowed tokens for given address.\n /// @param _owner Address of token owner.\n /// @param _spender Address of token spender.\n /// @return Returns remaining allowance for spender.\n function allowance(address _owner, address _spender)\n constant\n public\n returns (uint256 remaining)\n {\n return allowed[_owner][_spender];\n }\n\n /// @dev Returns number of tokens owned by given address.\n /// @param _owner Address of token owner.\n /// @return Returns balance of owner.\n function balanceOf(address _owner)\n constant\n public\n returns (uint256 balance)\n {\n return balances[_owner];\n }\n}\n" + } + }, + "settings": { + "optimizer": { + "enabled": false, + "runs": 200 + }, + "outputSelection": { + "*": { + "*": [ + "abi", + "evm.bytecode", + "evm.deployedBytecode", + "evm.methodIdentifiers", + "metadata", + "devdoc", + "userdoc", + "storageLayout", + "evm.gasEstimates" + ], + "": [ + "ast" + ] + } + }, + "metadata": { + "useLiteralContent": true + } + } +} \ No newline at end of file diff --git a/deployments/dfk/solcInputs/f830a0c701b69b2055ae5caebfbd7bc2.json b/deployments/dfk/solcInputs/f830a0c701b69b2055ae5caebfbd7bc2.json new file mode 100644 index 000000000..a03d211fd --- /dev/null +++ b/deployments/dfk/solcInputs/f830a0c701b69b2055ae5caebfbd7bc2.json @@ -0,0 +1,304 @@ +{ + "language": "Solidity", + "sources": { + "contracts/amm/AaveSwap.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.6.12;\n\nimport \"./Swap.sol\";\n\n/**\n * @title AaveSwap - A StableSwap implementation in solidity, integrated with Aave.\n * @notice This contract is responsible for custody of closely pegged assets (eg. group of stablecoins)\n * and automatic market making system. Users become an LP (Liquidity Provider) by depositing their tokens\n * in desired ratios for an exchange of the pool token that represents their share of the pool.\n * Users can burn pool tokens and withdraw their share of token(s).\n *\n * Each time a swap between the pooled tokens happens, a set fee incurs which effectively gets\n * distributed to the LPs.\n *\n * In case of emergencies, admin can pause additional deposits, swaps, or single-asset withdraws - which\n * stops the ratio of the tokens in the pool from changing.\n * Users can always withdraw their tokens via multi-asset withdraws.\n *\n * @dev Most of the logic is stored as a library `SwapUtils` for the sake of reducing contract's\n * deployment size.\n */\n\ncontract AaveSwap is Swap {\n address internal AAVE_REWARDS;\n address internal AAVE_LENDING_POOL;\n address internal REWARD_TOKEN;\n address internal REWARD_RECEIVER;\n address[] internal AAVE_ASSETS;\n\n /**\n * @notice Initializes this Swap contract with the given parameters.\n * This will also clone a LPToken contract that represents users'\n * LP positions. The owner of LPToken will be this contract - which means\n * only this contract is allowed to mint/burn tokens.\n *\n * @param _pooledTokens an array of ERC20s this pool will accept\n * @param decimals the decimals to use for each pooled token,\n * eg 8 for WBTC. Cannot be larger than POOL_PRECISION_DECIMALS\n * @param lpTokenName the long-form name of the token to be deployed\n * @param lpTokenSymbol the short symbol for the token to be deployed\n * @param _a the amplification coefficient * n * (n - 1). See the\n * StableSwap paper for details\n * @param _fee default swap fee to be initialized with\n * @param _adminFee default adminFee to be initialized with\n * @param lpTokenTargetAddress the address of an existing LPToken contract to use as a target\n */\n function initialize(\n IERC20[] memory _pooledTokens,\n uint8[] memory decimals,\n string memory lpTokenName,\n string memory lpTokenSymbol,\n uint256 _a,\n uint256 _fee,\n uint256 _adminFee,\n address lpTokenTargetAddress\n ) public virtual override initializer {\n Swap.initialize(\n _pooledTokens,\n decimals,\n lpTokenName,\n lpTokenSymbol,\n _a,\n _fee,\n _adminFee,\n lpTokenTargetAddress\n );\n AAVE_REWARDS = 0x01D83Fe6A10D2f2B7AF17034343746188272cAc9;\n AAVE_LENDING_POOL = 0x4F01AeD16D97E3aB5ab2B501154DC9bb0F1A5A2C;\n REWARD_TOKEN = 0xB31f66AA3C1e785363F0875A1B74E27b85FD66c7;\n AAVE_ASSETS = [0x53f7c5869a859F0AeC3D334ee8B4Cf01E3492f21];\n REWARD_RECEIVER = msg.sender;\n }\n\n function setRewardReceiver(address _reward_receiver) external onlyOwner {\n REWARD_RECEIVER = _reward_receiver;\n }\n\n function claimAaveRewards() external {\n AAVE_REWARDS.call(\n abi.encodeWithSignature(\n \"claimRewards(address[],uint256,address)\",\n AAVE_ASSETS,\n type(uint256).max,\n REWARD_RECEIVER\n )\n );\n }\n}\n" + }, + "contracts/amm/Swap.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.6.12;\n\nimport \"@openzeppelin/contracts/math/SafeMath.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/SafeERC20.sol\";\nimport \"@openzeppelin/contracts/proxy/Clones.sol\";\nimport \"@openzeppelin/contracts-upgradeable/utils/ReentrancyGuardUpgradeable.sol\";\nimport \"./OwnerPausableUpgradeable.sol\";\nimport \"./SwapUtils.sol\";\nimport \"./AmplificationUtils.sol\";\n\n/**\n * @title Swap - A StableSwap implementation in solidity.\n * @notice This contract is responsible for custody of closely pegged assets (eg. group of stablecoins)\n * and automatic market making system. Users become an LP (Liquidity Provider) by depositing their tokens\n * in desired ratios for an exchange of the pool token that represents their share of the pool.\n * Users can burn pool tokens and withdraw their share of token(s).\n *\n * Each time a swap between the pooled tokens happens, a set fee incurs which effectively gets\n * distributed to the LPs.\n *\n * In case of emergencies, admin can pause additional deposits, swaps, or single-asset withdraws - which\n * stops the ratio of the tokens in the pool from changing.\n * Users can always withdraw their tokens via multi-asset withdraws.\n *\n * @dev Most of the logic is stored as a library `SwapUtils` for the sake of reducing contract's\n * deployment size.\n */\ncontract Swap is OwnerPausableUpgradeable, ReentrancyGuardUpgradeable {\n using SafeERC20 for IERC20;\n using SafeMath for uint256;\n using SwapUtils for SwapUtils.Swap;\n using AmplificationUtils for SwapUtils.Swap;\n\n // Struct storing data responsible for automatic market maker functionalities. In order to\n // access this data, this contract uses SwapUtils library. For more details, see SwapUtils.sol\n SwapUtils.Swap public swapStorage;\n\n // Maps token address to an index in the pool. Used to prevent duplicate tokens in the pool.\n // getTokenIndex function also relies on this mapping to retrieve token index.\n mapping(address => uint8) private tokenIndexes;\n\n /*** EVENTS ***/\n\n // events replicated from SwapUtils to make the ABI easier for dumb\n // clients\n event TokenSwap(\n address indexed buyer,\n uint256 tokensSold,\n uint256 tokensBought,\n uint128 soldId,\n uint128 boughtId\n );\n event AddLiquidity(\n address indexed provider,\n uint256[] tokenAmounts,\n uint256[] fees,\n uint256 invariant,\n uint256 lpTokenSupply\n );\n event RemoveLiquidity(\n address indexed provider,\n uint256[] tokenAmounts,\n uint256 lpTokenSupply\n );\n event RemoveLiquidityOne(\n address indexed provider,\n uint256 lpTokenAmount,\n uint256 lpTokenSupply,\n uint256 boughtId,\n uint256 tokensBought\n );\n event RemoveLiquidityImbalance(\n address indexed provider,\n uint256[] tokenAmounts,\n uint256[] fees,\n uint256 invariant,\n uint256 lpTokenSupply\n );\n event NewAdminFee(uint256 newAdminFee);\n event NewSwapFee(uint256 newSwapFee);\n event RampA(\n uint256 oldA,\n uint256 newA,\n uint256 initialTime,\n uint256 futureTime\n );\n event StopRampA(uint256 currentA, uint256 time);\n\n /**\n * @notice Initializes this Swap contract with the given parameters.\n * This will also clone a LPToken contract that represents users'\n * LP positions. The owner of LPToken will be this contract - which means\n * only this contract is allowed to mint/burn tokens.\n *\n * @param _pooledTokens an array of ERC20s this pool will accept\n * @param decimals the decimals to use for each pooled token,\n * eg 8 for WBTC. Cannot be larger than POOL_PRECISION_DECIMALS\n * @param lpTokenName the long-form name of the token to be deployed\n * @param lpTokenSymbol the short symbol for the token to be deployed\n * @param _a the amplification coefficient * n * (n - 1). See the\n * StableSwap paper for details\n * @param _fee default swap fee to be initialized with\n * @param _adminFee default adminFee to be initialized with\n * @param lpTokenTargetAddress the address of an existing LPToken contract to use as a target\n */\n function initialize(\n IERC20[] memory _pooledTokens,\n uint8[] memory decimals,\n string memory lpTokenName,\n string memory lpTokenSymbol,\n uint256 _a,\n uint256 _fee,\n uint256 _adminFee,\n address lpTokenTargetAddress\n ) public virtual initializer {\n __OwnerPausable_init();\n __ReentrancyGuard_init();\n // Check _pooledTokens and precisions parameter\n require(_pooledTokens.length > 1, \"_pooledTokens.length <= 1\");\n require(_pooledTokens.length <= 32, \"_pooledTokens.length > 32\");\n require(\n _pooledTokens.length == decimals.length,\n \"_pooledTokens decimals mismatch\"\n );\n\n uint256[] memory precisionMultipliers = new uint256[](decimals.length);\n\n for (uint8 i = 0; i < _pooledTokens.length; i++) {\n if (i > 0) {\n // Check if index is already used. Check if 0th element is a duplicate.\n require(\n tokenIndexes[address(_pooledTokens[i])] == 0 &&\n _pooledTokens[0] != _pooledTokens[i],\n \"Duplicate tokens\"\n );\n }\n require(\n address(_pooledTokens[i]) != address(0),\n \"The 0 address isn't an ERC-20\"\n );\n require(\n decimals[i] <= SwapUtils.POOL_PRECISION_DECIMALS,\n \"Token decimals exceeds max\"\n );\n precisionMultipliers[i] =\n 10 **\n uint256(SwapUtils.POOL_PRECISION_DECIMALS).sub(\n uint256(decimals[i])\n );\n tokenIndexes[address(_pooledTokens[i])] = i;\n }\n\n // Check _a, _fee, _adminFee parameters\n require(_a < AmplificationUtils.MAX_A, \"_a exceeds maximum\");\n require(_fee < SwapUtils.MAX_SWAP_FEE, \"_fee exceeds maximum\");\n require(\n _adminFee < SwapUtils.MAX_ADMIN_FEE,\n \"_adminFee exceeds maximum\"\n );\n\n // Clone and initialize a LPToken contract\n LPToken lpToken = LPToken(Clones.clone(lpTokenTargetAddress));\n require(\n lpToken.initialize(lpTokenName, lpTokenSymbol),\n \"could not init lpToken clone\"\n );\n\n // Initialize swapStorage struct\n swapStorage.lpToken = lpToken;\n swapStorage.pooledTokens = _pooledTokens;\n swapStorage.tokenPrecisionMultipliers = precisionMultipliers;\n swapStorage.balances = new uint256[](_pooledTokens.length);\n swapStorage.initialA = _a.mul(AmplificationUtils.A_PRECISION);\n swapStorage.futureA = _a.mul(AmplificationUtils.A_PRECISION);\n // swapStorage.initialATime = 0;\n // swapStorage.futureATime = 0;\n swapStorage.swapFee = _fee;\n swapStorage.adminFee = _adminFee;\n }\n\n /*** MODIFIERS ***/\n\n /**\n * @notice Modifier to check deadline against current timestamp\n * @param deadline latest timestamp to accept this transaction\n */\n modifier deadlineCheck(uint256 deadline) {\n require(block.timestamp <= deadline, \"Deadline not met\");\n _;\n }\n\n /*** VIEW FUNCTIONS ***/\n\n /**\n * @notice Return A, the amplification coefficient * n * (n - 1)\n * @dev See the StableSwap paper for details\n * @return A parameter\n */\n function getA() external view virtual returns (uint256) {\n return swapStorage.getA();\n }\n\n /**\n * @notice Return A in its raw precision form\n * @dev See the StableSwap paper for details\n * @return A parameter in its raw precision form\n */\n function getAPrecise() external view virtual returns (uint256) {\n return swapStorage.getAPrecise();\n }\n\n /**\n * @notice Return address of the pooled token at given index. Reverts if tokenIndex is out of range.\n * @param index the index of the token\n * @return address of the token at given index\n */\n function getToken(uint8 index) public view virtual returns (IERC20) {\n require(index < swapStorage.pooledTokens.length, \"Out of range\");\n return swapStorage.pooledTokens[index];\n }\n\n /**\n * @notice Return the index of the given token address. Reverts if no matching\n * token is found.\n * @param tokenAddress address of the token\n * @return the index of the given token address\n */\n function getTokenIndex(address tokenAddress)\n public\n view\n virtual\n returns (uint8)\n {\n uint8 index = tokenIndexes[tokenAddress];\n require(\n address(getToken(index)) == tokenAddress,\n \"Token does not exist\"\n );\n return index;\n }\n\n /**\n * @notice Return current balance of the pooled token at given index\n * @param index the index of the token\n * @return current balance of the pooled token at given index with token's native precision\n */\n function getTokenBalance(uint8 index)\n external\n view\n virtual\n returns (uint256)\n {\n require(index < swapStorage.pooledTokens.length, \"Index out of range\");\n return swapStorage.balances[index];\n }\n\n /**\n * @notice Get the virtual price, to help calculate profit\n * @return the virtual price, scaled to the POOL_PRECISION_DECIMALS\n */\n function getVirtualPrice() external view virtual returns (uint256) {\n return swapStorage.getVirtualPrice();\n }\n\n /**\n * @notice Calculate amount of tokens you receive on swap\n * @param tokenIndexFrom the token the user wants to sell\n * @param tokenIndexTo the token the user wants to buy\n * @param dx the amount of tokens the user wants to sell. If the token charges\n * a fee on transfers, use the amount that gets transferred after the fee.\n * @return amount of tokens the user will receive\n */\n function calculateSwap(\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx\n ) external view virtual returns (uint256) {\n return swapStorage.calculateSwap(tokenIndexFrom, tokenIndexTo, dx);\n }\n\n /**\n * @notice A simple method to calculate prices from deposits or\n * withdrawals, excluding fees but including slippage. This is\n * helpful as an input into the various \"min\" parameters on calls\n * to fight front-running\n *\n * @dev This shouldn't be used outside frontends for user estimates.\n *\n * @param amounts an array of token amounts to deposit or withdrawal,\n * corresponding to pooledTokens. The amount should be in each\n * pooled token's native precision. If a token charges a fee on transfers,\n * use the amount that gets transferred after the fee.\n * @param deposit whether this is a deposit or a withdrawal\n * @return token amount the user will receive\n */\n function calculateTokenAmount(uint256[] calldata amounts, bool deposit)\n external\n view\n virtual\n returns (uint256)\n {\n return swapStorage.calculateTokenAmount(amounts, deposit);\n }\n\n /**\n * @notice A simple method to calculate amount of each underlying\n * tokens that is returned upon burning given amount of LP tokens\n * @param amount the amount of LP tokens that would be burned on withdrawal\n * @return array of token balances that the user will receive\n */\n function calculateRemoveLiquidity(uint256 amount)\n external\n view\n virtual\n returns (uint256[] memory)\n {\n return swapStorage.calculateRemoveLiquidity(amount);\n }\n\n /**\n * @notice Calculate the amount of underlying token available to withdraw\n * when withdrawing via only single token\n * @param tokenAmount the amount of LP token to burn\n * @param tokenIndex index of which token will be withdrawn\n * @return availableTokenAmount calculated amount of underlying token\n * available to withdraw\n */\n function calculateRemoveLiquidityOneToken(\n uint256 tokenAmount,\n uint8 tokenIndex\n ) external view virtual returns (uint256 availableTokenAmount) {\n return swapStorage.calculateWithdrawOneToken(tokenAmount, tokenIndex);\n }\n\n /**\n * @notice This function reads the accumulated amount of admin fees of the token with given index\n * @param index Index of the pooled token\n * @return admin's token balance in the token's precision\n */\n function getAdminBalance(uint256 index)\n external\n view\n virtual\n returns (uint256)\n {\n return swapStorage.getAdminBalance(index);\n }\n\n /*** STATE MODIFYING FUNCTIONS ***/\n\n /**\n * @notice Swap two tokens using this pool\n * @param tokenIndexFrom the token the user wants to swap from\n * @param tokenIndexTo the token the user wants to swap to\n * @param dx the amount of tokens the user wants to swap from\n * @param minDy the min amount the user would like to receive, or revert.\n * @param deadline latest timestamp to accept this transaction\n */\n function swap(\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx,\n uint256 minDy,\n uint256 deadline\n )\n external\n virtual\n nonReentrant\n whenNotPaused\n deadlineCheck(deadline)\n returns (uint256)\n {\n return swapStorage.swap(tokenIndexFrom, tokenIndexTo, dx, minDy);\n }\n\n /**\n * @notice Add liquidity to the pool with the given amounts of tokens\n * @param amounts the amounts of each token to add, in their native precision\n * @param minToMint the minimum LP tokens adding this amount of liquidity\n * should mint, otherwise revert. Handy for front-running mitigation\n * @param deadline latest timestamp to accept this transaction\n * @return amount of LP token user minted and received\n */\n function addLiquidity(\n uint256[] calldata amounts,\n uint256 minToMint,\n uint256 deadline\n )\n external\n virtual\n nonReentrant\n whenNotPaused\n deadlineCheck(deadline)\n returns (uint256)\n {\n return swapStorage.addLiquidity(amounts, minToMint);\n }\n\n /**\n * @notice Burn LP tokens to remove liquidity from the pool. Withdraw fee that decays linearly\n * over period of 4 weeks since last deposit will apply.\n * @dev Liquidity can always be removed, even when the pool is paused.\n * @param amount the amount of LP tokens to burn\n * @param minAmounts the minimum amounts of each token in the pool\n * acceptable for this burn. Useful as a front-running mitigation\n * @param deadline latest timestamp to accept this transaction\n * @return amounts of tokens user received\n */\n function removeLiquidity(\n uint256 amount,\n uint256[] calldata minAmounts,\n uint256 deadline\n )\n external\n virtual\n nonReentrant\n deadlineCheck(deadline)\n returns (uint256[] memory)\n {\n return swapStorage.removeLiquidity(amount, minAmounts);\n }\n\n /**\n * @notice Remove liquidity from the pool all in one token. Withdraw fee that decays linearly\n * over period of 4 weeks since last deposit will apply.\n * @param tokenAmount the amount of the token you want to receive\n * @param tokenIndex the index of the token you want to receive\n * @param minAmount the minimum amount to withdraw, otherwise revert\n * @param deadline latest timestamp to accept this transaction\n * @return amount of chosen token user received\n */\n function removeLiquidityOneToken(\n uint256 tokenAmount,\n uint8 tokenIndex,\n uint256 minAmount,\n uint256 deadline\n )\n external\n virtual\n nonReentrant\n whenNotPaused\n deadlineCheck(deadline)\n returns (uint256)\n {\n return\n swapStorage.removeLiquidityOneToken(\n tokenAmount,\n tokenIndex,\n minAmount\n );\n }\n\n /**\n * @notice Remove liquidity from the pool, weighted differently than the\n * pool's current balances. Withdraw fee that decays linearly\n * over period of 4 weeks since last deposit will apply.\n * @param amounts how much of each token to withdraw\n * @param maxBurnAmount the max LP token provider is willing to pay to\n * remove liquidity. Useful as a front-running mitigation.\n * @param deadline latest timestamp to accept this transaction\n * @return amount of LP tokens burned\n */\n function removeLiquidityImbalance(\n uint256[] calldata amounts,\n uint256 maxBurnAmount,\n uint256 deadline\n )\n external\n virtual\n nonReentrant\n whenNotPaused\n deadlineCheck(deadline)\n returns (uint256)\n {\n return swapStorage.removeLiquidityImbalance(amounts, maxBurnAmount);\n }\n\n /*** ADMIN FUNCTIONS ***/\n\n /**\n * @notice Withdraw all admin fees to the contract owner\n */\n function withdrawAdminFees() external onlyOwner {\n swapStorage.withdrawAdminFees(owner());\n }\n\n /**\n * @notice Update the admin fee. Admin fee takes portion of the swap fee.\n * @param newAdminFee new admin fee to be applied on future transactions\n */\n function setAdminFee(uint256 newAdminFee) external onlyOwner {\n swapStorage.setAdminFee(newAdminFee);\n }\n\n /**\n * @notice Update the swap fee to be applied on swaps\n * @param newSwapFee new swap fee to be applied on future transactions\n */\n function setSwapFee(uint256 newSwapFee) external onlyOwner {\n swapStorage.setSwapFee(newSwapFee);\n }\n\n /**\n * @notice Start ramping up or down A parameter towards given futureA and futureTime\n * Checks if the change is too rapid, and commits the new A value only when it falls under\n * the limit range.\n * @param futureA the new A to ramp towards\n * @param futureTime timestamp when the new A should be reached\n */\n function rampA(uint256 futureA, uint256 futureTime) external onlyOwner {\n swapStorage.rampA(futureA, futureTime);\n }\n\n /**\n * @notice Stop ramping A immediately. Reverts if ramp A is already stopped.\n */\n function stopRampA() external onlyOwner {\n swapStorage.stopRampA();\n }\n}\n" + }, + "@openzeppelin/contracts/math/SafeMath.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <0.8.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" + }, + "@openzeppelin/contracts/token/ERC20/SafeERC20.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <0.8.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" + }, + "@openzeppelin/contracts/proxy/Clones.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <0.8.0;\n\n/**\n * @dev https://eips.ethereum.org/EIPS/eip-1167[EIP 1167] is a standard for\n * deploying minimal proxy contracts, also known as \"clones\".\n *\n * > To simply and cheaply clone contract functionality in an immutable way, this standard specifies\n * > a minimal bytecode implementation that delegates all calls to a known, fixed address.\n *\n * The library includes functions to deploy a proxy using either `create` (traditional deployment) or `create2`\n * (salted deterministic deployment). It also includes functions to predict the addresses of clones deployed using the\n * deterministic method.\n *\n * _Available since v3.4._\n */\nlibrary Clones {\n /**\n * @dev Deploys and returns the address of a clone that mimics the behaviour of `master`.\n *\n * This function uses the create opcode, which should never revert.\n */\n function clone(address master) internal returns (address instance) {\n // solhint-disable-next-line no-inline-assembly\n assembly {\n let ptr := mload(0x40)\n mstore(ptr, 0x3d602d80600a3d3981f3363d3d373d3d3d363d73000000000000000000000000)\n mstore(add(ptr, 0x14), shl(0x60, master))\n mstore(add(ptr, 0x28), 0x5af43d82803e903d91602b57fd5bf30000000000000000000000000000000000)\n instance := create(0, ptr, 0x37)\n }\n require(instance != address(0), \"ERC1167: create failed\");\n }\n\n /**\n * @dev Deploys and returns the address of a clone that mimics the behaviour of `master`.\n *\n * This function uses the create2 opcode and a `salt` to deterministically deploy\n * the clone. Using the same `master` and `salt` multiple time will revert, since\n * the clones cannot be deployed twice at the same address.\n */\n function cloneDeterministic(address master, bytes32 salt) internal returns (address instance) {\n // solhint-disable-next-line no-inline-assembly\n assembly {\n let ptr := mload(0x40)\n mstore(ptr, 0x3d602d80600a3d3981f3363d3d373d3d3d363d73000000000000000000000000)\n mstore(add(ptr, 0x14), shl(0x60, master))\n mstore(add(ptr, 0x28), 0x5af43d82803e903d91602b57fd5bf30000000000000000000000000000000000)\n instance := create2(0, ptr, 0x37, salt)\n }\n require(instance != address(0), \"ERC1167: create2 failed\");\n }\n\n /**\n * @dev Computes the address of a clone deployed using {Clones-cloneDeterministic}.\n */\n function predictDeterministicAddress(address master, bytes32 salt, address deployer) internal pure returns (address predicted) {\n // solhint-disable-next-line no-inline-assembly\n assembly {\n let ptr := mload(0x40)\n mstore(ptr, 0x3d602d80600a3d3981f3363d3d373d3d3d363d73000000000000000000000000)\n mstore(add(ptr, 0x14), shl(0x60, master))\n mstore(add(ptr, 0x28), 0x5af43d82803e903d91602b57fd5bf3ff00000000000000000000000000000000)\n mstore(add(ptr, 0x38), shl(0x60, deployer))\n mstore(add(ptr, 0x4c), salt)\n mstore(add(ptr, 0x6c), keccak256(ptr, 0x37))\n predicted := keccak256(add(ptr, 0x37), 0x55)\n }\n }\n\n /**\n * @dev Computes the address of a clone deployed using {Clones-cloneDeterministic}.\n */\n function predictDeterministicAddress(address master, bytes32 salt) internal view returns (address predicted) {\n return predictDeterministicAddress(master, salt, address(this));\n }\n}\n" + }, + "@openzeppelin/contracts-upgradeable/utils/ReentrancyGuardUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <0.8.0;\nimport \"../proxy/Initializable.sol\";\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 ReentrancyGuardUpgradeable is Initializable {\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 function __ReentrancyGuard_init() internal initializer {\n __ReentrancyGuard_init_unchained();\n }\n\n function __ReentrancyGuard_init_unchained() internal initializer {\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 uint256[49] private __gap;\n}\n" + }, + "contracts/amm/OwnerPausableUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.6.12;\n\nimport \"@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol\";\nimport \"@openzeppelin/contracts-upgradeable/utils/PausableUpgradeable.sol\";\n\n/**\n * @title OwnerPausable\n * @notice An ownable contract allows the owner to pause and unpause the\n * contract without a delay.\n * @dev Only methods using the provided modifiers will be paused.\n */\nabstract contract OwnerPausableUpgradeable is\n OwnableUpgradeable,\n PausableUpgradeable\n{\n function __OwnerPausable_init() internal initializer {\n __Context_init_unchained();\n __Ownable_init_unchained();\n __Pausable_init_unchained();\n }\n\n /**\n * @notice Pause the contract. Revert if already paused.\n */\n function pause() external onlyOwner {\n PausableUpgradeable._pause();\n }\n\n /**\n * @notice Unpause the contract. Revert if already unpaused.\n */\n function unpause() external onlyOwner {\n PausableUpgradeable._unpause();\n }\n}\n" + }, + "contracts/amm/SwapUtils.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.6.12;\n\nimport \"@openzeppelin/contracts/math/SafeMath.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/SafeERC20.sol\";\nimport \"./AmplificationUtils.sol\";\nimport \"./LPToken.sol\";\nimport \"./MathUtils.sol\";\n\n/**\n * @title SwapUtils library\n * @notice A library to be used within Swap.sol. Contains functions responsible for custody and AMM functionalities.\n * @dev Contracts relying on this library must initialize SwapUtils.Swap struct then use this library\n * for SwapUtils.Swap struct. Note that this library contains both functions called by users and admins.\n * Admin functions should be protected within contracts using this library.\n */\nlibrary SwapUtils {\n using SafeERC20 for IERC20;\n using SafeMath for uint256;\n using MathUtils for uint256;\n\n /*** EVENTS ***/\n\n event TokenSwap(\n address indexed buyer,\n uint256 tokensSold,\n uint256 tokensBought,\n uint128 soldId,\n uint128 boughtId\n );\n event AddLiquidity(\n address indexed provider,\n uint256[] tokenAmounts,\n uint256[] fees,\n uint256 invariant,\n uint256 lpTokenSupply\n );\n event RemoveLiquidity(\n address indexed provider,\n uint256[] tokenAmounts,\n uint256 lpTokenSupply\n );\n event RemoveLiquidityOne(\n address indexed provider,\n uint256 lpTokenAmount,\n uint256 lpTokenSupply,\n uint256 boughtId,\n uint256 tokensBought\n );\n event RemoveLiquidityImbalance(\n address indexed provider,\n uint256[] tokenAmounts,\n uint256[] fees,\n uint256 invariant,\n uint256 lpTokenSupply\n );\n event NewAdminFee(uint256 newAdminFee);\n event NewSwapFee(uint256 newSwapFee);\n\n struct Swap {\n // variables around the ramp management of A,\n // the amplification coefficient * n * (n - 1)\n // see https://www.curve.fi/stableswap-paper.pdf for details\n uint256 initialA;\n uint256 futureA;\n uint256 initialATime;\n uint256 futureATime;\n // fee calculation\n uint256 swapFee;\n uint256 adminFee;\n LPToken lpToken;\n // contract references for all tokens being pooled\n IERC20[] pooledTokens;\n // multipliers for each pooled token's precision to get to POOL_PRECISION_DECIMALS\n // for example, TBTC has 18 decimals, so the multiplier should be 1. WBTC\n // has 8, so the multiplier should be 10 ** 18 / 10 ** 8 => 10 ** 10\n uint256[] tokenPrecisionMultipliers;\n // the pool balance of each token, in the token's precision\n // the contract's actual token balance might differ\n uint256[] balances;\n }\n\n // Struct storing variables used in calculations in the\n // calculateWithdrawOneTokenDY function to avoid stack too deep errors\n struct CalculateWithdrawOneTokenDYInfo {\n uint256 d0;\n uint256 d1;\n uint256 newY;\n uint256 feePerToken;\n uint256 preciseA;\n }\n\n // Struct storing variables used in calculations in the\n // {add,remove}Liquidity functions to avoid stack too deep errors\n struct ManageLiquidityInfo {\n uint256 d0;\n uint256 d1;\n uint256 d2;\n uint256 preciseA;\n LPToken lpToken;\n uint256 totalSupply;\n uint256[] balances;\n uint256[] multipliers;\n }\n\n // the precision all pools tokens will be converted to\n uint8 public constant POOL_PRECISION_DECIMALS = 18;\n\n // the denominator used to calculate admin and LP fees. For example, an\n // LP fee might be something like tradeAmount.mul(fee).div(FEE_DENOMINATOR)\n uint256 private constant FEE_DENOMINATOR = 10**10;\n\n // Max swap fee is 1% or 100bps of each swap\n uint256 public constant MAX_SWAP_FEE = 10**8;\n\n // Max adminFee is 100% of the swapFee\n // adminFee does not add additional fee on top of swapFee\n // Instead it takes a certain % of the swapFee. Therefore it has no impact on the\n // users but only on the earnings of LPs\n uint256 public constant MAX_ADMIN_FEE = 10**10;\n\n // Constant value used as max loop limit\n uint256 private constant MAX_LOOP_LIMIT = 256;\n\n /*** VIEW & PURE FUNCTIONS ***/\n\n function _getAPrecise(Swap storage self) internal view returns (uint256) {\n return AmplificationUtils._getAPrecise(self);\n }\n\n /**\n * @notice Calculate the dy, the amount of selected token that user receives and\n * the fee of withdrawing in one token\n * @param tokenAmount the amount to withdraw in the pool's precision\n * @param tokenIndex which token will be withdrawn\n * @param self Swap struct to read from\n * @return the amount of token user will receive\n */\n function calculateWithdrawOneToken(\n Swap storage self,\n uint256 tokenAmount,\n uint8 tokenIndex\n ) external view returns (uint256) {\n (uint256 availableTokenAmount, ) = _calculateWithdrawOneToken(\n self,\n tokenAmount,\n tokenIndex,\n self.lpToken.totalSupply()\n );\n return availableTokenAmount;\n }\n\n function _calculateWithdrawOneToken(\n Swap storage self,\n uint256 tokenAmount,\n uint8 tokenIndex,\n uint256 totalSupply\n ) internal view returns (uint256, uint256) {\n uint256 dy;\n uint256 newY;\n uint256 currentY;\n\n (dy, newY, currentY) = calculateWithdrawOneTokenDY(\n self,\n tokenIndex,\n tokenAmount,\n totalSupply\n );\n\n // dy_0 (without fees)\n // dy, dy_0 - dy\n\n uint256 dySwapFee = currentY\n .sub(newY)\n .div(self.tokenPrecisionMultipliers[tokenIndex])\n .sub(dy);\n\n return (dy, dySwapFee);\n }\n\n /**\n * @notice Calculate the dy of withdrawing in one token\n * @param self Swap struct to read from\n * @param tokenIndex which token will be withdrawn\n * @param tokenAmount the amount to withdraw in the pools precision\n * @return the d and the new y after withdrawing one token\n */\n function calculateWithdrawOneTokenDY(\n Swap storage self,\n uint8 tokenIndex,\n uint256 tokenAmount,\n uint256 totalSupply\n )\n internal\n view\n returns (\n uint256,\n uint256,\n uint256\n )\n {\n // Get the current D, then solve the stableswap invariant\n // y_i for D - tokenAmount\n uint256[] memory xp = _xp(self);\n\n require(tokenIndex < xp.length, \"Token index out of range\");\n\n\n CalculateWithdrawOneTokenDYInfo memory v\n = CalculateWithdrawOneTokenDYInfo(0, 0, 0, 0, 0);\n v.preciseA = _getAPrecise(self);\n v.d0 = getD(xp, v.preciseA);\n v.d1 = v.d0.sub(tokenAmount.mul(v.d0).div(totalSupply));\n\n require(tokenAmount <= xp[tokenIndex], \"Withdraw exceeds available\");\n\n v.newY = getYD(v.preciseA, tokenIndex, xp, v.d1);\n\n uint256[] memory xpReduced = new uint256[](xp.length);\n\n v.feePerToken = _feePerToken(self.swapFee, xp.length);\n for (uint256 i = 0; i < xp.length; i++) {\n uint256 xpi = xp[i];\n // if i == tokenIndex, dxExpected = xp[i] * d1 / d0 - newY\n // else dxExpected = xp[i] - (xp[i] * d1 / d0)\n // xpReduced[i] -= dxExpected * fee / FEE_DENOMINATOR\n xpReduced[i] = xpi.sub(\n (\n (i == tokenIndex)\n ? xpi.mul(v.d1).div(v.d0).sub(v.newY)\n : xpi.sub(xpi.mul(v.d1).div(v.d0))\n )\n .mul(v.feePerToken)\n .div(FEE_DENOMINATOR)\n );\n }\n\n uint256 dy = xpReduced[tokenIndex].sub(\n getYD(v.preciseA, tokenIndex, xpReduced, v.d1)\n );\n dy = dy.sub(1).div(self.tokenPrecisionMultipliers[tokenIndex]);\n\n return (dy, v.newY, xp[tokenIndex]);\n }\n\n /**\n * @notice Calculate the price of a token in the pool with given\n * precision-adjusted balances and a particular D.\n *\n * @dev This is accomplished via solving the invariant iteratively.\n * See the StableSwap paper and Curve.fi implementation for further details.\n *\n * x_1**2 + x1 * (sum' - (A*n**n - 1) * D / (A * n**n)) = D ** (n + 1) / (n ** (2 * n) * prod' * A)\n * x_1**2 + b*x_1 = c\n * x_1 = (x_1**2 + c) / (2*x_1 + b)\n *\n * @param a the amplification coefficient * n * (n - 1). See the StableSwap paper for details.\n * @param tokenIndex Index of token we are calculating for.\n * @param xp a precision-adjusted set of pool balances. Array should be\n * the same cardinality as the pool.\n * @param d the stableswap invariant\n * @return the price of the token, in the same precision as in xp\n */\n function getYD(\n uint256 a,\n uint8 tokenIndex,\n uint256[] memory xp,\n uint256 d\n ) internal pure returns (uint256) {\n uint256 numTokens = xp.length;\n require(tokenIndex < numTokens, \"Token not found\");\n\n uint256 c = d;\n uint256 s;\n uint256 nA = a.mul(numTokens);\n\n for (uint256 i = 0; i < numTokens; i++) {\n if (i != tokenIndex) {\n s = s.add(xp[i]);\n c = c.mul(d).div(xp[i].mul(numTokens));\n // If we were to protect the division loss we would have to keep the denominator separate\n // and divide at the end. However this leads to overflow with large numTokens or/and D.\n // c = c * D * D * D * ... overflow!\n }\n }\n c = c.mul(d).mul(AmplificationUtils.A_PRECISION).div(nA.mul(numTokens));\n\n uint256 b = s.add(d.mul(AmplificationUtils.A_PRECISION).div(nA));\n uint256 yPrev;\n uint256 y = d;\n for (uint256 i = 0; i < MAX_LOOP_LIMIT; i++) {\n yPrev = y;\n y = y.mul(y).add(c).div(y.mul(2).add(b).sub(d));\n if (y.within1(yPrev)) {\n return y;\n }\n }\n revert(\"Approximation did not converge\");\n }\n\n /**\n * @notice Get D, the StableSwap invariant, based on a set of balances and a particular A.\n * @param xp a precision-adjusted set of pool balances. Array should be the same cardinality\n * as the pool.\n * @param a the amplification coefficient * n * (n - 1) in A_PRECISION.\n * See the StableSwap paper for details\n * @return the invariant, at the precision of the pool\n */\n function getD(uint256[] memory xp, uint256 a)\n internal\n pure\n returns (uint256)\n {\n uint256 numTokens = xp.length;\n uint256 s;\n for (uint256 i = 0; i < numTokens; i++) {\n s = s.add(xp[i]);\n }\n if (s == 0) {\n return 0;\n }\n\n uint256 prevD;\n uint256 d = s;\n uint256 nA = a.mul(numTokens);\n\n for (uint256 i = 0; i < MAX_LOOP_LIMIT; i++) {\n uint256 dP = d;\n for (uint256 j = 0; j < numTokens; j++) {\n dP = dP.mul(d).div(xp[j].mul(numTokens));\n // If we were to protect the division loss we would have to keep the denominator separate\n // and divide at the end. However this leads to overflow with large numTokens or/and D.\n // dP = dP * D * D * D * ... overflow!\n }\n prevD = d;\n d = nA\n .mul(s)\n .div(AmplificationUtils.A_PRECISION)\n .add(dP.mul(numTokens))\n .mul(d)\n .div(\n nA\n .sub(AmplificationUtils.A_PRECISION)\n .mul(d)\n .div(AmplificationUtils.A_PRECISION)\n .add(numTokens.add(1).mul(dP))\n );\n if (d.within1(prevD)) {\n return d;\n }\n }\n\n // Convergence should occur in 4 loops or less. If this is reached, there may be something wrong\n // with the pool. If this were to occur repeatedly, LPs should withdraw via `removeLiquidity()`\n // function which does not rely on D.\n revert(\"D does not converge\");\n }\n\n /**\n * @notice Given a set of balances and precision multipliers, return the\n * precision-adjusted balances.\n *\n * @param balances an array of token balances, in their native precisions.\n * These should generally correspond with pooled tokens.\n *\n * @param precisionMultipliers an array of multipliers, corresponding to\n * the amounts in the balances array. When multiplied together they\n * should yield amounts at the pool's precision.\n *\n * @return an array of amounts \"scaled\" to the pool's precision\n */\n function _xp(\n uint256[] memory balances,\n uint256[] memory precisionMultipliers\n ) internal pure returns (uint256[] memory) {\n uint256 numTokens = balances.length;\n require(\n numTokens == precisionMultipliers.length,\n \"Balances must match multipliers\"\n );\n uint256[] memory xp = new uint256[](numTokens);\n for (uint256 i = 0; i < numTokens; i++) {\n xp[i] = balances[i].mul(precisionMultipliers[i]);\n }\n return xp;\n }\n\n /**\n * @notice Return the precision-adjusted balances of all tokens in the pool\n * @param self Swap struct to read from\n * @return the pool balances \"scaled\" to the pool's precision, allowing\n * them to be more easily compared.\n */\n function _xp(Swap storage self) internal view returns (uint256[] memory) {\n return _xp(self.balances, self.tokenPrecisionMultipliers);\n }\n\n /**\n * @notice Get the virtual price, to help calculate profit\n * @param self Swap struct to read from\n * @return the virtual price, scaled to precision of POOL_PRECISION_DECIMALS\n */\n function getVirtualPrice(Swap storage self)\n external\n view\n returns (uint256)\n {\n uint256 d = getD(_xp(self), _getAPrecise(self));\n LPToken lpToken = self.lpToken;\n uint256 supply = lpToken.totalSupply();\n if (supply > 0) {\n return d.mul(10**uint256(POOL_PRECISION_DECIMALS)).div(supply);\n }\n return 0;\n }\n\n /**\n * @notice Calculate the new balances of the tokens given the indexes of the token\n * that is swapped from (FROM) and the token that is swapped to (TO).\n * This function is used as a helper function to calculate how much TO token\n * the user should receive on swap.\n *\n * @param preciseA precise form of amplification coefficient\n * @param tokenIndexFrom index of FROM token\n * @param tokenIndexTo index of TO token\n * @param x the new total amount of FROM token\n * @param xp balances of the tokens in the pool\n * @return the amount of TO token that should remain in the pool\n */\n function getY(\n uint256 preciseA,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 x,\n uint256[] memory xp\n ) internal pure returns (uint256) {\n uint256 numTokens = xp.length;\n require(\n tokenIndexFrom != tokenIndexTo,\n \"Can't compare token to itself\"\n );\n require(\n tokenIndexFrom < numTokens && tokenIndexTo < numTokens,\n \"Tokens must be in pool\"\n );\n\n uint256 d = getD(xp, preciseA);\n uint256 c = d;\n uint256 s;\n uint256 nA = numTokens.mul(preciseA);\n\n uint256 _x;\n for (uint256 i = 0; i < numTokens; i++) {\n if (i == tokenIndexFrom) {\n _x = x;\n } else if (i != tokenIndexTo) {\n _x = xp[i];\n } else {\n continue;\n }\n s = s.add(_x);\n c = c.mul(d).div(_x.mul(numTokens));\n // If we were to protect the division loss we would have to keep the denominator separate\n // and divide at the end. However this leads to overflow with large numTokens or/and D.\n // c = c * D * D * D * ... overflow!\n }\n c = c.mul(d).mul(AmplificationUtils.A_PRECISION).div(nA.mul(numTokens));\n uint256 b = s.add(d.mul(AmplificationUtils.A_PRECISION).div(nA));\n uint256 yPrev;\n uint256 y = d;\n\n // iterative approximation\n for (uint256 i = 0; i < MAX_LOOP_LIMIT; i++) {\n yPrev = y;\n y = y.mul(y).add(c).div(y.mul(2).add(b).sub(d));\n if (y.within1(yPrev)) {\n return y;\n }\n }\n revert(\"Approximation did not converge\");\n }\n\n /**\n * @notice Externally calculates a swap between two tokens.\n * @param self Swap struct to read from\n * @param tokenIndexFrom the token to sell\n * @param tokenIndexTo the token to buy\n * @param dx the number of tokens to sell. If the token charges a fee on transfers,\n * use the amount that gets transferred after the fee.\n * @return dy the number of tokens the user will get\n */\n function calculateSwap(\n Swap storage self,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx\n ) external view returns (uint256 dy) {\n (dy, ) = _calculateSwap(\n self,\n tokenIndexFrom,\n tokenIndexTo,\n dx,\n self.balances\n );\n }\n\n /**\n * @notice Internally calculates a swap between two tokens.\n *\n * @dev The caller is expected to transfer the actual amounts (dx and dy)\n * using the token contracts.\n *\n * @param self Swap struct to read from\n * @param tokenIndexFrom the token to sell\n * @param tokenIndexTo the token to buy\n * @param dx the number of tokens to sell. If the token charges a fee on transfers,\n * use the amount that gets transferred after the fee.\n * @return dy the number of tokens the user will get\n * @return dyFee the associated fee\n */\n function _calculateSwap(\n Swap storage self,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx,\n uint256[] memory balances\n ) internal view returns (uint256 dy, uint256 dyFee) {\n uint256[] memory multipliers = self.tokenPrecisionMultipliers;\n uint256[] memory xp = _xp(balances, multipliers);\n require(\n tokenIndexFrom < xp.length && tokenIndexTo < xp.length,\n \"Token index out of range\"\n );\n uint256 x = dx.mul(multipliers[tokenIndexFrom]).add(xp[tokenIndexFrom]);\n uint256 y = getY(\n _getAPrecise(self),\n tokenIndexFrom,\n tokenIndexTo,\n x,\n xp\n );\n dy = xp[tokenIndexTo].sub(y).sub(1);\n dyFee = dy.mul(self.swapFee).div(FEE_DENOMINATOR);\n dy = dy.sub(dyFee).div(multipliers[tokenIndexTo]);\n }\n\n /**\n * @notice A simple method to calculate amount of each underlying\n * tokens that is returned upon burning given amount of\n * LP tokens\n *\n * @param amount the amount of LP tokens that would to be burned on\n * withdrawal\n * @return array of amounts of tokens user will receive\n */\n function calculateRemoveLiquidity(Swap storage self, uint256 amount)\n external\n view\n returns (uint256[] memory)\n {\n return\n _calculateRemoveLiquidity(\n self.balances,\n amount,\n self.lpToken.totalSupply()\n );\n }\n\n function _calculateRemoveLiquidity(\n uint256[] memory balances,\n uint256 amount,\n uint256 totalSupply\n ) internal pure returns (uint256[] memory) {\n require(amount <= totalSupply, \"Cannot exceed total supply\");\n\n uint256[] memory amounts = new uint256[](balances.length);\n\n for (uint256 i = 0; i < balances.length; i++) {\n amounts[i] = balances[i].mul(amount).div(totalSupply);\n }\n return amounts;\n }\n\n /**\n * @notice A simple method to calculate prices from deposits or\n * withdrawals, excluding fees but including slippage. This is\n * helpful as an input into the various \"min\" parameters on calls\n * to fight front-running\n *\n * @dev This shouldn't be used outside frontends for user estimates.\n *\n * @param self Swap struct to read from\n * @param amounts an array of token amounts to deposit or withdrawal,\n * corresponding to pooledTokens. The amount should be in each\n * pooled token's native precision. If a token charges a fee on transfers,\n * use the amount that gets transferred after the fee.\n * @param deposit whether this is a deposit or a withdrawal\n * @return if deposit was true, total amount of lp token that will be minted and if\n * deposit was false, total amount of lp token that will be burned\n */\n function calculateTokenAmount(\n Swap storage self,\n uint256[] calldata amounts,\n bool deposit\n ) external view returns (uint256) {\n uint256 a = _getAPrecise(self);\n uint256[] memory balances = self.balances;\n uint256[] memory multipliers = self.tokenPrecisionMultipliers;\n\n uint256 d0 = getD(_xp(balances, multipliers), a);\n for (uint256 i = 0; i < balances.length; i++) {\n if (deposit) {\n balances[i] = balances[i].add(amounts[i]);\n } else {\n balances[i] = balances[i].sub(\n amounts[i],\n \"Cannot withdraw more than available\"\n );\n }\n }\n uint256 d1 = getD(_xp(balances, multipliers), a);\n uint256 totalSupply = self.lpToken.totalSupply();\n\n if (deposit) {\n return d1.sub(d0).mul(totalSupply).div(d0);\n } else {\n return d0.sub(d1).mul(totalSupply).div(d0);\n }\n }\n\n /**\n * @notice return accumulated amount of admin fees of the token with given index\n * @param self Swap struct to read from\n * @param index Index of the pooled token\n * @return admin balance in the token's precision\n */\n function getAdminBalance(Swap storage self, uint256 index)\n external\n view\n returns (uint256)\n {\n require(index < self.pooledTokens.length, \"Token index out of range\");\n return\n self.pooledTokens[index].balanceOf(address(this)).sub(\n self.balances[index]\n );\n }\n\n /**\n * @notice internal helper function to calculate fee per token multiplier used in\n * swap fee calculations\n * @param swapFee swap fee for the tokens\n * @param numTokens number of tokens pooled\n */\n function _feePerToken(uint256 swapFee, uint256 numTokens)\n internal\n pure\n returns (uint256)\n {\n return swapFee.mul(numTokens).div(numTokens.sub(1).mul(4));\n }\n\n /*** STATE MODIFYING FUNCTIONS ***/\n\n /**\n * @notice swap two tokens in the pool\n * @param self Swap struct to read from and write to\n * @param tokenIndexFrom the token the user wants to sell\n * @param tokenIndexTo the token the user wants to buy\n * @param dx the amount of tokens the user wants to sell\n * @param minDy the min amount the user would like to receive, or revert.\n * @return amount of token user received on swap\n */\n function swap(\n Swap storage self,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx,\n uint256 minDy\n ) external returns (uint256) {\n {\n IERC20 tokenFrom = self.pooledTokens[tokenIndexFrom];\n require(\n dx <= tokenFrom.balanceOf(msg.sender),\n \"Cannot swap more than you own\"\n );\n // Transfer tokens first to see if a fee was charged on transfer\n uint256 beforeBalance = tokenFrom.balanceOf(address(this));\n tokenFrom.safeTransferFrom(msg.sender, address(this), dx);\n\n // Use the actual transferred amount for AMM math\n dx = tokenFrom.balanceOf(address(this)).sub(beforeBalance);\n }\n\n uint256 dy;\n uint256 dyFee;\n uint256[] memory balances = self.balances;\n (dy, dyFee) = _calculateSwap(\n self,\n tokenIndexFrom,\n tokenIndexTo,\n dx,\n balances\n );\n require(dy >= minDy, \"Swap didn't result in min tokens\");\n\n uint256 dyAdminFee = dyFee.mul(self.adminFee).div(FEE_DENOMINATOR).div(\n self.tokenPrecisionMultipliers[tokenIndexTo]\n );\n\n self.balances[tokenIndexFrom] = balances[tokenIndexFrom].add(dx);\n self.balances[tokenIndexTo] = balances[tokenIndexTo].sub(dy).sub(\n dyAdminFee\n );\n\n self.pooledTokens[tokenIndexTo].safeTransfer(msg.sender, dy);\n\n emit TokenSwap(msg.sender, dx, dy, tokenIndexFrom, tokenIndexTo);\n\n return dy;\n }\n\n /**\n * @notice Add liquidity to the pool\n * @param self Swap struct to read from and write to\n * @param amounts the amounts of each token to add, in their native precision\n * @param minToMint the minimum LP tokens adding this amount of liquidity\n * should mint, otherwise revert. Handy for front-running mitigation\n * allowed addresses. If the pool is not in the guarded launch phase, this parameter will be ignored.\n * @return amount of LP token user received\n */\n function addLiquidity(\n Swap storage self,\n uint256[] memory amounts,\n uint256 minToMint\n ) external returns (uint256) {\n IERC20[] memory pooledTokens = self.pooledTokens;\n require(\n amounts.length == pooledTokens.length,\n \"Amounts must match pooled tokens\"\n );\n\n // current state\n ManageLiquidityInfo memory v = ManageLiquidityInfo(\n 0,\n 0,\n 0,\n _getAPrecise(self),\n self.lpToken,\n 0,\n self.balances,\n self.tokenPrecisionMultipliers\n );\n v.totalSupply = v.lpToken.totalSupply();\n\n if (v.totalSupply != 0) {\n v.d0 = getD(_xp(v.balances, v.multipliers), v.preciseA);\n }\n\n uint256[] memory newBalances = new uint256[](pooledTokens.length);\n\n for (uint256 i = 0; i < pooledTokens.length; i++) {\n require(\n v.totalSupply != 0 || amounts[i] > 0,\n \"Must supply all tokens in pool\"\n );\n\n // Transfer tokens first to see if a fee was charged on transfer\n if (amounts[i] != 0) {\n uint256 beforeBalance = pooledTokens[i].balanceOf(\n address(this)\n );\n pooledTokens[i].safeTransferFrom(\n msg.sender,\n address(this),\n amounts[i]\n );\n\n // Update the amounts[] with actual transfer amount\n amounts[i] = pooledTokens[i].balanceOf(address(this)).sub(\n beforeBalance\n );\n }\n\n newBalances[i] = v.balances[i].add(amounts[i]);\n }\n\n // invariant after change\n v.d1 = getD(_xp(newBalances, v.multipliers), v.preciseA);\n require(v.d1 > v.d0, \"D should increase\");\n\n // updated to reflect fees and calculate the user's LP tokens\n v.d2 = v.d1;\n uint256[] memory fees = new uint256[](pooledTokens.length);\n\n if (v.totalSupply != 0) {\n uint256 feePerToken = _feePerToken(\n self.swapFee,\n pooledTokens.length\n );\n for (uint256 i = 0; i < pooledTokens.length; i++) {\n uint256 idealBalance = v.d1.mul(v.balances[i]).div(v.d0);\n fees[i] = feePerToken\n .mul(idealBalance.difference(newBalances[i]))\n .div(FEE_DENOMINATOR);\n self.balances[i] = newBalances[i].sub(\n fees[i].mul(self.adminFee).div(FEE_DENOMINATOR)\n );\n newBalances[i] = newBalances[i].sub(fees[i]);\n }\n v.d2 = getD(_xp(newBalances, v.multipliers), v.preciseA);\n } else {\n // the initial depositor doesn't pay fees\n self.balances = newBalances;\n }\n\n uint256 toMint;\n if (v.totalSupply == 0) {\n toMint = v.d1;\n } else {\n toMint = v.d2.sub(v.d0).mul(v.totalSupply).div(v.d0);\n }\n\n require(toMint >= minToMint, \"Couldn't mint min requested\");\n\n // mint the user's LP tokens\n v.lpToken.mint(msg.sender, toMint);\n\n emit AddLiquidity(\n msg.sender,\n amounts,\n fees,\n v.d1,\n v.totalSupply.add(toMint)\n );\n\n return toMint;\n }\n\n /**\n * @notice Burn LP tokens to remove liquidity from the pool.\n * @dev Liquidity can always be removed, even when the pool is paused.\n * @param self Swap struct to read from and write to\n * @param amount the amount of LP tokens to burn\n * @param minAmounts the minimum amounts of each token in the pool\n * acceptable for this burn. Useful as a front-running mitigation\n * @return amounts of tokens the user received\n */\n function removeLiquidity(\n Swap storage self,\n uint256 amount,\n uint256[] calldata minAmounts\n ) external returns (uint256[] memory) {\n LPToken lpToken = self.lpToken;\n IERC20[] memory pooledTokens = self.pooledTokens;\n require(amount <= lpToken.balanceOf(msg.sender), \">LP.balanceOf\");\n require(\n minAmounts.length == pooledTokens.length,\n \"minAmounts must match poolTokens\"\n );\n\n uint256[] memory balances = self.balances;\n uint256 totalSupply = lpToken.totalSupply();\n\n uint256[] memory amounts = _calculateRemoveLiquidity(\n balances,\n amount,\n totalSupply\n );\n\n for (uint256 i = 0; i < amounts.length; i++) {\n require(amounts[i] >= minAmounts[i], \"amounts[i] < minAmounts[i]\");\n self.balances[i] = balances[i].sub(amounts[i]);\n pooledTokens[i].safeTransfer(msg.sender, amounts[i]);\n }\n\n lpToken.burnFrom(msg.sender, amount);\n\n emit RemoveLiquidity(msg.sender, amounts, totalSupply.sub(amount));\n\n return amounts;\n }\n\n /**\n * @notice Remove liquidity from the pool all in one token.\n * @param self Swap struct to read from and write to\n * @param tokenAmount the amount of the lp tokens to burn\n * @param tokenIndex the index of the token you want to receive\n * @param minAmount the minimum amount to withdraw, otherwise revert\n * @return amount chosen token that user received\n */\n function removeLiquidityOneToken(\n Swap storage self,\n uint256 tokenAmount,\n uint8 tokenIndex,\n uint256 minAmount\n ) external returns (uint256) {\n LPToken lpToken = self.lpToken;\n IERC20[] memory pooledTokens = self.pooledTokens;\n\n require(tokenAmount <= lpToken.balanceOf(msg.sender), \">LP.balanceOf\");\n require(tokenIndex < pooledTokens.length, \"Token not found\");\n\n uint256 totalSupply = lpToken.totalSupply();\n\n (uint256 dy, uint256 dyFee) = _calculateWithdrawOneToken(\n self,\n tokenAmount,\n tokenIndex,\n totalSupply\n );\n\n require(dy >= minAmount, \"dy < minAmount\");\n\n self.balances[tokenIndex] = self.balances[tokenIndex].sub(\n dy.add(dyFee.mul(self.adminFee).div(FEE_DENOMINATOR))\n );\n lpToken.burnFrom(msg.sender, tokenAmount);\n pooledTokens[tokenIndex].safeTransfer(msg.sender, dy);\n\n emit RemoveLiquidityOne(\n msg.sender,\n tokenAmount,\n totalSupply,\n tokenIndex,\n dy\n );\n\n return dy;\n }\n\n /**\n * @notice Remove liquidity from the pool, weighted differently than the\n * pool's current balances.\n *\n * @param self Swap struct to read from and write to\n * @param amounts how much of each token to withdraw\n * @param maxBurnAmount the max LP token provider is willing to pay to\n * remove liquidity. Useful as a front-running mitigation.\n * @return actual amount of LP tokens burned in the withdrawal\n */\n function removeLiquidityImbalance(\n Swap storage self,\n uint256[] memory amounts,\n uint256 maxBurnAmount\n ) public returns (uint256) {\n ManageLiquidityInfo memory v = ManageLiquidityInfo(\n 0,\n 0,\n 0,\n _getAPrecise(self),\n self.lpToken,\n 0,\n self.balances,\n self.tokenPrecisionMultipliers\n );\n v.totalSupply = v.lpToken.totalSupply();\n\n IERC20[] memory pooledTokens = self.pooledTokens;\n\n require(\n amounts.length == pooledTokens.length,\n \"Amounts should match pool tokens\"\n );\n\n require(\n maxBurnAmount <= v.lpToken.balanceOf(msg.sender) &&\n maxBurnAmount != 0,\n \">LP.balanceOf\"\n );\n\n uint256 feePerToken = _feePerToken(self.swapFee, pooledTokens.length);\n uint256[] memory fees = new uint256[](pooledTokens.length);\n {\n uint256[] memory balances1 = new uint256[](pooledTokens.length);\n v.d0 = getD(_xp(v.balances, v.multipliers), v.preciseA);\n for (uint256 i = 0; i < pooledTokens.length; i++) {\n balances1[i] = v.balances[i].sub(\n amounts[i],\n \"Cannot withdraw more than available\"\n );\n }\n v.d1 = getD(_xp(balances1, v.multipliers), v.preciseA);\n\n for (uint256 i = 0; i < pooledTokens.length; i++) {\n uint256 idealBalance = v.d1.mul(v.balances[i]).div(v.d0);\n uint256 difference = idealBalance.difference(balances1[i]);\n fees[i] = feePerToken.mul(difference).div(FEE_DENOMINATOR);\n self.balances[i] = balances1[i].sub(\n fees[i].mul(self.adminFee).div(FEE_DENOMINATOR)\n );\n balances1[i] = balances1[i].sub(fees[i]);\n }\n\n v.d2 = getD(_xp(balances1, v.multipliers), v.preciseA);\n }\n uint256 tokenAmount = v.d0.sub(v.d2).mul(v.totalSupply).div(v.d0);\n require(tokenAmount != 0, \"Burnt amount cannot be zero\");\n tokenAmount = tokenAmount.add(1);\n\n require(tokenAmount <= maxBurnAmount, \"tokenAmount > maxBurnAmount\");\n\n v.lpToken.burnFrom(msg.sender, tokenAmount);\n\n for (uint256 i = 0; i < pooledTokens.length; i++) {\n pooledTokens[i].safeTransfer(msg.sender, amounts[i]);\n }\n\n emit RemoveLiquidityImbalance(\n msg.sender,\n amounts,\n fees,\n v.d1,\n v.totalSupply.sub(tokenAmount)\n );\n\n return tokenAmount;\n }\n\n /**\n * @notice withdraw all admin fees to a given address\n * @param self Swap struct to withdraw fees from\n * @param to Address to send the fees to\n */\n function withdrawAdminFees(Swap storage self, address to) external {\n IERC20[] memory pooledTokens = self.pooledTokens;\n for (uint256 i = 0; i < pooledTokens.length; i++) {\n IERC20 token = pooledTokens[i];\n uint256 balance = token.balanceOf(address(this)).sub(\n self.balances[i]\n );\n if (balance != 0) {\n token.safeTransfer(to, balance);\n }\n }\n }\n\n /**\n * @notice Sets the admin fee\n * @dev adminFee cannot be higher than 100% of the swap fee\n * @param self Swap struct to update\n * @param newAdminFee new admin fee to be applied on future transactions\n */\n function setAdminFee(Swap storage self, uint256 newAdminFee) external {\n require(newAdminFee <= MAX_ADMIN_FEE, \"Fee is too high\");\n self.adminFee = newAdminFee;\n\n emit NewAdminFee(newAdminFee);\n }\n\n /**\n * @notice update the swap fee\n * @dev fee cannot be higher than 1% of each swap\n * @param self Swap struct to update\n * @param newSwapFee new swap fee to be applied on future transactions\n */\n function setSwapFee(Swap storage self, uint256 newSwapFee) external {\n require(newSwapFee <= MAX_SWAP_FEE, \"Fee is too high\");\n self.swapFee = newSwapFee;\n\n emit NewSwapFee(newSwapFee);\n }\n}\n" + }, + "contracts/amm/AmplificationUtils.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.6.12;\n\nimport \"@openzeppelin/contracts/token/ERC20/SafeERC20.sol\";\nimport \"./SwapUtils.sol\";\n\n/**\n * @title AmplificationUtils library\n * @notice A library to calculate and ramp the A parameter of a given `SwapUtils.Swap` struct.\n * This library assumes the struct is fully validated.\n */\nlibrary AmplificationUtils {\n using SafeMath for uint256;\n\n event RampA(\n uint256 oldA,\n uint256 newA,\n uint256 initialTime,\n uint256 futureTime\n );\n event StopRampA(uint256 currentA, uint256 time);\n\n // Constant values used in ramping A calculations\n uint256 public constant A_PRECISION = 100;\n uint256 public constant MAX_A = 10**6;\n uint256 private constant MAX_A_CHANGE = 2;\n uint256 private constant MIN_RAMP_TIME = 7 days;\n\n /**\n * @notice Return A, the amplification coefficient * n * (n - 1)\n * @dev See the StableSwap paper for details\n * @param self Swap struct to read from\n * @return A parameter\n */\n function getA(SwapUtils.Swap storage self) external view returns (uint256) {\n return _getAPrecise(self).div(A_PRECISION);\n }\n\n /**\n * @notice Return A in its raw precision\n * @dev See the StableSwap paper for details\n * @param self Swap struct to read from\n * @return A parameter in its raw precision form\n */\n function getAPrecise(SwapUtils.Swap storage self)\n external\n view\n returns (uint256)\n {\n return _getAPrecise(self);\n }\n\n /**\n * @notice Return A in its raw precision\n * @dev See the StableSwap paper for details\n * @param self Swap struct to read from\n * @return A parameter in its raw precision form\n */\n function _getAPrecise(SwapUtils.Swap storage self)\n internal\n view\n returns (uint256)\n {\n uint256 t1 = self.futureATime; // time when ramp is finished\n uint256 a1 = self.futureA; // final A value when ramp is finished\n\n if (block.timestamp < t1) {\n uint256 t0 = self.initialATime; // time when ramp is started\n uint256 a0 = self.initialA; // initial A value when ramp is started\n if (a1 > a0) {\n // a0 + (a1 - a0) * (block.timestamp - t0) / (t1 - t0)\n return\n a0.add(\n a1.sub(a0).mul(block.timestamp.sub(t0)).div(t1.sub(t0))\n );\n } else {\n // a0 - (a0 - a1) * (block.timestamp - t0) / (t1 - t0)\n return\n a0.sub(\n a0.sub(a1).mul(block.timestamp.sub(t0)).div(t1.sub(t0))\n );\n }\n } else {\n return a1;\n }\n }\n\n /**\n * @notice Start ramping up or down A parameter towards given futureA_ and futureTime_\n * Checks if the change is too rapid, and commits the new A value only when it falls under\n * the limit range.\n * @param self Swap struct to update\n * @param futureA_ the new A to ramp towards\n * @param futureTime_ timestamp when the new A should be reached\n */\n function rampA(\n SwapUtils.Swap storage self,\n uint256 futureA_,\n uint256 futureTime_\n ) external {\n require(\n block.timestamp >= self.initialATime.add(1 days),\n \"Wait 1 day before starting ramp\"\n );\n require(\n futureTime_ >= block.timestamp.add(MIN_RAMP_TIME),\n \"Insufficient ramp time\"\n );\n require(\n futureA_ > 0 && futureA_ < MAX_A,\n \"futureA_ must be > 0 and < MAX_A\"\n );\n\n uint256 initialAPrecise = _getAPrecise(self);\n uint256 futureAPrecise = futureA_.mul(A_PRECISION);\n\n if (futureAPrecise < initialAPrecise) {\n require(\n futureAPrecise.mul(MAX_A_CHANGE) >= initialAPrecise,\n \"futureA_ is too small\"\n );\n } else {\n require(\n futureAPrecise <= initialAPrecise.mul(MAX_A_CHANGE),\n \"futureA_ is too large\"\n );\n }\n\n self.initialA = initialAPrecise;\n self.futureA = futureAPrecise;\n self.initialATime = block.timestamp;\n self.futureATime = futureTime_;\n\n emit RampA(\n initialAPrecise,\n futureAPrecise,\n block.timestamp,\n futureTime_\n );\n }\n\n /**\n * @notice Stops ramping A immediately. Once this function is called, rampA()\n * cannot be called for another 24 hours\n * @param self Swap struct to update\n */\n function stopRampA(SwapUtils.Swap storage self) external {\n require(self.futureATime > block.timestamp, \"Ramp is already stopped\");\n\n uint256 currentA = _getAPrecise(self);\n self.initialA = currentA;\n self.futureA = currentA;\n self.initialATime = block.timestamp;\n self.futureATime = block.timestamp;\n\n emit StopRampA(currentA, block.timestamp);\n }\n}\n" + }, + "@openzeppelin/contracts/token/ERC20/IERC20.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <0.8.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" + }, + "@openzeppelin/contracts/utils/Address.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.2 <0.8.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" + }, + "@openzeppelin/contracts-upgradeable/proxy/Initializable.sol": { + "content": "// SPDX-License-Identifier: MIT\n\n// solhint-disable-next-line compiler-version\npragma solidity >=0.4.24 <0.8.0;\n\nimport \"../utils/AddressUpgradeable.sol\";\n\n/**\n * @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed\n * behind a proxy. Since a proxied contract can't have a constructor, it's common to move constructor logic to an\n * external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer\n * function so it can only be called once. The {initializer} modifier provided by this contract will have this effect.\n *\n * TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as\n * possible by providing the encoded function call as the `_data` argument to {UpgradeableProxy-constructor}.\n *\n * CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure\n * that all initializers are idempotent. This is not verified automatically as constructors are by Solidity.\n */\nabstract contract Initializable {\n\n /**\n * @dev Indicates that the contract has been initialized.\n */\n bool private _initialized;\n\n /**\n * @dev Indicates that the contract is in the process of being initialized.\n */\n bool private _initializing;\n\n /**\n * @dev Modifier to protect an initializer function from being invoked twice.\n */\n modifier initializer() {\n require(_initializing || _isConstructor() || !_initialized, \"Initializable: contract is already initialized\");\n\n bool isTopLevelCall = !_initializing;\n if (isTopLevelCall) {\n _initializing = true;\n _initialized = true;\n }\n\n _;\n\n if (isTopLevelCall) {\n _initializing = false;\n }\n }\n\n /// @dev Returns true if and only if the function is running in the constructor\n function _isConstructor() private view returns (bool) {\n return !AddressUpgradeable.isContract(address(this));\n }\n}\n" + }, + "@openzeppelin/contracts-upgradeable/utils/AddressUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.2 <0.8.0;\n\n/**\n * @dev Collection of functions related to the address type\n */\nlibrary AddressUpgradeable {\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 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" + }, + "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <0.8.0;\n\nimport \"../utils/ContextUpgradeable.sol\";\nimport \"../proxy/Initializable.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 OwnableUpgradeable is Initializable, ContextUpgradeable {\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 function __Ownable_init() internal initializer {\n __Context_init_unchained();\n __Ownable_init_unchained();\n }\n\n function __Ownable_init_unchained() internal initializer {\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 uint256[49] private __gap;\n}\n" + }, + "@openzeppelin/contracts-upgradeable/utils/PausableUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <0.8.0;\n\nimport \"./ContextUpgradeable.sol\";\nimport \"../proxy/Initializable.sol\";\n\n/**\n * @dev Contract module which allows children to implement an emergency stop\n * mechanism that can be triggered by an authorized account.\n *\n * This module is used through inheritance. It will make available the\n * modifiers `whenNotPaused` and `whenPaused`, which can be applied to\n * the functions of your contract. Note that they will not be pausable by\n * simply including this module, only once the modifiers are put in place.\n */\nabstract contract PausableUpgradeable is Initializable, ContextUpgradeable {\n /**\n * @dev Emitted when the pause is triggered by `account`.\n */\n event Paused(address account);\n\n /**\n * @dev Emitted when the pause is lifted by `account`.\n */\n event Unpaused(address account);\n\n bool private _paused;\n\n /**\n * @dev Initializes the contract in unpaused state.\n */\n function __Pausable_init() internal initializer {\n __Context_init_unchained();\n __Pausable_init_unchained();\n }\n\n function __Pausable_init_unchained() internal initializer {\n _paused = false;\n }\n\n /**\n * @dev Returns true if the contract is paused, and false otherwise.\n */\n function paused() public view virtual returns (bool) {\n return _paused;\n }\n\n /**\n * @dev Modifier to make a function callable only when the contract is not paused.\n *\n * Requirements:\n *\n * - The contract must not be paused.\n */\n modifier whenNotPaused() {\n require(!paused(), \"Pausable: paused\");\n _;\n }\n\n /**\n * @dev Modifier to make a function callable only when the contract is paused.\n *\n * Requirements:\n *\n * - The contract must be paused.\n */\n modifier whenPaused() {\n require(paused(), \"Pausable: not paused\");\n _;\n }\n\n /**\n * @dev Triggers stopped state.\n *\n * Requirements:\n *\n * - The contract must not be paused.\n */\n function _pause() internal virtual whenNotPaused {\n _paused = true;\n emit Paused(_msgSender());\n }\n\n /**\n * @dev Returns to normal state.\n *\n * Requirements:\n *\n * - The contract must be paused.\n */\n function _unpause() internal virtual whenPaused {\n _paused = false;\n emit Unpaused(_msgSender());\n }\n uint256[49] private __gap;\n}\n" + }, + "@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <0.8.0;\nimport \"../proxy/Initializable.sol\";\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 ContextUpgradeable is Initializable {\n function __Context_init() internal initializer {\n __Context_init_unchained();\n }\n\n function __Context_init_unchained() internal initializer {\n }\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 uint256[50] private __gap;\n}\n" + }, + "contracts/amm/LPToken.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.6.12;\n\nimport \"@openzeppelin/contracts-upgradeable/token/ERC20/ERC20BurnableUpgradeable.sol\";\nimport \"@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol\";\nimport \"./interfaces/ISwap.sol\";\n\n/**\n * @title Liquidity Provider Token\n * @notice This token is an ERC20 detailed token with added capability to be minted by the owner.\n * It is used to represent user's shares when providing liquidity to swap contracts.\n * @dev Only Swap contracts should initialize and own LPToken contracts.\n */\ncontract LPToken is ERC20BurnableUpgradeable, OwnableUpgradeable {\n using SafeMathUpgradeable for uint256;\n\n /**\n * @notice Initializes this LPToken contract with the given name and symbol\n * @dev The caller of this function will become the owner. A Swap contract should call this\n * in its initializer function.\n * @param name name of this token\n * @param symbol symbol of this token\n */\n function initialize(string memory name, string memory symbol)\n external\n initializer\n returns (bool)\n {\n __Context_init_unchained();\n __ERC20_init_unchained(name, symbol);\n __Ownable_init_unchained();\n return true;\n }\n\n /**\n * @notice Mints the given amount of LPToken to the recipient.\n * @dev only owner can call this mint function\n * @param recipient address of account to receive the tokens\n * @param amount amount of tokens to mint\n */\n function mint(address recipient, uint256 amount) external onlyOwner {\n require(amount != 0, \"LPToken: cannot mint 0\");\n _mint(recipient, amount);\n }\n\n /**\n * @dev Overrides ERC20._beforeTokenTransfer() which get called on every transfers including\n * minting and burning. * This assumes the owner is set to a Swap contract's address.\n */\n function _beforeTokenTransfer(\n address from,\n address to,\n uint256 amount\n ) internal virtual override(ERC20Upgradeable) {\n super._beforeTokenTransfer(from, to, amount);\n require(to != address(this), \"LPToken: cannot send to itself\");\n }\n}\n" + }, + "contracts/amm/MathUtils.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.6.12;\n\nimport \"@openzeppelin/contracts/math/SafeMath.sol\";\n\n/**\n * @title MathUtils library\n * @notice A library to be used in conjunction with SafeMath. Contains functions for calculating\n * differences between two uint256.\n */\nlibrary MathUtils {\n /**\n * @notice Compares a and b and returns true if the difference between a and b\n * is less than 1 or equal to each other.\n * @param a uint256 to compare with\n * @param b uint256 to compare with\n * @return True if the difference between a and b is less than 1 or equal,\n * otherwise return false\n */\n function within1(uint256 a, uint256 b) internal pure returns (bool) {\n return (difference(a, b) <= 1);\n }\n\n /**\n * @notice Calculates absolute difference between a and b\n * @param a uint256 to compare with\n * @param b uint256 to compare with\n * @return Difference between a and b\n */\n function difference(uint256 a, uint256 b) internal pure returns (uint256) {\n if (a > b) {\n return a - b;\n }\n return b - a;\n }\n}\n" + }, + "@openzeppelin/contracts-upgradeable/token/ERC20/ERC20BurnableUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <0.8.0;\n\nimport \"../../utils/ContextUpgradeable.sol\";\nimport \"./ERC20Upgradeable.sol\";\nimport \"../../proxy/Initializable.sol\";\n\n/**\n * @dev Extension of {ERC20} that allows token holders to destroy both their own\n * tokens and those that they have an allowance for, in a way that can be\n * recognized off-chain (via event analysis).\n */\nabstract contract ERC20BurnableUpgradeable is Initializable, ContextUpgradeable, ERC20Upgradeable {\n function __ERC20Burnable_init() internal initializer {\n __Context_init_unchained();\n __ERC20Burnable_init_unchained();\n }\n\n function __ERC20Burnable_init_unchained() internal initializer {\n }\n using SafeMathUpgradeable for uint256;\n\n /**\n * @dev Destroys `amount` tokens from the caller.\n *\n * See {ERC20-_burn}.\n */\n function burn(uint256 amount) public virtual {\n _burn(_msgSender(), amount);\n }\n\n /**\n * @dev Destroys `amount` tokens from `account`, deducting from the caller's\n * allowance.\n *\n * See {ERC20-_burn} and {ERC20-allowance}.\n *\n * Requirements:\n *\n * - the caller must have allowance for ``accounts``'s tokens of at least\n * `amount`.\n */\n function burnFrom(address account, uint256 amount) public virtual {\n uint256 decreasedAllowance = allowance(account, _msgSender()).sub(amount, \"ERC20: burn amount exceeds allowance\");\n\n _approve(account, _msgSender(), decreasedAllowance);\n _burn(account, amount);\n }\n uint256[50] private __gap;\n}\n" + }, + "contracts/amm/interfaces/ISwap.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.6.12;\n\nimport \"@openzeppelin/contracts/token/ERC20/ERC20.sol\";\n\ninterface ISwap {\n // pool data view functions\n function getA() external view returns (uint256);\n\n function getToken(uint8 index) external view returns (IERC20);\n\n function getTokenIndex(address tokenAddress) external view returns (uint8);\n\n function getTokenBalance(uint8 index) external view returns (uint256);\n\n function getVirtualPrice() external view returns (uint256);\n\n // min return calculation functions\n function calculateSwap(\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx\n ) external view returns (uint256);\n\n function calculateTokenAmount(uint256[] calldata amounts, bool deposit)\n external\n view\n returns (uint256);\n\n function calculateRemoveLiquidity(uint256 amount)\n external\n view\n returns (uint256[] memory);\n\n function calculateRemoveLiquidityOneToken(\n uint256 tokenAmount,\n uint8 tokenIndex\n ) external view returns (uint256 availableTokenAmount);\n\n // state modifying functions\n function initialize(\n IERC20[] memory pooledTokens,\n uint8[] memory decimals,\n string memory lpTokenName,\n string memory lpTokenSymbol,\n uint256 a,\n uint256 fee,\n uint256 adminFee,\n address lpTokenTargetAddress\n ) external;\n\n function swap(\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx,\n uint256 minDy,\n uint256 deadline\n ) external returns (uint256);\n\n function addLiquidity(\n uint256[] calldata amounts,\n uint256 minToMint,\n uint256 deadline\n ) external returns (uint256);\n\n function removeLiquidity(\n uint256 amount,\n uint256[] calldata minAmounts,\n uint256 deadline\n ) external returns (uint256[] memory);\n\n function removeLiquidityOneToken(\n uint256 tokenAmount,\n uint8 tokenIndex,\n uint256 minAmount,\n uint256 deadline\n ) external returns (uint256);\n\n function removeLiquidityImbalance(\n uint256[] calldata amounts,\n uint256 maxBurnAmount,\n uint256 deadline\n ) external returns (uint256);\n}\n" + }, + "@openzeppelin/contracts-upgradeable/token/ERC20/ERC20Upgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <0.8.0;\n\nimport \"../../utils/ContextUpgradeable.sol\";\nimport \"./IERC20Upgradeable.sol\";\nimport \"../../math/SafeMathUpgradeable.sol\";\nimport \"../../proxy/Initializable.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 ERC20Upgradeable is Initializable, ContextUpgradeable, IERC20Upgradeable {\n using SafeMathUpgradeable 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 function __ERC20_init(string memory name_, string memory symbol_) internal initializer {\n __Context_init_unchained();\n __ERC20_init_unchained(name_, symbol_);\n }\n\n function __ERC20_init_unchained(string memory name_, string memory symbol_) internal initializer {\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 uint256[44] private __gap;\n}\n" + }, + "@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <0.8.0;\n\n/**\n * @dev Interface of the ERC20 standard as defined in the EIP.\n */\ninterface IERC20Upgradeable {\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" + }, + "@openzeppelin/contracts-upgradeable/math/SafeMathUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <0.8.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 SafeMathUpgradeable {\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" + }, + "@openzeppelin/contracts/token/ERC20/ERC20.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <0.8.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_) public {\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" + }, + "@openzeppelin/contracts/utils/Context.sol": { + "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" + }, + "contracts/amm/SwapFlashLoan.sol": { + "content": "// SPDX-License-Identifier: MIT WITH AGPL-3.0-only\n\npragma solidity 0.6.12;\n\nimport \"./Swap.sol\";\nimport \"./interfaces/IFlashLoanReceiver.sol\";\n\n/**\n * @title Swap - A StableSwap implementation in solidity.\n * @notice This contract is responsible for custody of closely pegged assets (eg. group of stablecoins)\n * and automatic market making system. Users become an LP (Liquidity Provider) by depositing their tokens\n * in desired ratios for an exchange of the pool token that represents their share of the pool.\n * Users can burn pool tokens and withdraw their share of token(s).\n *\n * Each time a swap between the pooled tokens happens, a set fee incurs which effectively gets\n * distributed to the LPs.\n *\n * In case of emergencies, admin can pause additional deposits, swaps, or single-asset withdraws - which\n * stops the ratio of the tokens in the pool from changing.\n * Users can always withdraw their tokens via multi-asset withdraws.\n *\n * @dev Most of the logic is stored as a library `SwapUtils` for the sake of reducing contract's\n * deployment size.\n */\ncontract SwapFlashLoan is Swap {\n // Total fee that is charged on all flashloans in BPS. Borrowers must repay the amount plus the flash loan fee.\n // This fee is split between the protocol and the pool.\n uint256 public flashLoanFeeBPS;\n // Share of the flash loan fee that goes to the protocol in BPS. A portion of each flash loan fee is allocated\n // to the protocol rather than the pool.\n uint256 public protocolFeeShareBPS;\n // Max BPS for limiting flash loan fee settings.\n uint256 public constant MAX_BPS = 10000;\n\n /*** EVENTS ***/\n event FlashLoan(\n address indexed receiver,\n uint8 tokenIndex,\n uint256 amount,\n uint256 amountFee,\n uint256 protocolFee\n );\n\n /**\n * @notice Initializes this Swap contract with the given parameters.\n * This will also clone a LPToken contract that represents users'\n * LP positions. The owner of LPToken will be this contract - which means\n * only this contract is allowed to mint/burn tokens.\n *\n * @param _pooledTokens an array of ERC20s this pool will accept\n * @param decimals the decimals to use for each pooled token,\n * eg 8 for WBTC. Cannot be larger than POOL_PRECISION_DECIMALS\n * @param lpTokenName the long-form name of the token to be deployed\n * @param lpTokenSymbol the short symbol for the token to be deployed\n * @param _a the amplification coefficient * n * (n - 1). See the\n * StableSwap paper for details\n * @param _fee default swap fee to be initialized with\n * @param _adminFee default adminFee to be initialized with\n * @param lpTokenTargetAddress the address of an existing LPToken contract to use as a target\n */\n function initialize(\n IERC20[] memory _pooledTokens,\n uint8[] memory decimals,\n string memory lpTokenName,\n string memory lpTokenSymbol,\n uint256 _a,\n uint256 _fee,\n uint256 _adminFee,\n address lpTokenTargetAddress\n ) public virtual override initializer {\n Swap.initialize(\n _pooledTokens,\n decimals,\n lpTokenName,\n lpTokenSymbol,\n _a,\n _fee,\n _adminFee,\n lpTokenTargetAddress\n );\n flashLoanFeeBPS = 8; // 8 bps\n protocolFeeShareBPS = 0; // 0 bps\n }\n\n /*** STATE MODIFYING FUNCTIONS ***/\n\n /**\n * @notice Borrow the specified token from this pool for this transaction only. This function will call\n * `IFlashLoanReceiver(receiver).executeOperation` and the `receiver` must return the full amount of the token\n * and the associated fee by the end of the callback transaction. If the conditions are not met, this call\n * is reverted.\n * @param receiver the address of the receiver of the token. This address must implement the IFlashLoanReceiver\n * interface and the callback function `executeOperation`.\n * @param token the protocol fee in bps to be applied on the total flash loan fee\n * @param amount the total amount to borrow in this transaction\n * @param params optional data to pass along to the callback function\n */\n function flashLoan(\n address receiver,\n IERC20 token,\n uint256 amount,\n bytes memory params\n ) external nonReentrant {\n uint8 tokenIndex = getTokenIndex(address(token));\n uint256 availableLiquidityBefore = token.balanceOf(address(this));\n uint256 protocolBalanceBefore = availableLiquidityBefore.sub(\n swapStorage.balances[tokenIndex]\n );\n require(\n amount > 0 && availableLiquidityBefore >= amount,\n \"invalid amount\"\n );\n\n // Calculate the additional amount of tokens the pool should end up with\n uint256 amountFee = amount.mul(flashLoanFeeBPS).div(10000);\n // Calculate the portion of the fee that will go to the protocol\n uint256 protocolFee = amountFee.mul(protocolFeeShareBPS).div(10000);\n require(amountFee > 0, \"amount is small for a flashLoan\");\n\n // Transfer the requested amount of tokens\n token.safeTransfer(receiver, amount);\n\n // Execute callback function on receiver\n IFlashLoanReceiver(receiver).executeOperation(\n address(this),\n address(token),\n amount,\n amountFee,\n params\n );\n\n uint256 availableLiquidityAfter = token.balanceOf(address(this));\n require(\n availableLiquidityAfter >= availableLiquidityBefore.add(amountFee),\n \"flashLoan fee is not met\"\n );\n\n swapStorage.balances[tokenIndex] = availableLiquidityAfter\n .sub(protocolBalanceBefore)\n .sub(protocolFee);\n emit FlashLoan(receiver, tokenIndex, amount, amountFee, protocolFee);\n }\n\n /*** ADMIN FUNCTIONS ***/\n\n /**\n * @notice Updates the flash loan fee parameters. This function can only be called by the owner.\n * @param newFlashLoanFeeBPS the total fee in bps to be applied on future flash loans\n * @param newProtocolFeeShareBPS the protocol fee in bps to be applied on the total flash loan fee\n */\n function setFlashLoanFees(\n uint256 newFlashLoanFeeBPS,\n uint256 newProtocolFeeShareBPS\n ) external onlyOwner {\n require(\n newFlashLoanFeeBPS > 0 &&\n newFlashLoanFeeBPS <= MAX_BPS &&\n newProtocolFeeShareBPS <= MAX_BPS,\n \"fees are not in valid range\"\n );\n flashLoanFeeBPS = newFlashLoanFeeBPS;\n protocolFeeShareBPS = newProtocolFeeShareBPS;\n }\n}\n" + }, + "contracts/amm/interfaces/IFlashLoanReceiver.sol": { + "content": "// SPDX-License-Identifier: AGPL-3.0-only\n\npragma solidity 0.6.12;\n\n/**\n * @title IFlashLoanReceiver interface\n * @notice Interface for the Nerve fee IFlashLoanReceiver. Modified from Aave's IFlashLoanReceiver interface.\n * https://github.com/aave/aave-protocol/blob/4b4545fb583fd4f400507b10f3c3114f45b8a037/contracts/flashloan/interfaces/IFlashLoanReceiver.sol\n * @author Aave\n * @dev implement this interface to develop a flashloan-compatible flashLoanReceiver contract\n **/\ninterface IFlashLoanReceiver {\n function executeOperation(\n address pool,\n address token,\n uint256 amount,\n uint256 fee,\n bytes calldata params\n ) external;\n}\n" + }, + "contracts/amm/helper/FlashLoanBorrowerExample.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.6.12;\n\nimport \"@openzeppelin/contracts/math/SafeMath.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/SafeERC20.sol\";\nimport \"../interfaces/IFlashLoanReceiver.sol\";\nimport \"../interfaces/ISwapFlashLoan.sol\";\nimport \"hardhat/console.sol\";\n\ncontract FlashLoanBorrowerExample is IFlashLoanReceiver {\n using SafeMath for uint256;\n\n // Typical executeOperation function should do the 3 following actions\n // 1. Check if the flashLoan was successful\n // 2. Do actions with the borrowed tokens\n // 3. Repay the debt to the `pool`\n function executeOperation(\n address pool,\n address token,\n uint256 amount,\n uint256 fee,\n bytes calldata params\n ) external override {\n // 1. Check if the flashLoan was valid\n require(\n IERC20(token).balanceOf(address(this)) >= amount,\n \"flashloan is broken?\"\n );\n\n // 2. Do actions with the borrowed token\n bytes32 paramsHash = keccak256(params);\n if (paramsHash == keccak256(bytes(\"dontRepayDebt\"))) {\n return;\n } else if (paramsHash == keccak256(bytes(\"reentrancy_addLiquidity\"))) {\n ISwapFlashLoan(pool).addLiquidity(\n new uint256[](0),\n 0,\n block.timestamp\n );\n } else if (paramsHash == keccak256(bytes(\"reentrancy_swap\"))) {\n ISwapFlashLoan(pool).swap(1, 0, 1e6, 0, now);\n } else if (\n paramsHash == keccak256(bytes(\"reentrancy_removeLiquidity\"))\n ) {\n ISwapFlashLoan(pool).removeLiquidity(1e18, new uint256[](0), now);\n } else if (\n paramsHash == keccak256(bytes(\"reentrancy_removeLiquidityOneToken\"))\n ) {\n ISwapFlashLoan(pool).removeLiquidityOneToken(1e18, 0, 1e18, now);\n }\n\n // 3. Payback debt\n uint256 totalDebt = amount.add(fee);\n IERC20(token).transfer(pool, totalDebt);\n }\n\n function flashLoan(\n ISwapFlashLoan swap,\n IERC20 token,\n uint256 amount,\n bytes memory params\n ) external {\n swap.flashLoan(address(this), token, amount, params);\n }\n}\n" + }, + "contracts/amm/interfaces/ISwapFlashLoan.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.6.12;\n\nimport \"./ISwap.sol\";\n\ninterface ISwapFlashLoan is ISwap {\n function flashLoan(\n address receiver,\n IERC20 token,\n uint256 amount,\n bytes memory params\n ) external;\n}\n" + }, + "hardhat/console.sol": { + "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" + }, + "contracts/amm/helper/test/TestSwapReturnValues.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.6.12;\n\nimport \"../../interfaces/ISwap.sol\";\nimport \"hardhat/console.sol\";\n\ncontract TestSwapReturnValues {\n using SafeMath for uint256;\n\n ISwap public swap;\n IERC20 public lpToken;\n uint8 public n;\n\n uint256 public constant MAX_INT = 2**256 - 1;\n\n constructor(\n ISwap swapContract,\n IERC20 lpTokenContract,\n uint8 numOfTokens\n ) public {\n swap = swapContract;\n lpToken = lpTokenContract;\n n = numOfTokens;\n\n // Pre-approve tokens\n for (uint8 i; i < n; i++) {\n swap.getToken(i).approve(address(swap), MAX_INT);\n }\n lpToken.approve(address(swap), MAX_INT);\n }\n\n function test_swap(\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx,\n uint256 minDy\n ) public {\n uint256 balanceBefore =\n swap.getToken(tokenIndexTo).balanceOf(address(this));\n uint256 returnValue =\n swap.swap(tokenIndexFrom, tokenIndexTo, dx, minDy, block.timestamp);\n uint256 balanceAfter =\n swap.getToken(tokenIndexTo).balanceOf(address(this));\n\n console.log(\n \"swap: Expected %s, got %s\",\n balanceAfter.sub(balanceBefore),\n returnValue\n );\n\n require(\n returnValue == balanceAfter.sub(balanceBefore),\n \"swap()'s return value does not match received amount\"\n );\n }\n\n function test_addLiquidity(uint256[] calldata amounts, uint256 minToMint)\n public\n {\n uint256 balanceBefore = lpToken.balanceOf(address(this));\n uint256 returnValue = swap.addLiquidity(amounts, minToMint, MAX_INT);\n uint256 balanceAfter = lpToken.balanceOf(address(this));\n\n console.log(\n \"addLiquidity: Expected %s, got %s\",\n balanceAfter.sub(balanceBefore),\n returnValue\n );\n\n require(\n returnValue == balanceAfter.sub(balanceBefore),\n \"addLiquidity()'s return value does not match minted amount\"\n );\n }\n\n function test_removeLiquidity(uint256 amount, uint256[] memory minAmounts)\n public\n {\n uint256[] memory balanceBefore = new uint256[](n);\n uint256[] memory balanceAfter = new uint256[](n);\n\n for (uint8 i = 0; i < n; i++) {\n balanceBefore[i] = swap.getToken(i).balanceOf(address(this));\n }\n\n uint256[] memory returnValue =\n swap.removeLiquidity(amount, minAmounts, MAX_INT);\n\n for (uint8 i = 0; i < n; i++) {\n balanceAfter[i] = swap.getToken(i).balanceOf(address(this));\n console.log(\n \"removeLiquidity: Expected %s, got %s\",\n balanceAfter[i].sub(balanceBefore[i]),\n returnValue[i]\n );\n require(\n balanceAfter[i].sub(balanceBefore[i]) == returnValue[i],\n \"removeLiquidity()'s return value does not match received amounts of tokens\"\n );\n }\n }\n\n function test_removeLiquidityImbalance(\n uint256[] calldata amounts,\n uint256 maxBurnAmount\n ) public {\n uint256 balanceBefore = lpToken.balanceOf(address(this));\n uint256 returnValue =\n swap.removeLiquidityImbalance(amounts, maxBurnAmount, MAX_INT);\n uint256 balanceAfter = lpToken.balanceOf(address(this));\n\n console.log(\n \"removeLiquidityImbalance: Expected %s, got %s\",\n balanceBefore.sub(balanceAfter),\n returnValue\n );\n\n require(\n returnValue == balanceBefore.sub(balanceAfter),\n \"removeLiquidityImbalance()'s return value does not match burned lpToken amount\"\n );\n }\n\n function test_removeLiquidityOneToken(\n uint256 tokenAmount,\n uint8 tokenIndex,\n uint256 minAmount\n ) public {\n uint256 balanceBefore =\n swap.getToken(tokenIndex).balanceOf(address(this));\n uint256 returnValue =\n swap.removeLiquidityOneToken(\n tokenAmount,\n tokenIndex,\n minAmount,\n MAX_INT\n );\n uint256 balanceAfter =\n swap.getToken(tokenIndex).balanceOf(address(this));\n\n console.log(\n \"removeLiquidityOneToken: Expected %s, got %s\",\n balanceAfter.sub(balanceBefore),\n returnValue\n );\n\n require(\n returnValue == balanceAfter.sub(balanceBefore),\n \"removeLiquidityOneToken()'s return value does not match received token amount\"\n );\n }\n}\n" + }, + "contracts/amm/SwapDeployer.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.6.12;\n\nimport \"@openzeppelin/contracts/access/Ownable.sol\";\nimport \"@openzeppelin/contracts/proxy/Clones.sol\";\nimport \"./interfaces/ISwap.sol\";\n\ncontract SwapDeployer is Ownable {\n event NewSwapPool(\n address indexed deployer,\n address swapAddress,\n IERC20[] pooledTokens\n );\n\n constructor() public Ownable() {}\n\n function deploy(\n address swapAddress,\n IERC20[] memory _pooledTokens,\n uint8[] memory decimals,\n string memory lpTokenName,\n string memory lpTokenSymbol,\n uint256 _a,\n uint256 _fee,\n uint256 _adminFee,\n address lpTokenTargetAddress\n ) external returns (address) {\n address swapClone = Clones.clone(swapAddress);\n ISwap(swapClone).initialize(\n _pooledTokens,\n decimals,\n lpTokenName,\n lpTokenSymbol,\n _a,\n _fee,\n _adminFee,\n lpTokenTargetAddress\n );\n Ownable(swapClone).transferOwnership(owner());\n emit NewSwapPool(msg.sender, swapClone, _pooledTokens);\n return swapClone;\n }\n}\n" + }, + "@openzeppelin/contracts/access/Ownable.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <0.8.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 () internal {\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" + }, + "contracts/bridge/SynapseERC20Factory.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.6.12;\n\nimport \"@openzeppelin/contracts/access/Ownable.sol\";\nimport \"@openzeppelin/contracts/proxy/Clones.sol\";\nimport \"./interfaces/ISynapseERC20.sol\";\n\ncontract SynapseERC20Factory {\n constructor() public {}\n\n event SynapseERC20Created(address contractAddress);\n\n /**\n * @notice Deploys a new node\n * @param synapseERC20Address address of the synapseERC20Address contract to initialize with\n * @param name Token name\n * @param symbol Token symbol\n * @param decimals Token name\n * @param owner admin address to be initialized with\n * @return Address of the newest node management contract created\n **/\n function deploy(\n address synapseERC20Address,\n string memory name,\n string memory symbol,\n uint8 decimals,\n address owner\n ) external returns (address) {\n address synERC20Clone = Clones.clone(synapseERC20Address);\n ISynapseERC20(synERC20Clone).initialize(name, symbol, decimals, owner);\n\n emit SynapseERC20Created(synERC20Clone);\n\n return synERC20Clone;\n }\n}\n" + }, + "contracts/bridge/interfaces/ISynapseERC20.sol": { + "content": "// SPDX-License-Identifier: MIT\n\n\npragma solidity 0.6.12;\n\ninterface ISynapseERC20 { \n function initialize(\n string memory _name, string memory _symbol, uint8 _decimals, address owner) external;\n\n function mint(address to, uint256 amount) external;\n}\n\n" + }, + "contracts/bridge/wrappers/AvaxJewelMigration.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.6.12;\n\nimport '@openzeppelin/contracts/token/ERC20/ERC20.sol';\nimport \"@openzeppelin/contracts/token/ERC20/SafeERC20.sol\";\nimport \"@openzeppelin/contracts/access/Ownable.sol\";\n\nimport '../interfaces/ISynapseBridge.sol';\n\ninterface IERC20Mintable is IERC20 {\n function mint(address to, uint256 amount) external;\n}\n\ncontract AvaxJewelMigration is Ownable {\n using SafeERC20 for IERC20;\n using SafeERC20 for IERC20Mintable;\n\n\n ISynapseBridge constant synapseBridge = ISynapseBridge(0xC05e61d0E7a63D27546389B7aD62FdFf5A91aACE);\n // MULTICHAIN JEWEL \n IERC20 constant legacyToken = IERC20(0x4f60a160D8C2DDdaAfe16FCC57566dB84D674BD6);\n // SYNAPSE JEWEL\n IERC20 constant newToken = IERC20(0x997Ddaa07d716995DE90577C123Db411584E5E46);\n uint256 constant MAX_UINT256 = 2**256 - 1;\n\n constructor() public {\n newToken.safeApprove(address(synapseBridge), MAX_UINT256);\n }\n\n function migrate(uint256 amount) public {\n legacyToken.safeTransferFrom(msg.sender, address(this), amount);\n IERC20Mintable(address(newToken)).mint(msg.sender, amount);\n }\n\n function migrateAndBridge(uint256 amount, address to, uint256 chainId) external {\n migrate(amount);\n synapseBridge.redeem(to, chainId, newToken, amount);\n }\n\n function redeemLegacy() external onlyOwner {\n uint256 legacyBalance = legacyToken.balanceOf(address(this));\n legacyToken.safeTransfer(owner(), legacyBalance);\n }\n} " + }, + "contracts/bridge/interfaces/ISynapseBridge.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.6.12;\n\nimport '@openzeppelin/contracts/token/ERC20/SafeERC20.sol';\nimport '@openzeppelin/contracts/token/ERC20/ERC20Burnable.sol';\n\ninterface ISynapseBridge {\n using SafeERC20 for IERC20;\n\n function deposit(\n address to,\n uint256 chainId,\n IERC20 token,\n uint256 amount\n ) external;\n\n function depositAndSwap(\n address to,\n uint256 chainId,\n IERC20 token,\n uint256 amount,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 minDy,\n uint256 deadline\n ) external;\n\n function redeem(\n address to,\n uint256 chainId,\n IERC20 token,\n uint256 amount\n ) external;\n\n\n function redeemv2(\n bytes32 to,\n uint256 chainId,\n IERC20 token,\n uint256 amount\n ) external;\n\n\n function redeemAndSwap(\n address to,\n uint256 chainId,\n IERC20 token,\n uint256 amount,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 minDy,\n uint256 deadline\n ) external;\n\n function redeemAndRemove(\n address to,\n uint256 chainId,\n IERC20 token,\n uint256 amount,\n uint8 liqTokenIndex,\n uint256 liqMinAmount,\n uint256 liqDeadline\n ) external;\n}\n" + }, + "@openzeppelin/contracts/token/ERC20/ERC20Burnable.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <0.8.0;\n\nimport \"../../utils/Context.sol\";\nimport \"./ERC20.sol\";\n\n/**\n * @dev Extension of {ERC20} that allows token holders to destroy both their own\n * tokens and those that they have an allowance for, in a way that can be\n * recognized off-chain (via event analysis).\n */\nabstract contract ERC20Burnable is Context, ERC20 {\n using SafeMath for uint256;\n\n /**\n * @dev Destroys `amount` tokens from the caller.\n *\n * See {ERC20-_burn}.\n */\n function burn(uint256 amount) public virtual {\n _burn(_msgSender(), amount);\n }\n\n /**\n * @dev Destroys `amount` tokens from `account`, deducting from the caller's\n * allowance.\n *\n * See {ERC20-_burn} and {ERC20-allowance}.\n *\n * Requirements:\n *\n * - the caller must have allowance for ``accounts``'s tokens of at least\n * `amount`.\n */\n function burnFrom(address account, uint256 amount) public virtual {\n uint256 decreasedAllowance = allowance(account, _msgSender()).sub(amount, \"ERC20: burn amount exceeds allowance\");\n\n _approve(account, _msgSender(), decreasedAllowance);\n _burn(account, amount);\n }\n}\n" + }, + "contracts/bridge/wrappers/MoonriverBridgeZap.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.6.12;\n\nimport \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/SafeERC20.sol\";\nimport \"../interfaces/ISwap.sol\";\nimport \"../interfaces/ISynapseBridge.sol\";\nimport \"../interfaces/IWETH9.sol\";\n\ninterface IFrax {\n function exchangeCanonicalForOld(address bridge_token_address, uint256 token_amount) external returns (uint256);\n}\n\ncontract MoonriverBridgeZap {\n using SafeERC20 for IERC20;\n\n ISynapseBridge synapseBridge;\n address payable public immutable WETH_ADDRESS;\n IFrax private constant CANOLICAL_FRAX = IFrax(0x1A93B23281CC1CDE4C4741353F3064709A16197d);\n IERC20 private constant SYN_FRAX = IERC20(0xE96AC70907ffF3Efee79f502C985A7A21Bce407d);\n\n mapping(address => address) public swapMap;\n mapping(address => IERC20[]) public swapTokensMap;\n\n uint256 constant MAX_UINT256 = 2**256 - 1;\n\n constructor(\n address payable _wethAddress,\n address _swapOne,\n address tokenOne,\n address _swapTwo,\n address tokenTwo,\n ISynapseBridge _synapseBridge\n ) public {\n WETH_ADDRESS = _wethAddress;\n synapseBridge = _synapseBridge;\n swapMap[tokenOne] = _swapOne;\n swapMap[tokenTwo] = _swapTwo;\n IERC20(_wethAddress).safeIncreaseAllowance(address(_synapseBridge), MAX_UINT256);\n if (address(_swapOne) != address(0)) {\n {\n uint8 i;\n for (; i < 32; i++) {\n try ISwap(_swapOne).getToken(i) returns (\n IERC20 token\n ) {\n swapTokensMap[_swapOne].push(token);\n token.safeApprove(address(_swapOne), MAX_UINT256);\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n } catch {\n break;\n }\n }\n require(i > 1, \"swap must have at least 2 tokens\");\n }\n }\n if (address(_swapTwo) != address(0)) {\n {\n uint8 i;\n for (; i < 32; i++) {\n try ISwap(_swapTwo).getToken(i) returns (\n IERC20 token\n ) {\n swapTokensMap[_swapTwo].push(token);\n token.safeApprove(address(_swapTwo), MAX_UINT256);\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n } catch {\n break;\n }\n }\n require(i > 1, \"swap must have at least 2 tokens\");\n }\n }\n }\n\n /**\n * @notice Calculate amount of tokens you receive on swap\n * @param tokenIndexFrom the token the user wants to sell\n * @param tokenIndexTo the token the user wants to buy\n * @param dx the amount of tokens the user wants to sell. If the token charges\n * a fee on transfers, use the amount that gets transferred after the fee.\n * @return amount of tokens the user will receive\n */\n function calculateSwap(\n IERC20 token,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx\n ) external view virtual returns (uint256) {\n ISwap swap = ISwap(\n swapMap[address(token)]\n );\n return swap.calculateSwap(tokenIndexFrom, tokenIndexTo, dx);\n }\n\n function swapAndRedeem(\n address to,\n uint256 chainId,\n IERC20 token,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx,\n uint256 minDy,\n uint256 deadline\n ) external {\n ISwap swap = ISwap(swapMap[address(token)]);\n require(address(swap) != address(0), \"Swap is 0x00\");\n IERC20[] memory tokens = swapTokensMap[address(swap)];\n tokens[tokenIndexFrom].safeTransferFrom(\n msg.sender,\n address(this),\n dx\n );\n // swap\n\n uint256 swappedAmount = swap.swap(\n tokenIndexFrom,\n tokenIndexTo,\n dx,\n minDy,\n deadline\n );\n // deposit into bridge, gets nUSD\n if (\n token.allowance(address(this), address(synapseBridge)) <\n swappedAmount\n ) {\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n }\n synapseBridge.redeem(to, chainId, token, swappedAmount);\n }\n\n function swapAndRedeemAndSwap(\n address to,\n uint256 chainId,\n IERC20 token,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx,\n uint256 minDy,\n uint256 deadline,\n uint8 swapTokenIndexFrom,\n uint8 swapTokenIndexTo,\n uint256 swapMinDy,\n uint256 swapDeadline\n ) external {\n require(\n address(swapMap[address(token)]) != address(0),\n \"Swap is 0x00\"\n );\n IERC20[] memory tokens = swapTokensMap[\n swapMap[address(token)]\n ];\n tokens[tokenIndexFrom].safeTransferFrom(\n msg.sender,\n address(this),\n dx\n );\n // swap\n\n uint256 swappedAmount = ISwap(swapMap[address(token)]).swap(tokenIndexFrom, tokenIndexTo, dx, minDy, deadline);\n // deposit into bridge, gets nUSD\n if (\n token.allowance(address(this), address(synapseBridge)) <\n swappedAmount\n ) {\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n }\n synapseBridge.redeemAndSwap(\n to,\n chainId,\n token,\n swappedAmount,\n swapTokenIndexFrom,\n swapTokenIndexTo,\n swapMinDy,\n swapDeadline\n );\n }\n\n function swapAndRedeemAndRemove(\n address to,\n uint256 chainId,\n IERC20 token,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx,\n uint256 minDy,\n uint256 deadline,\n uint8 liqTokenIndex,\n uint256 liqMinAmount,\n uint256 liqDeadline\n ) external {\n ISwap swap = ISwap(swapMap[address(token)]);\n require(address(swap) != address(0), \"Swap is 0x00\");\n IERC20[] memory tokens = swapTokensMap[address(swap)];\n tokens[tokenIndexFrom].safeTransferFrom(\n msg.sender,\n address(this),\n dx\n );\n // swap\n\n uint256 swappedAmount = swap.swap(\n tokenIndexFrom,\n tokenIndexTo,\n dx,\n minDy,\n deadline\n );\n // deposit into bridge, gets nUSD\n if (\n token.allowance(address(this), address(synapseBridge)) <\n swappedAmount\n ) {\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n }\n synapseBridge.redeemAndRemove(\n to,\n chainId,\n token,\n swappedAmount,\n liqTokenIndex,\n liqMinAmount,\n liqDeadline\n );\n }\n\n /**\n * @notice wraps SynapseBridge redeem()\n * @param to address on other chain to redeem underlying assets to\n * @param chainId which underlying chain to bridge assets onto\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n **/\n function redeem(\n address to,\n uint256 chainId,\n IERC20 token,\n uint256 amount\n ) external {\n token.safeTransferFrom(msg.sender, address(this), amount);\n if (address(token) == address(CANOLICAL_FRAX)) {\n uint256 swappedAmount = CANOLICAL_FRAX.exchangeCanonicalForOld(address(SYN_FRAX), amount);\n if (SYN_FRAX.allowance(address(this), address(synapseBridge)) < amount) {\n SYN_FRAX.safeApprove(address(synapseBridge), MAX_UINT256);\n }\n synapseBridge.redeem(to, chainId, SYN_FRAX, swappedAmount);\n } else {\n if (token.allowance(address(this), address(synapseBridge)) < amount) {\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n }\n synapseBridge.redeem(to, chainId, token, amount);\n }\n }\n\n /**\n * @notice Wraps SynapseBridge redeemv2() function\n * @param to address on other chain to bridge assets to\n * @param chainId which chain to bridge assets onto\n * @param token ERC20 compatible token to redeem into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n **/\n function redeemv2(\n bytes32 to,\n uint256 chainId,\n IERC20 token,\n uint256 amount\n ) external {\n token.safeTransferFrom(msg.sender, address(this), amount);\n\n if (token.allowance(address(this), address(synapseBridge)) < amount) {\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n }\n synapseBridge.redeemv2(to, chainId, token, amount);\n }\n\n /**\n * @notice wraps SynapseBridge redeem()\n * @param to address on other chain to redeem underlying assets to\n * @param chainId which underlying chain to bridge assets onto\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n **/\n function deposit(\n address to,\n uint256 chainId,\n IERC20 token,\n uint256 amount\n ) external {\n token.safeTransferFrom(msg.sender, address(this), amount);\n if (token.allowance(address(this), address(synapseBridge)) < amount) {\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n }\n synapseBridge.deposit(to, chainId, token, amount);\n }\n\n /**\n * @notice Wraps SynapseBridge deposit() function to make it compatible w/ ETH -> WETH conversions\n * @param to address on other chain to bridge assets to\n * @param chainId which chain to bridge assets onto\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n **/\n function depositETH(\n address to,\n uint256 chainId,\n uint256 amount\n ) external payable {\n require(msg.value > 0 && msg.value == amount, 'INCORRECT MSG VALUE');\n IWETH9(WETH_ADDRESS).deposit{value: msg.value}();\n synapseBridge.deposit(to, chainId, IERC20(WETH_ADDRESS), amount);\n }\n\n\n\n function swapETHAndRedeem(\n address to,\n uint256 chainId,\n IERC20 token,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx,\n uint256 minDy,\n uint256 deadline\n ) external payable {\n require(WETH_ADDRESS != address(0), \"WETH 0\");\n require(msg.value > 0 && msg.value == dx, \"INCORRECT MSG VALUE\");\n ISwap swap = ISwap(swapMap[address(token)]);\n require(address(swap) != address(0), \"Swap is 0x00\");\n IWETH9(WETH_ADDRESS).deposit{value: msg.value}();\n\n // swap\n uint256 swappedAmount = swap.swap(\n tokenIndexFrom,\n tokenIndexTo,\n dx,\n minDy,\n deadline\n );\n synapseBridge.redeem(to, chainId, token, swappedAmount);\n }\n\n /**\n * @notice Wraps redeemAndSwap on SynapseBridge.sol\n * Relays to nodes that (typically) a wrapped synAsset ERC20 token has been burned and the underlying needs to be redeeemed on the native chain. This function indicates to the nodes that they should attempt to redeem the LP token for the underlying assets (E.g \"swap\" out of the LP token)\n * @param to address on other chain to redeem underlying assets to\n * @param chainId which underlying chain to bridge assets onto\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n * @param tokenIndexFrom the token the user wants to swap from\n * @param tokenIndexTo the token the user wants to swap to\n * @param minDy the min amount the user would like to receive, or revert to only minting the SynERC20 token crosschain.\n * @param deadline latest timestamp to accept this transaction\n **/\n function redeemAndSwap(\n address to,\n uint256 chainId,\n IERC20 token,\n uint256 amount,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 minDy,\n uint256 deadline\n ) external {\n token.safeTransferFrom(msg.sender, address(this), amount);\n if (token.allowance(address(this), address(synapseBridge)) < amount) {\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n }\n synapseBridge.redeemAndSwap(\n to,\n chainId,\n token,\n amount,\n tokenIndexFrom,\n tokenIndexTo,\n minDy,\n deadline\n );\n }\n\n /**\n * @notice Wraps redeemAndRemove on SynapseBridge\n * Relays to nodes that (typically) a wrapped synAsset ERC20 token has been burned and the underlying needs to be redeeemed on the native chain. This function indicates to the nodes that they should attempt to redeem the LP token for the underlying assets (E.g \"swap\" out of the LP token)\n * @param to address on other chain to redeem underlying assets to\n * @param chainId which underlying chain to bridge assets onto\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount of (typically) LP token to pass to the nodes to attempt to removeLiquidity() with to redeem for the underlying assets of the LP token\n * @param liqTokenIndex Specifies which of the underlying LP assets the nodes should attempt to redeem for\n * @param liqMinAmount Specifies the minimum amount of the underlying asset needed for the nodes to execute the redeem/swap\n * @param liqDeadline Specificies the deadline that the nodes are allowed to try to redeem/swap the LP token\n **/\n function redeemAndRemove(\n address to,\n uint256 chainId,\n IERC20 token,\n uint256 amount,\n uint8 liqTokenIndex,\n uint256 liqMinAmount,\n uint256 liqDeadline\n ) external {\n token.safeTransferFrom(msg.sender, address(this), amount);\n if (token.allowance(address(this), address(synapseBridge)) < amount) {\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n }\n synapseBridge.redeemAndRemove(\n to,\n chainId,\n token,\n amount,\n liqTokenIndex,\n liqMinAmount,\n liqDeadline\n );\n }\n}\n" + }, + "contracts/bridge/interfaces/ISwap.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.6.12;\n\nimport '@openzeppelin/contracts/token/ERC20/ERC20.sol';\n\ninterface ISwap {\n // pool data view functions\n function getA() external view returns (uint256);\n\n function getToken(uint8 index) external view returns (IERC20);\n\n function getTokenIndex(address tokenAddress) external view returns (uint8);\n\n function getTokenBalance(uint8 index) external view returns (uint256);\n\n function getVirtualPrice() external view returns (uint256);\n\n // min return calculation functions\n function calculateSwap(\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx\n ) external view returns (uint256);\n\n function calculateTokenAmount(uint256[] calldata amounts, bool deposit)\n external\n view\n returns (uint256);\n\n function calculateRemoveLiquidity(uint256 amount)\n external\n view\n returns (uint256[] memory);\n\n function calculateRemoveLiquidityOneToken(\n uint256 tokenAmount,\n uint8 tokenIndex\n ) external view returns (uint256 availableTokenAmount);\n\n // state modifying functions\n function initialize(\n IERC20[] memory pooledTokens,\n uint8[] memory decimals,\n string memory lpTokenName,\n string memory lpTokenSymbol,\n uint256 a,\n uint256 fee,\n uint256 adminFee,\n address lpTokenTargetAddress\n ) external;\n\n function swap(\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx,\n uint256 minDy,\n uint256 deadline\n ) external returns (uint256);\n\n function addLiquidity(\n uint256[] calldata amounts,\n uint256 minToMint,\n uint256 deadline\n ) external returns (uint256);\n\n function removeLiquidity(\n uint256 amount,\n uint256[] calldata minAmounts,\n uint256 deadline\n ) external returns (uint256[] memory);\n\n function removeLiquidityOneToken(\n uint256 tokenAmount,\n uint8 tokenIndex,\n uint256 minAmount,\n uint256 deadline\n ) external returns (uint256);\n\n function removeLiquidityImbalance(\n uint256[] calldata amounts,\n uint256 maxBurnAmount,\n uint256 deadline\n ) external returns (uint256);\n}\n" + }, + "contracts/bridge/interfaces/IWETH9.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.4.0;\n\ninterface IWETH9 {\n function name() external view returns (string memory);\n\n function symbol() external view returns (string memory);\n\n function decimals() external view returns (uint8);\n\n function balanceOf(address) external view returns (uint256);\n\n function allowance(address, address) external view returns (uint256);\n\n receive() external payable;\n\n function deposit() external payable;\n\n function withdraw(uint256 wad) external;\n\n function totalSupply() external view returns (uint256);\n\n function approve(address guy, uint256 wad) external returns (bool);\n\n function transfer(address dst, uint256 wad) external returns (bool);\n\n function transferFrom(\n address src,\n address dst,\n uint256 wad\n ) external returns (bool);\n}" + }, + "contracts/bridge/wrappers/L2BridgeZap.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.6.12;\n\nimport \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/SafeERC20.sol\";\nimport \"../interfaces/ISwap.sol\";\nimport \"../interfaces/ISynapseBridge.sol\";\nimport \"../interfaces/IWETH9.sol\";\n\ncontract L2BridgeZap {\n using SafeERC20 for IERC20;\n\n ISynapseBridge synapseBridge;\n address payable public immutable WETH_ADDRESS;\n\n mapping(address => address) public swapMap;\n mapping(address => IERC20[]) public swapTokensMap;\n\n uint256 constant MAX_UINT256 = 2**256 - 1;\n\n constructor(\n address payable _wethAddress,\n address _swapOne,\n address tokenOne,\n address _swapTwo,\n address tokenTwo,\n ISynapseBridge _synapseBridge\n ) public {\n WETH_ADDRESS = _wethAddress;\n synapseBridge = _synapseBridge;\n swapMap[tokenOne] = _swapOne;\n swapMap[tokenTwo] = _swapTwo;\n if (_wethAddress != address(0)) {\n IERC20(_wethAddress).safeIncreaseAllowance(address(_synapseBridge), MAX_UINT256);\n }\n if (address(_swapOne) != address(0)) {\n {\n uint8 i;\n for (; i < 32; i++) {\n try ISwap(_swapOne).getToken(i) returns (\n IERC20 token\n ) {\n swapTokensMap[_swapOne].push(token);\n token.safeApprove(address(_swapOne), MAX_UINT256);\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n } catch {\n break;\n }\n }\n require(i > 1, \"swap must have at least 2 tokens\");\n }\n }\n if (address(_swapTwo) != address(0)) {\n {\n uint8 i;\n for (; i < 32; i++) {\n try ISwap(_swapTwo).getToken(i) returns (\n IERC20 token\n ) {\n swapTokensMap[_swapTwo].push(token);\n token.safeApprove(address(_swapTwo), MAX_UINT256);\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n } catch {\n break;\n }\n }\n require(i > 1, \"swap must have at least 2 tokens\");\n }\n }\n }\n\n /**\n * @notice Calculate amount of tokens you receive on swap\n * @param tokenIndexFrom the token the user wants to sell\n * @param tokenIndexTo the token the user wants to buy\n * @param dx the amount of tokens the user wants to sell. If the token charges\n * a fee on transfers, use the amount that gets transferred after the fee.\n * @return amount of tokens the user will receive\n */\n function calculateSwap(\n IERC20 token,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx\n ) external view virtual returns (uint256) {\n ISwap swap = ISwap(\n swapMap[address(token)]\n );\n return swap.calculateSwap(tokenIndexFrom, tokenIndexTo, dx);\n }\n\n function swapAndRedeem(\n address to,\n uint256 chainId,\n IERC20 token,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx,\n uint256 minDy,\n uint256 deadline\n ) external {\n ISwap swap = ISwap(swapMap[address(token)]);\n require(address(swap) != address(0), \"Swap is 0x00\");\n IERC20[] memory tokens = swapTokensMap[address(swap)];\n tokens[tokenIndexFrom].safeTransferFrom(\n msg.sender,\n address(this),\n dx\n );\n // swap\n\n uint256 swappedAmount = swap.swap(\n tokenIndexFrom,\n tokenIndexTo,\n dx,\n minDy,\n deadline\n );\n // deposit into bridge, gets nUSD\n if (\n token.allowance(address(this), address(synapseBridge)) <\n swappedAmount\n ) {\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n }\n synapseBridge.redeem(to, chainId, token, swappedAmount);\n }\n\n function swapAndRedeemAndSwap(\n address to,\n uint256 chainId,\n IERC20 token,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx,\n uint256 minDy,\n uint256 deadline,\n uint8 swapTokenIndexFrom,\n uint8 swapTokenIndexTo,\n uint256 swapMinDy,\n uint256 swapDeadline\n ) external {\n require(\n address(swapMap[address(token)]) != address(0),\n \"Swap is 0x00\"\n );\n IERC20[] memory tokens = swapTokensMap[\n swapMap[address(token)]\n ];\n tokens[tokenIndexFrom].safeTransferFrom(\n msg.sender,\n address(this),\n dx\n );\n // swap\n\n uint256 swappedAmount = ISwap(swapMap[address(token)]).swap(tokenIndexFrom, tokenIndexTo, dx, minDy, deadline);\n // deposit into bridge, gets nUSD\n if (\n token.allowance(address(this), address(synapseBridge)) <\n swappedAmount\n ) {\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n }\n synapseBridge.redeemAndSwap(\n to,\n chainId,\n token,\n swappedAmount,\n swapTokenIndexFrom,\n swapTokenIndexTo,\n swapMinDy,\n swapDeadline\n );\n }\n\n function swapAndRedeemAndRemove(\n address to,\n uint256 chainId,\n IERC20 token,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx,\n uint256 minDy,\n uint256 deadline,\n uint8 liqTokenIndex,\n uint256 liqMinAmount,\n uint256 liqDeadline\n ) external {\n ISwap swap = ISwap(swapMap[address(token)]);\n require(address(swap) != address(0), \"Swap is 0x00\");\n IERC20[] memory tokens = swapTokensMap[address(swap)];\n tokens[tokenIndexFrom].safeTransferFrom(\n msg.sender,\n address(this),\n dx\n );\n // swap\n\n uint256 swappedAmount = swap.swap(\n tokenIndexFrom,\n tokenIndexTo,\n dx,\n minDy,\n deadline\n );\n // deposit into bridge, gets nUSD\n if (\n token.allowance(address(this), address(synapseBridge)) <\n swappedAmount\n ) {\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n }\n synapseBridge.redeemAndRemove(\n to,\n chainId,\n token,\n swappedAmount,\n liqTokenIndex,\n liqMinAmount,\n liqDeadline\n );\n }\n\n /**\n * @notice wraps SynapseBridge redeem()\n * @param to address on other chain to redeem underlying assets to\n * @param chainId which underlying chain to bridge assets onto\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n **/\n function redeem(\n address to,\n uint256 chainId,\n IERC20 token,\n uint256 amount\n ) external {\n token.safeTransferFrom(msg.sender, address(this), amount);\n if (token.allowance(address(this), address(synapseBridge)) < amount) {\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n }\n synapseBridge.redeem(to, chainId, token, amount);\n }\n\n /**\n * @notice wraps SynapseBridge redeem()\n * @param to address on other chain to redeem underlying assets to\n * @param chainId which underlying chain to bridge assets onto\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n **/\n function deposit(\n address to,\n uint256 chainId,\n IERC20 token,\n uint256 amount\n ) external {\n token.safeTransferFrom(msg.sender, address(this), amount);\n if (token.allowance(address(this), address(synapseBridge)) < amount) {\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n }\n synapseBridge.deposit(to, chainId, token, amount);\n }\n\n /**\n * @notice Wraps SynapseBridge deposit() function to make it compatible w/ ETH -> WETH conversions\n * @param to address on other chain to bridge assets to\n * @param chainId which chain to bridge assets onto\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n **/\n function depositETH(\n address to,\n uint256 chainId,\n uint256 amount\n ) external payable {\n require(msg.value > 0 && msg.value == amount, 'INCORRECT MSG VALUE');\n IWETH9(WETH_ADDRESS).deposit{value: msg.value}();\n synapseBridge.deposit(to, chainId, IERC20(WETH_ADDRESS), amount);\n }\n\n\n function swapETHAndRedeem(\n address to,\n uint256 chainId,\n IERC20 token,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx,\n uint256 minDy,\n uint256 deadline\n ) external payable {\n require(WETH_ADDRESS != address(0), \"WETH 0\");\n require(msg.value > 0 && msg.value == dx, \"INCORRECT MSG VALUE\");\n ISwap swap = ISwap(swapMap[address(token)]);\n require(address(swap) != address(0), \"Swap is 0x00\");\n IWETH9(WETH_ADDRESS).deposit{value: msg.value}();\n\n // swap\n uint256 swappedAmount = swap.swap(\n tokenIndexFrom,\n tokenIndexTo,\n dx,\n minDy,\n deadline\n );\n synapseBridge.redeem(to, chainId, token, swappedAmount);\n }\n\n\n function swapETHAndRedeemAndSwap(\n address to,\n uint256 chainId,\n IERC20 token,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx,\n uint256 minDy,\n uint256 deadline,\n uint8 swapTokenIndexFrom,\n uint8 swapTokenIndexTo,\n uint256 swapMinDy,\n uint256 swapDeadline\n ) external payable {\n require(WETH_ADDRESS != address(0), \"WETH 0\");\n require(msg.value > 0 && msg.value == dx, \"INCORRECT MSG VALUE\");\n ISwap swap = ISwap(swapMap[address(token)]);\n require(address(swap) != address(0), \"Swap is 0x00\");\n IWETH9(WETH_ADDRESS).deposit{value: msg.value}();\n\n // swap\n uint256 swappedAmount = swap.swap(\n tokenIndexFrom,\n tokenIndexTo,\n dx,\n minDy,\n deadline\n );\n synapseBridge.redeemAndSwap(to, chainId, token, swappedAmount,swapTokenIndexFrom,\n swapTokenIndexTo,\n swapMinDy,\n swapDeadline);\n }\n\n\n /**\n * @notice Wraps redeemAndSwap on SynapseBridge.sol\n * Relays to nodes that (typically) a wrapped synAsset ERC20 token has been burned and the underlying needs to be redeeemed on the native chain. This function indicates to the nodes that they should attempt to redeem the LP token for the underlying assets (E.g \"swap\" out of the LP token)\n * @param to address on other chain to redeem underlying assets to\n * @param chainId which underlying chain to bridge assets onto\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n * @param tokenIndexFrom the token the user wants to swap from\n * @param tokenIndexTo the token the user wants to swap to\n * @param minDy the min amount the user would like to receive, or revert to only minting the SynERC20 token crosschain.\n * @param deadline latest timestamp to accept this transaction\n **/\n function redeemAndSwap(\n address to,\n uint256 chainId,\n IERC20 token,\n uint256 amount,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 minDy,\n uint256 deadline\n ) external {\n token.safeTransferFrom(msg.sender, address(this), amount);\n if (token.allowance(address(this), address(synapseBridge)) < amount) {\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n }\n synapseBridge.redeemAndSwap(\n to,\n chainId,\n token,\n amount,\n tokenIndexFrom,\n tokenIndexTo,\n minDy,\n deadline\n );\n }\n\n /**\n * @notice Wraps redeemAndRemove on SynapseBridge\n * Relays to nodes that (typically) a wrapped synAsset ERC20 token has been burned and the underlying needs to be redeeemed on the native chain. This function indicates to the nodes that they should attempt to redeem the LP token for the underlying assets (E.g \"swap\" out of the LP token)\n * @param to address on other chain to redeem underlying assets to\n * @param chainId which underlying chain to bridge assets onto\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount of (typically) LP token to pass to the nodes to attempt to removeLiquidity() with to redeem for the underlying assets of the LP token\n * @param liqTokenIndex Specifies which of the underlying LP assets the nodes should attempt to redeem for\n * @param liqMinAmount Specifies the minimum amount of the underlying asset needed for the nodes to execute the redeem/swap\n * @param liqDeadline Specificies the deadline that the nodes are allowed to try to redeem/swap the LP token\n **/\n function redeemAndRemove(\n address to,\n uint256 chainId,\n IERC20 token,\n uint256 amount,\n uint8 liqTokenIndex,\n uint256 liqMinAmount,\n uint256 liqDeadline\n ) external {\n token.safeTransferFrom(msg.sender, address(this), amount);\n if (token.allowance(address(this), address(synapseBridge)) < amount) {\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n }\n synapseBridge.redeemAndRemove(\n to,\n chainId,\n token,\n amount,\n liqTokenIndex,\n liqMinAmount,\n liqDeadline\n );\n }\n\n /**\n * @notice Wraps SynapseBridge redeemv2() function\n * @param to address on other chain to bridge assets to\n * @param chainId which chain to bridge assets onto\n * @param token ERC20 compatible token to redeem into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n **/\n function redeemv2(\n bytes32 to,\n uint256 chainId,\n IERC20 token,\n uint256 amount\n ) external {\n token.safeTransferFrom(msg.sender, address(this), amount);\n\n if (token.allowance(address(this), address(synapseBridge)) < amount) {\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n }\n synapseBridge.redeemv2(to, chainId, token, amount);\n }\n}\n" + }, + "contracts/bridge/wrappers/L1BridgeZap.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.6.12;\n\nimport '@openzeppelin/contracts/token/ERC20/IERC20.sol';\nimport '@openzeppelin/contracts/token/ERC20/SafeERC20.sol';\nimport '../interfaces/ISwap.sol';\nimport '../interfaces/ISynapseBridge.sol';\nimport \"../interfaces/IWETH9.sol\";\n\n\n/**\n * @title L1BridgeZap\n * @notice This contract is responsible for handling user Zaps into the SynapseBridge contract, through the Synapse Swap contracts. It does so\n * It does so by combining the action of addLiquidity() to the base swap pool, and then calling either deposit() or depositAndSwap() on the bridge.\n * This is done in hopes of automating portions of the bridge user experience to users, while keeping the SynapseBridge contract logic small.\n *\n * @dev This contract should be deployed with a base Swap.sol address and a SynapseBridge.sol address, otherwise, it will not function.\n */\ncontract L1BridgeZap {\n using SafeERC20 for IERC20;\n\n uint256 constant MAX_UINT256 = 2**256 - 1;\n \n ISwap baseSwap;\n ISynapseBridge synapseBridge;\n IERC20[] public baseTokens;\n address payable public immutable WETH_ADDRESS;\n \n\n /**\n * @notice Constructs the contract, approves each token inside of baseSwap to be used by baseSwap (needed for addLiquidity())\n */\n constructor(address payable _wethAddress, ISwap _baseSwap, ISynapseBridge _synapseBridge) public {\n WETH_ADDRESS = _wethAddress;\n baseSwap = _baseSwap;\n synapseBridge = _synapseBridge;\n IERC20(_wethAddress).safeIncreaseAllowance(address(_synapseBridge), MAX_UINT256);\n if (address(_baseSwap) != address(0)) {\n {\n uint8 i;\n for (; i < 32; i++) {\n try _baseSwap.getToken(i) returns (IERC20 token) {\n baseTokens.push(token);\n token.safeIncreaseAllowance(address(_baseSwap), MAX_UINT256);\n } catch {\n break;\n }\n }\n require(i > 1, 'baseSwap must have at least 2 tokens');\n }\n }\n }\n \n /**\n * @notice Wraps SynapseBridge deposit() function to make it compatible w/ ETH -> WETH conversions\n * @param to address on other chain to bridge assets to\n * @param chainId which chain to bridge assets onto\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n **/\n function depositETH(\n address to,\n uint256 chainId,\n uint256 amount\n ) external payable {\n require(msg.value > 0 && msg.value == amount, 'INCORRECT MSG VALUE');\n IWETH9(WETH_ADDRESS).deposit{value: msg.value}();\n synapseBridge.deposit(to, chainId, IERC20(WETH_ADDRESS), amount);\n }\n\n /**\n * @notice Wraps SynapseBridge depositAndSwap() function to make it compatible w/ ETH -> WETH conversions\n * @param to address on other chain to bridge assets to\n * @param chainId which chain to bridge assets onto\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n * @param tokenIndexFrom the token the user wants to swap from\n * @param tokenIndexTo the token the user wants to swap to\n * @param minDy the min amount the user would like to receive, or revert to only minting the SynERC20 token crosschain.\n * @param deadline latest timestamp to accept this transaction\n **/\n function depositETHAndSwap(\n address to,\n uint256 chainId,\n uint256 amount,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 minDy,\n uint256 deadline\n ) external payable {\n require(msg.value > 0 && msg.value == amount, 'INCORRECT MSG VALUE');\n IWETH9(WETH_ADDRESS).deposit{value: msg.value}();\n synapseBridge.depositAndSwap(to, chainId, IERC20(WETH_ADDRESS), amount, tokenIndexFrom, tokenIndexTo, minDy, deadline);\n }\n\n\n /**\n * @notice A simple method to calculate prices from deposits or\n * withdrawals, excluding fees but including slippage. This is\n * helpful as an input into the various \"min\" parameters on calls\n * to fight front-running\n *\n * @dev This shouldn't be used outside frontends for user estimates.\n *\n * @param amounts an array of token amounts to deposit or withdrawal,\n * corresponding to pooledTokens. The amount should be in each\n * pooled token's native precision.\n * @param deposit whether this is a deposit or a withdrawal\n * @return token amount the user will receive\n */\n function calculateTokenAmount(uint256[] calldata amounts, bool deposit)\n external\n view\n virtual\n returns (uint256)\n {\n return baseSwap.calculateTokenAmount(amounts, deposit);\n }\n\n /**\n * @notice Calculate the amount of underlying token available to withdraw\n * when withdrawing via only single token\n * @param tokenAmount the amount of LP token to burn\n * @param tokenIndex index of which token will be withdrawn\n * @return availableTokenAmount calculated amount of underlying token\n * available to withdraw\n */\n function calculateRemoveLiquidityOneToken(\n uint256 tokenAmount,\n uint8 tokenIndex\n ) external view virtual returns (uint256 availableTokenAmount) {\n return baseSwap.calculateRemoveLiquidityOneToken(tokenAmount, tokenIndex);\n }\n\n\n /**\n * @notice Combines adding liquidity to the given Swap, and calls deposit() on the bridge using that LP token\n * @param to address on other chain to bridge assets to\n * @param chainId which chain to bridge assets onto\n * @param token ERC20 compatible token to deposit into the bridge\n * @param liquidityAmounts the amounts of each token to add, in their native precision\n * @param minToMint the minimum LP tokens adding this amount of liquidity\n * should mint, otherwise revert. Handy for front-running mitigation\n * @param deadline latest timestamp to accept this transaction\n **/\n function zapAndDeposit(\n address to,\n uint256 chainId,\n IERC20 token,\n uint256[] calldata liquidityAmounts,\n uint256 minToMint,\n uint256 deadline\n ) external {\n // add liquidity\n for (uint256 i = 0; i < baseTokens.length; i++) {\n if (liquidityAmounts[i] != 0) {\n baseTokens[i].safeTransferFrom(\n msg.sender,\n address(this),\n liquidityAmounts[i]\n );\n }\n }\n\n uint256 liqAdded = baseSwap.addLiquidity(\n liquidityAmounts,\n minToMint,\n deadline\n );\n // deposit into bridge, gets nUSD\n if (token.allowance(address(this), address(synapseBridge)) < liqAdded) {\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n }\n synapseBridge.deposit(to, chainId, token, liqAdded);\n }\n\n /**\n * @notice Combines adding liquidity to the given Swap, and calls depositAndSwap() on the bridge using that LP token\n * @param to address on other chain to bridge assets to\n * @param chainId which chain to bridge assets onto\n * @param token ERC20 compatible token to deposit into the bridge\n * @param liquidityAmounts the amounts of each token to add, in their native precision\n * @param minToMint the minimum LP tokens adding this amount of liquidity\n * should mint, otherwise revert. Handy for front-running mitigation\n * @param liqDeadline latest timestamp to accept this transaction\n * @param tokenIndexFrom the token the user wants to swap from\n * @param tokenIndexTo the token the user wants to swap to\n * @param minDy the min amount the user would like to receive, or revert to only minting the SynERC20 token crosschain.\n * @param swapDeadline latest timestamp to accept this transaction\n **/\n function zapAndDepositAndSwap(\n address to,\n uint256 chainId,\n IERC20 token,\n uint256[] calldata liquidityAmounts,\n uint256 minToMint,\n uint256 liqDeadline,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 minDy,\n uint256 swapDeadline\n ) external {\n // add liquidity\n for (uint256 i = 0; i < baseTokens.length; i++) {\n if (liquidityAmounts[i] != 0) {\n baseTokens[i].safeTransferFrom(\n msg.sender,\n address(this),\n liquidityAmounts[i]\n );\n }\n }\n\n uint256 liqAdded = baseSwap.addLiquidity(\n liquidityAmounts,\n minToMint,\n liqDeadline\n );\n // deposit into bridge, bridge attemps to swap into desired asset\n if (token.allowance(address(this), address(synapseBridge)) < liqAdded) {\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n }\n synapseBridge.depositAndSwap(\n to,\n chainId,\n token,\n liqAdded,\n tokenIndexFrom,\n tokenIndexTo,\n minDy,\n swapDeadline\n );\n }\n\n /**\n * @notice Wraps SynapseBridge deposit() function\n * @param to address on other chain to bridge assets to\n * @param chainId which chain to bridge assets onto\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n **/\n function deposit(\n address to,\n uint256 chainId,\n IERC20 token,\n uint256 amount\n ) external {\n token.safeTransferFrom(msg.sender, address(this), amount);\n\n if (token.allowance(address(this), address(synapseBridge)) < amount) {\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n }\n synapseBridge.deposit(to, chainId, token, amount);\n }\n \n /**\n * @notice Wraps SynapseBridge depositAndSwap() function\n * @param to address on other chain to bridge assets to\n * @param chainId which chain to bridge assets onto\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n * @param tokenIndexFrom the token the user wants to swap from\n * @param tokenIndexTo the token the user wants to swap to\n * @param minDy the min amount the user would like to receive, or revert to only minting the SynERC20 token crosschain.\n * @param deadline latest timestamp to accept this transaction\n **/\n function depositAndSwap(\n address to,\n uint256 chainId,\n IERC20 token,\n uint256 amount,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 minDy,\n uint256 deadline\n ) external {\n token.safeTransferFrom(msg.sender, address(this), amount);\n \n if (token.allowance(address(this), address(synapseBridge)) < amount) {\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n }\n synapseBridge.depositAndSwap(to, chainId, token, amount, tokenIndexFrom, tokenIndexTo, minDy, deadline);\n }\n\n\n /**\n * @notice Wraps SynapseBridge redeem() function\n * @param to address on other chain to bridge assets to\n * @param chainId which chain to bridge assets onto\n * @param token ERC20 compatible token to redeem into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n **/\n function redeem(\n address to,\n uint256 chainId,\n IERC20 token,\n uint256 amount\n ) external {\n token.safeTransferFrom(msg.sender, address(this), amount);\n\n if (token.allowance(address(this), address(synapseBridge)) < amount) {\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n }\n synapseBridge.redeem(to, chainId, token, amount);\n }\n\n /**\n * @notice Wraps SynapseBridge redeemv2() function\n * @param to address on other chain to bridge assets to\n * @param chainId which chain to bridge assets onto\n * @param token ERC20 compatible token to redeem into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n **/\n function redeemv2(\n bytes32 to,\n uint256 chainId,\n IERC20 token,\n uint256 amount\n ) external {\n token.safeTransferFrom(msg.sender, address(this), amount);\n\n if (token.allowance(address(this), address(synapseBridge)) < amount) {\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n }\n synapseBridge.redeemv2(to, chainId, token, amount);\n }\n\n}\n" + }, + "contracts/bridge/wrappers/MigratorBridgeZap.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.6.12;\n\nimport '@openzeppelin/contracts/token/ERC20/IERC20.sol';\nimport '@openzeppelin/contracts/token/ERC20/SafeERC20.sol';\nimport '@openzeppelin/contracts/math/SafeMath.sol';\n\nimport '../interfaces/ISynapseBridge.sol';\nimport '../interfaces/IERC20Migrator.sol';\n\ncontract MigratorBridgeZap {\n using SafeERC20 for IERC20;\n using SafeMath for uint256;\n \n ISynapseBridge constant synapseBridge = ISynapseBridge(0xd123f70AE324d34A9E76b67a27bf77593bA8749f);\n IERC20Migrator constant erc20Migrator = IERC20Migrator(0xf0284FB86adA5E4D82555C529677eEA3B2C3E022); \n IERC20 constant legacyToken = IERC20(0x42F6f551ae042cBe50C739158b4f0CAC0Edb9096);\n IERC20 constant newToken = IERC20(0xa4080f1778e69467E905B8d6F72f6e441f9e9484);\n uint256 constant MAX_UINT256 = 2**256 - 1;\n\n constructor() public {\n legacyToken.safeApprove(address(erc20Migrator), MAX_UINT256);\n newToken.safeApprove(address(synapseBridge), MAX_UINT256);\n }\n\n function migrate(uint256 amount) external {\n legacyToken.safeTransferFrom(msg.sender, address(this), amount);\n erc20Migrator.migrate(amount);\n newToken.safeTransfer(msg.sender, amount.mul(5).div(2));\n }\n\n function migrateAndBridge(uint256 amount, address to, uint256 chainId) external {\n legacyToken.safeTransferFrom(msg.sender, address(this), amount);\n erc20Migrator.migrate(amount);\n synapseBridge.redeem(to, chainId, newToken, amount.mul(5).div(2));\n }\n}" + }, + "contracts/bridge/interfaces/IERC20Migrator.sol": { + "content": "// SPDX-License-Identifier: MIT\n\n\npragma solidity 0.6.12;\n\ninterface IERC20Migrator { \n function migrate(uint256 amount) external;\n}\n\n" + }, + "contracts/bridge/wrappers/JewelBridgeSwap.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.6.12;\n\nimport '@openzeppelin/contracts/token/ERC20/ERC20.sol';\nimport \"@openzeppelin/contracts/token/ERC20/SafeERC20.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/ERC20Burnable.sol\";\nimport \"@openzeppelin/contracts/math/SafeMath.sol\";\n\ninterface IERC20Mintable is IERC20 {\n function mint(address to, uint256 amount) external;\n}\n\ncontract JewelBridgeSwap {\n using SafeERC20 for IERC20;\n using SafeERC20 for IERC20Mintable;\n using SafeMath for uint256;\n\n // Maps token address to an index in the pool. Used to prevent duplicate tokens in the pool.\n // getTokenIndex function also relies on this mapping to retrieve token index.\n mapping(address => uint8) private tokenIndexes;\n IERC20[2] pooledTokens;\n \n constructor(IERC20 tokenA, IERC20 mintableTokenB) public {\n pooledTokens[0] = tokenA;\n pooledTokens[1] = mintableTokenB;\n tokenIndexes[address(tokenA)] = 0;\n tokenIndexes[address(mintableTokenB)] = 1;\n }\n\n /**\n * @notice Return address of the pooled token at given index. Reverts if tokenIndex is out of range.\n * @param index the index of the token\n * @return address of the token at given index\n */\n function getToken(uint8 index) public view returns (IERC20) {\n require(index < pooledTokens.length, \"Out of range\");\n return pooledTokens[index];\n }\n\n /**\n * @notice Return the index of the given token address. Reverts if no matching\n * token is found.\n * @param tokenAddress address of the token\n * @return the index of the given token address\n */\n function getTokenIndex(address tokenAddress)\n public\n view\n returns (uint8)\n {\n uint8 index = tokenIndexes[tokenAddress];\n require(\n address(getToken(index)) == tokenAddress,\n \"Token does not exist\"\n );\n return index;\n }\n\n /**\n * @notice Calculate amount of tokens you receive on swap\n * @param tokenIndexFrom the token the user wants to sell\n * @param tokenIndexTo the token the user wants to buy\n * @param dx the amount of tokens the user wants to swap. \n * @return amount of tokens the user will receive\n */\n function calculateSwap(\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx\n ) external view returns (uint256) {\n return dx;\n }\n\n /**\n * @notice Swap two tokens using this pool\n * @param tokenIndexFrom the token the user wants to swap from\n * @param tokenIndexTo the token the user wants to swap to\n * @param dx the amount of tokens the user wants to swap from\n * @param minDy the min amount the user would like to receive, or revert.\n * @param deadline latest timestamp to accept this transaction\n */\n function swap(\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx,\n uint256 minDy,\n uint256 deadline\n )\n external\n returns (uint256)\n {\n {\n IERC20 tokenFrom = pooledTokens[tokenIndexFrom];\n require(\n dx <= tokenFrom.balanceOf(msg.sender),\n \"Cannot swap more than you own\"\n );\n // Transfer tokens first to see if a fee was charged on transfer\n uint256 beforeBalance = tokenFrom.balanceOf(address(this));\n tokenFrom.safeTransferFrom(msg.sender, address(this), dx);\n\n // Use the actual transferred amount for AMM math\n dx = tokenFrom.balanceOf(address(this)).sub(beforeBalance);\n }\n\n // redeem JEWEL for synJEWEL\n if (tokenIndexFrom == 0 && tokenIndexTo == 1) {\n IERC20Mintable(address(pooledTokens[tokenIndexTo])).mint(msg.sender, dx);\n return dx;\n // redeem synJEWEL for JEWEL\n } else if (tokenIndexFrom == 1 && tokenIndexTo == 0) {\n ERC20Burnable(address(pooledTokens[tokenIndexFrom])).burn(dx);\n pooledTokens[tokenIndexTo].safeTransfer(msg.sender, dx);\n return dx;\n } else {\n revert(\"Unsupported indexes\");\n }\n }\n}" + }, + "contracts/bridge/testing/SynapseToken.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity >=0.6.0 <0.8.0;\n\n\nimport \"@openzeppelin/contracts/token/ERC20/ERC20.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/ERC20Burnable.sol\";\nimport \"@openzeppelin/contracts/access/AccessControl.sol\";\nimport \"@openzeppelin/contracts/drafts/ERC20Permit.sol\";\n\ncontract Synapse is ERC20, ERC20Burnable, AccessControl, ERC20Permit {\n bytes32 public constant MINTER_ROLE = keccak256(\"MINTER_ROLE\");\n\n constructor() public ERC20(\"Synapse\", \"SYN\") ERC20Permit(\"Synapse\") {\n _setupRole(DEFAULT_ADMIN_ROLE, msg.sender);\n _setupRole(MINTER_ROLE, msg.sender);\n }\n\n function mint(address to, uint256 amount) external {\n require(hasRole(MINTER_ROLE, msg.sender));\n _mint(to, amount);\n }\n}" + }, + "@openzeppelin/contracts/access/AccessControl.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <0.8.0;\n\nimport \"../utils/EnumerableSet.sol\";\nimport \"../utils/Address.sol\";\nimport \"../utils/Context.sol\";\n\n/**\n * @dev Contract module that allows children to implement role-based access\n * control mechanisms.\n *\n * Roles are referred to by their `bytes32` identifier. These should be exposed\n * in the external API and be unique. The best way to achieve this is by\n * using `public constant` hash digests:\n *\n * ```\n * bytes32 public constant MY_ROLE = keccak256(\"MY_ROLE\");\n * ```\n *\n * Roles can be used to represent a set of permissions. To restrict access to a\n * function call, use {hasRole}:\n *\n * ```\n * function foo() public {\n * require(hasRole(MY_ROLE, msg.sender));\n * ...\n * }\n * ```\n *\n * Roles can be granted and revoked dynamically via the {grantRole} and\n * {revokeRole} functions. Each role has an associated admin role, and only\n * accounts that have a role's admin role can call {grantRole} and {revokeRole}.\n *\n * By default, the admin role for all roles is `DEFAULT_ADMIN_ROLE`, which means\n * that only accounts with this role will be able to grant or revoke other\n * roles. More complex role relationships can be created by using\n * {_setRoleAdmin}.\n *\n * WARNING: The `DEFAULT_ADMIN_ROLE` is also its own admin: it has permission to\n * grant and revoke this role. Extra precautions should be taken to secure\n * accounts that have been granted it.\n */\nabstract contract AccessControl is Context {\n using EnumerableSet for EnumerableSet.AddressSet;\n using Address for address;\n\n struct RoleData {\n EnumerableSet.AddressSet members;\n bytes32 adminRole;\n }\n\n mapping (bytes32 => RoleData) private _roles;\n\n bytes32 public constant DEFAULT_ADMIN_ROLE = 0x00;\n\n /**\n * @dev Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole`\n *\n * `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite\n * {RoleAdminChanged} not being emitted signaling this.\n *\n * _Available since v3.1._\n */\n event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole);\n\n /**\n * @dev Emitted when `account` is granted `role`.\n *\n * `sender` is the account that originated the contract call, an admin role\n * bearer except when using {_setupRole}.\n */\n event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender);\n\n /**\n * @dev Emitted when `account` is revoked `role`.\n *\n * `sender` is the account that originated the contract call:\n * - if using `revokeRole`, it is the admin role bearer\n * - if using `renounceRole`, it is the role bearer (i.e. `account`)\n */\n event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender);\n\n /**\n * @dev Returns `true` if `account` has been granted `role`.\n */\n function hasRole(bytes32 role, address account) public view returns (bool) {\n return _roles[role].members.contains(account);\n }\n\n /**\n * @dev Returns the number of accounts that have `role`. Can be used\n * together with {getRoleMember} to enumerate all bearers of a role.\n */\n function getRoleMemberCount(bytes32 role) public view returns (uint256) {\n return _roles[role].members.length();\n }\n\n /**\n * @dev Returns one of the accounts that have `role`. `index` must be a\n * value between 0 and {getRoleMemberCount}, non-inclusive.\n *\n * Role bearers are not sorted in any particular way, and their ordering may\n * change at any point.\n *\n * WARNING: When using {getRoleMember} and {getRoleMemberCount}, make sure\n * you perform all queries on the same block. See the following\n * https://forum.openzeppelin.com/t/iterating-over-elements-on-enumerableset-in-openzeppelin-contracts/2296[forum post]\n * for more information.\n */\n function getRoleMember(bytes32 role, uint256 index) public view returns (address) {\n return _roles[role].members.at(index);\n }\n\n /**\n * @dev Returns the admin role that controls `role`. See {grantRole} and\n * {revokeRole}.\n *\n * To change a role's admin, use {_setRoleAdmin}.\n */\n function getRoleAdmin(bytes32 role) public view returns (bytes32) {\n return _roles[role].adminRole;\n }\n\n /**\n * @dev Grants `role` to `account`.\n *\n * If `account` had not been already granted `role`, emits a {RoleGranted}\n * event.\n *\n * Requirements:\n *\n * - the caller must have ``role``'s admin role.\n */\n function grantRole(bytes32 role, address account) public virtual {\n require(hasRole(_roles[role].adminRole, _msgSender()), \"AccessControl: sender must be an admin to grant\");\n\n _grantRole(role, account);\n }\n\n /**\n * @dev Revokes `role` from `account`.\n *\n * If `account` had been granted `role`, emits a {RoleRevoked} event.\n *\n * Requirements:\n *\n * - the caller must have ``role``'s admin role.\n */\n function revokeRole(bytes32 role, address account) public virtual {\n require(hasRole(_roles[role].adminRole, _msgSender()), \"AccessControl: sender must be an admin to revoke\");\n\n _revokeRole(role, account);\n }\n\n /**\n * @dev Revokes `role` from the calling account.\n *\n * Roles are often managed via {grantRole} and {revokeRole}: this function's\n * purpose is to provide a mechanism for accounts to lose their privileges\n * if they are compromised (such as when a trusted device is misplaced).\n *\n * If the calling account had been granted `role`, emits a {RoleRevoked}\n * event.\n *\n * Requirements:\n *\n * - the caller must be `account`.\n */\n function renounceRole(bytes32 role, address account) public virtual {\n require(account == _msgSender(), \"AccessControl: can only renounce roles for self\");\n\n _revokeRole(role, account);\n }\n\n /**\n * @dev Grants `role` to `account`.\n *\n * If `account` had not been already granted `role`, emits a {RoleGranted}\n * event. Note that unlike {grantRole}, this function doesn't perform any\n * checks on the calling account.\n *\n * [WARNING]\n * ====\n * This function should only be called from the constructor when setting\n * up the initial roles for the system.\n *\n * Using this function in any other way is effectively circumventing the admin\n * system imposed by {AccessControl}.\n * ====\n */\n function _setupRole(bytes32 role, address account) internal virtual {\n _grantRole(role, account);\n }\n\n /**\n * @dev Sets `adminRole` as ``role``'s admin role.\n *\n * Emits a {RoleAdminChanged} event.\n */\n function _setRoleAdmin(bytes32 role, bytes32 adminRole) internal virtual {\n emit RoleAdminChanged(role, _roles[role].adminRole, adminRole);\n _roles[role].adminRole = adminRole;\n }\n\n function _grantRole(bytes32 role, address account) private {\n if (_roles[role].members.add(account)) {\n emit RoleGranted(role, account, _msgSender());\n }\n }\n\n function _revokeRole(bytes32 role, address account) private {\n if (_roles[role].members.remove(account)) {\n emit RoleRevoked(role, account, _msgSender());\n }\n }\n}\n" + }, + "@openzeppelin/contracts/drafts/ERC20Permit.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.5 <0.8.0;\n\nimport \"../token/ERC20/ERC20.sol\";\nimport \"./IERC20Permit.sol\";\nimport \"../cryptography/ECDSA.sol\";\nimport \"../utils/Counters.sol\";\nimport \"./EIP712.sol\";\n\n/**\n * @dev Implementation of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in\n * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612].\n *\n * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by\n * presenting a message signed by the account. By not relying on `{IERC20-approve}`, the token holder account doesn't\n * need to send a transaction, and thus is not required to hold Ether at all.\n *\n * _Available since v3.4._\n */\nabstract contract ERC20Permit is ERC20, IERC20Permit, EIP712 {\n using Counters for Counters.Counter;\n\n mapping (address => Counters.Counter) private _nonces;\n\n // solhint-disable-next-line var-name-mixedcase\n bytes32 private immutable _PERMIT_TYPEHASH = keccak256(\"Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)\");\n\n /**\n * @dev Initializes the {EIP712} domain separator using the `name` parameter, and setting `version` to `\"1\"`.\n *\n * It's a good idea to use the same `name` that is defined as the ERC20 token name.\n */\n constructor(string memory name) internal EIP712(name, \"1\") {\n }\n\n /**\n * @dev See {IERC20Permit-permit}.\n */\n function permit(address owner, address spender, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s) public virtual override {\n // solhint-disable-next-line not-rely-on-time\n require(block.timestamp <= deadline, \"ERC20Permit: expired deadline\");\n\n bytes32 structHash = keccak256(\n abi.encode(\n _PERMIT_TYPEHASH,\n owner,\n spender,\n value,\n _nonces[owner].current(),\n deadline\n )\n );\n\n bytes32 hash = _hashTypedDataV4(structHash);\n\n address signer = ECDSA.recover(hash, v, r, s);\n require(signer == owner, \"ERC20Permit: invalid signature\");\n\n _nonces[owner].increment();\n _approve(owner, spender, value);\n }\n\n /**\n * @dev See {IERC20Permit-nonces}.\n */\n function nonces(address owner) public view override returns (uint256) {\n return _nonces[owner].current();\n }\n\n /**\n * @dev See {IERC20Permit-DOMAIN_SEPARATOR}.\n */\n // solhint-disable-next-line func-name-mixedcase\n function DOMAIN_SEPARATOR() external view override returns (bytes32) {\n return _domainSeparatorV4();\n }\n}\n" + }, + "@openzeppelin/contracts/utils/EnumerableSet.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <0.8.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" + }, + "@openzeppelin/contracts/drafts/IERC20Permit.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <0.8.0;\n\n/**\n * @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in\n * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612].\n *\n * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by\n * presenting a message signed by the account. By not relying on `{IERC20-approve}`, the token holder account doesn't\n * need to send a transaction, and thus is not required to hold Ether at all.\n */\ninterface IERC20Permit {\n /**\n * @dev Sets `value` as the allowance of `spender` over `owner`'s tokens,\n * given `owner`'s signed approval.\n *\n * IMPORTANT: The same issues {IERC20-approve} has related to transaction\n * ordering also apply here.\n *\n * Emits an {Approval} event.\n *\n * Requirements:\n *\n * - `spender` cannot be the zero address.\n * - `deadline` must be a timestamp in the future.\n * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner`\n * over the EIP712-formatted function arguments.\n * - the signature must use ``owner``'s current nonce (see {nonces}).\n *\n * For more information on the signature format, see the\n * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP\n * section].\n */\n function permit(address owner, address spender, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s) external;\n\n /**\n * @dev Returns the current nonce for `owner`. This value must be\n * included whenever a signature is generated for {permit}.\n *\n * Every successful call to {permit} increases ``owner``'s nonce by one. This\n * prevents a signature from being used multiple times.\n */\n function nonces(address owner) external view returns (uint256);\n\n /**\n * @dev Returns the domain separator used in the encoding of the signature for `permit`, as defined by {EIP712}.\n */\n // solhint-disable-next-line func-name-mixedcase\n function DOMAIN_SEPARATOR() external view returns (bytes32);\n}\n" + }, + "@openzeppelin/contracts/cryptography/ECDSA.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <0.8.0;\n\n/**\n * @dev Elliptic Curve Digital Signature Algorithm (ECDSA) operations.\n *\n * These functions can be used to verify that a message was signed by the holder\n * of the private keys of a given address.\n */\nlibrary ECDSA {\n /**\n * @dev Returns the address that signed a hashed message (`hash`) with\n * `signature`. This address can then be used for verification purposes.\n *\n * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:\n * this function rejects them by requiring the `s` value to be in the lower\n * half order, and the `v` value to be either 27 or 28.\n *\n * IMPORTANT: `hash` _must_ be the result of a hash operation for the\n * verification to be secure: it is possible to craft signatures that\n * recover to arbitrary addresses for non-hashed data. A safe way to ensure\n * this is by receiving a hash of the original message (which may otherwise\n * be too long), and then calling {toEthSignedMessageHash} on it.\n */\n function recover(bytes32 hash, bytes memory signature) internal pure returns (address) {\n // Check the signature length\n if (signature.length != 65) {\n revert(\"ECDSA: invalid signature length\");\n }\n\n // Divide the signature in r, s and v variables\n bytes32 r;\n bytes32 s;\n uint8 v;\n\n // ecrecover takes the signature parameters, and the only way to get them\n // currently is to use assembly.\n // solhint-disable-next-line no-inline-assembly\n assembly {\n r := mload(add(signature, 0x20))\n s := mload(add(signature, 0x40))\n v := byte(0, mload(add(signature, 0x60)))\n }\n\n return recover(hash, v, r, s);\n }\n\n /**\n * @dev Overload of {ECDSA-recover-bytes32-bytes-} that receives the `v`,\n * `r` and `s` signature fields separately.\n */\n function recover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) internal pure returns (address) {\n // EIP-2 still allows signature malleability for ecrecover(). Remove this possibility and make the signature\n // unique. Appendix F in the Ethereum Yellow paper (https://ethereum.github.io/yellowpaper/paper.pdf), defines\n // the valid range for s in (281): 0 < s < secp256k1n ÷ 2 + 1, and for v in (282): v ∈ {27, 28}. Most\n // signatures from current libraries generate a unique signature with an s-value in the lower half order.\n //\n // If your library generates malleable signatures, such as s-values in the upper range, calculate a new s-value\n // with 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 - s1 and flip v from 27 to 28 or\n // vice versa. If your library also generates signatures with 0/1 for v instead 27/28, add 27 to v to accept\n // these malleable signatures as well.\n require(uint256(s) <= 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0, \"ECDSA: invalid signature 's' value\");\n require(v == 27 || v == 28, \"ECDSA: invalid signature 'v' value\");\n\n // If the signature is valid (and not malleable), return the signer address\n address signer = ecrecover(hash, v, r, s);\n require(signer != address(0), \"ECDSA: invalid signature\");\n\n return signer;\n }\n\n /**\n * @dev Returns an Ethereum Signed Message, created from a `hash`. This\n * replicates the behavior of the\n * https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_sign[`eth_sign`]\n * JSON-RPC method.\n *\n * See {recover}.\n */\n function toEthSignedMessageHash(bytes32 hash) internal pure returns (bytes32) {\n // 32 is the length in bytes of hash,\n // enforced by the type signature above\n return keccak256(abi.encodePacked(\"\\x19Ethereum Signed Message:\\n32\", hash));\n }\n}\n" + }, + "@openzeppelin/contracts/utils/Counters.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <0.8.0;\n\nimport \"../math/SafeMath.sol\";\n\n/**\n * @title Counters\n * @author Matt Condon (@shrugs)\n * @dev Provides counters that can only be incremented or decremented by one. This can be used e.g. to track the number\n * of elements in a mapping, issuing ERC721 ids, or counting request ids.\n *\n * Include with `using Counters for Counters.Counter;`\n * Since it is not possible to overflow a 256 bit integer with increments of one, `increment` can skip the {SafeMath}\n * overflow check, thereby saving gas. This does assume however correct usage, in that the underlying `_value` is never\n * directly accessed.\n */\nlibrary Counters {\n using SafeMath for uint256;\n\n struct Counter {\n // This variable should never be directly accessed by users of the library: interactions must be restricted to\n // the library's function. As of Solidity v0.5.2, this cannot be enforced, though there is a proposal to add\n // this feature: see https://github.com/ethereum/solidity/issues/4637\n uint256 _value; // default: 0\n }\n\n function current(Counter storage counter) internal view returns (uint256) {\n return counter._value;\n }\n\n function increment(Counter storage counter) internal {\n // The {SafeMath} overflow check can be skipped here, see the comment at the top\n counter._value += 1;\n }\n\n function decrement(Counter storage counter) internal {\n counter._value = counter._value.sub(1);\n }\n}\n" + }, + "@openzeppelin/contracts/drafts/EIP712.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <0.8.0;\n\n/**\n * @dev https://eips.ethereum.org/EIPS/eip-712[EIP 712] is a standard for hashing and signing of typed structured data.\n *\n * The encoding specified in the EIP is very generic, and such a generic implementation in Solidity is not feasible,\n * thus this contract does not implement the encoding itself. Protocols need to implement the type-specific encoding\n * they need in their contracts using a combination of `abi.encode` and `keccak256`.\n *\n * This contract implements the EIP 712 domain separator ({_domainSeparatorV4}) that is used as part of the encoding\n * scheme, and the final step of the encoding to obtain the message digest that is then signed via ECDSA\n * ({_hashTypedDataV4}).\n *\n * The implementation of the domain separator was designed to be as efficient as possible while still properly updating\n * the chain id to protect against replay attacks on an eventual fork of the chain.\n *\n * NOTE: This contract implements the version of the encoding known as \"v4\", as implemented by the JSON RPC method\n * https://docs.metamask.io/guide/signing-data.html[`eth_signTypedDataV4` in MetaMask].\n *\n * _Available since v3.4._\n */\nabstract contract EIP712 {\n /* solhint-disable var-name-mixedcase */\n // Cache the domain separator as an immutable value, but also store the chain id that it corresponds to, in order to\n // invalidate the cached domain separator if the chain id changes.\n bytes32 private immutable _CACHED_DOMAIN_SEPARATOR;\n uint256 private immutable _CACHED_CHAIN_ID;\n\n bytes32 private immutable _HASHED_NAME;\n bytes32 private immutable _HASHED_VERSION;\n bytes32 private immutable _TYPE_HASH;\n /* solhint-enable var-name-mixedcase */\n\n /**\n * @dev Initializes the domain separator and parameter caches.\n *\n * The meaning of `name` and `version` is specified in\n * https://eips.ethereum.org/EIPS/eip-712#definition-of-domainseparator[EIP 712]:\n *\n * - `name`: the user readable name of the signing domain, i.e. the name of the DApp or the protocol.\n * - `version`: the current major version of the signing domain.\n *\n * NOTE: These parameters cannot be changed except through a xref:learn::upgrading-smart-contracts.adoc[smart\n * contract upgrade].\n */\n constructor(string memory name, string memory version) internal {\n bytes32 hashedName = keccak256(bytes(name));\n bytes32 hashedVersion = keccak256(bytes(version));\n bytes32 typeHash = keccak256(\"EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)\");\n _HASHED_NAME = hashedName;\n _HASHED_VERSION = hashedVersion;\n _CACHED_CHAIN_ID = _getChainId();\n _CACHED_DOMAIN_SEPARATOR = _buildDomainSeparator(typeHash, hashedName, hashedVersion);\n _TYPE_HASH = typeHash;\n }\n\n /**\n * @dev Returns the domain separator for the current chain.\n */\n function _domainSeparatorV4() internal view virtual returns (bytes32) {\n if (_getChainId() == _CACHED_CHAIN_ID) {\n return _CACHED_DOMAIN_SEPARATOR;\n } else {\n return _buildDomainSeparator(_TYPE_HASH, _HASHED_NAME, _HASHED_VERSION);\n }\n }\n\n function _buildDomainSeparator(bytes32 typeHash, bytes32 name, bytes32 version) private view returns (bytes32) {\n return keccak256(\n abi.encode(\n typeHash,\n name,\n version,\n _getChainId(),\n address(this)\n )\n );\n }\n\n /**\n * @dev Given an already https://eips.ethereum.org/EIPS/eip-712#definition-of-hashstruct[hashed struct], this\n * function returns the hash of the fully encoded EIP712 message for this domain.\n *\n * This hash can be used together with {ECDSA-recover} to obtain the signer of a message. For example:\n *\n * ```solidity\n * bytes32 digest = _hashTypedDataV4(keccak256(abi.encode(\n * keccak256(\"Mail(address to,string contents)\"),\n * mailTo,\n * keccak256(bytes(mailContents))\n * )));\n * address signer = ECDSA.recover(digest, signature);\n * ```\n */\n function _hashTypedDataV4(bytes32 structHash) internal view virtual returns (bytes32) {\n return keccak256(abi.encodePacked(\"\\x19\\x01\", _domainSeparatorV4(), structHash));\n }\n\n function _getChainId() private view returns (uint256 chainId) {\n this; // silence state mutability warning without generating bytecode - see https://github.com/ethereum/solidity/issues/2691\n // solhint-disable-next-line no-inline-assembly\n assembly {\n chainId := chainid()\n }\n }\n}\n" + }, + "contracts/bridge/mocks/ERC20Mock.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.6.12;\n\nimport \"@openzeppelin/contracts/token/ERC20/ERC20.sol\";\n\ncontract ERC20Mock is ERC20 {\n constructor(\n string memory name,\n string memory symbol,\n uint256 supply\n ) public ERC20(name, symbol) {\n _mint(msg.sender, supply);\n }\n\n function mint(address to, uint256 amount) external {\n _mint(to, amount);\n }\n}" + }, + "contracts/bridge/interfaces/IMetaSwapDeposit.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.6.12;\nimport '@openzeppelin/contracts/token/ERC20/ERC20.sol';\n\n/**\n * @title IMetaSwapDeposit interface\n * @notice Interface for the meta swap contract.\n * @dev implement this interface to develop a a factory-patterned ECDSA node management contract\n **/\ninterface IMetaSwapDeposit {\n // min return calculation functions\n function calculateSwap(\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx\n ) external view returns (uint256);\n\n function swap(\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx,\n uint256 minDy,\n uint256 deadline\n ) external returns (uint256);\n\n function getToken(uint256 index) external view returns (IERC20);\n}\n" + }, + "contracts/amm/interfaces/IMetaSwapDeposit.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.6.12;\n\nimport \"@openzeppelin/contracts/token/ERC20/ERC20.sol\";\nimport \"./ISwap.sol\";\nimport \"./IMetaSwap.sol\";\n\ninterface IMetaSwapDeposit {\n function initialize(\n ISwap baseSwap_,\n IMetaSwap metaSwap_,\n IERC20 metaLPToken_\n ) external;\n}\n" + }, + "contracts/amm/interfaces/IMetaSwap.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.6.12;\n\nimport \"@openzeppelin/contracts/token/ERC20/ERC20.sol\";\n\ninterface IMetaSwap {\n // pool data view functions\n function getA() external view returns (uint256);\n\n function getToken(uint8 index) external view returns (IERC20);\n\n function getTokenIndex(address tokenAddress) external view returns (uint8);\n\n function getTokenBalance(uint8 index) external view returns (uint256);\n\n function getVirtualPrice() external view returns (uint256);\n\n function isGuarded() external view returns (bool);\n\n // min return calculation functions\n function calculateSwap(\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx\n ) external view returns (uint256);\n\n function calculateSwapUnderlying(\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx\n ) external view returns (uint256);\n\n function calculateTokenAmount(uint256[] calldata amounts, bool deposit)\n external\n view\n returns (uint256);\n\n function calculateRemoveLiquidity(uint256 amount)\n external\n view\n returns (uint256[] memory);\n\n function calculateRemoveLiquidityOneToken(\n uint256 tokenAmount,\n uint8 tokenIndex\n ) external view returns (uint256 availableTokenAmount);\n\n // state modifying functions\n function initializeMetaSwap(\n IERC20[] memory pooledTokens,\n uint8[] memory decimals,\n string memory lpTokenName,\n string memory lpTokenSymbol,\n uint256 a,\n uint256 fee,\n uint256 adminFee,\n address lpTokenTargetAddress,\n address baseSwap\n ) external;\n\n function swap(\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx,\n uint256 minDy,\n uint256 deadline\n ) external returns (uint256);\n\n function swapUnderlying(\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx,\n uint256 minDy,\n uint256 deadline\n ) external returns (uint256);\n\n function addLiquidity(\n uint256[] calldata amounts,\n uint256 minToMint,\n uint256 deadline\n ) external returns (uint256);\n\n function removeLiquidity(\n uint256 amount,\n uint256[] calldata minAmounts,\n uint256 deadline\n ) external returns (uint256[] memory);\n\n function removeLiquidityOneToken(\n uint256 tokenAmount,\n uint8 tokenIndex,\n uint256 minAmount,\n uint256 deadline\n ) external returns (uint256);\n\n function removeLiquidityImbalance(\n uint256[] calldata amounts,\n uint256 maxBurnAmount,\n uint256 deadline\n ) external returns (uint256);\n\n function swapStorage()\n external\n view\n returns (\n uint256 initialA,\n uint256 futureA,\n uint256 initialATime,\n uint256 futureATime,\n uint256 swapFee,\n uint256 adminFee,\n address lpToken\n );\n}\n" + }, + "contracts/amm/helper/GenericERC20.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.6.12;\n\nimport \"@openzeppelin/contracts/token/ERC20/ERC20.sol\";\nimport \"@openzeppelin/contracts/access/Ownable.sol\";\n\n/**\n * @title Generic ERC20 token\n * @notice This contract simulates a generic ERC20 token that is mintable and burnable.\n */\ncontract GenericERC20 is ERC20, Ownable {\n /**\n * @notice Deploy this contract with given name, symbol, and decimals\n * @dev the caller of this constructor will become the owner of this contract\n * @param name_ name of this token\n * @param symbol_ symbol of this token\n * @param decimals_ number of decimals this token will be based on\n */\n constructor(\n string memory name_,\n string memory symbol_,\n uint8 decimals_\n ) public ERC20(name_, symbol_) {\n _setupDecimals(decimals_);\n }\n\n /**\n * @notice Mints given amount of tokens to recipient\n * @dev only owner can call this mint function\n * @param recipient address of account to receive the tokens\n * @param amount amount of tokens to mint\n */\n function mint(address recipient, uint256 amount) external onlyOwner {\n require(amount != 0, \"amount == 0\");\n _mint(recipient, amount);\n }\n}\n" + }, + "contracts/bridge/wrappers/HarmonyBridgeZap.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.6.12;\n\nimport \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/SafeERC20.sol\";\nimport \"../interfaces/ISwap.sol\";\nimport \"../interfaces/ISynapseBridge.sol\";\nimport \"../interfaces/IWETH9.sol\";\n\ninterface IFrax {\n function exchangeCanonicalForOld(address bridge_token_address, uint256 token_amount) external returns (uint256);\n}\n\ncontract HarmonyBridgeZap {\n using SafeERC20 for IERC20;\n\n ISynapseBridge synapseBridge;\n address payable public immutable WETH_ADDRESS;\n IFrax private constant CANOLICAL_FRAX = IFrax(0xFa7191D292d5633f702B0bd7E3E3BcCC0e633200);\n IERC20 private constant SYN_FRAX = IERC20(0x1852F70512298d56e9c8FDd905e02581E04ddb2a);\n\n mapping(address => address) public swapMap;\n mapping(address => IERC20[]) public swapTokensMap;\n\n uint256 constant MAX_UINT256 = 2**256 - 1;\n\n constructor(\n address payable _wethAddress,\n address _swapOne,\n address tokenOne,\n address _swapTwo,\n address tokenTwo,\n address _swapThree,\n address tokenThree,\n ISynapseBridge _synapseBridge\n ) public {\n WETH_ADDRESS = _wethAddress;\n synapseBridge = _synapseBridge;\n swapMap[tokenOne] = _swapOne;\n swapMap[tokenTwo] = _swapTwo;\n swapMap[tokenThree] = _swapThree;\n\n if (address(_swapOne) != address(0)) {\n {\n uint8 i;\n for (; i < 32; i++) {\n try ISwap(_swapOne).getToken(i) returns (\n IERC20 token\n ) {\n swapTokensMap[_swapOne].push(token);\n token.safeApprove(address(_swapOne), MAX_UINT256);\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n } catch {\n break;\n }\n }\n require(i > 1, \"swap must have at least 2 tokens\");\n }\n }\n if (address(_swapTwo) != address(0)) {\n {\n uint8 i;\n for (; i < 32; i++) {\n try ISwap(_swapTwo).getToken(i) returns (\n IERC20 token\n ) {\n swapTokensMap[_swapTwo].push(token);\n token.safeApprove(address(_swapTwo), MAX_UINT256);\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n } catch {\n break;\n }\n }\n require(i > 1, \"swap must have at least 2 tokens\");\n }\n }\n\n if (address(_swapThree) != address(0)) {\n {\n uint8 i;\n for (; i < 32; i++) {\n try ISwap(_swapThree).getToken(i) returns (\n IERC20 token\n ) {\n swapTokensMap[_swapThree].push(token);\n token.safeApprove(address(_swapThree), MAX_UINT256);\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n } catch {\n break;\n }\n }\n require(i > 1, \"swap must have at least 2 tokens\");\n }\n }\n }\n\n /**\n * @notice Calculate amount of tokens you receive on swap\n * @param tokenIndexFrom the token the user wants to sell\n * @param tokenIndexTo the token the user wants to buy\n * @param dx the amount of tokens the user wants to sell. If the token charges\n * a fee on transfers, use the amount that gets transferred after the fee.\n * @return amount of tokens the user will receive\n */\n function calculateSwap(\n IERC20 token,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx\n ) external view virtual returns (uint256) {\n ISwap swap = ISwap(\n swapMap[address(token)]\n );\n return swap.calculateSwap(tokenIndexFrom, tokenIndexTo, dx);\n }\n\n function swapAndRedeem(\n address to,\n uint256 chainId,\n IERC20 token,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx,\n uint256 minDy,\n uint256 deadline\n ) external {\n ISwap swap = ISwap(swapMap[address(token)]);\n require(address(swap) != address(0), \"Swap is 0x00\");\n IERC20[] memory tokens = swapTokensMap[address(swap)];\n tokens[tokenIndexFrom].safeTransferFrom(\n msg.sender,\n address(this),\n dx\n );\n // swap\n\n uint256 swappedAmount = swap.swap(\n tokenIndexFrom,\n tokenIndexTo,\n dx,\n minDy,\n deadline\n );\n // deposit into bridge, gets nUSD\n if (\n token.allowance(address(this), address(synapseBridge)) <\n swappedAmount\n ) {\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n }\n synapseBridge.redeem(to, chainId, token, swappedAmount);\n }\n\n function swapAndRedeemAndSwap(\n address to,\n uint256 chainId,\n IERC20 token,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx,\n uint256 minDy,\n uint256 deadline,\n uint8 swapTokenIndexFrom,\n uint8 swapTokenIndexTo,\n uint256 swapMinDy,\n uint256 swapDeadline\n ) external {\n require(\n address(swapMap[address(token)]) != address(0),\n \"Swap is 0x00\"\n );\n IERC20[] memory tokens = swapTokensMap[\n swapMap[address(token)]\n ];\n tokens[tokenIndexFrom].safeTransferFrom(\n msg.sender,\n address(this),\n dx\n );\n // swap\n\n uint256 swappedAmount = ISwap(swapMap[address(token)]).swap(tokenIndexFrom, tokenIndexTo, dx, minDy, deadline);\n // deposit into bridge, gets nUSD\n if (\n token.allowance(address(this), address(synapseBridge)) <\n swappedAmount\n ) {\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n }\n synapseBridge.redeemAndSwap(\n to,\n chainId,\n token,\n swappedAmount,\n swapTokenIndexFrom,\n swapTokenIndexTo,\n swapMinDy,\n swapDeadline\n );\n }\n\n function swapAndRedeemAndRemove(\n address to,\n uint256 chainId,\n IERC20 token,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx,\n uint256 minDy,\n uint256 deadline,\n uint8 liqTokenIndex,\n uint256 liqMinAmount,\n uint256 liqDeadline\n ) external {\n ISwap swap = ISwap(swapMap[address(token)]);\n require(address(swap) != address(0), \"Swap is 0x00\");\n IERC20[] memory tokens = swapTokensMap[address(swap)];\n tokens[tokenIndexFrom].safeTransferFrom(\n msg.sender,\n address(this),\n dx\n );\n // swap\n\n uint256 swappedAmount = swap.swap(\n tokenIndexFrom,\n tokenIndexTo,\n dx,\n minDy,\n deadline\n );\n // deposit into bridge, gets nUSD\n if (\n token.allowance(address(this), address(synapseBridge)) <\n swappedAmount\n ) {\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n }\n synapseBridge.redeemAndRemove(\n to,\n chainId,\n token,\n swappedAmount,\n liqTokenIndex,\n liqMinAmount,\n liqDeadline\n );\n }\n\n /**\n * @notice wraps SynapseBridge redeem()\n * @param to address on other chain to redeem underlying assets to\n * @param chainId which underlying chain to bridge assets onto\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n **/\n function redeem(\n address to,\n uint256 chainId,\n IERC20 token,\n uint256 amount\n ) external {\n token.safeTransferFrom(msg.sender, address(this), amount);\n if (address(token) == address(CANOLICAL_FRAX)) {\n uint256 swappedAmount = CANOLICAL_FRAX.exchangeCanonicalForOld(address(SYN_FRAX), amount);\n if (SYN_FRAX.allowance(address(this), address(synapseBridge)) < amount) {\n SYN_FRAX.safeApprove(address(synapseBridge), MAX_UINT256);\n }\n synapseBridge.redeem(to, chainId, SYN_FRAX, swappedAmount);\n } else {\n if (token.allowance(address(this), address(synapseBridge)) < amount) {\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n }\n synapseBridge.redeem(to, chainId, token, amount);\n }\n \n }\n\n /**\n * @notice Wraps SynapseBridge redeemv2() function\n * @param to address on other chain to bridge assets to\n * @param chainId which chain to bridge assets onto\n * @param token ERC20 compatible token to redeem into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n **/\n function redeemv2(\n bytes32 to,\n uint256 chainId,\n IERC20 token,\n uint256 amount\n ) external {\n token.safeTransferFrom(msg.sender, address(this), amount);\n\n if (token.allowance(address(this), address(synapseBridge)) < amount) {\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n }\n synapseBridge.redeemv2(to, chainId, token, amount);\n }\n\n /**\n * @notice wraps SynapseBridge redeem()\n * @param to address on other chain to redeem underlying assets to\n * @param chainId which underlying chain to bridge assets onto\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n **/\n function deposit(\n address to,\n uint256 chainId,\n IERC20 token,\n uint256 amount\n ) external {\n token.safeTransferFrom(msg.sender, address(this), amount);\n if (token.allowance(address(this), address(synapseBridge)) < amount) {\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n }\n synapseBridge.deposit(to, chainId, token, amount);\n }\n\n function swapETHAndRedeem(\n address to,\n uint256 chainId,\n IERC20 token,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx,\n uint256 minDy,\n uint256 deadline\n ) external payable {\n require(WETH_ADDRESS != address(0), \"WETH 0\");\n require(msg.value > 0 && msg.value == dx, \"INCORRECT MSG VALUE\");\n ISwap swap = ISwap(swapMap[address(token)]);\n require(address(swap) != address(0), \"Swap is 0x00\");\n IWETH9(WETH_ADDRESS).deposit{value: msg.value}();\n\n // swap\n uint256 swappedAmount = swap.swap(\n tokenIndexFrom,\n tokenIndexTo,\n dx,\n minDy,\n deadline\n );\n synapseBridge.redeem(to, chainId, token, swappedAmount);\n }\n\n /**\n * @notice Wraps redeemAndSwap on SynapseBridge.sol\n * Relays to nodes that (typically) a wrapped synAsset ERC20 token has been burned and the underlying needs to be redeeemed on the native chain. This function indicates to the nodes that they should attempt to redeem the LP token for the underlying assets (E.g \"swap\" out of the LP token)\n * @param to address on other chain to redeem underlying assets to\n * @param chainId which underlying chain to bridge assets onto\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n * @param tokenIndexFrom the token the user wants to swap from\n * @param tokenIndexTo the token the user wants to swap to\n * @param minDy the min amount the user would like to receive, or revert to only minting the SynERC20 token crosschain.\n * @param deadline latest timestamp to accept this transaction\n **/\n function redeemAndSwap(\n address to,\n uint256 chainId,\n IERC20 token,\n uint256 amount,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 minDy,\n uint256 deadline\n ) external {\n token.safeTransferFrom(msg.sender, address(this), amount);\n if (token.allowance(address(this), address(synapseBridge)) < amount) {\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n }\n synapseBridge.redeemAndSwap(\n to,\n chainId,\n token,\n amount,\n tokenIndexFrom,\n tokenIndexTo,\n minDy,\n deadline\n );\n }\n\n /**\n * @notice Wraps redeemAndRemove on SynapseBridge\n * Relays to nodes that (typically) a wrapped synAsset ERC20 token has been burned and the underlying needs to be redeeemed on the native chain. This function indicates to the nodes that they should attempt to redeem the LP token for the underlying assets (E.g \"swap\" out of the LP token)\n * @param to address on other chain to redeem underlying assets to\n * @param chainId which underlying chain to bridge assets onto\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount of (typically) LP token to pass to the nodes to attempt to removeLiquidity() with to redeem for the underlying assets of the LP token\n * @param liqTokenIndex Specifies which of the underlying LP assets the nodes should attempt to redeem for\n * @param liqMinAmount Specifies the minimum amount of the underlying asset needed for the nodes to execute the redeem/swap\n * @param liqDeadline Specificies the deadline that the nodes are allowed to try to redeem/swap the LP token\n **/\n function redeemAndRemove(\n address to,\n uint256 chainId,\n IERC20 token,\n uint256 amount,\n uint8 liqTokenIndex,\n uint256 liqMinAmount,\n uint256 liqDeadline\n ) external {\n token.safeTransferFrom(msg.sender, address(this), amount);\n if (token.allowance(address(this), address(synapseBridge)) < amount) {\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n }\n synapseBridge.redeemAndRemove(\n to,\n chainId,\n token,\n amount,\n liqTokenIndex,\n liqMinAmount,\n liqDeadline\n );\n }\n}\n" + }, + "contracts/bridge/wrappers/AvalancheBridgeZap.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.6.12;\n\nimport \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/SafeERC20.sol\";\nimport \"../interfaces/ISwap.sol\";\nimport \"../interfaces/ISynapseBridge.sol\";\nimport \"../interfaces/IWETH9.sol\";\n\ncontract AvalancheBridgeZap {\n using SafeERC20 for IERC20;\n\n ISynapseBridge synapseBridge;\n address payable public immutable WETH_ADDRESS;\n\n mapping(address => address) public swapMap;\n mapping(address => IERC20[]) public swapTokensMap;\n\n uint256 constant MAX_UINT256 = 2**256 - 1;\n\n constructor(\n address payable _wethAddress,\n address _swapOne,\n address tokenOne,\n address _swapTwo,\n address tokenTwo,\n ISynapseBridge _synapseBridge\n ) public {\n WETH_ADDRESS = _wethAddress;\n synapseBridge = _synapseBridge;\n swapMap[tokenOne] = _swapOne;\n swapMap[tokenTwo] = _swapTwo;\n if (_wethAddress != address(0)) {\n IERC20(_wethAddress).safeIncreaseAllowance(address(_synapseBridge), MAX_UINT256);\n }\n if (address(_swapOne) != address(0)) {\n {\n uint8 i;\n for (; i < 32; i++) {\n try ISwap(_swapOne).getToken(i) returns (\n IERC20 token\n ) {\n swapTokensMap[_swapOne].push(token);\n token.safeApprove(address(_swapOne), MAX_UINT256);\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n } catch {\n break;\n }\n }\n require(i > 1, \"swap must have at least 2 tokens\");\n }\n }\n if (address(_swapTwo) != address(0)) {\n {\n uint8 i;\n for (; i < 32; i++) {\n try ISwap(_swapTwo).getToken(i) returns (\n IERC20 token\n ) {\n swapTokensMap[_swapTwo].push(token);\n token.safeApprove(address(_swapTwo), MAX_UINT256);\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n } catch {\n break;\n }\n }\n require(i > 1, \"swap must have at least 2 tokens\");\n }\n }\n }\n\n /**\n * @notice Calculate amount of tokens you receive on swap\n * @param tokenIndexFrom the token the user wants to sell\n * @param tokenIndexTo the token the user wants to buy\n * @param dx the amount of tokens the user wants to sell. If the token charges\n * a fee on transfers, use the amount that gets transferred after the fee.\n * @return amount of tokens the user will receive\n */\n function calculateSwap(\n IERC20 token,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx\n ) external view virtual returns (uint256) {\n ISwap swap = ISwap(\n swapMap[address(token)]\n );\n return swap.calculateSwap(tokenIndexFrom, tokenIndexTo, dx);\n }\n\n function swapAndRedeem(\n address to,\n uint256 chainId,\n IERC20 token,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx,\n uint256 minDy,\n uint256 deadline\n ) external {\n ISwap swap = ISwap(swapMap[address(token)]);\n require(address(swap) != address(0), \"Swap is 0x00\");\n IERC20[] memory tokens = swapTokensMap[address(swap)];\n tokens[tokenIndexFrom].safeTransferFrom(\n msg.sender,\n address(this),\n dx\n );\n // swap\n\n uint256 swappedAmount = swap.swap(\n tokenIndexFrom,\n tokenIndexTo,\n dx,\n minDy,\n deadline\n );\n // deposit into bridge, gets nUSD\n if (\n token.allowance(address(this), address(synapseBridge)) <\n swappedAmount\n ) {\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n }\n synapseBridge.redeem(to, chainId, token, swappedAmount);\n }\n\n function swapAndRedeemAndSwap(\n address to,\n uint256 chainId,\n IERC20 token,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx,\n uint256 minDy,\n uint256 deadline,\n uint8 swapTokenIndexFrom,\n uint8 swapTokenIndexTo,\n uint256 swapMinDy,\n uint256 swapDeadline\n ) external {\n require(\n address(swapMap[address(token)]) != address(0),\n \"Swap is 0x00\"\n );\n IERC20[] memory tokens = swapTokensMap[\n swapMap[address(token)]\n ];\n tokens[tokenIndexFrom].safeTransferFrom(\n msg.sender,\n address(this),\n dx\n );\n // swap\n\n uint256 swappedAmount = ISwap(swapMap[address(token)]).swap(tokenIndexFrom, tokenIndexTo, dx, minDy, deadline);\n // deposit into bridge, gets nUSD\n if (\n token.allowance(address(this), address(synapseBridge)) <\n swappedAmount\n ) {\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n }\n synapseBridge.redeemAndSwap(\n to,\n chainId,\n token,\n swappedAmount,\n swapTokenIndexFrom,\n swapTokenIndexTo,\n swapMinDy,\n swapDeadline\n );\n }\n\n function swapAndRedeemAndRemove(\n address to,\n uint256 chainId,\n IERC20 token,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx,\n uint256 minDy,\n uint256 deadline,\n uint8 liqTokenIndex,\n uint256 liqMinAmount,\n uint256 liqDeadline\n ) external {\n ISwap swap = ISwap(swapMap[address(token)]);\n require(address(swap) != address(0), \"Swap is 0x00\");\n IERC20[] memory tokens = swapTokensMap[address(swap)];\n tokens[tokenIndexFrom].safeTransferFrom(\n msg.sender,\n address(this),\n dx\n );\n // swap\n\n uint256 swappedAmount = swap.swap(\n tokenIndexFrom,\n tokenIndexTo,\n dx,\n minDy,\n deadline\n );\n // deposit into bridge, gets nUSD\n if (\n token.allowance(address(this), address(synapseBridge)) <\n swappedAmount\n ) {\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n }\n synapseBridge.redeemAndRemove(\n to,\n chainId,\n token,\n swappedAmount,\n liqTokenIndex,\n liqMinAmount,\n liqDeadline\n );\n }\n\n /**\n * @notice wraps SynapseBridge redeem()\n * @param to address on other chain to redeem underlying assets to\n * @param chainId which underlying chain to bridge assets onto\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n **/\n function redeem(\n address to,\n uint256 chainId,\n IERC20 token,\n uint256 amount\n ) external {\n token.safeTransferFrom(msg.sender, address(this), amount);\n if (token.allowance(address(this), address(synapseBridge)) < amount) {\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n }\n synapseBridge.redeem(to, chainId, token, amount);\n }\n\n /**\n * @notice wraps SynapseBridge redeem()\n * @param to address on other chain to redeem underlying assets to\n * @param chainId which underlying chain to bridge assets onto\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n **/\n function deposit(\n address to,\n uint256 chainId,\n IERC20 token,\n uint256 amount\n ) external {\n token.safeTransferFrom(msg.sender, address(this), amount);\n if (token.allowance(address(this), address(synapseBridge)) < amount) {\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n }\n synapseBridge.deposit(to, chainId, token, amount);\n }\n\n /**\n * @notice Wraps SynapseBridge deposit() function to make it compatible w/ ETH -> WETH conversions\n * @param to address on other chain to bridge assets to\n * @param chainId which chain to bridge assets onto\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n **/\n function depositETH(\n address to,\n uint256 chainId,\n uint256 amount\n ) external payable {\n require(msg.value > 0 && msg.value == amount, 'INCORRECT MSG VALUE');\n IWETH9(WETH_ADDRESS).deposit{value: msg.value}();\n synapseBridge.deposit(to, chainId, IERC20(WETH_ADDRESS), amount);\n }\n\n\n function swapETHAndRedeem(\n address to,\n uint256 chainId,\n IERC20 token,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx,\n uint256 minDy,\n uint256 deadline\n ) external payable {\n require(WETH_ADDRESS != address(0), \"WETH 0\");\n require(msg.value > 0 && msg.value == dx, \"INCORRECT MSG VALUE\");\n ISwap swap = ISwap(swapMap[address(token)]);\n require(address(swap) != address(0), \"Swap is 0x00\");\n IWETH9(WETH_ADDRESS).deposit{value: msg.value}();\n\n // swap\n uint256 swappedAmount = swap.swap(\n tokenIndexFrom,\n tokenIndexTo,\n dx,\n minDy,\n deadline\n );\n synapseBridge.redeem(to, chainId, token, swappedAmount);\n }\n\n\n function swapETHAndRedeemAndSwap(\n address to,\n uint256 chainId,\n IERC20 token,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx,\n uint256 minDy,\n uint256 deadline,\n uint8 swapTokenIndexFrom,\n uint8 swapTokenIndexTo,\n uint256 swapMinDy,\n uint256 swapDeadline\n ) external payable {\n require(WETH_ADDRESS != address(0), \"WETH 0\");\n require(msg.value > 0 && msg.value == dx, \"INCORRECT MSG VALUE\");\n ISwap swap = ISwap(swapMap[address(token)]);\n require(address(swap) != address(0), \"Swap is 0x00\");\n IWETH9(WETH_ADDRESS).deposit{value: msg.value}();\n\n // swap\n uint256 swappedAmount = swap.swap(\n tokenIndexFrom,\n tokenIndexTo,\n dx,\n minDy,\n deadline\n );\n synapseBridge.redeemAndSwap(to, chainId, token, swappedAmount,swapTokenIndexFrom,\n swapTokenIndexTo,\n swapMinDy,\n swapDeadline);\n }\n\n\n /**\n * @notice Wraps redeemAndSwap on SynapseBridge.sol\n * Relays to nodes that (typically) a wrapped synAsset ERC20 token has been burned and the underlying needs to be redeeemed on the native chain. This function indicates to the nodes that they should attempt to redeem the LP token for the underlying assets (E.g \"swap\" out of the LP token)\n * @param to address on other chain to redeem underlying assets to\n * @param chainId which underlying chain to bridge assets onto\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n * @param tokenIndexFrom the token the user wants to swap from\n * @param tokenIndexTo the token the user wants to swap to\n * @param minDy the min amount the user would like to receive, or revert to only minting the SynERC20 token crosschain.\n * @param deadline latest timestamp to accept this transaction\n **/\n function redeemAndSwap(\n address to,\n uint256 chainId,\n IERC20 token,\n uint256 amount,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 minDy,\n uint256 deadline\n ) external {\n token.safeTransferFrom(msg.sender, address(this), amount);\n if (token.allowance(address(this), address(synapseBridge)) < amount) {\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n }\n synapseBridge.redeemAndSwap(\n to,\n chainId,\n token,\n amount,\n tokenIndexFrom,\n tokenIndexTo,\n minDy,\n deadline\n );\n }\n\n /**\n * @notice Wraps redeemAndRemove on SynapseBridge\n * Relays to nodes that (typically) a wrapped synAsset ERC20 token has been burned and the underlying needs to be redeeemed on the native chain. This function indicates to the nodes that they should attempt to redeem the LP token for the underlying assets (E.g \"swap\" out of the LP token)\n * @param to address on other chain to redeem underlying assets to\n * @param chainId which underlying chain to bridge assets onto\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount of (typically) LP token to pass to the nodes to attempt to removeLiquidity() with to redeem for the underlying assets of the LP token\n * @param liqTokenIndex Specifies which of the underlying LP assets the nodes should attempt to redeem for\n * @param liqMinAmount Specifies the minimum amount of the underlying asset needed for the nodes to execute the redeem/swap\n * @param liqDeadline Specificies the deadline that the nodes are allowed to try to redeem/swap the LP token\n **/\n function redeemAndRemove(\n address to,\n uint256 chainId,\n IERC20 token,\n uint256 amount,\n uint8 liqTokenIndex,\n uint256 liqMinAmount,\n uint256 liqDeadline\n ) external {\n token.safeTransferFrom(msg.sender, address(this), amount);\n if (token.allowance(address(this), address(synapseBridge)) < amount) {\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n }\n synapseBridge.redeemAndRemove(\n to,\n chainId,\n token,\n amount,\n liqTokenIndex,\n liqMinAmount,\n liqDeadline\n );\n }\n\n /**\n * @notice Wraps SynapseBridge redeemv2() function\n * @param to address on other chain to bridge assets to\n * @param chainId which chain to bridge assets onto\n * @param token ERC20 compatible token to redeem into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n **/\n function redeemv2(\n bytes32 to,\n uint256 chainId,\n IERC20 token,\n uint256 amount\n ) external {\n token.safeTransferFrom(msg.sender, address(this), amount);\n\n if (token.allowance(address(this), address(synapseBridge)) < amount) {\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n }\n synapseBridge.redeemv2(to, chainId, token, amount);\n }\n}\n" + }, + "contracts/bridge/SynapseBridge.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.6.12;\n\nimport \"@openzeppelin/contracts-upgradeable/proxy/Initializable.sol\";\nimport \"@openzeppelin/contracts-upgradeable/access/AccessControlUpgradeable.sol\";\nimport \"@openzeppelin/contracts-upgradeable/utils/ReentrancyGuardUpgradeable.sol\";\nimport \"@openzeppelin/contracts-upgradeable/utils/PausableUpgradeable.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/SafeERC20.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/ERC20Burnable.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport \"@openzeppelin/contracts/math/SafeMath.sol\";\n\nimport \"./interfaces/ISwap.sol\";\nimport \"./interfaces/IWETH9.sol\";\n\ninterface IERC20Mintable is IERC20 {\n function mint(address to, uint256 amount) external;\n}\n\ncontract SynapseBridge is\n Initializable,\n AccessControlUpgradeable,\n ReentrancyGuardUpgradeable,\n PausableUpgradeable\n{\n using SafeERC20 for IERC20;\n using SafeERC20 for IERC20Mintable;\n using SafeMath for uint256;\n\n bytes32 public constant NODEGROUP_ROLE = keccak256(\"NODEGROUP_ROLE\");\n bytes32 public constant GOVERNANCE_ROLE = keccak256(\"GOVERNANCE_ROLE\");\n\n mapping(address => uint256) private fees;\n\n uint256 public startBlockNumber;\n uint256 public constant bridgeVersion = 6;\n uint256 public chainGasAmount;\n address payable public WETH_ADDRESS;\n\n mapping(bytes32 => bool) private kappaMap;\n\n receive() external payable {}\n\n function initialize() external initializer {\n startBlockNumber = block.number;\n _setupRole(DEFAULT_ADMIN_ROLE, msg.sender);\n __AccessControl_init();\n }\n\n function setChainGasAmount(uint256 amount) external {\n require(hasRole(GOVERNANCE_ROLE, msg.sender), \"Not governance\");\n chainGasAmount = amount;\n }\n\n function setWethAddress(address payable _wethAddress) external {\n require(hasRole(DEFAULT_ADMIN_ROLE, msg.sender), \"Not admin\");\n WETH_ADDRESS = _wethAddress;\n }\n\n function addKappas(bytes32[] calldata kappas) external {\n require(hasRole(GOVERNANCE_ROLE, msg.sender), \"Not governance\");\n for (uint256 i = 0; i < kappas.length; ++i) {\n kappaMap[kappas[i]] = true;\n }\n }\n\n event TokenDeposit(\n address indexed to,\n uint256 chainId,\n IERC20 token,\n uint256 amount\n );\n event TokenRedeem(\n address indexed to,\n uint256 chainId,\n IERC20 token,\n uint256 amount\n );\n event TokenWithdraw(\n address indexed to,\n IERC20 token,\n uint256 amount,\n uint256 fee,\n bytes32 indexed kappa\n );\n event TokenMint(\n address indexed to,\n IERC20Mintable token,\n uint256 amount,\n uint256 fee,\n bytes32 indexed kappa\n );\n event TokenDepositAndSwap(\n address indexed to,\n uint256 chainId,\n IERC20 token,\n uint256 amount,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 minDy,\n uint256 deadline\n );\n event TokenMintAndSwap(\n address indexed to,\n IERC20Mintable token,\n uint256 amount,\n uint256 fee,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 minDy,\n uint256 deadline,\n bool swapSuccess,\n bytes32 indexed kappa\n );\n event TokenRedeemAndSwap(\n address indexed to,\n uint256 chainId,\n IERC20 token,\n uint256 amount,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 minDy,\n uint256 deadline\n );\n event TokenRedeemAndRemove(\n address indexed to,\n uint256 chainId,\n IERC20 token,\n uint256 amount,\n uint8 swapTokenIndex,\n uint256 swapMinAmount,\n uint256 swapDeadline\n );\n event TokenWithdrawAndRemove(\n address indexed to,\n IERC20 token,\n uint256 amount,\n uint256 fee,\n uint8 swapTokenIndex,\n uint256 swapMinAmount,\n uint256 swapDeadline,\n bool swapSuccess,\n bytes32 indexed kappa\n );\n\n // v2 events\n event TokenRedeemV2(\n bytes32 indexed to,\n uint256 chainId,\n IERC20 token,\n uint256 amount\n );\n\n // VIEW FUNCTIONS ***/\n function getFeeBalance(address tokenAddress)\n external\n view\n returns (uint256)\n {\n return fees[tokenAddress];\n }\n\n function kappaExists(bytes32 kappa) external view returns (bool) {\n return kappaMap[kappa];\n }\n\n // FEE FUNCTIONS ***/\n /**\n * * @notice withdraw specified ERC20 token fees to a given address\n * * @param token ERC20 token in which fees acccumulated to transfer\n * * @param to Address to send the fees to\n */\n function withdrawFees(IERC20 token, address to) external whenNotPaused {\n require(hasRole(GOVERNANCE_ROLE, msg.sender), \"Not governance\");\n require(to != address(0), \"Address is 0x000\");\n if (fees[address(token)] != 0) {\n token.safeTransfer(to, fees[address(token)]);\n fees[address(token)] = 0;\n }\n }\n\n // PAUSABLE FUNCTIONS ***/\n function pause() external {\n require(hasRole(GOVERNANCE_ROLE, msg.sender), \"Not governance\");\n _pause();\n }\n\n function unpause() external {\n require(hasRole(GOVERNANCE_ROLE, msg.sender), \"Not governance\");\n _unpause();\n }\n\n /**\n * @notice Relays to nodes to transfers an ERC20 token cross-chain\n * @param to address on other chain to bridge assets to\n * @param chainId which chain to bridge assets onto\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n **/\n function deposit(\n address to,\n uint256 chainId,\n IERC20 token,\n uint256 amount\n ) external nonReentrant whenNotPaused {\n emit TokenDeposit(to, chainId, token, amount);\n token.safeTransferFrom(msg.sender, address(this), amount);\n }\n\n /**\n * @notice Relays to nodes that (typically) a wrapped synAsset ERC20 token has been burned and the underlying needs to be redeeemed on the native chain\n * @param to address on other chain to redeem underlying assets to\n * @param chainId which underlying chain to bridge assets onto\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n **/\n function redeem(\n address to,\n uint256 chainId,\n ERC20Burnable token,\n uint256 amount\n ) external nonReentrant whenNotPaused {\n emit TokenRedeem(to, chainId, token, amount);\n token.burnFrom(msg.sender, amount);\n }\n\n /**\n * @notice Function to be called by the node group to withdraw the underlying assets from the contract\n * @param to address on chain to send underlying assets to\n * @param token ERC20 compatible token to withdraw from the bridge\n * @param amount Amount in native token decimals to withdraw\n * @param fee Amount in native token decimals to save to the contract as fees\n * @param kappa kappa\n **/\n function withdraw(\n address to,\n IERC20 token,\n uint256 amount,\n uint256 fee,\n bytes32 kappa\n ) external nonReentrant whenNotPaused {\n require(\n hasRole(NODEGROUP_ROLE, msg.sender),\n \"Caller is not a node group\"\n );\n require(amount > fee, \"Amount must be greater than fee\");\n require(!kappaMap[kappa], \"Kappa is already present\");\n kappaMap[kappa] = true;\n fees[address(token)] = fees[address(token)].add(fee);\n if (address(token) == WETH_ADDRESS && WETH_ADDRESS != address(0)) {\n IWETH9(WETH_ADDRESS).withdraw(amount.sub(fee));\n (bool success, ) = to.call{value: amount.sub(fee)}(\"\");\n require(success, \"ETH_TRANSFER_FAILED\");\n emit TokenWithdraw(to, token, amount, fee, kappa);\n } else {\n emit TokenWithdraw(to, token, amount, fee, kappa);\n token.safeTransfer(to, amount.sub(fee));\n }\n }\n\n /**\n * @notice Nodes call this function to mint a SynERC20 (or any asset that the bridge is given minter access to). This is called by the nodes after a TokenDeposit event is emitted.\n * @dev This means the SynapseBridge.sol contract must have minter access to the token attempting to be minted\n * @param to address on other chain to redeem underlying assets to\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain post-fees\n * @param fee Amount in native token decimals to save to the contract as fees\n * @param kappa kappa\n **/\n function mint(\n address payable to,\n IERC20Mintable token,\n uint256 amount,\n uint256 fee,\n bytes32 kappa\n ) external nonReentrant whenNotPaused {\n require(\n hasRole(NODEGROUP_ROLE, msg.sender),\n \"Caller is not a node group\"\n );\n require(amount > fee, \"Amount must be greater than fee\");\n require(!kappaMap[kappa], \"Kappa is already present\");\n kappaMap[kappa] = true;\n fees[address(token)] = fees[address(token)].add(fee);\n emit TokenMint(to, token, amount.sub(fee), fee, kappa);\n token.mint(address(this), amount);\n IERC20(token).safeTransfer(to, amount.sub(fee));\n if (chainGasAmount != 0 && address(this).balance > chainGasAmount) {\n to.call.value(chainGasAmount)(\"\");\n }\n }\n\n /**\n * @notice Relays to nodes to both transfer an ERC20 token cross-chain, and then have the nodes execute a swap through a liquidity pool on behalf of the user.\n * @param to address on other chain to bridge assets to\n * @param chainId which chain to bridge assets onto\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n * @param tokenIndexFrom the token the user wants to swap from\n * @param tokenIndexTo the token the user wants to swap to\n * @param minDy the min amount the user would like to receive, or revert to only minting the SynERC20 token crosschain.\n * @param deadline latest timestamp to accept this transaction\n **/\n function depositAndSwap(\n address to,\n uint256 chainId,\n IERC20 token,\n uint256 amount,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 minDy,\n uint256 deadline\n ) external nonReentrant whenNotPaused {\n emit TokenDepositAndSwap(\n to,\n chainId,\n token,\n amount,\n tokenIndexFrom,\n tokenIndexTo,\n minDy,\n deadline\n );\n token.safeTransferFrom(msg.sender, address(this), amount);\n }\n\n /**\n * @notice Relays to nodes that (typically) a wrapped synAsset ERC20 token has been burned and the underlying needs to be redeeemed on the native chain. This function indicates to the nodes that they should attempt to redeem the LP token for the underlying assets (E.g \"swap\" out of the LP token)\n * @param to address on other chain to redeem underlying assets to\n * @param chainId which underlying chain to bridge assets onto\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n * @param tokenIndexFrom the token the user wants to swap from\n * @param tokenIndexTo the token the user wants to swap to\n * @param minDy the min amount the user would like to receive, or revert to only minting the SynERC20 token crosschain.\n * @param deadline latest timestamp to accept this transaction\n **/\n function redeemAndSwap(\n address to,\n uint256 chainId,\n ERC20Burnable token,\n uint256 amount,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 minDy,\n uint256 deadline\n ) external nonReentrant whenNotPaused {\n emit TokenRedeemAndSwap(\n to,\n chainId,\n token,\n amount,\n tokenIndexFrom,\n tokenIndexTo,\n minDy,\n deadline\n );\n token.burnFrom(msg.sender, amount);\n }\n\n /**\n * @notice Relays to nodes that (typically) a wrapped synAsset ERC20 token has been burned and the underlying needs to be redeeemed on the native chain. This function indicates to the nodes that they should attempt to redeem the LP token for the underlying assets (E.g \"swap\" out of the LP token)\n * @param to address on other chain to redeem underlying assets to\n * @param chainId which underlying chain to bridge assets onto\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n * @param swapTokenIndex Specifies which of the underlying LP assets the nodes should attempt to redeem for\n * @param swapMinAmount Specifies the minimum amount of the underlying asset needed for the nodes to execute the redeem/swap\n * @param swapDeadline Specificies the deadline that the nodes are allowed to try to redeem/swap the LP token\n **/\n function redeemAndRemove(\n address to,\n uint256 chainId,\n ERC20Burnable token,\n uint256 amount,\n uint8 swapTokenIndex,\n uint256 swapMinAmount,\n uint256 swapDeadline\n ) external nonReentrant whenNotPaused {\n emit TokenRedeemAndRemove(\n to,\n chainId,\n token,\n amount,\n swapTokenIndex,\n swapMinAmount,\n swapDeadline\n );\n token.burnFrom(msg.sender, amount);\n }\n\n /**\n * @notice Nodes call this function to mint a SynERC20 (or any asset that the bridge is given minter access to), and then attempt to swap the SynERC20 into the desired destination asset. This is called by the nodes after a TokenDepositAndSwap event is emitted.\n * @dev This means the BridgeDeposit.sol contract must have minter access to the token attempting to be minted\n * @param to address on other chain to redeem underlying assets to\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain post-fees\n * @param fee Amount in native token decimals to save to the contract as fees\n * @param pool Destination chain's pool to use to swap SynERC20 -> Asset. The nodes determine this by using PoolConfig.sol.\n * @param tokenIndexFrom Index of the SynERC20 asset in the pool\n * @param tokenIndexTo Index of the desired final asset\n * @param minDy Minumum amount (in final asset decimals) that must be swapped for, otherwise the user will receive the SynERC20.\n * @param deadline Epoch time of the deadline that the swap is allowed to be executed.\n * @param kappa kappa\n **/\n function mintAndSwap(\n address payable to,\n IERC20Mintable token,\n uint256 amount,\n uint256 fee,\n ISwap pool,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 minDy,\n uint256 deadline,\n bytes32 kappa\n ) external nonReentrant whenNotPaused {\n require(\n hasRole(NODEGROUP_ROLE, msg.sender),\n \"Caller is not a node group\"\n );\n require(amount > fee, \"Amount must be greater than fee\");\n require(!kappaMap[kappa], \"Kappa is already present\");\n kappaMap[kappa] = true;\n fees[address(token)] = fees[address(token)].add(fee);\n // Transfer gas airdrop\n if (chainGasAmount != 0 && address(this).balance > chainGasAmount) {\n to.call.value(chainGasAmount)(\"\");\n }\n // first check to make sure more will be given than min amount required\n uint256 expectedOutput = ISwap(pool).calculateSwap(\n tokenIndexFrom,\n tokenIndexTo,\n amount.sub(fee)\n );\n\n if (expectedOutput >= minDy) {\n // proceed with swap\n token.mint(address(this), amount);\n token.safeIncreaseAllowance(address(pool), amount);\n try\n ISwap(pool).swap(\n tokenIndexFrom,\n tokenIndexTo,\n amount.sub(fee),\n minDy,\n deadline\n )\n returns (uint256 finalSwappedAmount) {\n // Swap succeeded, transfer swapped asset\n IERC20 swappedTokenTo = ISwap(pool).getToken(tokenIndexTo);\n if (\n address(swappedTokenTo) == WETH_ADDRESS &&\n WETH_ADDRESS != address(0)\n ) {\n IWETH9(WETH_ADDRESS).withdraw(finalSwappedAmount);\n (bool success, ) = to.call{value: finalSwappedAmount}(\"\");\n require(success, \"ETH_TRANSFER_FAILED\");\n emit TokenMintAndSwap(\n to,\n token,\n finalSwappedAmount,\n fee,\n tokenIndexFrom,\n tokenIndexTo,\n minDy,\n deadline,\n true,\n kappa\n );\n } else {\n swappedTokenTo.safeTransfer(to, finalSwappedAmount);\n emit TokenMintAndSwap(\n to,\n token,\n finalSwappedAmount,\n fee,\n tokenIndexFrom,\n tokenIndexTo,\n minDy,\n deadline,\n true,\n kappa\n );\n }\n } catch {\n IERC20(token).safeTransfer(to, amount.sub(fee));\n emit TokenMintAndSwap(\n to,\n token,\n amount.sub(fee),\n fee,\n tokenIndexFrom,\n tokenIndexTo,\n minDy,\n deadline,\n false,\n kappa\n );\n }\n } else {\n token.mint(address(this), amount);\n IERC20(token).safeTransfer(to, amount.sub(fee));\n emit TokenMintAndSwap(\n to,\n token,\n amount.sub(fee),\n fee,\n tokenIndexFrom,\n tokenIndexTo,\n minDy,\n deadline,\n false,\n kappa\n );\n }\n }\n\n /**\n * @notice Function to be called by the node group to withdraw the underlying assets from the contract\n * @param to address on chain to send underlying assets to\n * @param token ERC20 compatible token to withdraw from the bridge\n * @param amount Amount in native token decimals to withdraw\n * @param fee Amount in native token decimals to save to the contract as fees\n * @param pool Destination chain's pool to use to swap SynERC20 -> Asset. The nodes determine this by using PoolConfig.sol.\n * @param swapTokenIndex Specifies which of the underlying LP assets the nodes should attempt to redeem for\n * @param swapMinAmount Specifies the minimum amount of the underlying asset needed for the nodes to execute the redeem/swap\n * @param swapDeadline Specificies the deadline that the nodes are allowed to try to redeem/swap the LP token\n * @param kappa kappa\n **/\n function withdrawAndRemove(\n address to,\n IERC20 token,\n uint256 amount,\n uint256 fee,\n ISwap pool,\n uint8 swapTokenIndex,\n uint256 swapMinAmount,\n uint256 swapDeadline,\n bytes32 kappa\n ) external nonReentrant whenNotPaused {\n require(\n hasRole(NODEGROUP_ROLE, msg.sender),\n \"Caller is not a node group\"\n );\n require(amount > fee, \"Amount must be greater than fee\");\n require(!kappaMap[kappa], \"Kappa is already present\");\n kappaMap[kappa] = true;\n fees[address(token)] = fees[address(token)].add(fee);\n // first check to make sure more will be given than min amount required\n uint256 expectedOutput = ISwap(pool).calculateRemoveLiquidityOneToken(\n amount.sub(fee),\n swapTokenIndex\n );\n\n if (expectedOutput >= swapMinAmount) {\n token.safeIncreaseAllowance(address(pool), amount.sub(fee));\n try\n ISwap(pool).removeLiquidityOneToken(\n amount.sub(fee),\n swapTokenIndex,\n swapMinAmount,\n swapDeadline\n )\n returns (uint256 finalSwappedAmount) {\n // Swap succeeded, transfer swapped asset\n IERC20 swappedTokenTo = ISwap(pool).getToken(swapTokenIndex);\n swappedTokenTo.safeTransfer(to, finalSwappedAmount);\n emit TokenWithdrawAndRemove(\n to,\n token,\n finalSwappedAmount,\n fee,\n swapTokenIndex,\n swapMinAmount,\n swapDeadline,\n true,\n kappa\n );\n } catch {\n IERC20(token).safeTransfer(to, amount.sub(fee));\n emit TokenWithdrawAndRemove(\n to,\n token,\n amount.sub(fee),\n fee,\n swapTokenIndex,\n swapMinAmount,\n swapDeadline,\n false,\n kappa\n );\n }\n } else {\n token.safeTransfer(to, amount.sub(fee));\n emit TokenWithdrawAndRemove(\n to,\n token,\n amount.sub(fee),\n fee,\n swapTokenIndex,\n swapMinAmount,\n swapDeadline,\n false,\n kappa\n );\n }\n }\n\n // BRIDGE FUNCTIONS TO HANDLE DIFF ADDRESSES\n /**\n * @notice Relays to nodes that (typically) a wrapped synAsset ERC20 token has been burned and the underlying needs to be redeeemed on the native chain\n * @param to address on other chain to redeem underlying assets to\n * @param chainId which underlying chain to bridge assets onto\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n **/\n function redeemV2(\n bytes32 to,\n uint256 chainId,\n ERC20Burnable token,\n uint256 amount\n ) external nonReentrant whenNotPaused {\n emit TokenRedeemV2(to, chainId, token, amount);\n token.burnFrom(msg.sender, amount);\n }\n}\n" + }, + "@openzeppelin/contracts-upgradeable/access/AccessControlUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <0.8.0;\n\nimport \"../utils/EnumerableSetUpgradeable.sol\";\nimport \"../utils/AddressUpgradeable.sol\";\nimport \"../utils/ContextUpgradeable.sol\";\nimport \"../proxy/Initializable.sol\";\n\n/**\n * @dev Contract module that allows children to implement role-based access\n * control mechanisms.\n *\n * Roles are referred to by their `bytes32` identifier. These should be exposed\n * in the external API and be unique. The best way to achieve this is by\n * using `public constant` hash digests:\n *\n * ```\n * bytes32 public constant MY_ROLE = keccak256(\"MY_ROLE\");\n * ```\n *\n * Roles can be used to represent a set of permissions. To restrict access to a\n * function call, use {hasRole}:\n *\n * ```\n * function foo() public {\n * require(hasRole(MY_ROLE, msg.sender));\n * ...\n * }\n * ```\n *\n * Roles can be granted and revoked dynamically via the {grantRole} and\n * {revokeRole} functions. Each role has an associated admin role, and only\n * accounts that have a role's admin role can call {grantRole} and {revokeRole}.\n *\n * By default, the admin role for all roles is `DEFAULT_ADMIN_ROLE`, which means\n * that only accounts with this role will be able to grant or revoke other\n * roles. More complex role relationships can be created by using\n * {_setRoleAdmin}.\n *\n * WARNING: The `DEFAULT_ADMIN_ROLE` is also its own admin: it has permission to\n * grant and revoke this role. Extra precautions should be taken to secure\n * accounts that have been granted it.\n */\nabstract contract AccessControlUpgradeable is Initializable, ContextUpgradeable {\n function __AccessControl_init() internal initializer {\n __Context_init_unchained();\n __AccessControl_init_unchained();\n }\n\n function __AccessControl_init_unchained() internal initializer {\n }\n using EnumerableSetUpgradeable for EnumerableSetUpgradeable.AddressSet;\n using AddressUpgradeable for address;\n\n struct RoleData {\n EnumerableSetUpgradeable.AddressSet members;\n bytes32 adminRole;\n }\n\n mapping (bytes32 => RoleData) private _roles;\n\n bytes32 public constant DEFAULT_ADMIN_ROLE = 0x00;\n\n /**\n * @dev Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole`\n *\n * `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite\n * {RoleAdminChanged} not being emitted signaling this.\n *\n * _Available since v3.1._\n */\n event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole);\n\n /**\n * @dev Emitted when `account` is granted `role`.\n *\n * `sender` is the account that originated the contract call, an admin role\n * bearer except when using {_setupRole}.\n */\n event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender);\n\n /**\n * @dev Emitted when `account` is revoked `role`.\n *\n * `sender` is the account that originated the contract call:\n * - if using `revokeRole`, it is the admin role bearer\n * - if using `renounceRole`, it is the role bearer (i.e. `account`)\n */\n event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender);\n\n /**\n * @dev Returns `true` if `account` has been granted `role`.\n */\n function hasRole(bytes32 role, address account) public view returns (bool) {\n return _roles[role].members.contains(account);\n }\n\n /**\n * @dev Returns the number of accounts that have `role`. Can be used\n * together with {getRoleMember} to enumerate all bearers of a role.\n */\n function getRoleMemberCount(bytes32 role) public view returns (uint256) {\n return _roles[role].members.length();\n }\n\n /**\n * @dev Returns one of the accounts that have `role`. `index` must be a\n * value between 0 and {getRoleMemberCount}, non-inclusive.\n *\n * Role bearers are not sorted in any particular way, and their ordering may\n * change at any point.\n *\n * WARNING: When using {getRoleMember} and {getRoleMemberCount}, make sure\n * you perform all queries on the same block. See the following\n * https://forum.openzeppelin.com/t/iterating-over-elements-on-enumerableset-in-openzeppelin-contracts/2296[forum post]\n * for more information.\n */\n function getRoleMember(bytes32 role, uint256 index) public view returns (address) {\n return _roles[role].members.at(index);\n }\n\n /**\n * @dev Returns the admin role that controls `role`. See {grantRole} and\n * {revokeRole}.\n *\n * To change a role's admin, use {_setRoleAdmin}.\n */\n function getRoleAdmin(bytes32 role) public view returns (bytes32) {\n return _roles[role].adminRole;\n }\n\n /**\n * @dev Grants `role` to `account`.\n *\n * If `account` had not been already granted `role`, emits a {RoleGranted}\n * event.\n *\n * Requirements:\n *\n * - the caller must have ``role``'s admin role.\n */\n function grantRole(bytes32 role, address account) public virtual {\n require(hasRole(_roles[role].adminRole, _msgSender()), \"AccessControl: sender must be an admin to grant\");\n\n _grantRole(role, account);\n }\n\n /**\n * @dev Revokes `role` from `account`.\n *\n * If `account` had been granted `role`, emits a {RoleRevoked} event.\n *\n * Requirements:\n *\n * - the caller must have ``role``'s admin role.\n */\n function revokeRole(bytes32 role, address account) public virtual {\n require(hasRole(_roles[role].adminRole, _msgSender()), \"AccessControl: sender must be an admin to revoke\");\n\n _revokeRole(role, account);\n }\n\n /**\n * @dev Revokes `role` from the calling account.\n *\n * Roles are often managed via {grantRole} and {revokeRole}: this function's\n * purpose is to provide a mechanism for accounts to lose their privileges\n * if they are compromised (such as when a trusted device is misplaced).\n *\n * If the calling account had been granted `role`, emits a {RoleRevoked}\n * event.\n *\n * Requirements:\n *\n * - the caller must be `account`.\n */\n function renounceRole(bytes32 role, address account) public virtual {\n require(account == _msgSender(), \"AccessControl: can only renounce roles for self\");\n\n _revokeRole(role, account);\n }\n\n /**\n * @dev Grants `role` to `account`.\n *\n * If `account` had not been already granted `role`, emits a {RoleGranted}\n * event. Note that unlike {grantRole}, this function doesn't perform any\n * checks on the calling account.\n *\n * [WARNING]\n * ====\n * This function should only be called from the constructor when setting\n * up the initial roles for the system.\n *\n * Using this function in any other way is effectively circumventing the admin\n * system imposed by {AccessControl}.\n * ====\n */\n function _setupRole(bytes32 role, address account) internal virtual {\n _grantRole(role, account);\n }\n\n /**\n * @dev Sets `adminRole` as ``role``'s admin role.\n *\n * Emits a {RoleAdminChanged} event.\n */\n function _setRoleAdmin(bytes32 role, bytes32 adminRole) internal virtual {\n emit RoleAdminChanged(role, _roles[role].adminRole, adminRole);\n _roles[role].adminRole = adminRole;\n }\n\n function _grantRole(bytes32 role, address account) private {\n if (_roles[role].members.add(account)) {\n emit RoleGranted(role, account, _msgSender());\n }\n }\n\n function _revokeRole(bytes32 role, address account) private {\n if (_roles[role].members.remove(account)) {\n emit RoleRevoked(role, account, _msgSender());\n }\n }\n uint256[49] private __gap;\n}\n" + }, + "@openzeppelin/contracts-upgradeable/utils/EnumerableSetUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <0.8.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 EnumerableSetUpgradeable {\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" + }, + "contracts/bridge/MoonriverSynapseBridge.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.6.12;\n\nimport \"@openzeppelin/contracts-upgradeable/proxy/Initializable.sol\";\nimport \"@openzeppelin/contracts-upgradeable/access/AccessControlUpgradeable.sol\";\nimport \"@openzeppelin/contracts-upgradeable/utils/ReentrancyGuardUpgradeable.sol\";\nimport \"@openzeppelin/contracts-upgradeable/utils/PausableUpgradeable.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/SafeERC20.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/ERC20Burnable.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport \"@openzeppelin/contracts/math/SafeMath.sol\";\n\nimport \"./interfaces/ISwap.sol\";\nimport \"./interfaces/IWETH9.sol\";\n\ninterface IERC20Mintable is IERC20 {\n function mint(address to, uint256 amount) external;\n}\n\ninterface IFrax {\n function exchangeOldForCanonical(\n address bridge_token_address,\n uint256 token_amount\n ) external returns (uint256);\n}\n\ncontract MRSynapseBridge is\n Initializable,\n AccessControlUpgradeable,\n ReentrancyGuardUpgradeable,\n PausableUpgradeable\n{\n using SafeERC20 for IERC20;\n using SafeERC20 for IERC20Mintable;\n using SafeMath for uint256;\n\n bytes32 public constant NODEGROUP_ROLE = keccak256(\"NODEGROUP_ROLE\");\n bytes32 public constant GOVERNANCE_ROLE = keccak256(\"GOVERNANCE_ROLE\");\n\n mapping(address => uint256) private fees;\n\n uint256 public startBlockNumber;\n uint256 public constant bridgeVersion = 6;\n uint256 public chainGasAmount;\n address payable public WETH_ADDRESS;\n\n mapping(bytes32 => bool) private kappaMap;\n\n receive() external payable {}\n\n function initialize() external initializer {\n startBlockNumber = block.number;\n _setupRole(DEFAULT_ADMIN_ROLE, msg.sender);\n __AccessControl_init();\n }\n\n function setChainGasAmount(uint256 amount) external {\n require(hasRole(GOVERNANCE_ROLE, msg.sender), \"Not governance\");\n chainGasAmount = amount;\n }\n\n function setWethAddress(address payable _wethAddress) external {\n require(hasRole(DEFAULT_ADMIN_ROLE, msg.sender), \"Not admin\");\n WETH_ADDRESS = _wethAddress;\n }\n\n function addKappas(bytes32[] calldata kappas) external {\n require(hasRole(GOVERNANCE_ROLE, msg.sender), \"Not governance\");\n for (uint256 i = 0; i < kappas.length; ++i) {\n kappaMap[kappas[i]] = true;\n }\n }\n\n event TokenDeposit(\n address indexed to,\n uint256 chainId,\n IERC20 token,\n uint256 amount\n );\n event TokenRedeem(\n address indexed to,\n uint256 chainId,\n IERC20 token,\n uint256 amount\n );\n event TokenWithdraw(\n address indexed to,\n IERC20 token,\n uint256 amount,\n uint256 fee,\n bytes32 indexed kappa\n );\n event TokenMint(\n address indexed to,\n IERC20Mintable token,\n uint256 amount,\n uint256 fee,\n bytes32 indexed kappa\n );\n event TokenDepositAndSwap(\n address indexed to,\n uint256 chainId,\n IERC20 token,\n uint256 amount,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 minDy,\n uint256 deadline\n );\n event TokenMintAndSwap(\n address indexed to,\n IERC20Mintable token,\n uint256 amount,\n uint256 fee,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 minDy,\n uint256 deadline,\n bool swapSuccess,\n bytes32 indexed kappa\n );\n event TokenRedeemAndSwap(\n address indexed to,\n uint256 chainId,\n IERC20 token,\n uint256 amount,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 minDy,\n uint256 deadline\n );\n event TokenRedeemAndRemove(\n address indexed to,\n uint256 chainId,\n IERC20 token,\n uint256 amount,\n uint8 swapTokenIndex,\n uint256 swapMinAmount,\n uint256 swapDeadline\n );\n event TokenWithdrawAndRemove(\n address indexed to,\n IERC20 token,\n uint256 amount,\n uint256 fee,\n uint8 swapTokenIndex,\n uint256 swapMinAmount,\n uint256 swapDeadline,\n bool swapSuccess,\n bytes32 indexed kappa\n );\n\n // v2 events\n event TokenRedeemV2(\n bytes32 indexed to,\n uint256 chainId,\n IERC20 token,\n uint256 amount\n );\n\n // VIEW FUNCTIONS ***/\n function getFeeBalance(address tokenAddress)\n external\n view\n returns (uint256)\n {\n return fees[tokenAddress];\n }\n\n function kappaExists(bytes32 kappa) external view returns (bool) {\n return kappaMap[kappa];\n }\n\n // FEE FUNCTIONS ***/\n /**\n * * @notice withdraw specified ERC20 token fees to a given address\n * * @param token ERC20 token in which fees acccumulated to transfer\n * * @param to Address to send the fees to\n */\n function withdrawFees(IERC20 token, address to) external whenNotPaused {\n require(hasRole(GOVERNANCE_ROLE, msg.sender), \"Not governance\");\n require(to != address(0), \"Address is 0x000\");\n if (fees[address(token)] != 0) {\n token.safeTransfer(to, fees[address(token)]);\n fees[address(token)] = 0;\n }\n }\n\n // PAUSABLE FUNCTIONS ***/\n function pause() external {\n require(hasRole(GOVERNANCE_ROLE, msg.sender), \"Not governance\");\n _pause();\n }\n\n function unpause() external {\n require(hasRole(GOVERNANCE_ROLE, msg.sender), \"Not governance\");\n _unpause();\n }\n\n /**\n * @notice Relays to nodes to transfers an ERC20 token cross-chain\n * @param to address on other chain to bridge assets to\n * @param chainId which chain to bridge assets onto\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n **/\n function deposit(\n address to,\n uint256 chainId,\n IERC20 token,\n uint256 amount\n ) external nonReentrant whenNotPaused {\n emit TokenDeposit(to, chainId, token, amount);\n token.safeTransferFrom(msg.sender, address(this), amount);\n }\n\n /**\n * @notice Relays to nodes that (typically) a wrapped synAsset ERC20 token has been burned and the underlying needs to be redeeemed on the native chain\n * @param to address on other chain to redeem underlying assets to\n * @param chainId which underlying chain to bridge assets onto\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n **/\n function redeem(\n address to,\n uint256 chainId,\n ERC20Burnable token,\n uint256 amount\n ) external nonReentrant whenNotPaused {\n emit TokenRedeem(to, chainId, token, amount);\n token.burnFrom(msg.sender, amount);\n }\n\n /**\n * @notice Function to be called by the node group to withdraw the underlying assets from the contract\n * @param to address on chain to send underlying assets to\n * @param token ERC20 compatible token to withdraw from the bridge\n * @param amount Amount in native token decimals to withdraw\n * @param fee Amount in native token decimals to save to the contract as fees\n * @param kappa kappa\n **/\n function withdraw(\n address to,\n IERC20 token,\n uint256 amount,\n uint256 fee,\n bytes32 kappa\n ) external nonReentrant whenNotPaused {\n require(\n hasRole(NODEGROUP_ROLE, msg.sender),\n \"Caller is not a node group\"\n );\n require(amount > fee, \"Amount must be greater than fee\");\n require(!kappaMap[kappa], \"Kappa is already present\");\n kappaMap[kappa] = true;\n fees[address(token)] = fees[address(token)].add(fee);\n if (address(token) == WETH_ADDRESS && WETH_ADDRESS != address(0)) {\n IWETH9(WETH_ADDRESS).withdraw(amount.sub(fee));\n (bool success, ) = to.call{value: amount.sub(fee)}(\"\");\n require(success, \"ETH_TRANSFER_FAILED\");\n emit TokenWithdraw(to, token, amount, fee, kappa);\n } else {\n emit TokenWithdraw(to, token, amount, fee, kappa);\n token.safeTransfer(to, amount.sub(fee));\n }\n }\n\n /**\n * @notice Nodes call this function to mint a SynERC20 (or any asset that the bridge is given minter access to). This is called by the nodes after a TokenDeposit event is emitted.\n * @dev This means the SynapseBridge.sol contract must have minter access to the token attempting to be minted\n * @param to address on other chain to redeem underlying assets to\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain post-fees\n * @param fee Amount in native token decimals to save to the contract as fees\n * @param kappa kappa\n **/\n function mint(\n address payable to,\n IERC20Mintable token,\n uint256 amount,\n uint256 fee,\n bytes32 kappa\n ) external nonReentrant whenNotPaused {\n require(\n hasRole(NODEGROUP_ROLE, msg.sender),\n \"Caller is not a node group\"\n );\n require(amount > fee, \"Amount must be greater than fee\");\n require(!kappaMap[kappa], \"Kappa is already present\");\n kappaMap[kappa] = true;\n fees[address(token)] = fees[address(token)].add(fee);\n emit TokenMint(to, token, amount.sub(fee), fee, kappa);\n token.mint(address(this), amount);\n // checks if synFRAX\n if (address(token) == 0xE96AC70907ffF3Efee79f502C985A7A21Bce407d) {\n token.safeIncreaseAllowance(\n 0x1A93B23281CC1CDE4C4741353F3064709A16197d,\n amount.sub(fee)\n );\n try\n IFrax(0x1A93B23281CC1CDE4C4741353F3064709A16197d)\n .exchangeOldForCanonical(address(token), amount.sub(fee))\n returns (uint256 canolical_tokens_out) {\n IERC20(0x1A93B23281CC1CDE4C4741353F3064709A16197d).safeTransfer(\n to,\n canolical_tokens_out\n );\n } catch {\n IERC20(token).safeTransfer(to, amount.sub(fee));\n }\n } else {\n IERC20(token).safeTransfer(to, amount.sub(fee));\n }\n if (chainGasAmount != 0 && address(this).balance > chainGasAmount) {\n to.call.value(chainGasAmount)(\"\");\n }\n }\n\n /**\n * @notice Relays to nodes to both transfer an ERC20 token cross-chain, and then have the nodes execute a swap through a liquidity pool on behalf of the user.\n * @param to address on other chain to bridge assets to\n * @param chainId which chain to bridge assets onto\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n * @param tokenIndexFrom the token the user wants to swap from\n * @param tokenIndexTo the token the user wants to swap to\n * @param minDy the min amount the user would like to receive, or revert to only minting the SynERC20 token crosschain.\n * @param deadline latest timestamp to accept this transaction\n **/\n function depositAndSwap(\n address to,\n uint256 chainId,\n IERC20 token,\n uint256 amount,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 minDy,\n uint256 deadline\n ) external nonReentrant whenNotPaused {\n emit TokenDepositAndSwap(\n to,\n chainId,\n token,\n amount,\n tokenIndexFrom,\n tokenIndexTo,\n minDy,\n deadline\n );\n token.safeTransferFrom(msg.sender, address(this), amount);\n }\n\n /**\n * @notice Relays to nodes that (typically) a wrapped synAsset ERC20 token has been burned and the underlying needs to be redeeemed on the native chain. This function indicates to the nodes that they should attempt to redeem the LP token for the underlying assets (E.g \"swap\" out of the LP token)\n * @param to address on other chain to redeem underlying assets to\n * @param chainId which underlying chain to bridge assets onto\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n * @param tokenIndexFrom the token the user wants to swap from\n * @param tokenIndexTo the token the user wants to swap to\n * @param minDy the min amount the user would like to receive, or revert to only minting the SynERC20 token crosschain.\n * @param deadline latest timestamp to accept this transaction\n **/\n function redeemAndSwap(\n address to,\n uint256 chainId,\n ERC20Burnable token,\n uint256 amount,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 minDy,\n uint256 deadline\n ) external nonReentrant whenNotPaused {\n emit TokenRedeemAndSwap(\n to,\n chainId,\n token,\n amount,\n tokenIndexFrom,\n tokenIndexTo,\n minDy,\n deadline\n );\n token.burnFrom(msg.sender, amount);\n }\n\n /**\n * @notice Relays to nodes that (typically) a wrapped synAsset ERC20 token has been burned and the underlying needs to be redeeemed on the native chain. This function indicates to the nodes that they should attempt to redeem the LP token for the underlying assets (E.g \"swap\" out of the LP token)\n * @param to address on other chain to redeem underlying assets to\n * @param chainId which underlying chain to bridge assets onto\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n * @param swapTokenIndex Specifies which of the underlying LP assets the nodes should attempt to redeem for\n * @param swapMinAmount Specifies the minimum amount of the underlying asset needed for the nodes to execute the redeem/swap\n * @param swapDeadline Specificies the deadline that the nodes are allowed to try to redeem/swap the LP token\n **/\n function redeemAndRemove(\n address to,\n uint256 chainId,\n ERC20Burnable token,\n uint256 amount,\n uint8 swapTokenIndex,\n uint256 swapMinAmount,\n uint256 swapDeadline\n ) external nonReentrant whenNotPaused {\n emit TokenRedeemAndRemove(\n to,\n chainId,\n token,\n amount,\n swapTokenIndex,\n swapMinAmount,\n swapDeadline\n );\n token.burnFrom(msg.sender, amount);\n }\n\n /**\n * @notice Nodes call this function to mint a SynERC20 (or any asset that the bridge is given minter access to), and then attempt to swap the SynERC20 into the desired destination asset. This is called by the nodes after a TokenDepositAndSwap event is emitted.\n * @dev This means the BridgeDeposit.sol contract must have minter access to the token attempting to be minted\n * @param to address on other chain to redeem underlying assets to\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain post-fees\n * @param fee Amount in native token decimals to save to the contract as fees\n * @param pool Destination chain's pool to use to swap SynERC20 -> Asset. The nodes determine this by using PoolConfig.sol.\n * @param tokenIndexFrom Index of the SynERC20 asset in the pool\n * @param tokenIndexTo Index of the desired final asset\n * @param minDy Minumum amount (in final asset decimals) that must be swapped for, otherwise the user will receive the SynERC20.\n * @param deadline Epoch time of the deadline that the swap is allowed to be executed.\n * @param kappa kappa\n **/\n function mintAndSwap(\n address payable to,\n IERC20Mintable token,\n uint256 amount,\n uint256 fee,\n ISwap pool,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 minDy,\n uint256 deadline,\n bytes32 kappa\n ) external nonReentrant whenNotPaused {\n require(\n hasRole(NODEGROUP_ROLE, msg.sender),\n \"Caller is not a node group\"\n );\n require(amount > fee, \"Amount must be greater than fee\");\n require(!kappaMap[kappa], \"Kappa is already present\");\n kappaMap[kappa] = true;\n fees[address(token)] = fees[address(token)].add(fee);\n // Transfer gas airdrop\n if (chainGasAmount != 0 && address(this).balance > chainGasAmount) {\n to.call.value(chainGasAmount)(\"\");\n }\n // first check to make sure more will be given than min amount required\n uint256 expectedOutput = ISwap(pool).calculateSwap(\n tokenIndexFrom,\n tokenIndexTo,\n amount.sub(fee)\n );\n\n if (expectedOutput >= minDy) {\n // proceed with swap\n token.mint(address(this), amount);\n token.safeIncreaseAllowance(address(pool), amount);\n try\n ISwap(pool).swap(\n tokenIndexFrom,\n tokenIndexTo,\n amount.sub(fee),\n minDy,\n deadline\n )\n returns (uint256 finalSwappedAmount) {\n // Swap succeeded, transfer swapped asset\n IERC20 swappedTokenTo = ISwap(pool).getToken(tokenIndexTo);\n if (\n address(swappedTokenTo) == WETH_ADDRESS &&\n WETH_ADDRESS != address(0)\n ) {\n IWETH9(WETH_ADDRESS).withdraw(finalSwappedAmount);\n (bool success, ) = to.call{value: finalSwappedAmount}(\"\");\n require(success, \"ETH_TRANSFER_FAILED\");\n emit TokenMintAndSwap(\n to,\n token,\n finalSwappedAmount,\n fee,\n tokenIndexFrom,\n tokenIndexTo,\n minDy,\n deadline,\n true,\n kappa\n );\n } else {\n swappedTokenTo.safeTransfer(to, finalSwappedAmount);\n emit TokenMintAndSwap(\n to,\n token,\n finalSwappedAmount,\n fee,\n tokenIndexFrom,\n tokenIndexTo,\n minDy,\n deadline,\n true,\n kappa\n );\n }\n } catch {\n IERC20(token).safeTransfer(to, amount.sub(fee));\n emit TokenMintAndSwap(\n to,\n token,\n amount.sub(fee),\n fee,\n tokenIndexFrom,\n tokenIndexTo,\n minDy,\n deadline,\n false,\n kappa\n );\n }\n } else {\n token.mint(address(this), amount);\n IERC20(token).safeTransfer(to, amount.sub(fee));\n emit TokenMintAndSwap(\n to,\n token,\n amount.sub(fee),\n fee,\n tokenIndexFrom,\n tokenIndexTo,\n minDy,\n deadline,\n false,\n kappa\n );\n }\n }\n\n /**\n * @notice Function to be called by the node group to withdraw the underlying assets from the contract\n * @param to address on chain to send underlying assets to\n * @param token ERC20 compatible token to withdraw from the bridge\n * @param amount Amount in native token decimals to withdraw\n * @param fee Amount in native token decimals to save to the contract as fees\n * @param pool Destination chain's pool to use to swap SynERC20 -> Asset. The nodes determine this by using PoolConfig.sol.\n * @param swapTokenIndex Specifies which of the underlying LP assets the nodes should attempt to redeem for\n * @param swapMinAmount Specifies the minimum amount of the underlying asset needed for the nodes to execute the redeem/swap\n * @param swapDeadline Specificies the deadline that the nodes are allowed to try to redeem/swap the LP token\n * @param kappa kappa\n **/\n function withdrawAndRemove(\n address to,\n IERC20 token,\n uint256 amount,\n uint256 fee,\n ISwap pool,\n uint8 swapTokenIndex,\n uint256 swapMinAmount,\n uint256 swapDeadline,\n bytes32 kappa\n ) external nonReentrant whenNotPaused {\n require(\n hasRole(NODEGROUP_ROLE, msg.sender),\n \"Caller is not a node group\"\n );\n require(amount > fee, \"Amount must be greater than fee\");\n require(!kappaMap[kappa], \"Kappa is already present\");\n kappaMap[kappa] = true;\n fees[address(token)] = fees[address(token)].add(fee);\n // first check to make sure more will be given than min amount required\n uint256 expectedOutput = ISwap(pool).calculateRemoveLiquidityOneToken(\n amount.sub(fee),\n swapTokenIndex\n );\n\n if (expectedOutput >= swapMinAmount) {\n token.safeIncreaseAllowance(address(pool), amount.sub(fee));\n try\n ISwap(pool).removeLiquidityOneToken(\n amount.sub(fee),\n swapTokenIndex,\n swapMinAmount,\n swapDeadline\n )\n returns (uint256 finalSwappedAmount) {\n // Swap succeeded, transfer swapped asset\n IERC20 swappedTokenTo = ISwap(pool).getToken(swapTokenIndex);\n swappedTokenTo.safeTransfer(to, finalSwappedAmount);\n emit TokenWithdrawAndRemove(\n to,\n token,\n finalSwappedAmount,\n fee,\n swapTokenIndex,\n swapMinAmount,\n swapDeadline,\n true,\n kappa\n );\n } catch {\n IERC20(token).safeTransfer(to, amount.sub(fee));\n emit TokenWithdrawAndRemove(\n to,\n token,\n amount.sub(fee),\n fee,\n swapTokenIndex,\n swapMinAmount,\n swapDeadline,\n false,\n kappa\n );\n }\n } else {\n token.safeTransfer(to, amount.sub(fee));\n emit TokenWithdrawAndRemove(\n to,\n token,\n amount.sub(fee),\n fee,\n swapTokenIndex,\n swapMinAmount,\n swapDeadline,\n false,\n kappa\n );\n }\n }\n\n // BRIDGE FUNCTIONS TO HANDLE DIFF ADDRESSES\n /**\n * @notice Relays to nodes that (typically) a wrapped synAsset ERC20 token has been burned and the underlying needs to be redeeemed on the native chain\n * @param to address on other chain to redeem underlying assets to\n * @param chainId which underlying chain to bridge assets onto\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n **/\n function redeemV2(\n bytes32 to,\n uint256 chainId,\n ERC20Burnable token,\n uint256 amount\n ) external nonReentrant whenNotPaused {\n emit TokenRedeemV2(to, chainId, token, amount);\n token.burnFrom(msg.sender, amount);\n }\n}\n" + }, + "contracts/bridge/HarmonySynapseBridge.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.6.12;\n\nimport \"@openzeppelin/contracts-upgradeable/proxy/Initializable.sol\";\nimport \"@openzeppelin/contracts-upgradeable/access/AccessControlUpgradeable.sol\";\nimport \"@openzeppelin/contracts-upgradeable/utils/ReentrancyGuardUpgradeable.sol\";\nimport \"@openzeppelin/contracts-upgradeable/utils/PausableUpgradeable.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/SafeERC20.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/ERC20Burnable.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport \"@openzeppelin/contracts/math/SafeMath.sol\";\n\nimport \"./interfaces/ISwap.sol\";\nimport \"./interfaces/IWETH9.sol\";\n\ninterface IERC20Mintable is IERC20 {\n function mint(address to, uint256 amount) external;\n}\n\ninterface IFrax {\n function exchangeOldForCanonical(\n address bridge_token_address,\n uint256 token_amount\n ) external returns (uint256);\n}\n\ncontract HarmonySynapseBridge is\n Initializable,\n AccessControlUpgradeable,\n ReentrancyGuardUpgradeable,\n PausableUpgradeable\n{\n using SafeERC20 for IERC20;\n using SafeERC20 for IERC20Mintable;\n using SafeMath for uint256;\n\n bytes32 public constant NODEGROUP_ROLE = keccak256(\"NODEGROUP_ROLE\");\n bytes32 public constant GOVERNANCE_ROLE = keccak256(\"GOVERNANCE_ROLE\");\n\n mapping(address => uint256) private fees;\n\n uint256 public startBlockNumber;\n uint256 public constant bridgeVersion = 6;\n uint256 public chainGasAmount;\n address payable public WETH_ADDRESS;\n\n mapping(bytes32 => bool) private kappaMap;\n\n receive() external payable {}\n\n function initialize() external initializer {\n startBlockNumber = block.number;\n _setupRole(DEFAULT_ADMIN_ROLE, msg.sender);\n __AccessControl_init();\n }\n\n function setChainGasAmount(uint256 amount) external {\n require(hasRole(GOVERNANCE_ROLE, msg.sender), \"Not governance\");\n chainGasAmount = amount;\n }\n\n function setWethAddress(address payable _wethAddress) external {\n require(hasRole(DEFAULT_ADMIN_ROLE, msg.sender), \"Not admin\");\n WETH_ADDRESS = _wethAddress;\n }\n\n function addKappas(bytes32[] calldata kappas) external {\n require(hasRole(GOVERNANCE_ROLE, msg.sender), \"Not governance\");\n for (uint256 i = 0; i < kappas.length; ++i) {\n kappaMap[kappas[i]] = true;\n }\n }\n\n event TokenDeposit(\n address indexed to,\n uint256 chainId,\n IERC20 token,\n uint256 amount\n );\n event TokenRedeem(\n address indexed to,\n uint256 chainId,\n IERC20 token,\n uint256 amount\n );\n event TokenWithdraw(\n address indexed to,\n IERC20 token,\n uint256 amount,\n uint256 fee,\n bytes32 indexed kappa\n );\n event TokenMint(\n address indexed to,\n IERC20Mintable token,\n uint256 amount,\n uint256 fee,\n bytes32 indexed kappa\n );\n event TokenDepositAndSwap(\n address indexed to,\n uint256 chainId,\n IERC20 token,\n uint256 amount,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 minDy,\n uint256 deadline\n );\n event TokenMintAndSwap(\n address indexed to,\n IERC20Mintable token,\n uint256 amount,\n uint256 fee,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 minDy,\n uint256 deadline,\n bool swapSuccess,\n bytes32 indexed kappa\n );\n event TokenRedeemAndSwap(\n address indexed to,\n uint256 chainId,\n IERC20 token,\n uint256 amount,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 minDy,\n uint256 deadline\n );\n event TokenRedeemAndRemove(\n address indexed to,\n uint256 chainId,\n IERC20 token,\n uint256 amount,\n uint8 swapTokenIndex,\n uint256 swapMinAmount,\n uint256 swapDeadline\n );\n event TokenWithdrawAndRemove(\n address indexed to,\n IERC20 token,\n uint256 amount,\n uint256 fee,\n uint8 swapTokenIndex,\n uint256 swapMinAmount,\n uint256 swapDeadline,\n bool swapSuccess,\n bytes32 indexed kappa\n );\n\n // v2 events\n event TokenRedeemV2(\n bytes32 indexed to,\n uint256 chainId,\n IERC20 token,\n uint256 amount\n );\n\n // VIEW FUNCTIONS ***/\n function getFeeBalance(address tokenAddress)\n external\n view\n returns (uint256)\n {\n return fees[tokenAddress];\n }\n\n function kappaExists(bytes32 kappa) external view returns (bool) {\n return kappaMap[kappa];\n }\n\n // FEE FUNCTIONS ***/\n /**\n * * @notice withdraw specified ERC20 token fees to a given address\n * * @param token ERC20 token in which fees acccumulated to transfer\n * * @param to Address to send the fees to\n */\n function withdrawFees(IERC20 token, address to) external whenNotPaused {\n require(hasRole(GOVERNANCE_ROLE, msg.sender), \"Not governance\");\n require(to != address(0), \"Address is 0x000\");\n if (fees[address(token)] != 0) {\n token.safeTransfer(to, fees[address(token)]);\n fees[address(token)] = 0;\n }\n }\n\n // PAUSABLE FUNCTIONS ***/\n function pause() external {\n require(hasRole(GOVERNANCE_ROLE, msg.sender), \"Not governance\");\n _pause();\n }\n\n function unpause() external {\n require(hasRole(GOVERNANCE_ROLE, msg.sender), \"Not governance\");\n _unpause();\n }\n\n /**\n * @notice Relays to nodes to transfers an ERC20 token cross-chain\n * @param to address on other chain to bridge assets to\n * @param chainId which chain to bridge assets onto\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n **/\n function deposit(\n address to,\n uint256 chainId,\n IERC20 token,\n uint256 amount\n ) external nonReentrant whenNotPaused {\n emit TokenDeposit(to, chainId, token, amount);\n token.safeTransferFrom(msg.sender, address(this), amount);\n }\n\n /**\n * @notice Relays to nodes that (typically) a wrapped synAsset ERC20 token has been burned and the underlying needs to be redeeemed on the native chain\n * @param to address on other chain to redeem underlying assets to\n * @param chainId which underlying chain to bridge assets onto\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n **/\n function redeem(\n address to,\n uint256 chainId,\n ERC20Burnable token,\n uint256 amount\n ) external nonReentrant whenNotPaused {\n emit TokenRedeem(to, chainId, token, amount);\n token.burnFrom(msg.sender, amount);\n }\n\n /**\n * @notice Function to be called by the node group to withdraw the underlying assets from the contract\n * @param to address on chain to send underlying assets to\n * @param token ERC20 compatible token to withdraw from the bridge\n * @param amount Amount in native token decimals to withdraw\n * @param fee Amount in native token decimals to save to the contract as fees\n * @param kappa kappa\n **/\n function withdraw(\n address to,\n IERC20 token,\n uint256 amount,\n uint256 fee,\n bytes32 kappa\n ) external nonReentrant whenNotPaused {\n require(\n hasRole(NODEGROUP_ROLE, msg.sender),\n \"Caller is not a node group\"\n );\n require(amount > fee, \"Amount must be greater than fee\");\n require(!kappaMap[kappa], \"Kappa is already present\");\n kappaMap[kappa] = true;\n fees[address(token)] = fees[address(token)].add(fee);\n if (address(token) == WETH_ADDRESS && WETH_ADDRESS != address(0)) {\n IWETH9(WETH_ADDRESS).withdraw(amount.sub(fee));\n (bool success, ) = to.call{value: amount.sub(fee)}(\"\");\n require(success, \"ETH_TRANSFER_FAILED\");\n emit TokenWithdraw(to, token, amount, fee, kappa);\n } else {\n emit TokenWithdraw(to, token, amount, fee, kappa);\n token.safeTransfer(to, amount.sub(fee));\n }\n }\n\n /**\n * @notice Nodes call this function to mint a SynERC20 (or any asset that the bridge is given minter access to). This is called by the nodes after a TokenDeposit event is emitted.\n * @dev This means the SynapseBridge.sol contract must have minter access to the token attempting to be minted\n * @param to address on other chain to redeem underlying assets to\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain post-fees\n * @param fee Amount in native token decimals to save to the contract as fees\n * @param kappa kappa\n **/\n function mint(\n address payable to,\n IERC20Mintable token,\n uint256 amount,\n uint256 fee,\n bytes32 kappa\n ) external nonReentrant whenNotPaused {\n require(\n hasRole(NODEGROUP_ROLE, msg.sender),\n \"Caller is not a node group\"\n );\n require(amount > fee, \"Amount must be greater than fee\");\n require(!kappaMap[kappa], \"Kappa is already present\");\n kappaMap[kappa] = true;\n fees[address(token)] = fees[address(token)].add(fee);\n emit TokenMint(to, token, amount.sub(fee), fee, kappa);\n token.mint(address(this), amount);\n // checks if synFRAX\n if (address(token) == 0x1852F70512298d56e9c8FDd905e02581E04ddb2a) {\n if (\n token.allowance(\n address(this),\n 0xFa7191D292d5633f702B0bd7E3E3BcCC0e633200\n ) < amount.sub(fee)\n ) {\n token.safeApprove(\n address(0xFa7191D292d5633f702B0bd7E3E3BcCC0e633200),\n 0\n );\n token.safeApprove(\n address(0xFa7191D292d5633f702B0bd7E3E3BcCC0e633200),\n type(uint256).max\n );\n }\n try\n IFrax(0xFa7191D292d5633f702B0bd7E3E3BcCC0e633200)\n .exchangeOldForCanonical(address(token), amount.sub(fee))\n returns (uint256 canolical_tokens_out) {\n IERC20(0xFa7191D292d5633f702B0bd7E3E3BcCC0e633200).safeTransfer(\n to,\n canolical_tokens_out\n );\n } catch {\n IERC20(token).safeTransfer(to, amount.sub(fee));\n }\n } else {\n IERC20(token).safeTransfer(to, amount.sub(fee));\n }\n if (chainGasAmount != 0 && address(this).balance > chainGasAmount) {\n to.call.value(chainGasAmount)(\"\");\n }\n }\n\n /**\n * @notice Relays to nodes to both transfer an ERC20 token cross-chain, and then have the nodes execute a swap through a liquidity pool on behalf of the user.\n * @param to address on other chain to bridge assets to\n * @param chainId which chain to bridge assets onto\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n * @param tokenIndexFrom the token the user wants to swap from\n * @param tokenIndexTo the token the user wants to swap to\n * @param minDy the min amount the user would like to receive, or revert to only minting the SynERC20 token crosschain.\n * @param deadline latest timestamp to accept this transaction\n **/\n function depositAndSwap(\n address to,\n uint256 chainId,\n IERC20 token,\n uint256 amount,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 minDy,\n uint256 deadline\n ) external nonReentrant whenNotPaused {\n emit TokenDepositAndSwap(\n to,\n chainId,\n token,\n amount,\n tokenIndexFrom,\n tokenIndexTo,\n minDy,\n deadline\n );\n token.safeTransferFrom(msg.sender, address(this), amount);\n }\n\n /**\n * @notice Relays to nodes that (typically) a wrapped synAsset ERC20 token has been burned and the underlying needs to be redeeemed on the native chain. This function indicates to the nodes that they should attempt to redeem the LP token for the underlying assets (E.g \"swap\" out of the LP token)\n * @param to address on other chain to redeem underlying assets to\n * @param chainId which underlying chain to bridge assets onto\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n * @param tokenIndexFrom the token the user wants to swap from\n * @param tokenIndexTo the token the user wants to swap to\n * @param minDy the min amount the user would like to receive, or revert to only minting the SynERC20 token crosschain.\n * @param deadline latest timestamp to accept this transaction\n **/\n function redeemAndSwap(\n address to,\n uint256 chainId,\n ERC20Burnable token,\n uint256 amount,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 minDy,\n uint256 deadline\n ) external nonReentrant whenNotPaused {\n emit TokenRedeemAndSwap(\n to,\n chainId,\n token,\n amount,\n tokenIndexFrom,\n tokenIndexTo,\n minDy,\n deadline\n );\n token.burnFrom(msg.sender, amount);\n }\n\n /**\n * @notice Relays to nodes that (typically) a wrapped synAsset ERC20 token has been burned and the underlying needs to be redeeemed on the native chain. This function indicates to the nodes that they should attempt to redeem the LP token for the underlying assets (E.g \"swap\" out of the LP token)\n * @param to address on other chain to redeem underlying assets to\n * @param chainId which underlying chain to bridge assets onto\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n * @param swapTokenIndex Specifies which of the underlying LP assets the nodes should attempt to redeem for\n * @param swapMinAmount Specifies the minimum amount of the underlying asset needed for the nodes to execute the redeem/swap\n * @param swapDeadline Specificies the deadline that the nodes are allowed to try to redeem/swap the LP token\n **/\n function redeemAndRemove(\n address to,\n uint256 chainId,\n ERC20Burnable token,\n uint256 amount,\n uint8 swapTokenIndex,\n uint256 swapMinAmount,\n uint256 swapDeadline\n ) external nonReentrant whenNotPaused {\n emit TokenRedeemAndRemove(\n to,\n chainId,\n token,\n amount,\n swapTokenIndex,\n swapMinAmount,\n swapDeadline\n );\n token.burnFrom(msg.sender, amount);\n }\n\n /**\n * @notice Nodes call this function to mint a SynERC20 (or any asset that the bridge is given minter access to), and then attempt to swap the SynERC20 into the desired destination asset. This is called by the nodes after a TokenDepositAndSwap event is emitted.\n * @dev This means the BridgeDeposit.sol contract must have minter access to the token attempting to be minted\n * @param to address on other chain to redeem underlying assets to\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain post-fees\n * @param fee Amount in native token decimals to save to the contract as fees\n * @param pool Destination chain's pool to use to swap SynERC20 -> Asset. The nodes determine this by using PoolConfig.sol.\n * @param tokenIndexFrom Index of the SynERC20 asset in the pool\n * @param tokenIndexTo Index of the desired final asset\n * @param minDy Minumum amount (in final asset decimals) that must be swapped for, otherwise the user will receive the SynERC20.\n * @param deadline Epoch time of the deadline that the swap is allowed to be executed.\n * @param kappa kappa\n **/\n function mintAndSwap(\n address payable to,\n IERC20Mintable token,\n uint256 amount,\n uint256 fee,\n ISwap pool,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 minDy,\n uint256 deadline,\n bytes32 kappa\n ) external nonReentrant whenNotPaused {\n require(\n hasRole(NODEGROUP_ROLE, msg.sender),\n \"Caller is not a node group\"\n );\n require(amount > fee, \"Amount must be greater than fee\");\n require(!kappaMap[kappa], \"Kappa is already present\");\n kappaMap[kappa] = true;\n fees[address(token)] = fees[address(token)].add(fee);\n // Transfer gas airdrop\n if (chainGasAmount != 0 && address(this).balance > chainGasAmount) {\n to.call.value(chainGasAmount)(\"\");\n }\n // first check to make sure more will be given than min amount required\n uint256 expectedOutput = ISwap(pool).calculateSwap(\n tokenIndexFrom,\n tokenIndexTo,\n amount.sub(fee)\n );\n\n if (expectedOutput >= minDy) {\n // proceed with swap\n token.mint(address(this), amount);\n token.safeIncreaseAllowance(address(pool), amount);\n try\n ISwap(pool).swap(\n tokenIndexFrom,\n tokenIndexTo,\n amount.sub(fee),\n minDy,\n deadline\n )\n returns (uint256 finalSwappedAmount) {\n // Swap succeeded, transfer swapped asset\n IERC20 swappedTokenTo = ISwap(pool).getToken(tokenIndexTo);\n if (\n address(swappedTokenTo) == WETH_ADDRESS &&\n WETH_ADDRESS != address(0)\n ) {\n IWETH9(WETH_ADDRESS).withdraw(finalSwappedAmount);\n (bool success, ) = to.call{value: finalSwappedAmount}(\"\");\n require(success, \"ETH_TRANSFER_FAILED\");\n emit TokenMintAndSwap(\n to,\n token,\n finalSwappedAmount,\n fee,\n tokenIndexFrom,\n tokenIndexTo,\n minDy,\n deadline,\n true,\n kappa\n );\n } else {\n swappedTokenTo.safeTransfer(to, finalSwappedAmount);\n emit TokenMintAndSwap(\n to,\n token,\n finalSwappedAmount,\n fee,\n tokenIndexFrom,\n tokenIndexTo,\n minDy,\n deadline,\n true,\n kappa\n );\n }\n } catch {\n IERC20(token).safeTransfer(to, amount.sub(fee));\n emit TokenMintAndSwap(\n to,\n token,\n amount.sub(fee),\n fee,\n tokenIndexFrom,\n tokenIndexTo,\n minDy,\n deadline,\n false,\n kappa\n );\n }\n } else {\n token.mint(address(this), amount);\n IERC20(token).safeTransfer(to, amount.sub(fee));\n emit TokenMintAndSwap(\n to,\n token,\n amount.sub(fee),\n fee,\n tokenIndexFrom,\n tokenIndexTo,\n minDy,\n deadline,\n false,\n kappa\n );\n }\n }\n\n /**\n * @notice Function to be called by the node group to withdraw the underlying assets from the contract\n * @param to address on chain to send underlying assets to\n * @param token ERC20 compatible token to withdraw from the bridge\n * @param amount Amount in native token decimals to withdraw\n * @param fee Amount in native token decimals to save to the contract as fees\n * @param pool Destination chain's pool to use to swap SynERC20 -> Asset. The nodes determine this by using PoolConfig.sol.\n * @param swapTokenIndex Specifies which of the underlying LP assets the nodes should attempt to redeem for\n * @param swapMinAmount Specifies the minimum amount of the underlying asset needed for the nodes to execute the redeem/swap\n * @param swapDeadline Specificies the deadline that the nodes are allowed to try to redeem/swap the LP token\n * @param kappa kappa\n **/\n function withdrawAndRemove(\n address to,\n IERC20 token,\n uint256 amount,\n uint256 fee,\n ISwap pool,\n uint8 swapTokenIndex,\n uint256 swapMinAmount,\n uint256 swapDeadline,\n bytes32 kappa\n ) external nonReentrant whenNotPaused {\n require(\n hasRole(NODEGROUP_ROLE, msg.sender),\n \"Caller is not a node group\"\n );\n require(amount > fee, \"Amount must be greater than fee\");\n require(!kappaMap[kappa], \"Kappa is already present\");\n kappaMap[kappa] = true;\n fees[address(token)] = fees[address(token)].add(fee);\n // first check to make sure more will be given than min amount required\n uint256 expectedOutput = ISwap(pool).calculateRemoveLiquidityOneToken(\n amount.sub(fee),\n swapTokenIndex\n );\n\n if (expectedOutput >= swapMinAmount) {\n token.safeIncreaseAllowance(address(pool), amount.sub(fee));\n try\n ISwap(pool).removeLiquidityOneToken(\n amount.sub(fee),\n swapTokenIndex,\n swapMinAmount,\n swapDeadline\n )\n returns (uint256 finalSwappedAmount) {\n // Swap succeeded, transfer swapped asset\n IERC20 swappedTokenTo = ISwap(pool).getToken(swapTokenIndex);\n swappedTokenTo.safeTransfer(to, finalSwappedAmount);\n emit TokenWithdrawAndRemove(\n to,\n token,\n finalSwappedAmount,\n fee,\n swapTokenIndex,\n swapMinAmount,\n swapDeadline,\n true,\n kappa\n );\n } catch {\n IERC20(token).safeTransfer(to, amount.sub(fee));\n emit TokenWithdrawAndRemove(\n to,\n token,\n amount.sub(fee),\n fee,\n swapTokenIndex,\n swapMinAmount,\n swapDeadline,\n false,\n kappa\n );\n }\n } else {\n token.safeTransfer(to, amount.sub(fee));\n emit TokenWithdrawAndRemove(\n to,\n token,\n amount.sub(fee),\n fee,\n swapTokenIndex,\n swapMinAmount,\n swapDeadline,\n false,\n kappa\n );\n }\n }\n\n // BRIDGE FUNCTIONS TO HANDLE DIFF ADDRESSES\n /**\n * @notice Relays to nodes that (typically) a wrapped synAsset ERC20 token has been burned and the underlying needs to be redeeemed on the native chain\n * @param to address on other chain to redeem underlying assets to\n * @param chainId which underlying chain to bridge assets onto\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n **/\n function redeemV2(\n bytes32 to,\n uint256 chainId,\n ERC20Burnable token,\n uint256 amount\n ) external nonReentrant whenNotPaused {\n emit TokenRedeemV2(to, chainId, token, amount);\n token.burnFrom(msg.sender, amount);\n }\n}\n" + }, + "contracts/bridge/SynapseERC20.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.6.12;\n\nimport \"@openzeppelin/contracts-upgradeable/token/ERC20/ERC20Upgradeable.sol\";\nimport \"@openzeppelin/contracts-upgradeable/token/ERC20/ERC20BurnableUpgradeable.sol\";\nimport \"@openzeppelin/contracts-upgradeable/drafts/ERC20PermitUpgradeable.sol\";\nimport \"@openzeppelin/contracts-upgradeable/access/AccessControlUpgradeable.sol\";\nimport \"@openzeppelin/contracts-upgradeable/proxy/Initializable.sol\";\n\ncontract SynapseERC20 is\n Initializable,\n ContextUpgradeable,\n AccessControlUpgradeable,\n ERC20BurnableUpgradeable,\n ERC20PermitUpgradeable\n{\n bytes32 public constant MINTER_ROLE = keccak256(\"MINTER_ROLE\");\n\n /**\n * @notice Initializes this ERC20 contract with the given parameters.\n * @param name Token name\n * @param symbol Token symbol\n * @param decimals Token name\n * @param owner admin address to be initialized with\n */\n function initialize(\n string memory name,\n string memory symbol,\n uint8 decimals,\n address owner\n ) external initializer {\n __Context_init_unchained();\n __AccessControl_init_unchained();\n __ERC20_init_unchained(name, symbol);\n __ERC20Burnable_init_unchained();\n _setupDecimals(decimals);\n __ERC20Permit_init(name);\n _setupRole(DEFAULT_ADMIN_ROLE, owner);\n }\n\n function mint(address to, uint256 amount) external {\n require(hasRole(MINTER_ROLE, msg.sender), \"Not a minter\");\n _mint(to, amount);\n }\n}\n" + }, + "@openzeppelin/contracts-upgradeable/drafts/ERC20PermitUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.5 <0.8.0;\n\nimport \"../token/ERC20/ERC20Upgradeable.sol\";\nimport \"./IERC20PermitUpgradeable.sol\";\nimport \"../cryptography/ECDSAUpgradeable.sol\";\nimport \"../utils/CountersUpgradeable.sol\";\nimport \"./EIP712Upgradeable.sol\";\nimport \"../proxy/Initializable.sol\";\n\n/**\n * @dev Implementation of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in\n * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612].\n *\n * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by\n * presenting a message signed by the account. By not relying on `{IERC20-approve}`, the token holder account doesn't\n * need to send a transaction, and thus is not required to hold Ether at all.\n *\n * _Available since v3.4._\n */\nabstract contract ERC20PermitUpgradeable is Initializable, ERC20Upgradeable, IERC20PermitUpgradeable, EIP712Upgradeable {\n using CountersUpgradeable for CountersUpgradeable.Counter;\n\n mapping (address => CountersUpgradeable.Counter) private _nonces;\n\n // solhint-disable-next-line var-name-mixedcase\n bytes32 private _PERMIT_TYPEHASH;\n\n /**\n * @dev Initializes the {EIP712} domain separator using the `name` parameter, and setting `version` to `\"1\"`.\n *\n * It's a good idea to use the same `name` that is defined as the ERC20 token name.\n */\n function __ERC20Permit_init(string memory name) internal initializer {\n __Context_init_unchained();\n __EIP712_init_unchained(name, \"1\");\n __ERC20Permit_init_unchained(name);\n }\n\n function __ERC20Permit_init_unchained(string memory name) internal initializer {\n _PERMIT_TYPEHASH = keccak256(\"Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)\");\n }\n\n /**\n * @dev See {IERC20Permit-permit}.\n */\n function permit(address owner, address spender, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s) public virtual override {\n // solhint-disable-next-line not-rely-on-time\n require(block.timestamp <= deadline, \"ERC20Permit: expired deadline\");\n\n bytes32 structHash = keccak256(\n abi.encode(\n _PERMIT_TYPEHASH,\n owner,\n spender,\n value,\n _nonces[owner].current(),\n deadline\n )\n );\n\n bytes32 hash = _hashTypedDataV4(structHash);\n\n address signer = ECDSAUpgradeable.recover(hash, v, r, s);\n require(signer == owner, \"ERC20Permit: invalid signature\");\n\n _nonces[owner].increment();\n _approve(owner, spender, value);\n }\n\n /**\n * @dev See {IERC20Permit-nonces}.\n */\n function nonces(address owner) public view override returns (uint256) {\n return _nonces[owner].current();\n }\n\n /**\n * @dev See {IERC20Permit-DOMAIN_SEPARATOR}.\n */\n // solhint-disable-next-line func-name-mixedcase\n function DOMAIN_SEPARATOR() external view override returns (bytes32) {\n return _domainSeparatorV4();\n }\n uint256[49] private __gap;\n}\n" + }, + "@openzeppelin/contracts-upgradeable/drafts/IERC20PermitUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <0.8.0;\n\n/**\n * @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in\n * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612].\n *\n * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by\n * presenting a message signed by the account. By not relying on `{IERC20-approve}`, the token holder account doesn't\n * need to send a transaction, and thus is not required to hold Ether at all.\n */\ninterface IERC20PermitUpgradeable {\n /**\n * @dev Sets `value` as the allowance of `spender` over `owner`'s tokens,\n * given `owner`'s signed approval.\n *\n * IMPORTANT: The same issues {IERC20-approve} has related to transaction\n * ordering also apply here.\n *\n * Emits an {Approval} event.\n *\n * Requirements:\n *\n * - `spender` cannot be the zero address.\n * - `deadline` must be a timestamp in the future.\n * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner`\n * over the EIP712-formatted function arguments.\n * - the signature must use ``owner``'s current nonce (see {nonces}).\n *\n * For more information on the signature format, see the\n * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP\n * section].\n */\n function permit(address owner, address spender, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s) external;\n\n /**\n * @dev Returns the current nonce for `owner`. This value must be\n * included whenever a signature is generated for {permit}.\n *\n * Every successful call to {permit} increases ``owner``'s nonce by one. This\n * prevents a signature from being used multiple times.\n */\n function nonces(address owner) external view returns (uint256);\n\n /**\n * @dev Returns the domain separator used in the encoding of the signature for `permit`, as defined by {EIP712}.\n */\n // solhint-disable-next-line func-name-mixedcase\n function DOMAIN_SEPARATOR() external view returns (bytes32);\n}\n" + }, + "@openzeppelin/contracts-upgradeable/cryptography/ECDSAUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <0.8.0;\n\n/**\n * @dev Elliptic Curve Digital Signature Algorithm (ECDSA) operations.\n *\n * These functions can be used to verify that a message was signed by the holder\n * of the private keys of a given address.\n */\nlibrary ECDSAUpgradeable {\n /**\n * @dev Returns the address that signed a hashed message (`hash`) with\n * `signature`. This address can then be used for verification purposes.\n *\n * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:\n * this function rejects them by requiring the `s` value to be in the lower\n * half order, and the `v` value to be either 27 or 28.\n *\n * IMPORTANT: `hash` _must_ be the result of a hash operation for the\n * verification to be secure: it is possible to craft signatures that\n * recover to arbitrary addresses for non-hashed data. A safe way to ensure\n * this is by receiving a hash of the original message (which may otherwise\n * be too long), and then calling {toEthSignedMessageHash} on it.\n */\n function recover(bytes32 hash, bytes memory signature) internal pure returns (address) {\n // Check the signature length\n if (signature.length != 65) {\n revert(\"ECDSA: invalid signature length\");\n }\n\n // Divide the signature in r, s and v variables\n bytes32 r;\n bytes32 s;\n uint8 v;\n\n // ecrecover takes the signature parameters, and the only way to get them\n // currently is to use assembly.\n // solhint-disable-next-line no-inline-assembly\n assembly {\n r := mload(add(signature, 0x20))\n s := mload(add(signature, 0x40))\n v := byte(0, mload(add(signature, 0x60)))\n }\n\n return recover(hash, v, r, s);\n }\n\n /**\n * @dev Overload of {ECDSA-recover-bytes32-bytes-} that receives the `v`,\n * `r` and `s` signature fields separately.\n */\n function recover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) internal pure returns (address) {\n // EIP-2 still allows signature malleability for ecrecover(). Remove this possibility and make the signature\n // unique. Appendix F in the Ethereum Yellow paper (https://ethereum.github.io/yellowpaper/paper.pdf), defines\n // the valid range for s in (281): 0 < s < secp256k1n ÷ 2 + 1, and for v in (282): v ∈ {27, 28}. Most\n // signatures from current libraries generate a unique signature with an s-value in the lower half order.\n //\n // If your library generates malleable signatures, such as s-values in the upper range, calculate a new s-value\n // with 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 - s1 and flip v from 27 to 28 or\n // vice versa. If your library also generates signatures with 0/1 for v instead 27/28, add 27 to v to accept\n // these malleable signatures as well.\n require(uint256(s) <= 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0, \"ECDSA: invalid signature 's' value\");\n require(v == 27 || v == 28, \"ECDSA: invalid signature 'v' value\");\n\n // If the signature is valid (and not malleable), return the signer address\n address signer = ecrecover(hash, v, r, s);\n require(signer != address(0), \"ECDSA: invalid signature\");\n\n return signer;\n }\n\n /**\n * @dev Returns an Ethereum Signed Message, created from a `hash`. This\n * replicates the behavior of the\n * https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_sign[`eth_sign`]\n * JSON-RPC method.\n *\n * See {recover}.\n */\n function toEthSignedMessageHash(bytes32 hash) internal pure returns (bytes32) {\n // 32 is the length in bytes of hash,\n // enforced by the type signature above\n return keccak256(abi.encodePacked(\"\\x19Ethereum Signed Message:\\n32\", hash));\n }\n}\n" + }, + "@openzeppelin/contracts-upgradeable/utils/CountersUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <0.8.0;\n\nimport \"../math/SafeMathUpgradeable.sol\";\n\n/**\n * @title Counters\n * @author Matt Condon (@shrugs)\n * @dev Provides counters that can only be incremented or decremented by one. This can be used e.g. to track the number\n * of elements in a mapping, issuing ERC721 ids, or counting request ids.\n *\n * Include with `using Counters for Counters.Counter;`\n * Since it is not possible to overflow a 256 bit integer with increments of one, `increment` can skip the {SafeMath}\n * overflow check, thereby saving gas. This does assume however correct usage, in that the underlying `_value` is never\n * directly accessed.\n */\nlibrary CountersUpgradeable {\n using SafeMathUpgradeable for uint256;\n\n struct Counter {\n // This variable should never be directly accessed by users of the library: interactions must be restricted to\n // the library's function. As of Solidity v0.5.2, this cannot be enforced, though there is a proposal to add\n // this feature: see https://github.com/ethereum/solidity/issues/4637\n uint256 _value; // default: 0\n }\n\n function current(Counter storage counter) internal view returns (uint256) {\n return counter._value;\n }\n\n function increment(Counter storage counter) internal {\n // The {SafeMath} overflow check can be skipped here, see the comment at the top\n counter._value += 1;\n }\n\n function decrement(Counter storage counter) internal {\n counter._value = counter._value.sub(1);\n }\n}\n" + }, + "@openzeppelin/contracts-upgradeable/drafts/EIP712Upgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <0.8.0;\nimport \"../proxy/Initializable.sol\";\n\n/**\n * @dev https://eips.ethereum.org/EIPS/eip-712[EIP 712] is a standard for hashing and signing of typed structured data.\n *\n * The encoding specified in the EIP is very generic, and such a generic implementation in Solidity is not feasible,\n * thus this contract does not implement the encoding itself. Protocols need to implement the type-specific encoding\n * they need in their contracts using a combination of `abi.encode` and `keccak256`.\n *\n * This contract implements the EIP 712 domain separator ({_domainSeparatorV4}) that is used as part of the encoding\n * scheme, and the final step of the encoding to obtain the message digest that is then signed via ECDSA\n * ({_hashTypedDataV4}).\n *\n * The implementation of the domain separator was designed to be as efficient as possible while still properly updating\n * the chain id to protect against replay attacks on an eventual fork of the chain.\n *\n * NOTE: This contract implements the version of the encoding known as \"v4\", as implemented by the JSON RPC method\n * https://docs.metamask.io/guide/signing-data.html[`eth_signTypedDataV4` in MetaMask].\n *\n * _Available since v3.4._\n */\nabstract contract EIP712Upgradeable is Initializable {\n /* solhint-disable var-name-mixedcase */\n bytes32 private _HASHED_NAME;\n bytes32 private _HASHED_VERSION;\n bytes32 private constant _TYPE_HASH = keccak256(\"EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)\");\n /* solhint-enable var-name-mixedcase */\n\n /**\n * @dev Initializes the domain separator and parameter caches.\n *\n * The meaning of `name` and `version` is specified in\n * https://eips.ethereum.org/EIPS/eip-712#definition-of-domainseparator[EIP 712]:\n *\n * - `name`: the user readable name of the signing domain, i.e. the name of the DApp or the protocol.\n * - `version`: the current major version of the signing domain.\n *\n * NOTE: These parameters cannot be changed except through a xref:learn::upgrading-smart-contracts.adoc[smart\n * contract upgrade].\n */\n function __EIP712_init(string memory name, string memory version) internal initializer {\n __EIP712_init_unchained(name, version);\n }\n\n function __EIP712_init_unchained(string memory name, string memory version) internal initializer {\n bytes32 hashedName = keccak256(bytes(name));\n bytes32 hashedVersion = keccak256(bytes(version));\n _HASHED_NAME = hashedName;\n _HASHED_VERSION = hashedVersion;\n }\n\n /**\n * @dev Returns the domain separator for the current chain.\n */\n function _domainSeparatorV4() internal view returns (bytes32) {\n return _buildDomainSeparator(_TYPE_HASH, _EIP712NameHash(), _EIP712VersionHash());\n }\n\n function _buildDomainSeparator(bytes32 typeHash, bytes32 name, bytes32 version) private view returns (bytes32) {\n return keccak256(\n abi.encode(\n typeHash,\n name,\n version,\n _getChainId(),\n address(this)\n )\n );\n }\n\n /**\n * @dev Given an already https://eips.ethereum.org/EIPS/eip-712#definition-of-hashstruct[hashed struct], this\n * function returns the hash of the fully encoded EIP712 message for this domain.\n *\n * This hash can be used together with {ECDSA-recover} to obtain the signer of a message. For example:\n *\n * ```solidity\n * bytes32 digest = _hashTypedDataV4(keccak256(abi.encode(\n * keccak256(\"Mail(address to,string contents)\"),\n * mailTo,\n * keccak256(bytes(mailContents))\n * )));\n * address signer = ECDSA.recover(digest, signature);\n * ```\n */\n function _hashTypedDataV4(bytes32 structHash) internal view virtual returns (bytes32) {\n return keccak256(abi.encodePacked(\"\\x19\\x01\", _domainSeparatorV4(), structHash));\n }\n\n function _getChainId() private view returns (uint256 chainId) {\n this; // silence state mutability warning without generating bytecode - see https://github.com/ethereum/solidity/issues/2691\n // solhint-disable-next-line no-inline-assembly\n assembly {\n chainId := chainid()\n }\n }\n\n /**\n * @dev The hash of the name parameter for the EIP712 domain.\n *\n * NOTE: This function reads from storage by default, but can be redefined to return a constant value if gas costs\n * are a concern.\n */\n function _EIP712NameHash() internal virtual view returns (bytes32) {\n return _HASHED_NAME;\n }\n\n /**\n * @dev The hash of the version parameter for the EIP712 domain.\n *\n * NOTE: This function reads from storage by default, but can be redefined to return a constant value if gas costs\n * are a concern.\n */\n function _EIP712VersionHash() internal virtual view returns (bytes32) {\n return _HASHED_VERSION;\n }\n uint256[50] private __gap;\n}\n" + }, + "contracts/auxiliary/DummyWethProxy.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.6.12;\nimport \"@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol\";\nimport \"@openzeppelin/contracts-upgradeable/proxy/Initializable.sol\";\n\ninterface IWETH9 {\n function name() external view returns (string memory);\n\n function symbol() external view returns (string memory);\n\n function decimals() external view returns (uint8);\n\n function balanceOf(address) external view returns (uint256);\n\n function allowance(address, address) external view returns (uint256);\n\n receive() external payable;\n\n function deposit() external payable;\n\n function withdraw(uint256 wad) external;\n\n function totalSupply() external view returns (uint256);\n\n function approve(address guy, uint256 wad) external returns (bool);\n\n function transfer(address dst, uint256 wad) external returns (bool);\n\n function transferFrom(\n address src,\n address dst,\n uint256 wad\n ) external returns (bool);\n}\n\ncontract DummyWethProxy is Initializable, OwnableUpgradeable {\n function initialize() external initializer {\n __Ownable_init();\n }\n\n IWETH9 public WETH;\n\n function setWETHAddress(address payable _weth) external onlyOwner {\n WETH = IWETH9(_weth);\n }\n\n function withdrawToSelf(uint256 amount) external {\n WETH.withdraw(amount);\n }\n\n function rescue(uint256 amount) external onlyOwner {\n WETH.transfer(owner(), amount);\n }\n\n receive() external payable {}\n\n fallback() external payable {}\n}\n" + }, + "contracts/amm/helper/test/TestMathUtils.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.6.12;\n\nimport \"../../MathUtils.sol\";\n\ncontract TestMathUtils {\n using MathUtils for uint256;\n\n function difference(uint256 a, uint256 b) public pure returns (uint256) {\n return a.difference(b);\n }\n\n function within1(uint256 a, uint256 b) public pure returns (bool) {\n return a.within1(b);\n }\n}\n" + }, + "contracts/bridge/ERC20Migrator.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.6.12;\n\nimport \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/SafeERC20.sol\";\nimport \"@openzeppelin/contracts/math/SafeMath.sol\";\n\n/**\n * @title ERC20Migrator\n * @dev This contract can be used to migrate an ERC20 token from one\n * contract to another, where each token holder has to opt-in to the migration.\n * To opt-in, users must approve for this contract the number of tokens they\n * want to migrate. Once the allowance is set up, anyone can trigger the\n * migration to the new token contract. In this way, token holders \"turn in\"\n * their old balance and will be minted an equal amount in the new token.\n * The new token contract must be mintable.\n * ```\n */\n\ninterface IERC20Mintable is IERC20 {\n function mint(address to, uint256 amount) external;\n}\n\ncontract ERC20Migrator {\n using SafeERC20 for IERC20;\n using SafeMath for uint256;\n\n // Address of the old token contract\n IERC20 private _legacyToken;\n\n // Address of the new token contract\n IERC20Mintable private _newToken;\n\n /**\n * @param legacyToken address of the old token contract\n */\n constructor(IERC20 legacyToken, IERC20Mintable newToken) public {\n _legacyToken = legacyToken;\n _newToken = newToken;\n }\n\n /**\n * @dev Returns the legacy token that is being migrated.\n */\n function legacyToken() external view returns (IERC20) {\n return _legacyToken;\n }\n\n /**\n * @dev Returns the new token to which we are migrating.\n */\n function newToken() external view returns (IERC20) {\n return _newToken;\n }\n\n /**\n * @dev Transfers part of an account's balance in the old token to this\n * contract, and mints the same amount of new tokens for that account.\n * @param amount amount of tokens to be migrated\n */\n function migrate(uint256 amount) external {\n _legacyToken.safeTransferFrom(msg.sender, address(this), amount);\n uint256 amountToMint = amount.mul(5).div(2);\n _newToken.mint(msg.sender, amountToMint);\n }\n}\n" + }, + "contracts/bridge/ECDSANodeManagement.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.6.12;\n\nimport \"./utils/AddressArrayUtils.sol\";\nimport \"@openzeppelin/contracts/math/SafeMath.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/SafeERC20.sol\";\n\ncontract ECDSANodeManagement {\n using AddressArrayUtils for address[];\n using SafeMath for uint256;\n using SafeERC20 for IERC20;\n\n // Status of the keep.\n // Active means the keep is active.\n // Closed means the keep was closed happily.\n // Terminated means the keep was closed due to misbehavior.\n enum Status {\n Active,\n Closed,\n Terminated\n }\n\n // Address of the keep's owner.\n address public owner;\n\n // List of keep members' addresses.\n address[] public members;\n\n // Minimum number of honest keep members required to produce a signature.\n uint256 public honestThreshold;\n\n // Keep's ECDSA public key serialized to 64-bytes, where X and Y coordinates\n // are padded with zeros to 32-byte each.\n bytes public publicKey;\n\n // The timestamp at which keep has been created and key generation process\n // started.\n uint256 internal keyGenerationStartTimestamp;\n\n // Map stores public key by member addresses. All members should submit the\n // same public key.\n mapping(address => bytes) internal submittedPublicKeys;\n\n // The current status of the keep.\n // If the keep is Active members monitor it and support requests from the\n // keep owner.\n // If the owner decides to close the keep the flag is set to Closed.\n // If the owner seizes member bonds the flag is set to Terminated.\n Status internal status;\n\n // Flags execution of contract initialization.\n bool internal isInitialized;\n\n // Notification that the submitted public key does not match a key submitted\n // by other member. The event contains address of the member who tried to\n // submit a public key and a conflicting public key submitted already by other\n // member.\n event ConflictingPublicKeySubmitted(\n address indexed submittingMember,\n bytes conflictingPublicKey\n );\n\n // Notification that keep's ECDSA public key has been successfully established.\n event PublicKeyPublished(bytes publicKey);\n\n // Notification that the keep was closed by the owner.\n // Members no longer need to support this keep.\n event KeepClosed();\n\n // Notification that the keep has been terminated by the owner.\n // Members no longer need to support this keep.\n event KeepTerminated();\n\n /// @notice Returns keep's ECDSA public key.\n /// @return Keep's ECDSA public key.\n function getPublicKey() external view returns (bytes memory) {\n return publicKey;\n }\n\n /// @notice Submits a public key to the keep.\n /// @dev Public key is published successfully if all members submit the same\n /// value. In case of conflicts with others members submissions it will emit\n /// `ConflictingPublicKeySubmitted` event. When all submitted keys match\n /// it will store the key as keep's public key and emit a `PublicKeyPublished`\n /// event.\n /// @param _publicKey Signer's public key.\n function submitPublicKey(bytes calldata _publicKey) external onlyMember {\n require(\n !hasMemberSubmittedPublicKey(msg.sender),\n \"Member already submitted a public key\"\n );\n\n require(_publicKey.length == 64, \"Public key must be 64 bytes long\");\n\n submittedPublicKeys[msg.sender] = _publicKey;\n\n // Check if public keys submitted by all keep members are the same as\n // the currently submitted one.\n uint256 matchingPublicKeysCount = 0;\n for (uint256 i = 0; i < members.length; i++) {\n if (\n keccak256(submittedPublicKeys[members[i]]) !=\n keccak256(_publicKey)\n ) {\n // Emit an event only if compared member already submitted a value.\n if (hasMemberSubmittedPublicKey(members[i])) {\n emit ConflictingPublicKeySubmitted(\n msg.sender,\n submittedPublicKeys[members[i]]\n );\n }\n } else {\n matchingPublicKeysCount++;\n }\n }\n\n if (matchingPublicKeysCount != members.length) {\n return;\n }\n\n // All submitted signatures match.\n publicKey = _publicKey;\n emit PublicKeyPublished(_publicKey);\n }\n\n /// @notice Gets the owner of the keep.\n /// @return Address of the keep owner.\n function getOwner() external view returns (address) {\n return owner;\n }\n\n /// @notice Gets the timestamp the keep was opened at.\n /// @return Timestamp the keep was opened at.\n function getOpenedTimestamp() external view returns (uint256) {\n return keyGenerationStartTimestamp;\n }\n\n /// @notice Closes keep when owner decides that they no longer need it.\n /// Releases bonds to the keep members.\n /// @dev The function can be called only by the owner of the keep and only\n /// if the keep has not been already closed.\n function closeKeep() public onlyOwner onlyWhenActive {\n markAsClosed();\n }\n\n /// @notice Returns true if the keep is active.\n /// @return true if the keep is active, false otherwise.\n function isActive() public view returns (bool) {\n return status == Status.Active;\n }\n\n /// @notice Returns true if the keep is closed and members no longer support\n /// this keep.\n /// @return true if the keep is closed, false otherwise.\n function isClosed() public view returns (bool) {\n return status == Status.Closed;\n }\n\n /// @notice Returns true if the keep has been terminated.\n /// Keep is terminated when bonds are seized and members no longer support\n /// this keep.\n /// @return true if the keep has been terminated, false otherwise.\n function isTerminated() public view returns (bool) {\n return status == Status.Terminated;\n }\n\n /// @notice Returns members of the keep.\n /// @return List of the keep members' addresses.\n function getMembers() public view returns (address[] memory) {\n return members;\n }\n\n /// @notice Initialization function.\n /// @dev We use clone factory to create new keep. That is why this contract\n /// doesn't have a constructor. We provide keep parameters for each instance\n /// function after cloning instances from the master contract.\n /// Initialization must happen in the same transaction in which the clone is\n /// created.\n /// @param _owner Address of the keep owner.\n /// @param _members Addresses of the keep members.\n /// @param _honestThreshold Minimum number of honest keep members.\n function initialize(\n address _owner,\n address[] memory _members,\n uint256 _honestThreshold\n ) public {\n require(!isInitialized, \"Contract already initialized\");\n require(_owner != address(0));\n owner = _owner;\n members = _members;\n honestThreshold = _honestThreshold;\n\n status = Status.Active;\n isInitialized = true;\n\n /* solium-disable-next-line security/no-block-members*/\n keyGenerationStartTimestamp = block.timestamp;\n }\n\n /// @notice Checks if the member already submitted a public key.\n /// @param _member Address of the member.\n /// @return True if member already submitted a public key, else false.\n function hasMemberSubmittedPublicKey(address _member)\n internal\n view\n returns (bool)\n {\n return submittedPublicKeys[_member].length != 0;\n }\n\n /// @notice Marks the keep as closed.\n /// Keep can be marked as closed only when there is no signing in progress\n /// or the requested signing process has timed out.\n function markAsClosed() internal {\n status = Status.Closed;\n emit KeepClosed();\n }\n\n /// @notice Marks the keep as terminated.\n /// Keep can be marked as terminated only when there is no signing in progress\n /// or the requested signing process has timed out.\n function markAsTerminated() internal {\n status = Status.Terminated;\n emit KeepTerminated();\n }\n\n /// @notice Coverts a public key to an ethereum address.\n /// @param _publicKey Public key provided as 64-bytes concatenation of\n /// X and Y coordinates (32-bytes each).\n /// @return Ethereum address.\n function publicKeyToAddress(bytes memory _publicKey)\n internal\n pure\n returns (address)\n {\n // We hash the public key and then truncate last 20 bytes of the digest\n // which is the ethereum address.\n return address(uint160(uint256(keccak256(_publicKey))));\n }\n\n /// @notice Terminates the keep.\n function terminateKeep() internal {\n markAsTerminated();\n }\n\n /// @notice Checks if the caller is the keep's owner.\n /// @dev Throws an error if called by any account other than owner.\n modifier onlyOwner() {\n require(owner == msg.sender, \"Caller is not the keep owner\");\n _;\n }\n\n /// @notice Checks if the caller is a keep member.\n /// @dev Throws an error if called by any account other than one of the members.\n modifier onlyMember() {\n require(members.contains(msg.sender), \"Caller is not the keep member\");\n _;\n }\n\n /// @notice Checks if the keep is currently active.\n /// @dev Throws an error if called when the keep has been already closed.\n modifier onlyWhenActive() {\n require(isActive(), \"Keep is not active\");\n _;\n }\n}\n" + }, + "contracts/bridge/utils/AddressArrayUtils.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.6.12;\n\nlibrary AddressArrayUtils {\n function contains(address[] memory self, address _address)\n internal\n pure\n returns (bool)\n {\n for (uint256 i = 0; i < self.length; i++) {\n if (_address == self[i]) {\n return true;\n }\n }\n return false;\n }\n}" + }, + "contracts/bridge/testing/NodeEnv.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.6.12;\npragma experimental ABIEncoderV2;\n\nimport '@openzeppelin/contracts/access/AccessControl.sol';\nimport \"../utils/EnumerableStringMap.sol\";\n\n/**\n * @title NodeEnv contract\n * @author Synapse Authors\n * @notice This contract implements a key-value store for storing variables on which synapse nodes must coordinate\n * methods are purposely arbitrary to allow these fields to be defined in synapse improvement proposals.\n * @notice This token is used for configuring different tokens on the bridge and mapping them across chains.\n**/\ncontract NodeEnv is AccessControl {\n using EnumerableStringMap for EnumerableStringMap.StringToStringMap;\n // BRIDGEMANAGER_ROLE owns the bridge. They are the only user that can call setters on this contract\n bytes32 public constant BRIDGEMANAGER_ROLE = keccak256('BRIDGEMANAGER_ROLE');\n // _config stores the config\n EnumerableStringMap.StringToStringMap private _config; // key is tokenAddress,chainID\n\n // ConfigUpdate is emitted when the config is updated by the user\n event ConfigUpdate(\n string key\n );\n\n constructor() public {\n _setupRole(DEFAULT_ADMIN_ROLE, msg.sender);\n _setupRole(BRIDGEMANAGER_ROLE, msg.sender);\n }\n\n /**\n * @notice get the length of the config\n *\n * @dev this is useful for enumerating through all keys in the env\n */\n function keyCount()\n external\n view\n returns (uint256){\n return _config.length();\n }\n\n /**\n * @notice gets the key/value pair by it's index\n *\n * Requirements:\n *\n * - `index` must be strictly less than {length}.\n */\n function keyValueByIndex(uint256 index) external view returns(string memory, string memory){\n return _config.at(index);\n }\n\n /**\n * @notice gets the value associated with the key\n */\n function get(string calldata _key) external view returns(string memory){\n string memory key = _key;\n return _config.get(key);\n }\n\n /**\n * @notice sets the key\n *\n * @dev caller must have bridge manager role\n */\n function set(string calldata _key, string calldata _value) external returns(bool) {\n require(\n hasRole(BRIDGEMANAGER_ROLE, msg.sender),\n 'Caller is not Bridge Manager'\n );\n string memory key = _key;\n string memory value = _value;\n\n return _config.set(key, value);\n }\n}" + }, + "contracts/bridge/utils/EnumerableStringMap.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.6.12;\n\nimport \"@openzeppelin/contracts/utils/EnumerableSet.sol\";\n\n/**\n * @title EnumerableStringMap\n * @dev Library for managing an enumerable variant of Solidity's\n * https://solidity.readthedocs.io/en/latest/types.html#mapping-types[`mapping`]\n * type.\n *\n * Maps have the following properties:\n *\n * - Entries are added, removed, and checked for existence in constant time\n * (O(1)).\n * - Entries are enumerated in O(n). No guarantees are made on the ordering.\n *\n * this isn't a terribly gas efficient implementation because it emphasizes usability over gas efficiency\n * by allowing arbitrary length string memorys. If Gettetrs/Setters are going to be used frequently in contracts\n * consider using the OpenZeppeling Bytes32 implementation\n *\n * this also differs from the OpenZeppelin implementation by keccac256 hashing the string memorys\n * so we can use enumerable bytes32 set\n */\nlibrary EnumerableStringMap {\n using EnumerableSet for EnumerableSet.Bytes32Set;\n\n // To implement this library for multiple types with as little code\n // repetition as possible, we write it in terms of a generic Map type with\n // bytes32 keys and values.\n // The Map implementation uses private functions, and user-facing\n // implementations (such as Uint256ToAddressMap) are just wrappers around\n // the underlying Map.\n // This means that we can only create new EnumerableMaps for types that fit\n // in bytes32.\n\n struct Map {\n // Storage of keys as a set\n EnumerableSet.Bytes32Set _keys;\n // Mapping of keys to resulting values to allow key lookup in the set\n mapping(bytes32 => string) _hashKeyMap;\n // values\n mapping(bytes32 => string) _values;\n }\n\n /**\n * @dev Adds a key-value pair to a map, or updates the value for an existing\n * key. O(1).\n *\n * Returns true if the key was added to the map, that is if it was not\n * already present.\n */\n function _set(\n Map storage map,\n string memory key,\n string memory value\n ) private returns (bool) {\n bytes32 keyHash = keccak256(abi.encodePacked(key));\n map._values[keyHash] = value;\n map._hashKeyMap[keyHash] = key;\n return map._keys.add(keyHash);\n }\n\n /**\n * @dev Removes a key-value pair from a map. O(1).\n *\n * Returns true if the key was removed from the map, that is if it was present.\n */\n function _remove(Map storage map, bytes32 keyHash) private returns (bool) {\n delete map._values[keyHash];\n delete map._hashKeyMap[keyHash];\n return map._keys.remove(keyHash);\n }\n\n /**\n * @dev Returns true if the key is in the map. O(1).\n */\n function _contains(Map storage map, bytes32 keyHash) private view returns (bool) {\n return map._keys.contains(keyHash);\n }\n\n /**\n * @dev Returns the number of key-value pairs in the map. O(1).\n */\n function _length(Map storage map) private view returns (uint256) {\n return map._keys.length();\n }\n\n /**\n * @dev Returns the key-value pair stored at position `index` in the map. O(1).\n *\n * Note that there are no guarantees on the ordering of entries inside the\n * array, and it may change when more entries are added or removed.\n *\n * Requirements:\n *\n * - `index` must be strictly less than {length}.\n */\n function _at(Map storage map, uint256 index) private view returns (string memory, string memory) {\n bytes32 keyHash = map._keys.at(index);\n return (map._hashKeyMap[keyHash], map._values[keyHash]);\n }\n\n /**\n * @dev Tries to returns the value associated with `key`. O(1).\n * Does not revert if `key` is not in the map.\n */\n function _tryGet(Map storage map, bytes32 keyHash) private view returns (bool, string memory) {\n string memory value = map._values[keyHash];\n if (keccak256(bytes(value)) == keccak256(bytes(\"\"))) {\n return (_contains(map, keyHash), \"\");\n } else {\n return (true, value);\n }\n }\n\n /**\n * @dev Returns the value associated with `key`. O(1).\n *\n * Requirements:\n *\n * - `key` must be in the map.\n */\n function _get(Map storage map, bytes32 keyHash) private view returns (string memory) {\n string memory value = map._values[keyHash];\n require(_contains(map, keyHash), \"EnumerableMap: nonexistent key\");\n return value;\n }\n\n // StringToStringMap\n struct StringToStringMap {\n Map _inner;\n }\n\n /**\n * @dev Adds a key-value pair to a map, or updates the value for an existing\n * key. O(1).\n *\n * Returns true if the key was added to the map, that is if it was not\n * already present.\n */\n function set(\n StringToStringMap storage map,\n string memory key,\n string memory value\n ) internal returns (bool) {\n return _set(map._inner, key, value);\n }\n\n /**\n * @dev Removes a value from a set. O(1).\n *\n * Returns true if the key was removed from the map, that is if it was present.\n */\n function remove(StringToStringMap storage map, string memory key) internal returns (bool) {\n return _remove(map._inner, keccak256(abi.encodePacked(key)));\n }\n\n /**\n * @dev Returns true if the key is in the map. O(1).\n */\n function contains(StringToStringMap storage map, string memory key) internal view returns (bool) {\n return _contains(map._inner, keccak256(abi.encodePacked(key)));\n }\n\n /**\n * @dev Returns the number of elements in the map. O(1).\n */\n function length(StringToStringMap storage map) internal view returns (uint256) {\n return _length(map._inner);\n }\n\n /**\n * @dev Returns the element stored at position `index` in the set. O(1).\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(StringToStringMap storage map, uint256 index) internal view returns (string memory, string memory) {\n return _at(map._inner, index);\n }\n\n /**\n * @dev Tries to returns the value associated with `key`. O(1).\n * Does not revert if `key` is not in the map.\n *\n * _Available since v3.4._\n */\n function tryGet(StringToStringMap storage map, uint256 key) internal view returns (bool, string memory) {\n (bool success, string memory value) = _tryGet(map._inner, bytes32(key));\n return (success, value);\n }\n\n /**\n * @dev Returns the value associated with `key`. O(1).\n *\n * Requirements:\n *\n * - `key` must be in the map.\n */\n function get(StringToStringMap storage map, string memory key) internal view returns (string memory) {\n return _get(map._inner, keccak256(abi.encodePacked(key)));\n }\n}" + }, + "contracts/bridge/PoolConfig.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.6.12;\npragma experimental ABIEncoderV2;\n\nimport \"@openzeppelin/contracts/access/AccessControl.sol\";\n\ncontract PoolConfig is AccessControl {\n bytes32 public constant BRIDGEMANAGER_ROLE =\n keccak256(\"BRIDGEMANAGER_ROLE\");\n mapping(address => mapping(uint256 => Pool)) private _pool; // key is tokenAddress,chainID\n\n struct Pool {\n address tokenAddress;\n uint256 chainId;\n address poolAddress;\n bool metaswap;\n }\n\n constructor() public {\n _setupRole(DEFAULT_ADMIN_ROLE, msg.sender);\n _setupRole(BRIDGEMANAGER_ROLE, msg.sender);\n }\n\n function getPoolConfig(address tokenAddress, uint256 chainID)\n external\n view\n returns (Pool memory)\n {\n return _pool[tokenAddress][chainID];\n }\n\n function setPoolConfig(\n address tokenAddress,\n uint256 chainID,\n address poolAddress,\n bool metaswap\n ) external returns (Pool memory) {\n require(\n hasRole(BRIDGEMANAGER_ROLE, msg.sender),\n \"Caller is not Bridge Manager\"\n );\n Pool memory newPool = Pool(\n tokenAddress,\n chainID,\n poolAddress,\n metaswap\n );\n _pool[tokenAddress][chainID] = newPool;\n return newPool;\n }\n}\n" + }, + "contracts/bridge/BridgeConfigV3.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.6.12;\npragma experimental ABIEncoderV2;\n\nimport \"@openzeppelin/contracts/access/AccessControl.sol\";\nimport \"@openzeppelin/contracts/math/SafeMath.sol\";\n\n/**\n * @title BridgeConfig contract\n * @notice This token is used for configuring different tokens on the bridge and mapping them across chains.\n **/\n\ncontract BridgeConfigV3 is AccessControl {\n using SafeMath for uint256;\n bytes32 public constant BRIDGEMANAGER_ROLE =\n keccak256(\"BRIDGEMANAGER_ROLE\");\n bytes32[] private _allTokenIDs;\n mapping(bytes32 => Token[]) private _allTokens; // key is tokenID\n mapping(uint256 => mapping(string => bytes32)) private _tokenIDMap; // key is chainID,tokenAddress\n mapping(bytes32 => mapping(uint256 => Token)) private _tokens; // key is tokenID,chainID\n mapping(address => mapping(uint256 => Pool)) private _pool; // key is tokenAddress,chainID\n mapping(uint256 => uint256) private _maxGasPrice; // key is tokenID,chainID\n uint256 public constant bridgeConfigVersion = 3;\n\n // the denominator used to calculate fees. For example, an\n // LP fee might be something like tradeAmount.mul(fee).div(FEE_DENOMINATOR)\n uint256 private constant FEE_DENOMINATOR = 10**10;\n\n // this struct must be initialized using setTokenConfig for each token that directly interacts with the bridge\n struct Token {\n uint256 chainId;\n string tokenAddress;\n uint8 tokenDecimals;\n uint256 maxSwap;\n uint256 minSwap;\n uint256 swapFee;\n uint256 maxSwapFee;\n uint256 minSwapFee;\n bool hasUnderlying;\n bool isUnderlying;\n }\n\n struct Pool {\n address tokenAddress;\n uint256 chainId;\n address poolAddress;\n bool metaswap;\n }\n\n constructor() public {\n _setupRole(DEFAULT_ADMIN_ROLE, msg.sender);\n }\n\n /**\n * @notice Returns a list of all existing token IDs converted to strings\n */\n function getAllTokenIDs() public view returns (string[] memory result) {\n uint256 length = _allTokenIDs.length;\n result = new string[](length);\n for (uint256 i = 0; i < length; ++i) {\n result[i] = toString(_allTokenIDs[i]);\n }\n }\n\n function _getTokenID(string memory tokenAddress, uint256 chainID)\n internal\n view\n returns (string memory)\n {\n return toString(_tokenIDMap[chainID][tokenAddress]);\n }\n\n function getTokenID(string memory tokenAddress, uint256 chainID)\n public\n view\n returns (string memory)\n {\n return _getTokenID(_toLower(tokenAddress), chainID);\n }\n\n /**\n * @notice Returns the token ID (string) of the cross-chain token inputted\n * @param tokenAddress address of token to get ID for\n * @param chainID chainID of which to get token ID for\n */\n function getTokenID(address tokenAddress, uint256 chainID)\n public\n view\n returns (string memory)\n {\n return _getTokenID(_toLower(toString(tokenAddress)), chainID);\n }\n\n /**\n * @notice Returns the full token config struct\n * @param tokenID String input of the token ID for the token\n * @param chainID Chain ID of which token address + config to get\n */\n function getToken(string memory tokenID, uint256 chainID)\n public\n view\n returns (Token memory token)\n {\n return _tokens[toBytes32(tokenID)][chainID];\n }\n\n /**\n * @notice Returns the full token config struct\n * @param tokenID String input of the token ID for the token\n * @param chainID Chain ID of which token address + config to get\n */\n function getTokenByID(string memory tokenID, uint256 chainID)\n public\n view\n returns (Token memory token)\n {\n return _tokens[toBytes32(tokenID)][chainID];\n }\n\n /**\n * @notice Returns token config struct, given an address and chainID\n * @param tokenAddress Matches the token ID by using a combo of address + chain ID\n * @param chainID Chain ID of which token to get config for\n */\n function getTokenByAddress(string memory tokenAddress, uint256 chainID)\n public\n view\n returns (Token memory token)\n {\n return _tokens[_tokenIDMap[chainID][_toLower(tokenAddress)]][chainID];\n }\n\n function getTokenByEVMAddress(address tokenAddress, uint256 chainID)\n public\n view\n returns (Token memory token)\n {\n return\n _tokens[_tokenIDMap[chainID][_toLower(toString(tokenAddress))]][\n chainID\n ];\n }\n\n /**\n * @notice Returns true if the token has an underlying token -- meaning the token is deposited into the bridge\n * @param tokenID String to check if it is a withdraw/underlying token\n */\n function hasUnderlyingToken(string memory tokenID)\n public\n view\n returns (bool)\n {\n bytes32 bytesTokenID = toBytes32(tokenID);\n Token[] memory _mcTokens = _allTokens[bytesTokenID];\n for (uint256 i = 0; i < _mcTokens.length; ++i) {\n if (_mcTokens[i].hasUnderlying) {\n return true;\n }\n }\n return false;\n }\n\n /**\n * @notice Returns which token is the underlying token to withdraw\n * @param tokenID string token ID\n */\n function getUnderlyingToken(string memory tokenID)\n public\n view\n returns (Token memory token)\n {\n bytes32 bytesTokenID = toBytes32(tokenID);\n Token[] memory _mcTokens = _allTokens[bytesTokenID];\n for (uint256 i = 0; i < _mcTokens.length; ++i) {\n if (_mcTokens[i].isUnderlying) {\n return _mcTokens[i];\n }\n }\n }\n\n /**\n @notice Public function returning if token ID exists given a string\n */\n function isTokenIDExist(string memory tokenID) public view returns (bool) {\n return _isTokenIDExist(toBytes32(tokenID));\n }\n\n /**\n @notice Internal function returning if token ID exists given bytes32 version of the ID\n */\n function _isTokenIDExist(bytes32 tokenID) internal view returns (bool) {\n for (uint256 i = 0; i < _allTokenIDs.length; ++i) {\n if (_allTokenIDs[i] == tokenID) {\n return true;\n }\n }\n return false;\n }\n\n /**\n * @notice Internal function which handles logic of setting token ID and dealing with mappings\n * @param tokenID bytes32 version of ID\n * @param chainID which chain to set the token config for\n * @param tokenToAdd Token object to set the mapping to\n */\n function _setTokenConfig(\n bytes32 tokenID,\n uint256 chainID,\n Token memory tokenToAdd\n ) internal returns (bool) {\n _tokens[tokenID][chainID] = tokenToAdd;\n if (!_isTokenIDExist(tokenID)) {\n _allTokenIDs.push(tokenID);\n }\n\n Token[] storage _mcTokens = _allTokens[tokenID];\n for (uint256 i = 0; i < _mcTokens.length; ++i) {\n if (_mcTokens[i].chainId == chainID) {\n string memory oldToken = _mcTokens[i].tokenAddress;\n if (!compareStrings(tokenToAdd.tokenAddress, oldToken)) {\n _mcTokens[i].tokenAddress = tokenToAdd.tokenAddress;\n _tokenIDMap[chainID][oldToken] = keccak256(\"\");\n _tokenIDMap[chainID][tokenToAdd.tokenAddress] = tokenID;\n }\n }\n }\n _mcTokens.push(tokenToAdd);\n _tokenIDMap[chainID][tokenToAdd.tokenAddress] = tokenID;\n return true;\n }\n\n /**\n * @notice Main write function of this contract - Handles creating the struct and passing it to the internal logic function\n * @param tokenID string ID to set the token config object form\n * @param chainID chain ID to use for the token config object\n * @param tokenAddress token address of the token on the given chain\n * @param tokenDecimals decimals of token\n * @param maxSwap maximum amount of token allowed to be transferred at once - in native token decimals\n * @param minSwap minimum amount of token needed to be transferred at once - in native token decimals\n * @param swapFee percent based swap fee -- 10e6 == 10bps\n * @param maxSwapFee max swap fee to be charged - in native token decimals\n * @param minSwapFee min swap fee to be charged - in native token decimals - especially useful for mainnet ETH\n * @param hasUnderlying bool which represents whether this is a global mint token or one to withdraw()\n * @param isUnderlying bool which represents if this token is the one to withdraw on the given chain\n */\n function setTokenConfig(\n string calldata tokenID,\n uint256 chainID,\n address tokenAddress,\n uint8 tokenDecimals,\n uint256 maxSwap,\n uint256 minSwap,\n uint256 swapFee,\n uint256 maxSwapFee,\n uint256 minSwapFee,\n bool hasUnderlying,\n bool isUnderlying\n ) public returns (bool) {\n require(hasRole(BRIDGEMANAGER_ROLE, msg.sender));\n return\n setTokenConfig(\n tokenID,\n chainID,\n toString(tokenAddress),\n tokenDecimals,\n maxSwap,\n minSwap,\n swapFee,\n maxSwapFee,\n minSwapFee,\n hasUnderlying,\n isUnderlying\n );\n }\n\n /**\n * @notice Main write function of this contract - Handles creating the struct and passing it to the internal logic function\n * @param tokenID string ID to set the token config object form\n * @param chainID chain ID to use for the token config object\n * @param tokenAddress token address of the token on the given chain\n * @param tokenDecimals decimals of token\n * @param maxSwap maximum amount of token allowed to be transferred at once - in native token decimals\n * @param minSwap minimum amount of token needed to be transferred at once - in native token decimals\n * @param swapFee percent based swap fee -- 10e6 == 10bps\n * @param maxSwapFee max swap fee to be charged - in native token decimals\n * @param minSwapFee min swap fee to be charged - in native token decimals - especially useful for mainnet ETH\n * @param hasUnderlying bool which represents whether this is a global mint token or one to withdraw()\n * @param isUnderlying bool which represents if this token is the one to withdraw on the given chain\n */\n function setTokenConfig(\n string calldata tokenID,\n uint256 chainID,\n string memory tokenAddress,\n uint8 tokenDecimals,\n uint256 maxSwap,\n uint256 minSwap,\n uint256 swapFee,\n uint256 maxSwapFee,\n uint256 minSwapFee,\n bool hasUnderlying,\n bool isUnderlying\n ) public returns (bool) {\n require(hasRole(BRIDGEMANAGER_ROLE, msg.sender));\n Token memory tokenToAdd;\n tokenToAdd.tokenAddress = _toLower(tokenAddress);\n tokenToAdd.tokenDecimals = tokenDecimals;\n tokenToAdd.maxSwap = maxSwap;\n tokenToAdd.minSwap = minSwap;\n tokenToAdd.swapFee = swapFee;\n tokenToAdd.maxSwapFee = maxSwapFee;\n tokenToAdd.minSwapFee = minSwapFee;\n tokenToAdd.hasUnderlying = hasUnderlying;\n tokenToAdd.isUnderlying = isUnderlying;\n tokenToAdd.chainId = chainID;\n\n return _setTokenConfig(toBytes32(tokenID), chainID, tokenToAdd);\n }\n\n function _calculateSwapFee(\n string memory tokenAddress,\n uint256 chainID,\n uint256 amount\n ) internal view returns (uint256) {\n Token memory token = _tokens[_tokenIDMap[chainID][tokenAddress]][\n chainID\n ];\n uint256 calculatedSwapFee = amount.mul(token.swapFee).div(\n FEE_DENOMINATOR\n );\n if (\n calculatedSwapFee > token.minSwapFee &&\n calculatedSwapFee < token.maxSwapFee\n ) {\n return calculatedSwapFee;\n } else if (calculatedSwapFee > token.maxSwapFee) {\n return token.maxSwapFee;\n } else {\n return token.minSwapFee;\n }\n }\n\n /**\n * @notice Calculates bridge swap fee based on the destination chain's token transfer.\n * @dev This means the fee should be calculated based on the chain that the nodes emit a tx on\n * @param tokenAddress address of the destination token to query token config for\n * @param chainID destination chain ID to query the token config for\n * @param amount in native token decimals\n * @return Fee calculated in token decimals\n */\n function calculateSwapFee(\n string memory tokenAddress,\n uint256 chainID,\n uint256 amount\n ) external view returns (uint256) {\n return _calculateSwapFee(_toLower(tokenAddress), chainID, amount);\n }\n\n /**\n * @notice Calculates bridge swap fee based on the destination chain's token transfer.\n * @dev This means the fee should be calculated based on the chain that the nodes emit a tx on\n * @param tokenAddress address of the destination token to query token config for\n * @param chainID destination chain ID to query the token config for\n * @param amount in native token decimals\n * @return Fee calculated in token decimals\n */\n function calculateSwapFee(\n address tokenAddress,\n uint256 chainID,\n uint256 amount\n ) external view returns (uint256) {\n return\n _calculateSwapFee(\n _toLower(toString(tokenAddress)),\n chainID,\n amount\n );\n }\n\n // GAS PRICING\n\n /**\n * @notice sets the max gas price for a chain\n */\n function setMaxGasPrice(uint256 chainID, uint256 maxPrice) public {\n require(hasRole(BRIDGEMANAGER_ROLE, msg.sender));\n _maxGasPrice[chainID] = maxPrice;\n }\n\n /**\n * @notice gets the max gas price for a chain\n */\n function getMaxGasPrice(uint256 chainID) public view returns (uint256) {\n return _maxGasPrice[chainID];\n }\n\n // POOL CONFIG\n\n function getPoolConfig(address tokenAddress, uint256 chainID)\n external\n view\n returns (Pool memory)\n {\n return _pool[tokenAddress][chainID];\n }\n\n function setPoolConfig(\n address tokenAddress,\n uint256 chainID,\n address poolAddress,\n bool metaswap\n ) external returns (Pool memory) {\n require(\n hasRole(BRIDGEMANAGER_ROLE, msg.sender),\n \"Caller is not Bridge Manager\"\n );\n Pool memory newPool = Pool(\n tokenAddress,\n chainID,\n poolAddress,\n metaswap\n );\n _pool[tokenAddress][chainID] = newPool;\n return newPool;\n }\n\n // UTILITY FUNCTIONS\n\n function toString(bytes32 data) internal pure returns (string memory) {\n uint8 i = 0;\n while (i < 32 && data[i] != 0) {\n ++i;\n }\n bytes memory bs = new bytes(i);\n for (uint8 j = 0; j < i; ++j) {\n bs[j] = data[j];\n }\n return string(bs);\n }\n\n // toBytes32 converts a string to a bytes 32\n function toBytes32(string memory str)\n internal\n pure\n returns (bytes32 result)\n {\n require(bytes(str).length <= 32);\n assembly {\n result := mload(add(str, 32))\n }\n }\n\n function toString(address x) internal pure returns (string memory) {\n bytes memory s = new bytes(40);\n for (uint256 i = 0; i < 20; i++) {\n bytes1 b = bytes1(uint8(uint256(uint160(x)) / (2**(8 * (19 - i)))));\n bytes1 hi = bytes1(uint8(b) / 16);\n bytes1 lo = bytes1(uint8(b) - 16 * uint8(hi));\n s[2 * i] = char(hi);\n s[2 * i + 1] = char(lo);\n }\n\n string memory addrPrefix = \"0x\";\n\n return concat(addrPrefix, string(s));\n }\n\n function concat(string memory _x, string memory _y)\n internal\n pure\n returns (string memory)\n {\n bytes memory _xBytes = bytes(_x);\n bytes memory _yBytes = bytes(_y);\n\n string memory _tmpValue = new string(_xBytes.length + _yBytes.length);\n bytes memory _newValue = bytes(_tmpValue);\n\n uint256 i;\n uint256 j;\n\n for (i = 0; i < _xBytes.length; i++) {\n _newValue[j++] = _xBytes[i];\n }\n\n for (i = 0; i < _yBytes.length; i++) {\n _newValue[j++] = _yBytes[i];\n }\n\n return string(_newValue);\n }\n\n function char(bytes1 b) internal pure returns (bytes1 c) {\n if (uint8(b) < 10) {\n c = bytes1(uint8(b) + 0x30);\n } else {\n c = bytes1(uint8(b) + 0x57);\n }\n }\n\n function compareStrings(string memory a, string memory b)\n internal\n pure\n returns (bool)\n {\n return (keccak256(abi.encodePacked((a))) ==\n keccak256(abi.encodePacked((b))));\n }\n\n function _toLower(string memory str) internal pure returns (string memory) {\n bytes memory bStr = bytes(str);\n bytes memory bLower = new bytes(bStr.length);\n for (uint256 i = 0; i < bStr.length; i++) {\n // Uppercase character...\n if ((uint8(bStr[i]) >= 65) && (uint8(bStr[i]) <= 90)) {\n // So we add 32 to make it lowercase\n bLower[i] = bytes1(uint8(bStr[i]) + 32);\n } else {\n bLower[i] = bStr[i];\n }\n }\n return string(bLower);\n }\n}\n" + }, + "contracts/bridge/wrappers/GMXWrapper.sol": { + "content": "// SPDX-License-Identifier: MIT\n\nimport '@openzeppelin/contracts/math/SafeMath.sol';\n\npragma solidity 0.6.12;\n\ninterface IGMX {\n function burn(address _account, uint256 _amount) external;\n function balanceOf(address account) external view returns (uint256);\n function mint(address _account, uint256 _amount) external;\n}\n\ncontract GMXWrapper {\n using SafeMath for uint256;\n\n address constant public gmx = 0x62edc0692BD897D2295872a9FFCac5425011c661;\n address constant public bridge = 0xC05e61d0E7a63D27546389B7aD62FdFf5A91aACE;\n\n function transfer(address _recipient, uint256 _amount) external returns (bool) {\n require(msg.sender == bridge);\n _transfer(msg.sender, _recipient, _amount);\n return true;\n }\n\n function _transfer(address _sender, address _recipient, uint256 _amount) private {\n require(_sender != address(0), \"BaseToken: transfer from the zero address\");\n require(_recipient != address(0), \"BaseToken: transfer to the zero address\");\n IGMX(gmx).burn(_sender, _amount);\n IGMX(gmx).mint(_recipient, _amount);\n }\n\n function mint(address _addr, uint256 _amount) external {\n require(msg.sender == bridge);\n uint256 preMint = IGMX(gmx).balanceOf(_addr);\n IGMX(gmx).mint(_addr, _amount);\n uint256 postMint = IGMX(gmx).balanceOf(_addr);\n require(preMint.add(_amount) == postMint, \"Mint incomplete\");\n }\n\n function burnFrom(address _addr, uint256 _amount) external {\n require(msg.sender == bridge);\n uint256 preBurn = IGMX(gmx).balanceOf(_addr);\n IGMX(gmx).burn(_addr, _amount);\n uint256 postBurn = IGMX(gmx).balanceOf(_addr);\n require(postBurn.add(_amount) == preBurn, \"Burn incomplete\");\n }\n}" + }, + "contracts/amm/SwapEthWrapper.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.6.12;\n\nimport \"@openzeppelin/contracts/math/SafeMath.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/SafeERC20.sol\";\nimport \"./Swap.sol\";\nimport \"./interfaces/IWETH9.sol\";\n\n/**\n * @title SwapEthWrapper\n * @notice A wrapper contract for Swap contracts that have WETH as one of the pooled tokens.\n * @author Jongseung Lim (@weeb_mcgee)\n */\ncontract SwapEthWrapper {\n using SafeERC20 for IERC20;\n using SafeMath for uint256;\n\n // constants\n uint8 private constant MAX_UINT8 = 2**8 - 1;\n uint256 private constant MAX_UINT256 = 2**256 - 1;\n\n // immutables\n Swap public immutable SWAP;\n LPToken public immutable LP_TOKEN;\n address payable public immutable WETH_ADDRESS;\n address public immutable OWNER;\n uint8 public immutable WETH_INDEX;\n\n IERC20[] public pooledTokens;\n\n /**\n * @notice Deploys this contract with given WETH9 address and Swap address. It will attempt to\n * fetch information about the given Swap pool. If the Swap pool does not contain WETH9,\n * this call will be reverted. Owner address must be given so that `rescue()` function\n * can be limited.\n * @param wethAddress address to the WETH9 contract\n * @param swap address to the Swap contract that has WETH9 as one of the tokens\n * @param owner address that will be allowed to call `rescue()`\n */\n constructor(\n address payable wethAddress,\n Swap swap,\n address owner\n ) public {\n (, , , , , , LPToken lpToken) = swap.swapStorage();\n uint8 wethIndex = MAX_UINT8;\n\n for (uint8 i = 0; i < MAX_UINT8; i++) {\n try swap.getToken(i) returns (IERC20 token) {\n pooledTokens.push(token);\n if (address(token) == wethAddress) {\n wethIndex = i;\n }\n // Approve pooled tokens to be used by Swap\n token.approve(address(swap), MAX_UINT256);\n } catch {\n break;\n }\n }\n require(wethIndex != MAX_UINT8, \"WETH was not found in the swap pool\");\n\n // Set immutable variables\n WETH_INDEX = wethIndex;\n WETH_ADDRESS = wethAddress;\n SWAP = swap;\n LP_TOKEN = lpToken;\n OWNER = owner;\n\n // Approve LPToken to be used by Swap\n lpToken.approve(address(swap), MAX_UINT256);\n }\n\n /**\n * @notice Add liquidity to the pool with the given amounts of tokens.\n * @dev The msg.value of this call should match the value in amounts array\n * in position of WETH9.\n * @param amounts the amounts of each token to add, in their native precision\n * @param minToMint the minimum LP tokens adding this amount of liquidity\n * should mint, otherwise revert. Handy for front-running mitigation\n * @param deadline latest timestamp to accept this transaction\n * @return amount of LP token user minted and received\n */\n function addLiquidity(\n uint256[] memory amounts,\n uint256 minToMint,\n uint256 deadline\n ) external payable returns (uint256) {\n // If using ETH, deposit them to WETH.\n require(msg.value == amounts[WETH_INDEX], \"INCORRECT_MSG_VALUE\");\n if (msg.value > 0) {\n IWETH9(WETH_ADDRESS).deposit{value: msg.value}();\n }\n // Go through amounts array and transfer respective tokens to this contract.\n for (uint256 i = 0; i < amounts.length; i++) {\n uint256 amount = amounts[i];\n if (i != WETH_INDEX && amount > 0) {\n pooledTokens[i].safeTransferFrom(\n msg.sender,\n address(this),\n amount\n );\n }\n }\n // Add the assets to the pool\n uint256 lpTokenAmount = SWAP.addLiquidity(amounts, minToMint, deadline);\n // Send the LPToken to msg.sender\n IERC20(address(LP_TOKEN)).safeTransfer(msg.sender, lpTokenAmount);\n return lpTokenAmount;\n }\n\n /**\n * @notice Burn LP tokens to remove liquidity from the pool.\n * @dev Liquidity can always be removed, even when the pool is paused. Caller\n * will receive ETH instead of WETH9.\n * @param amount the amount of LP tokens to burn\n * @param minAmounts the minimum amounts of each token in the pool\n * acceptable for this burn. Useful as a front-running mitigation\n * @param deadline latest timestamp to accept this transaction\n * @return amounts of tokens user received\n */\n function removeLiquidity(\n uint256 amount,\n uint256[] calldata minAmounts,\n uint256 deadline\n ) external returns (uint256[] memory) {\n // Transfer LPToken from msg.sender to this contract.\n IERC20(address(LP_TOKEN)).safeTransferFrom(\n msg.sender,\n address(this),\n amount\n );\n // Remove liquidity\n uint256[] memory amounts = SWAP.removeLiquidity(\n amount,\n minAmounts,\n deadline\n );\n // Send the tokens back to the user\n for (uint256 i = 0; i < amounts.length; i++) {\n if (i != WETH_INDEX) {\n pooledTokens[i].safeTransfer(msg.sender, amounts[i]);\n } else {\n IWETH9(WETH_ADDRESS).withdraw(amounts[i]);\n // slither-disable-next-line arbitrary-send\n (bool success, ) = msg.sender.call{value: amounts[i]}(\"\");\n require(success, \"ETH_TRANSFER_FAILED\");\n }\n }\n return amounts;\n }\n\n /**\n * @notice Remove liquidity from the pool all in one token.\n * @dev Caller will receive ETH instead of WETH9.\n * @param tokenAmount the amount of the token you want to receive\n * @param tokenIndex the index of the token you want to receive\n * @param minAmount the minimum amount to withdraw, otherwise revert\n * @param deadline latest timestamp to accept this transaction\n * @return amount of chosen token user received\n */\n function removeLiquidityOneToken(\n uint256 tokenAmount,\n uint8 tokenIndex,\n uint256 minAmount,\n uint256 deadline\n ) external returns (uint256) {\n // Transfer LPToken from msg.sender to this contract.\n IERC20(address(LP_TOKEN)).safeTransferFrom(\n msg.sender,\n address(this),\n tokenAmount\n );\n // Withdraw via single token\n uint256 amount = SWAP.removeLiquidityOneToken(\n tokenAmount,\n tokenIndex,\n minAmount,\n deadline\n );\n // Transfer the token to msg.sender accordingly\n if (tokenIndex != WETH_INDEX) {\n pooledTokens[tokenIndex].safeTransfer(msg.sender, amount);\n } else {\n IWETH9(WETH_ADDRESS).withdraw(amount);\n // slither-disable-next-line arbitrary-send\n (bool success, ) = msg.sender.call{value: amount}(\"\");\n require(success, \"ETH_TRANSFER_FAILED\");\n }\n return amount;\n }\n\n /**\n * @notice Remove liquidity from the pool, weighted differently than the\n * pool's current balances.\n * @dev Caller will receive ETH instead of WETH9.\n * @param amounts how much of each token to withdraw\n * @param maxBurnAmount the max LP token provider is willing to pay to\n * remove liquidity. Useful as a front-running mitigation.\n * @param deadline latest timestamp to accept this transaction\n * @return amount of LP tokens burned\n */\n function removeLiquidityImbalance(\n uint256[] calldata amounts,\n uint256 maxBurnAmount,\n uint256 deadline\n ) external returns (uint256) {\n // Transfer LPToken from msg.sender to this contract.\n IERC20(address(LP_TOKEN)).safeTransferFrom(\n msg.sender,\n address(this),\n maxBurnAmount\n );\n // Withdraw in imbalanced ratio\n uint256 burnedLpTokenAmount = SWAP.removeLiquidityImbalance(\n amounts,\n maxBurnAmount,\n deadline\n );\n // Send the tokens back to the user\n for (uint256 i = 0; i < amounts.length; i++) {\n if (i != WETH_INDEX) {\n pooledTokens[i].safeTransfer(msg.sender, amounts[i]);\n } else {\n IWETH9(WETH_ADDRESS).withdraw(amounts[i]);\n // slither-disable-next-line arbitrary-send\n (bool success, ) = msg.sender.call{value: amounts[i]}(\"\");\n require(success, \"ETH_TRANSFER_FAILED\");\n }\n }\n // Send any extra LP tokens back as well\n uint256 extraLpTokenAmount = maxBurnAmount.sub(burnedLpTokenAmount);\n if (extraLpTokenAmount > 0) {\n IERC20(address(LP_TOKEN)).safeTransfer(\n msg.sender,\n extraLpTokenAmount\n );\n }\n return burnedLpTokenAmount;\n }\n\n /**\n * @notice Swap two tokens using the underlying pool. If tokenIndexFrom\n * represents WETH9 in the pool, the caller must set msg.value equal to dx.\n * If the user is swapping to WETH9 in the pool, the user will receive ETH instead.\n * @param tokenIndexFrom the token the user wants to swap from\n * @param tokenIndexTo the token the user wants to swap to\n * @param dx the amount of tokens the user wants to swap from\n * @param minDy the min amount the user would like to receive, or revert.\n * @param deadline latest timestamp to accept this transaction\n */\n function swap(\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx,\n uint256 minDy,\n uint256 deadline\n ) external payable returns (uint256) {\n // Transfer tokens from msg.sender to this contract\n if (tokenIndexFrom != WETH_INDEX) {\n IERC20(pooledTokens[tokenIndexFrom]).safeTransferFrom(\n msg.sender,\n address(this),\n dx\n );\n } else {\n require(msg.value == dx, \"INCORRECT_MSG_VALUE\");\n IWETH9(WETH_ADDRESS).deposit{value: msg.value}();\n }\n // Execute swap\n uint256 dy = SWAP.swap(\n tokenIndexFrom,\n tokenIndexTo,\n dx,\n minDy,\n deadline\n );\n // Transfer the swapped tokens to msg.sender\n if (tokenIndexTo != WETH_INDEX) {\n IERC20(pooledTokens[tokenIndexTo]).safeTransfer(msg.sender, dy);\n } else {\n IWETH9(WETH_ADDRESS).withdraw(dy);\n // slither-disable-next-line arbitrary-send\n (bool success, ) = msg.sender.call{value: dy}(\"\");\n require(success, \"ETH_TRANSFER_FAILED\");\n }\n return dy;\n }\n\n /**\n * @notice Rescues any of the ETH, the pooled tokens, or the LPToken that may be stuck\n * in this contract. Only the OWNER can call this function.\n */\n function rescue() external {\n require(msg.sender == OWNER, \"CALLED_BY_NON_OWNER\");\n IERC20[] memory tokens = pooledTokens;\n for (uint256 i = 0; i < tokens.length; i++) {\n tokens[i].safeTransfer(\n msg.sender,\n tokens[i].balanceOf(address(this))\n );\n }\n IERC20 lpToken_ = IERC20(address(LP_TOKEN));\n lpToken_.safeTransfer(msg.sender, lpToken_.balanceOf(address(this)));\n // slither-disable-next-line arbitrary-send\n (bool success, ) = msg.sender.call{value: address(this).balance}(\"\");\n require(success, \"ETH_TRANSFER_FAILED\");\n }\n\n receive() external payable {}\n\n // VIEW FUNCTIONS\n\n /**\n * @notice A simple method to calculate prices from deposits or\n * withdrawals, excluding fees but including slippage. This is\n * helpful as an input into the various \"min\" parameters on calls\n * to fight front-running\n *\n * @dev This shouldn't be used outside frontends for user estimates.\n *\n * @param amounts an array of token amounts to deposit or withdrawal,\n * corresponding to pooledTokens. The amount should be in each\n * pooled token's native precision. If a token charges a fee on transfers,\n * use the amount that gets transferred after the fee.\n * @param deposit whether this is a deposit or a withdrawal\n * @return token amount the user will receive\n */\n function calculateTokenAmount(uint256[] calldata amounts, bool deposit)\n external\n view\n returns (uint256)\n {\n return SWAP.calculateTokenAmount(amounts, deposit);\n }\n\n /**\n * @notice A simple method to calculate amount of each underlying\n * tokens that is returned upon burning given amount of LP tokens\n * @param amount the amount of LP tokens that would be burned on withdrawal\n * @return array of token balances that the user will receive\n */\n function calculateRemoveLiquidity(uint256 amount)\n external\n view\n returns (uint256[] memory)\n {\n return SWAP.calculateRemoveLiquidity(amount);\n }\n\n /**\n * @notice Calculate the amount of underlying token available to withdraw\n * when withdrawing via only single token\n * @param tokenAmount the amount of LP token to burn\n * @param tokenIndex index of which token will be withdrawn\n * @return availableTokenAmount calculated amount of underlying token\n * available to withdraw\n */\n function calculateRemoveLiquidityOneToken(\n uint256 tokenAmount,\n uint8 tokenIndex\n ) external view returns (uint256 availableTokenAmount) {\n return SWAP.calculateRemoveLiquidityOneToken(tokenAmount, tokenIndex);\n }\n}\n" + }, + "contracts/amm/interfaces/IWETH9.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.4.0;\n\ninterface IWETH9 {\n function name() external view returns (string memory);\n\n function symbol() external view returns (string memory);\n\n function decimals() external view returns (uint8);\n\n function balanceOf(address) external view returns (uint256);\n\n function allowance(address, address) external view returns (uint256);\n\n receive() external payable;\n\n function deposit() external payable;\n\n function withdraw(uint256 wad) external;\n\n function totalSupply() external view returns (uint256);\n\n function approve(address guy, uint256 wad) external returns (bool);\n\n function transfer(address dst, uint256 wad) external returns (bool);\n\n function transferFrom(\n address src,\n address dst,\n uint256 wad\n ) external returns (bool);\n}\n" + }, + "contracts/amm/helper/BaseSwapDeposit.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.6.12;\n\nimport \"@openzeppelin/contracts/math/SafeMath.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/SafeERC20.sol\";\nimport \"../interfaces/ISwap.sol\";\nimport \"@openzeppelin/contracts/utils/ReentrancyGuard.sol\";\n\ncontract BaseSwapDeposit is ReentrancyGuard {\n using SafeERC20 for IERC20;\n using SafeMath for uint256;\n\n ISwap public baseSwap;\n IERC20[] public baseTokens;\n\n uint256 constant MAX_UINT256 = 2**256 - 1;\n\n constructor(ISwap _baseSwap) public {\n baseSwap = _baseSwap;\n // Check and approve base level tokens to be deposited to the base Swap contract\n {\n uint8 i;\n for (; i < 32; i++) {\n try _baseSwap.getToken(i) returns (IERC20 token) {\n baseTokens.push(token);\n token.safeApprove(address(_baseSwap), MAX_UINT256);\n } catch {\n break;\n }\n }\n require(i > 1, \"baseSwap must have at least 2 tokens\");\n }\n }\n\n // Mutative functions\n\n /**\n * @notice Swap two underlying tokens using the meta pool and the base pool\n * @param tokenIndexFrom the token the user wants to swap from\n * @param tokenIndexTo the token the user wants to swap to\n * @param dx the amount of tokens the user wants to swap from\n * @param minDy the min amount the user would like to receive, or revert.\n * @param deadline latest timestamp to accept this transaction\n */\n function swap(\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx,\n uint256 minDy,\n uint256 deadline\n ) external nonReentrant returns (uint256) {\n baseTokens[tokenIndexFrom].safeTransferFrom(msg.sender, address(this), dx);\n uint256 tokenToAmount =\n baseSwap.swap(\n tokenIndexFrom,\n tokenIndexTo,\n dx,\n minDy,\n deadline\n );\n baseTokens[tokenIndexTo].safeTransfer(msg.sender, tokenToAmount);\n return tokenToAmount;\n }\n\n /**\n * @notice Calculate amount of tokens you receive on swap\n * @param tokenIndexFrom the token the user wants to sell\n * @param tokenIndexTo the token the user wants to buy\n * @param dx the amount of tokens the user wants to sell. If the token charges\n * a fee on transfers, use the amount that gets transferred after the fee.\n * @return amount of tokens the user will receive\n */\n function calculateSwap(\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx\n ) external view returns (uint256) {\n return\n baseSwap.calculateSwap(tokenIndexFrom, tokenIndexTo, dx);\n }\n\n /**\n * @notice Returns the address of the pooled token at given index. Reverts if tokenIndex is out of range.\n * @param index the index of the token\n * @return address of the token at given index\n */\n function getToken(uint256 index) external view returns (IERC20) {\n require(index < baseTokens.length, \"index out of range\");\n return baseTokens[index];\n }\n\n}" + }, + "@openzeppelin/contracts/utils/ReentrancyGuard.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <0.8.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 () internal {\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" + }, + "contracts/amm/AaveSwapWrapper.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.6.12;\n\nimport \"@openzeppelin/contracts/math/SafeMath.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/SafeERC20.sol\";\nimport \"./Swap.sol\";\n\ninterface ILendingPool {\n /**\n * @dev Deposits an `amount` of underlying asset into the reserve, receiving in return overlying aTokens.\n * - E.g. User deposits 100 USDC and gets in return 100 aUSDC\n * @param asset The address of the underlying asset to deposit\n * @param amount The amount to be deposited\n * @param onBehalfOf The address that will receive the aTokens, same as msg.sender if the user\n * wants to receive them on his own wallet, or a different address if the beneficiary of aTokens\n * is a different wallet\n * @param referralCode Code used to register the integrator originating the operation, for potential rewards.\n * 0 if the action is executed directly by the user, without any middle-man\n **/\n function deposit(\n address asset,\n uint256 amount,\n address onBehalfOf,\n uint16 referralCode\n ) external;\n\n /**\n * @dev Withdraws an `amount` of underlying asset from the reserve, burning the equivalent aTokens owned\n * E.g. User has 100 aUSDC, calls withdraw() and receives 100 USDC, burning the 100 aUSDC\n * @param asset The address of the underlying asset to withdraw\n * @param amount The underlying amount to be withdrawn\n * - Send the value type(uint256).max in order to withdraw the whole aToken balance\n * @param to Address that will receive the underlying, same as msg.sender if the user\n * wants to receive it on his own wallet, or a different address if the beneficiary is a\n * different wallet\n * @return The final amount withdrawn\n **/\n function withdraw(\n address asset,\n uint256 amount,\n address to\n ) external returns (uint256);\n}\n\n/**\n * @title AaveSwapWrapper\n * @notice A wrapper contract for interacting with aTokens\n */\ncontract AaveSwapWrapper {\n using SafeERC20 for IERC20;\n using SafeMath for uint256;\n mapping(uint8 => bool) private isUnderlyingIndex;\n\n // constants\n uint8 private constant MAX_UINT8 = 2**8 - 1;\n uint256 private constant MAX_UINT256 = 2**256 - 1;\n\n // immutables\n Swap public immutable SWAP;\n LPToken public immutable LP_TOKEN;\n address public immutable OWNER;\n IERC20[] public POOLED_TOKENS;\n IERC20[] public UNDERLYING_TOKENS;\n ILendingPool public LENDING_POOL;\n\n constructor(\n Swap swap,\n IERC20[] memory underlyingTokens,\n address lendingPool,\n address owner\n ) public {\n (, , , , , , LPToken lpToken) = swap.swapStorage();\n for (uint8 i = 0; i < MAX_UINT8; i++) {\n try swap.getToken(i) returns (IERC20 token) {\n POOLED_TOKENS.push(token);\n // Approve pooled tokens to be used by Swap\n token.approve(address(swap), MAX_UINT256);\n } catch {\n break;\n }\n }\n\n for (uint8 i = 0; i < POOLED_TOKENS.length; i++) {\n if (POOLED_TOKENS[i] == underlyingTokens[i]) {\n isUnderlyingIndex[i] = true;\n } else {\n isUnderlyingIndex[i] = false;\n underlyingTokens[i].approve(lendingPool, MAX_UINT256);\n }\n }\n\n // Set immutable variables\n SWAP = swap;\n LP_TOKEN = lpToken;\n OWNER = owner;\n UNDERLYING_TOKENS = underlyingTokens;\n LENDING_POOL = ILendingPool(lendingPool);\n\n // Approve LPToken to be used by Swap\n lpToken.approve(address(swap), MAX_UINT256);\n }\n\n /**\n * @notice Add liquidity to the pool with the given amounts of tokens.\n * @param amounts the amounts of each token to add, in their native precision\n * @param minToMint the minimum LP tokens adding this amount of liquidity\n * should mint, otherwise revert. Handy for front-running mitigation\n * @param deadline latest timestamp to accept this transaction\n * @return amount of LP token user minted and received\n */\n function addLiquidity(\n uint256[] memory amounts,\n uint256 minToMint,\n uint256 deadline\n ) external returns (uint256) {\n // Go through amounts array and transfer respective tokens to this contract.\n for (uint8 i = 0; i < amounts.length; i++) {\n uint256 amount = amounts[i];\n if (amount > 0) {\n UNDERLYING_TOKENS[i].safeTransferFrom(\n msg.sender,\n address(this),\n amount\n );\n if (isUnderlyingIndex[i] == false) {\n LENDING_POOL.deposit(\n address(UNDERLYING_TOKENS[i]),\n amount,\n address(this),\n 0\n );\n }\n }\n }\n\n // Add the assets to the pool\n uint256 lpTokenAmount = SWAP.addLiquidity(amounts, minToMint, deadline);\n // Send the LPToken to msg.sender\n IERC20(address(LP_TOKEN)).safeTransfer(msg.sender, lpTokenAmount);\n return lpTokenAmount;\n }\n\n /**\n * @notice Burn LP tokens to remove liquidity from the pool.\n * @dev Liquidity can always be removed, even when the pool is paused. Caller\n * will receive ETH instead of WETH9.\n * @param amount the amount of LP tokens to burn\n * @param minAmounts the minimum amounts of each token in the pool\n * acceptable for this burn. Useful as a front-running mitigation\n * @param deadline latest timestamp to accept this transaction\n * @return amounts of tokens user received\n */\n function removeLiquidity(\n uint256 amount,\n uint256[] calldata minAmounts,\n uint256 deadline\n ) external returns (uint256[] memory) {\n // Transfer LPToken from msg.sender to this contract.\n IERC20(address(LP_TOKEN)).safeTransferFrom(\n msg.sender,\n address(this),\n amount\n );\n // Remove liquidity\n uint256[] memory amounts = SWAP.removeLiquidity(\n amount,\n minAmounts,\n deadline\n );\n // Send the tokens back to the user\n for (uint8 i = 0; i < amounts.length; i++) {\n if (isUnderlyingIndex[i] == true) {\n UNDERLYING_TOKENS[i].safeTransfer(msg.sender, amounts[i]);\n } else {\n LENDING_POOL.withdraw(\n address(UNDERLYING_TOKENS[i]),\n amounts[i],\n msg.sender\n );\n // underlyingTokens[i].safeTransfer(msg.sender, amounts[i]);\n }\n }\n return amounts;\n }\n\n /**\n * @notice Remove liquidity from the pool all in one token.\n * @dev Caller will receive ETH instead of WETH9.\n * @param tokenAmount the amount of the token you want to receive\n * @param tokenIndex the index of the token you want to receive\n * @param minAmount the minimum amount to withdraw, otherwise revert\n * @param deadline latest timestamp to accept this transaction\n * @return amount of chosen token user received\n */\n function removeLiquidityOneToken(\n uint256 tokenAmount,\n uint8 tokenIndex,\n uint256 minAmount,\n uint256 deadline\n ) external returns (uint256) {\n // Transfer LPToken from msg.sender to this contract.\n IERC20(address(LP_TOKEN)).safeTransferFrom(\n msg.sender,\n address(this),\n tokenAmount\n );\n // Withdraw via single token\n uint256 amount = SWAP.removeLiquidityOneToken(\n tokenAmount,\n tokenIndex,\n minAmount,\n deadline\n );\n // Transfer the token to msg.sender accordingly\n if (isUnderlyingIndex[tokenIndex] == true) {\n UNDERLYING_TOKENS[tokenIndex].safeTransfer(msg.sender, amount);\n } else {\n LENDING_POOL.withdraw(\n address(UNDERLYING_TOKENS[tokenIndex]),\n amount,\n msg.sender\n );\n }\n return amount;\n }\n\n /**\n * @notice Swap two tokens using the underlying pool. If tokenIndexFrom\n * represents WETH9 in the pool, the caller must set msg.value equal to dx.\n * If the user is swapping to WETH9 in the pool, the user will receive ETH instead.\n * @param tokenIndexFrom the token the user wants to swap from\n * @param tokenIndexTo the token the user wants to swap to\n * @param dx the amount of tokens the user wants to swap from\n * @param minDy the min amount the user would like to receive, or revert.\n * @param deadline latest timestamp to accept this transaction\n */\n function swap(\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx,\n uint256 minDy,\n uint256 deadline\n ) external returns (uint256) {\n // Transfer tokens from msg.sender to this contract\n UNDERLYING_TOKENS[tokenIndexFrom].safeTransferFrom(\n msg.sender,\n address(this),\n dx\n );\n if (isUnderlyingIndex[tokenIndexFrom] == false) {\n LENDING_POOL.deposit(\n address(UNDERLYING_TOKENS[tokenIndexFrom]),\n dx,\n address(this),\n 0\n );\n }\n // Execute swap\n uint256 dy = SWAP.swap(\n tokenIndexFrom,\n tokenIndexTo,\n dx,\n minDy,\n deadline\n );\n // Transfer the swapped tokens to msg.sender\n if (isUnderlyingIndex[tokenIndexTo] == false) {\n LENDING_POOL.withdraw(\n address(UNDERLYING_TOKENS[tokenIndexTo]),\n dy,\n msg.sender\n );\n } else {\n UNDERLYING_TOKENS[tokenIndexTo].safeTransfer(msg.sender, dy);\n }\n return dy;\n }\n\n /**\n * @notice Rescues any of the ETH, the pooled tokens, or the LPToken that may be stuck\n * in this contract. Only the OWNER can call this function.\n */\n function rescue() external {\n require(msg.sender == OWNER, \"CALLED_BY_NON_OWNER\");\n IERC20[] memory tokens = POOLED_TOKENS;\n for (uint256 i = 0; i < tokens.length; i++) {\n tokens[i].safeTransfer(\n msg.sender,\n tokens[i].balanceOf(address(this))\n );\n }\n\n for (uint256 i = 0; i < UNDERLYING_TOKENS.length; i++) {\n UNDERLYING_TOKENS[i].safeTransfer(\n msg.sender,\n UNDERLYING_TOKENS[i].balanceOf(address(this))\n );\n }\n\n IERC20 lpToken_ = IERC20(address(LP_TOKEN));\n lpToken_.safeTransfer(msg.sender, lpToken_.balanceOf(address(this)));\n }\n\n // VIEW FUNCTIONS\n\n /**\n * @notice Calculate amount of tokens you receive on swap\n * @param tokenIndexFrom the token the user wants to sell\n * @param tokenIndexTo the token the user wants to buy\n * @param dx the amount of tokens the user wants to sell. If the token charges\n * a fee on transfers, use the amount that gets transferred after the fee.\n * @return amount of tokens the user will receive\n */\n function calculateSwap(\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx\n ) external view virtual returns (uint256) {\n return SWAP.calculateSwap(tokenIndexFrom, tokenIndexTo, dx);\n }\n\n /**\n * @notice A simple method to calculate prices from deposits or\n * withdrawals, excluding fees but including slippage. This is\n * helpful as an input into the various \"min\" parameters on calls\n * to fight front-running\n *\n * @dev This shouldn't be used outside frontends for user estimates.\n *\n * @param amounts an array of token amounts to deposit or withdrawal,\n * corresponding to pooledTokens. The amount should be in each\n * pooled token's native precision. If a token charges a fee on transfers,\n * use the amount that gets transferred after the fee.\n * @param deposit whether this is a deposit or a withdrawal\n * @return token amount the user will receive\n */\n function calculateTokenAmount(uint256[] calldata amounts, bool deposit)\n external\n view\n returns (uint256)\n {\n return SWAP.calculateTokenAmount(amounts, deposit);\n }\n\n /**\n * @notice A simple method to calculate amount of each underlying\n * tokens that is returned upon burning given amount of LP tokens\n * @param amount the amount of LP tokens that would be burned on withdrawal\n * @return array of token balances that the user will receive\n */\n function calculateRemoveLiquidity(uint256 amount)\n external\n view\n returns (uint256[] memory)\n {\n return SWAP.calculateRemoveLiquidity(amount);\n }\n\n /**\n * @notice Calculate the amount of underlying token available to withdraw\n * when withdrawing via only single token\n * @param tokenAmount the amount of LP token to burn\n * @param tokenIndex index of which token will be withdrawn\n * @return availableTokenAmount calculated amount of underlying token\n * available to withdraw\n */\n function calculateRemoveLiquidityOneToken(\n uint256 tokenAmount,\n uint8 tokenIndex\n ) external view returns (uint256 availableTokenAmount) {\n return SWAP.calculateRemoveLiquidityOneToken(tokenAmount, tokenIndex);\n }\n\n /**\n * @notice Return address of the pooled token at given index. Reverts if tokenIndex is out of range.\n * @param index the index of the token\n * @return address of the token at given index\n */\n function getToken(uint8 index) public view virtual returns (IERC20) {\n if (index < UNDERLYING_TOKENS.length) {\n return UNDERLYING_TOKENS[index];\n } else {\n revert();\n }\n }\n}\n" + }, + "contracts/bridge/ECDSAFactory.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.6.12;\n\nimport \"@openzeppelin/contracts/access/Ownable.sol\";\nimport \"@openzeppelin/contracts/proxy/Clones.sol\";\nimport \"./interfaces/IECDSANodeManagement.sol\";\n\ncontract ECDSAFactory is Ownable {\n event ECDSANodeGroupCreated(\n address indexed keepAddress,\n address[] members,\n address indexed owner,\n uint256 honestThreshold\n );\n\n struct LatestNodeGroup {\n address keepAddress;\n address[] members;\n address owner;\n uint256 honestThreshold;\n }\n\n LatestNodeGroup public latestNodeGroup;\n\n constructor() public Ownable() {}\n\n /// @notice Returns members of the keep.\n /// @return List of the keep members' addresses.\n function getMembers() public view returns (address[] memory) {\n return latestNodeGroup.members;\n }\n\n /**\n @notice Deploys a new node \n @param nodeMgmtAddress address of the ECDSANodeManagement contract to initialize with\n @param owner Owner of the ECDSANodeManagement contract who can determine if the node group is closed or active\n @param members Array of node group members addresses\n @param honestThreshold Number of signers to process a transaction \n @return Address of the newest node management contract created\n **/\n function deploy(\n address nodeMgmtAddress,\n address owner,\n address[] memory members,\n uint256 honestThreshold\n ) external onlyOwner returns (address) {\n address nodeClone = Clones.clone(nodeMgmtAddress);\n IECDSANodeManagement(nodeClone).initialize(\n owner,\n members,\n honestThreshold\n );\n\n latestNodeGroup.keepAddress = nodeClone;\n latestNodeGroup.members = members;\n latestNodeGroup.owner = owner;\n latestNodeGroup.honestThreshold = honestThreshold;\n\n emit ECDSANodeGroupCreated(nodeClone, members, owner, honestThreshold);\n return nodeClone;\n }\n}\n" + }, + "contracts/bridge/interfaces/IECDSANodeManagement.sol": { + "content": "// SPDX-License-Identifier: MIT\n\n\npragma solidity 0.6.12;\n\n/**\n * @title IECDSANodeManagement interface\n * @notice Interface for the ECDSA node management interface.\n * @dev implement this interface to develop a a factory-patterned ECDSA node management contract\n **/\ninterface IECDSANodeManagement { \n function initialize(\n address _owner,\n address[] memory _members,\n uint256 _honestThreshold) external;\n}\n\n" + }, + "contracts/auxiliary/DummyWeth.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.6.12;\nimport \"@openzeppelin/contracts/access/Ownable.sol\";\n\ninterface IWETH9 {\n function name() external view returns (string memory);\n\n function symbol() external view returns (string memory);\n\n function decimals() external view returns (uint8);\n\n function balanceOf(address) external view returns (uint256);\n\n function allowance(address, address) external view returns (uint256);\n\n receive() external payable;\n\n function deposit() external payable;\n\n function withdraw(uint256 wad) external;\n\n function totalSupply() external view returns (uint256);\n\n function approve(address guy, uint256 wad) external returns (bool);\n\n function transfer(address dst, uint256 wad) external returns (bool);\n\n function transferFrom(\n address src,\n address dst,\n uint256 wad\n ) external returns (bool);\n}\n\ncontract DummyWeth is Ownable {\n IWETH9 public WETH;\n\n function setWETHAddress(address payable _weth) external onlyOwner {\n WETH = IWETH9(_weth);\n }\n\n function withdrawToSelf(uint256 amount) external {\n WETH.withdraw(amount);\n }\n\n function rescue(uint256 amount) external onlyOwner {\n WETH.transfer(owner(), amount);\n }\n\n receive() external payable {}\n\n fallback() external payable {}\n}\n" + } + }, + "settings": { + "optimizer": { + "enabled": true, + "runs": 10000 + }, + "outputSelection": { + "*": { + "*": [ + "abi", + "evm.bytecode", + "evm.deployedBytecode", + "evm.methodIdentifiers", + "metadata", + "devdoc", + "userdoc", + "storageLayout", + "evm.gasEstimates", + "devdoc", + "userdoc" + ], + "": [ + "ast" + ] + } + }, + "metadata": { + "useLiteralContent": true + } + } +} \ No newline at end of file diff --git a/deployments/dfk/solcInputs/f890e19d95a4324c05c431b6e8cd0070.json b/deployments/dfk/solcInputs/f890e19d95a4324c05c431b6e8cd0070.json new file mode 100644 index 000000000..1e6c8dabf --- /dev/null +++ b/deployments/dfk/solcInputs/f890e19d95a4324c05c431b6e8cd0070.json @@ -0,0 +1,298 @@ +{ + "language": "Solidity", + "sources": { + "contracts/amm/AaveSwap.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.6.12;\n\nimport \"./Swap.sol\";\n\n/**\n * @title AaveSwap - A StableSwap implementation in solidity, integrated with Aave.\n * @notice This contract is responsible for custody of closely pegged assets (eg. group of stablecoins)\n * and automatic market making system. Users become an LP (Liquidity Provider) by depositing their tokens\n * in desired ratios for an exchange of the pool token that represents their share of the pool.\n * Users can burn pool tokens and withdraw their share of token(s).\n *\n * Each time a swap between the pooled tokens happens, a set fee incurs which effectively gets\n * distributed to the LPs.\n *\n * In case of emergencies, admin can pause additional deposits, swaps, or single-asset withdraws - which\n * stops the ratio of the tokens in the pool from changing.\n * Users can always withdraw their tokens via multi-asset withdraws.\n *\n * @dev Most of the logic is stored as a library `SwapUtils` for the sake of reducing contract's\n * deployment size.\n */\n\ncontract AaveSwap is Swap {\n address internal AAVE_REWARDS;\n address internal AAVE_LENDING_POOL;\n address internal REWARD_TOKEN;\n address internal REWARD_RECEIVER;\n address[] internal AAVE_ASSETS;\n\n /**\n * @notice Initializes this Swap contract with the given parameters.\n * This will also clone a LPToken contract that represents users'\n * LP positions. The owner of LPToken will be this contract - which means\n * only this contract is allowed to mint/burn tokens.\n *\n * @param _pooledTokens an array of ERC20s this pool will accept\n * @param decimals the decimals to use for each pooled token,\n * eg 8 for WBTC. Cannot be larger than POOL_PRECISION_DECIMALS\n * @param lpTokenName the long-form name of the token to be deployed\n * @param lpTokenSymbol the short symbol for the token to be deployed\n * @param _a the amplification coefficient * n * (n - 1). See the\n * StableSwap paper for details\n * @param _fee default swap fee to be initialized with\n * @param _adminFee default adminFee to be initialized with\n * @param lpTokenTargetAddress the address of an existing LPToken contract to use as a target\n */\n function initialize(\n IERC20[] memory _pooledTokens,\n uint8[] memory decimals,\n string memory lpTokenName,\n string memory lpTokenSymbol,\n uint256 _a,\n uint256 _fee,\n uint256 _adminFee,\n address lpTokenTargetAddress\n ) public virtual override initializer {\n Swap.initialize(\n _pooledTokens,\n decimals,\n lpTokenName,\n lpTokenSymbol,\n _a,\n _fee,\n _adminFee,\n lpTokenTargetAddress\n );\n AAVE_REWARDS = 0x01D83Fe6A10D2f2B7AF17034343746188272cAc9;\n AAVE_LENDING_POOL = 0x4F01AeD16D97E3aB5ab2B501154DC9bb0F1A5A2C;\n REWARD_TOKEN = 0xB31f66AA3C1e785363F0875A1B74E27b85FD66c7;\n AAVE_ASSETS = [0x53f7c5869a859F0AeC3D334ee8B4Cf01E3492f21];\n REWARD_RECEIVER = msg.sender;\n }\n\n function setRewardReceiver(address _reward_receiver) external onlyOwner {\n REWARD_RECEIVER = _reward_receiver;\n }\n\n function claimAaveRewards() external {\n AAVE_REWARDS.call(\n abi.encodeWithSignature(\n \"claimRewards(address[],uint256,address)\",\n AAVE_ASSETS,\n type(uint256).max,\n REWARD_RECEIVER\n )\n );\n }\n}\n" + }, + "contracts/amm/Swap.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.6.12;\n\nimport \"@openzeppelin/contracts/math/SafeMath.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/SafeERC20.sol\";\nimport \"@openzeppelin/contracts/proxy/Clones.sol\";\nimport \"@openzeppelin/contracts-upgradeable/utils/ReentrancyGuardUpgradeable.sol\";\nimport \"./OwnerPausableUpgradeable.sol\";\nimport \"./SwapUtils.sol\";\nimport \"./AmplificationUtils.sol\";\n\n/**\n * @title Swap - A StableSwap implementation in solidity.\n * @notice This contract is responsible for custody of closely pegged assets (eg. group of stablecoins)\n * and automatic market making system. Users become an LP (Liquidity Provider) by depositing their tokens\n * in desired ratios for an exchange of the pool token that represents their share of the pool.\n * Users can burn pool tokens and withdraw their share of token(s).\n *\n * Each time a swap between the pooled tokens happens, a set fee incurs which effectively gets\n * distributed to the LPs.\n *\n * In case of emergencies, admin can pause additional deposits, swaps, or single-asset withdraws - which\n * stops the ratio of the tokens in the pool from changing.\n * Users can always withdraw their tokens via multi-asset withdraws.\n *\n * @dev Most of the logic is stored as a library `SwapUtils` for the sake of reducing contract's\n * deployment size.\n */\ncontract Swap is OwnerPausableUpgradeable, ReentrancyGuardUpgradeable {\n using SafeERC20 for IERC20;\n using SafeMath for uint256;\n using SwapUtils for SwapUtils.Swap;\n using AmplificationUtils for SwapUtils.Swap;\n\n // Struct storing data responsible for automatic market maker functionalities. In order to\n // access this data, this contract uses SwapUtils library. For more details, see SwapUtils.sol\n SwapUtils.Swap public swapStorage;\n\n // Maps token address to an index in the pool. Used to prevent duplicate tokens in the pool.\n // getTokenIndex function also relies on this mapping to retrieve token index.\n mapping(address => uint8) private tokenIndexes;\n\n /*** EVENTS ***/\n\n // events replicated from SwapUtils to make the ABI easier for dumb\n // clients\n event TokenSwap(\n address indexed buyer,\n uint256 tokensSold,\n uint256 tokensBought,\n uint128 soldId,\n uint128 boughtId\n );\n event AddLiquidity(\n address indexed provider,\n uint256[] tokenAmounts,\n uint256[] fees,\n uint256 invariant,\n uint256 lpTokenSupply\n );\n event RemoveLiquidity(\n address indexed provider,\n uint256[] tokenAmounts,\n uint256 lpTokenSupply\n );\n event RemoveLiquidityOne(\n address indexed provider,\n uint256 lpTokenAmount,\n uint256 lpTokenSupply,\n uint256 boughtId,\n uint256 tokensBought\n );\n event RemoveLiquidityImbalance(\n address indexed provider,\n uint256[] tokenAmounts,\n uint256[] fees,\n uint256 invariant,\n uint256 lpTokenSupply\n );\n event NewAdminFee(uint256 newAdminFee);\n event NewSwapFee(uint256 newSwapFee);\n event RampA(\n uint256 oldA,\n uint256 newA,\n uint256 initialTime,\n uint256 futureTime\n );\n event StopRampA(uint256 currentA, uint256 time);\n\n /**\n * @notice Initializes this Swap contract with the given parameters.\n * This will also clone a LPToken contract that represents users'\n * LP positions. The owner of LPToken will be this contract - which means\n * only this contract is allowed to mint/burn tokens.\n *\n * @param _pooledTokens an array of ERC20s this pool will accept\n * @param decimals the decimals to use for each pooled token,\n * eg 8 for WBTC. Cannot be larger than POOL_PRECISION_DECIMALS\n * @param lpTokenName the long-form name of the token to be deployed\n * @param lpTokenSymbol the short symbol for the token to be deployed\n * @param _a the amplification coefficient * n * (n - 1). See the\n * StableSwap paper for details\n * @param _fee default swap fee to be initialized with\n * @param _adminFee default adminFee to be initialized with\n * @param lpTokenTargetAddress the address of an existing LPToken contract to use as a target\n */\n function initialize(\n IERC20[] memory _pooledTokens,\n uint8[] memory decimals,\n string memory lpTokenName,\n string memory lpTokenSymbol,\n uint256 _a,\n uint256 _fee,\n uint256 _adminFee,\n address lpTokenTargetAddress\n ) public virtual initializer {\n __OwnerPausable_init();\n __ReentrancyGuard_init();\n // Check _pooledTokens and precisions parameter\n require(_pooledTokens.length > 1, \"_pooledTokens.length <= 1\");\n require(_pooledTokens.length <= 32, \"_pooledTokens.length > 32\");\n require(\n _pooledTokens.length == decimals.length,\n \"_pooledTokens decimals mismatch\"\n );\n\n uint256[] memory precisionMultipliers = new uint256[](decimals.length);\n\n for (uint8 i = 0; i < _pooledTokens.length; i++) {\n if (i > 0) {\n // Check if index is already used. Check if 0th element is a duplicate.\n require(\n tokenIndexes[address(_pooledTokens[i])] == 0 &&\n _pooledTokens[0] != _pooledTokens[i],\n \"Duplicate tokens\"\n );\n }\n require(\n address(_pooledTokens[i]) != address(0),\n \"The 0 address isn't an ERC-20\"\n );\n require(\n decimals[i] <= SwapUtils.POOL_PRECISION_DECIMALS,\n \"Token decimals exceeds max\"\n );\n precisionMultipliers[i] =\n 10 **\n uint256(SwapUtils.POOL_PRECISION_DECIMALS).sub(\n uint256(decimals[i])\n );\n tokenIndexes[address(_pooledTokens[i])] = i;\n }\n\n // Check _a, _fee, _adminFee parameters\n require(_a < AmplificationUtils.MAX_A, \"_a exceeds maximum\");\n require(_fee < SwapUtils.MAX_SWAP_FEE, \"_fee exceeds maximum\");\n require(\n _adminFee < SwapUtils.MAX_ADMIN_FEE,\n \"_adminFee exceeds maximum\"\n );\n\n // Clone and initialize a LPToken contract\n LPToken lpToken = LPToken(Clones.clone(lpTokenTargetAddress));\n require(\n lpToken.initialize(lpTokenName, lpTokenSymbol),\n \"could not init lpToken clone\"\n );\n\n // Initialize swapStorage struct\n swapStorage.lpToken = lpToken;\n swapStorage.pooledTokens = _pooledTokens;\n swapStorage.tokenPrecisionMultipliers = precisionMultipliers;\n swapStorage.balances = new uint256[](_pooledTokens.length);\n swapStorage.initialA = _a.mul(AmplificationUtils.A_PRECISION);\n swapStorage.futureA = _a.mul(AmplificationUtils.A_PRECISION);\n // swapStorage.initialATime = 0;\n // swapStorage.futureATime = 0;\n swapStorage.swapFee = _fee;\n swapStorage.adminFee = _adminFee;\n }\n\n /*** MODIFIERS ***/\n\n /**\n * @notice Modifier to check deadline against current timestamp\n * @param deadline latest timestamp to accept this transaction\n */\n modifier deadlineCheck(uint256 deadline) {\n require(block.timestamp <= deadline, \"Deadline not met\");\n _;\n }\n\n /*** VIEW FUNCTIONS ***/\n\n /**\n * @notice Return A, the amplification coefficient * n * (n - 1)\n * @dev See the StableSwap paper for details\n * @return A parameter\n */\n function getA() external view virtual returns (uint256) {\n return swapStorage.getA();\n }\n\n /**\n * @notice Return A in its raw precision form\n * @dev See the StableSwap paper for details\n * @return A parameter in its raw precision form\n */\n function getAPrecise() external view virtual returns (uint256) {\n return swapStorage.getAPrecise();\n }\n\n /**\n * @notice Return address of the pooled token at given index. Reverts if tokenIndex is out of range.\n * @param index the index of the token\n * @return address of the token at given index\n */\n function getToken(uint8 index) public view virtual returns (IERC20) {\n require(index < swapStorage.pooledTokens.length, \"Out of range\");\n return swapStorage.pooledTokens[index];\n }\n\n /**\n * @notice Return the index of the given token address. Reverts if no matching\n * token is found.\n * @param tokenAddress address of the token\n * @return the index of the given token address\n */\n function getTokenIndex(address tokenAddress)\n public\n view\n virtual\n returns (uint8)\n {\n uint8 index = tokenIndexes[tokenAddress];\n require(\n address(getToken(index)) == tokenAddress,\n \"Token does not exist\"\n );\n return index;\n }\n\n /**\n * @notice Return current balance of the pooled token at given index\n * @param index the index of the token\n * @return current balance of the pooled token at given index with token's native precision\n */\n function getTokenBalance(uint8 index)\n external\n view\n virtual\n returns (uint256)\n {\n require(index < swapStorage.pooledTokens.length, \"Index out of range\");\n return swapStorage.balances[index];\n }\n\n /**\n * @notice Get the virtual price, to help calculate profit\n * @return the virtual price, scaled to the POOL_PRECISION_DECIMALS\n */\n function getVirtualPrice() external view virtual returns (uint256) {\n return swapStorage.getVirtualPrice();\n }\n\n /**\n * @notice Calculate amount of tokens you receive on swap\n * @param tokenIndexFrom the token the user wants to sell\n * @param tokenIndexTo the token the user wants to buy\n * @param dx the amount of tokens the user wants to sell. If the token charges\n * a fee on transfers, use the amount that gets transferred after the fee.\n * @return amount of tokens the user will receive\n */\n function calculateSwap(\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx\n ) external view virtual returns (uint256) {\n return swapStorage.calculateSwap(tokenIndexFrom, tokenIndexTo, dx);\n }\n\n /**\n * @notice A simple method to calculate prices from deposits or\n * withdrawals, excluding fees but including slippage. This is\n * helpful as an input into the various \"min\" parameters on calls\n * to fight front-running\n *\n * @dev This shouldn't be used outside frontends for user estimates.\n *\n * @param amounts an array of token amounts to deposit or withdrawal,\n * corresponding to pooledTokens. The amount should be in each\n * pooled token's native precision. If a token charges a fee on transfers,\n * use the amount that gets transferred after the fee.\n * @param deposit whether this is a deposit or a withdrawal\n * @return token amount the user will receive\n */\n function calculateTokenAmount(uint256[] calldata amounts, bool deposit)\n external\n view\n virtual\n returns (uint256)\n {\n return swapStorage.calculateTokenAmount(amounts, deposit);\n }\n\n /**\n * @notice A simple method to calculate amount of each underlying\n * tokens that is returned upon burning given amount of LP tokens\n * @param amount the amount of LP tokens that would be burned on withdrawal\n * @return array of token balances that the user will receive\n */\n function calculateRemoveLiquidity(uint256 amount)\n external\n view\n virtual\n returns (uint256[] memory)\n {\n return swapStorage.calculateRemoveLiquidity(amount);\n }\n\n /**\n * @notice Calculate the amount of underlying token available to withdraw\n * when withdrawing via only single token\n * @param tokenAmount the amount of LP token to burn\n * @param tokenIndex index of which token will be withdrawn\n * @return availableTokenAmount calculated amount of underlying token\n * available to withdraw\n */\n function calculateRemoveLiquidityOneToken(\n uint256 tokenAmount,\n uint8 tokenIndex\n ) external view virtual returns (uint256 availableTokenAmount) {\n return swapStorage.calculateWithdrawOneToken(tokenAmount, tokenIndex);\n }\n\n /**\n * @notice This function reads the accumulated amount of admin fees of the token with given index\n * @param index Index of the pooled token\n * @return admin's token balance in the token's precision\n */\n function getAdminBalance(uint256 index)\n external\n view\n virtual\n returns (uint256)\n {\n return swapStorage.getAdminBalance(index);\n }\n\n /*** STATE MODIFYING FUNCTIONS ***/\n\n /**\n * @notice Swap two tokens using this pool\n * @param tokenIndexFrom the token the user wants to swap from\n * @param tokenIndexTo the token the user wants to swap to\n * @param dx the amount of tokens the user wants to swap from\n * @param minDy the min amount the user would like to receive, or revert.\n * @param deadline latest timestamp to accept this transaction\n */\n function swap(\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx,\n uint256 minDy,\n uint256 deadline\n )\n external\n virtual\n nonReentrant\n whenNotPaused\n deadlineCheck(deadline)\n returns (uint256)\n {\n return swapStorage.swap(tokenIndexFrom, tokenIndexTo, dx, minDy);\n }\n\n /**\n * @notice Add liquidity to the pool with the given amounts of tokens\n * @param amounts the amounts of each token to add, in their native precision\n * @param minToMint the minimum LP tokens adding this amount of liquidity\n * should mint, otherwise revert. Handy for front-running mitigation\n * @param deadline latest timestamp to accept this transaction\n * @return amount of LP token user minted and received\n */\n function addLiquidity(\n uint256[] calldata amounts,\n uint256 minToMint,\n uint256 deadline\n )\n external\n virtual\n nonReentrant\n whenNotPaused\n deadlineCheck(deadline)\n returns (uint256)\n {\n return swapStorage.addLiquidity(amounts, minToMint);\n }\n\n /**\n * @notice Burn LP tokens to remove liquidity from the pool. Withdraw fee that decays linearly\n * over period of 4 weeks since last deposit will apply.\n * @dev Liquidity can always be removed, even when the pool is paused.\n * @param amount the amount of LP tokens to burn\n * @param minAmounts the minimum amounts of each token in the pool\n * acceptable for this burn. Useful as a front-running mitigation\n * @param deadline latest timestamp to accept this transaction\n * @return amounts of tokens user received\n */\n function removeLiquidity(\n uint256 amount,\n uint256[] calldata minAmounts,\n uint256 deadline\n )\n external\n virtual\n nonReentrant\n deadlineCheck(deadline)\n returns (uint256[] memory)\n {\n return swapStorage.removeLiquidity(amount, minAmounts);\n }\n\n /**\n * @notice Remove liquidity from the pool all in one token. Withdraw fee that decays linearly\n * over period of 4 weeks since last deposit will apply.\n * @param tokenAmount the amount of the token you want to receive\n * @param tokenIndex the index of the token you want to receive\n * @param minAmount the minimum amount to withdraw, otherwise revert\n * @param deadline latest timestamp to accept this transaction\n * @return amount of chosen token user received\n */\n function removeLiquidityOneToken(\n uint256 tokenAmount,\n uint8 tokenIndex,\n uint256 minAmount,\n uint256 deadline\n )\n external\n virtual\n nonReentrant\n whenNotPaused\n deadlineCheck(deadline)\n returns (uint256)\n {\n return\n swapStorage.removeLiquidityOneToken(\n tokenAmount,\n tokenIndex,\n minAmount\n );\n }\n\n /**\n * @notice Remove liquidity from the pool, weighted differently than the\n * pool's current balances. Withdraw fee that decays linearly\n * over period of 4 weeks since last deposit will apply.\n * @param amounts how much of each token to withdraw\n * @param maxBurnAmount the max LP token provider is willing to pay to\n * remove liquidity. Useful as a front-running mitigation.\n * @param deadline latest timestamp to accept this transaction\n * @return amount of LP tokens burned\n */\n function removeLiquidityImbalance(\n uint256[] calldata amounts,\n uint256 maxBurnAmount,\n uint256 deadline\n )\n external\n virtual\n nonReentrant\n whenNotPaused\n deadlineCheck(deadline)\n returns (uint256)\n {\n return swapStorage.removeLiquidityImbalance(amounts, maxBurnAmount);\n }\n\n /*** ADMIN FUNCTIONS ***/\n\n /**\n * @notice Withdraw all admin fees to the contract owner\n */\n function withdrawAdminFees() external onlyOwner {\n swapStorage.withdrawAdminFees(owner());\n }\n\n /**\n * @notice Update the admin fee. Admin fee takes portion of the swap fee.\n * @param newAdminFee new admin fee to be applied on future transactions\n */\n function setAdminFee(uint256 newAdminFee) external onlyOwner {\n swapStorage.setAdminFee(newAdminFee);\n }\n\n /**\n * @notice Update the swap fee to be applied on swaps\n * @param newSwapFee new swap fee to be applied on future transactions\n */\n function setSwapFee(uint256 newSwapFee) external onlyOwner {\n swapStorage.setSwapFee(newSwapFee);\n }\n\n /**\n * @notice Start ramping up or down A parameter towards given futureA and futureTime\n * Checks if the change is too rapid, and commits the new A value only when it falls under\n * the limit range.\n * @param futureA the new A to ramp towards\n * @param futureTime timestamp when the new A should be reached\n */\n function rampA(uint256 futureA, uint256 futureTime) external onlyOwner {\n swapStorage.rampA(futureA, futureTime);\n }\n\n /**\n * @notice Stop ramping A immediately. Reverts if ramp A is already stopped.\n */\n function stopRampA() external onlyOwner {\n swapStorage.stopRampA();\n }\n}\n" + }, + "@openzeppelin/contracts/math/SafeMath.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <0.8.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" + }, + "@openzeppelin/contracts/token/ERC20/SafeERC20.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <0.8.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" + }, + "@openzeppelin/contracts/proxy/Clones.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <0.8.0;\n\n/**\n * @dev https://eips.ethereum.org/EIPS/eip-1167[EIP 1167] is a standard for\n * deploying minimal proxy contracts, also known as \"clones\".\n *\n * > To simply and cheaply clone contract functionality in an immutable way, this standard specifies\n * > a minimal bytecode implementation that delegates all calls to a known, fixed address.\n *\n * The library includes functions to deploy a proxy using either `create` (traditional deployment) or `create2`\n * (salted deterministic deployment). It also includes functions to predict the addresses of clones deployed using the\n * deterministic method.\n *\n * _Available since v3.4._\n */\nlibrary Clones {\n /**\n * @dev Deploys and returns the address of a clone that mimics the behaviour of `master`.\n *\n * This function uses the create opcode, which should never revert.\n */\n function clone(address master) internal returns (address instance) {\n // solhint-disable-next-line no-inline-assembly\n assembly {\n let ptr := mload(0x40)\n mstore(ptr, 0x3d602d80600a3d3981f3363d3d373d3d3d363d73000000000000000000000000)\n mstore(add(ptr, 0x14), shl(0x60, master))\n mstore(add(ptr, 0x28), 0x5af43d82803e903d91602b57fd5bf30000000000000000000000000000000000)\n instance := create(0, ptr, 0x37)\n }\n require(instance != address(0), \"ERC1167: create failed\");\n }\n\n /**\n * @dev Deploys and returns the address of a clone that mimics the behaviour of `master`.\n *\n * This function uses the create2 opcode and a `salt` to deterministically deploy\n * the clone. Using the same `master` and `salt` multiple time will revert, since\n * the clones cannot be deployed twice at the same address.\n */\n function cloneDeterministic(address master, bytes32 salt) internal returns (address instance) {\n // solhint-disable-next-line no-inline-assembly\n assembly {\n let ptr := mload(0x40)\n mstore(ptr, 0x3d602d80600a3d3981f3363d3d373d3d3d363d73000000000000000000000000)\n mstore(add(ptr, 0x14), shl(0x60, master))\n mstore(add(ptr, 0x28), 0x5af43d82803e903d91602b57fd5bf30000000000000000000000000000000000)\n instance := create2(0, ptr, 0x37, salt)\n }\n require(instance != address(0), \"ERC1167: create2 failed\");\n }\n\n /**\n * @dev Computes the address of a clone deployed using {Clones-cloneDeterministic}.\n */\n function predictDeterministicAddress(address master, bytes32 salt, address deployer) internal pure returns (address predicted) {\n // solhint-disable-next-line no-inline-assembly\n assembly {\n let ptr := mload(0x40)\n mstore(ptr, 0x3d602d80600a3d3981f3363d3d373d3d3d363d73000000000000000000000000)\n mstore(add(ptr, 0x14), shl(0x60, master))\n mstore(add(ptr, 0x28), 0x5af43d82803e903d91602b57fd5bf3ff00000000000000000000000000000000)\n mstore(add(ptr, 0x38), shl(0x60, deployer))\n mstore(add(ptr, 0x4c), salt)\n mstore(add(ptr, 0x6c), keccak256(ptr, 0x37))\n predicted := keccak256(add(ptr, 0x37), 0x55)\n }\n }\n\n /**\n * @dev Computes the address of a clone deployed using {Clones-cloneDeterministic}.\n */\n function predictDeterministicAddress(address master, bytes32 salt) internal view returns (address predicted) {\n return predictDeterministicAddress(master, salt, address(this));\n }\n}\n" + }, + "@openzeppelin/contracts-upgradeable/utils/ReentrancyGuardUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <0.8.0;\nimport \"../proxy/Initializable.sol\";\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 ReentrancyGuardUpgradeable is Initializable {\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 function __ReentrancyGuard_init() internal initializer {\n __ReentrancyGuard_init_unchained();\n }\n\n function __ReentrancyGuard_init_unchained() internal initializer {\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 uint256[49] private __gap;\n}\n" + }, + "contracts/amm/OwnerPausableUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.6.12;\n\nimport \"@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol\";\nimport \"@openzeppelin/contracts-upgradeable/utils/PausableUpgradeable.sol\";\n\n/**\n * @title OwnerPausable\n * @notice An ownable contract allows the owner to pause and unpause the\n * contract without a delay.\n * @dev Only methods using the provided modifiers will be paused.\n */\nabstract contract OwnerPausableUpgradeable is\n OwnableUpgradeable,\n PausableUpgradeable\n{\n function __OwnerPausable_init() internal initializer {\n __Context_init_unchained();\n __Ownable_init_unchained();\n __Pausable_init_unchained();\n }\n\n /**\n * @notice Pause the contract. Revert if already paused.\n */\n function pause() external onlyOwner {\n PausableUpgradeable._pause();\n }\n\n /**\n * @notice Unpause the contract. Revert if already unpaused.\n */\n function unpause() external onlyOwner {\n PausableUpgradeable._unpause();\n }\n}\n" + }, + "contracts/amm/SwapUtils.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.6.12;\n\nimport \"@openzeppelin/contracts/math/SafeMath.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/SafeERC20.sol\";\nimport \"./AmplificationUtils.sol\";\nimport \"./LPToken.sol\";\nimport \"./MathUtils.sol\";\n\n/**\n * @title SwapUtils library\n * @notice A library to be used within Swap.sol. Contains functions responsible for custody and AMM functionalities.\n * @dev Contracts relying on this library must initialize SwapUtils.Swap struct then use this library\n * for SwapUtils.Swap struct. Note that this library contains both functions called by users and admins.\n * Admin functions should be protected within contracts using this library.\n */\nlibrary SwapUtils {\n using SafeERC20 for IERC20;\n using SafeMath for uint256;\n using MathUtils for uint256;\n\n /*** EVENTS ***/\n\n event TokenSwap(\n address indexed buyer,\n uint256 tokensSold,\n uint256 tokensBought,\n uint128 soldId,\n uint128 boughtId\n );\n event AddLiquidity(\n address indexed provider,\n uint256[] tokenAmounts,\n uint256[] fees,\n uint256 invariant,\n uint256 lpTokenSupply\n );\n event RemoveLiquidity(\n address indexed provider,\n uint256[] tokenAmounts,\n uint256 lpTokenSupply\n );\n event RemoveLiquidityOne(\n address indexed provider,\n uint256 lpTokenAmount,\n uint256 lpTokenSupply,\n uint256 boughtId,\n uint256 tokensBought\n );\n event RemoveLiquidityImbalance(\n address indexed provider,\n uint256[] tokenAmounts,\n uint256[] fees,\n uint256 invariant,\n uint256 lpTokenSupply\n );\n event NewAdminFee(uint256 newAdminFee);\n event NewSwapFee(uint256 newSwapFee);\n\n struct Swap {\n // variables around the ramp management of A,\n // the amplification coefficient * n * (n - 1)\n // see https://www.curve.fi/stableswap-paper.pdf for details\n uint256 initialA;\n uint256 futureA;\n uint256 initialATime;\n uint256 futureATime;\n // fee calculation\n uint256 swapFee;\n uint256 adminFee;\n LPToken lpToken;\n // contract references for all tokens being pooled\n IERC20[] pooledTokens;\n // multipliers for each pooled token's precision to get to POOL_PRECISION_DECIMALS\n // for example, TBTC has 18 decimals, so the multiplier should be 1. WBTC\n // has 8, so the multiplier should be 10 ** 18 / 10 ** 8 => 10 ** 10\n uint256[] tokenPrecisionMultipliers;\n // the pool balance of each token, in the token's precision\n // the contract's actual token balance might differ\n uint256[] balances;\n }\n\n // Struct storing variables used in calculations in the\n // calculateWithdrawOneTokenDY function to avoid stack too deep errors\n struct CalculateWithdrawOneTokenDYInfo {\n uint256 d0;\n uint256 d1;\n uint256 newY;\n uint256 feePerToken;\n uint256 preciseA;\n }\n\n // Struct storing variables used in calculations in the\n // {add,remove}Liquidity functions to avoid stack too deep errors\n struct ManageLiquidityInfo {\n uint256 d0;\n uint256 d1;\n uint256 d2;\n uint256 preciseA;\n LPToken lpToken;\n uint256 totalSupply;\n uint256[] balances;\n uint256[] multipliers;\n }\n\n // the precision all pools tokens will be converted to\n uint8 public constant POOL_PRECISION_DECIMALS = 18;\n\n // the denominator used to calculate admin and LP fees. For example, an\n // LP fee might be something like tradeAmount.mul(fee).div(FEE_DENOMINATOR)\n uint256 private constant FEE_DENOMINATOR = 10**10;\n\n // Max swap fee is 1% or 100bps of each swap\n uint256 public constant MAX_SWAP_FEE = 10**8;\n\n // Max adminFee is 100% of the swapFee\n // adminFee does not add additional fee on top of swapFee\n // Instead it takes a certain % of the swapFee. Therefore it has no impact on the\n // users but only on the earnings of LPs\n uint256 public constant MAX_ADMIN_FEE = 10**10;\n\n // Constant value used as max loop limit\n uint256 private constant MAX_LOOP_LIMIT = 256;\n\n /*** VIEW & PURE FUNCTIONS ***/\n\n function _getAPrecise(Swap storage self) internal view returns (uint256) {\n return AmplificationUtils._getAPrecise(self);\n }\n\n /**\n * @notice Calculate the dy, the amount of selected token that user receives and\n * the fee of withdrawing in one token\n * @param tokenAmount the amount to withdraw in the pool's precision\n * @param tokenIndex which token will be withdrawn\n * @param self Swap struct to read from\n * @return the amount of token user will receive\n */\n function calculateWithdrawOneToken(\n Swap storage self,\n uint256 tokenAmount,\n uint8 tokenIndex\n ) external view returns (uint256) {\n (uint256 availableTokenAmount, ) = _calculateWithdrawOneToken(\n self,\n tokenAmount,\n tokenIndex,\n self.lpToken.totalSupply()\n );\n return availableTokenAmount;\n }\n\n function _calculateWithdrawOneToken(\n Swap storage self,\n uint256 tokenAmount,\n uint8 tokenIndex,\n uint256 totalSupply\n ) internal view returns (uint256, uint256) {\n uint256 dy;\n uint256 newY;\n uint256 currentY;\n\n (dy, newY, currentY) = calculateWithdrawOneTokenDY(\n self,\n tokenIndex,\n tokenAmount,\n totalSupply\n );\n\n // dy_0 (without fees)\n // dy, dy_0 - dy\n\n uint256 dySwapFee = currentY\n .sub(newY)\n .div(self.tokenPrecisionMultipliers[tokenIndex])\n .sub(dy);\n\n return (dy, dySwapFee);\n }\n\n /**\n * @notice Calculate the dy of withdrawing in one token\n * @param self Swap struct to read from\n * @param tokenIndex which token will be withdrawn\n * @param tokenAmount the amount to withdraw in the pools precision\n * @return the d and the new y after withdrawing one token\n */\n function calculateWithdrawOneTokenDY(\n Swap storage self,\n uint8 tokenIndex,\n uint256 tokenAmount,\n uint256 totalSupply\n )\n internal\n view\n returns (\n uint256,\n uint256,\n uint256\n )\n {\n // Get the current D, then solve the stableswap invariant\n // y_i for D - tokenAmount\n uint256[] memory xp = _xp(self);\n\n require(tokenIndex < xp.length, \"Token index out of range\");\n\n\n CalculateWithdrawOneTokenDYInfo memory v\n = CalculateWithdrawOneTokenDYInfo(0, 0, 0, 0, 0);\n v.preciseA = _getAPrecise(self);\n v.d0 = getD(xp, v.preciseA);\n v.d1 = v.d0.sub(tokenAmount.mul(v.d0).div(totalSupply));\n\n require(tokenAmount <= xp[tokenIndex], \"Withdraw exceeds available\");\n\n v.newY = getYD(v.preciseA, tokenIndex, xp, v.d1);\n\n uint256[] memory xpReduced = new uint256[](xp.length);\n\n v.feePerToken = _feePerToken(self.swapFee, xp.length);\n for (uint256 i = 0; i < xp.length; i++) {\n uint256 xpi = xp[i];\n // if i == tokenIndex, dxExpected = xp[i] * d1 / d0 - newY\n // else dxExpected = xp[i] - (xp[i] * d1 / d0)\n // xpReduced[i] -= dxExpected * fee / FEE_DENOMINATOR\n xpReduced[i] = xpi.sub(\n (\n (i == tokenIndex)\n ? xpi.mul(v.d1).div(v.d0).sub(v.newY)\n : xpi.sub(xpi.mul(v.d1).div(v.d0))\n )\n .mul(v.feePerToken)\n .div(FEE_DENOMINATOR)\n );\n }\n\n uint256 dy = xpReduced[tokenIndex].sub(\n getYD(v.preciseA, tokenIndex, xpReduced, v.d1)\n );\n dy = dy.sub(1).div(self.tokenPrecisionMultipliers[tokenIndex]);\n\n return (dy, v.newY, xp[tokenIndex]);\n }\n\n /**\n * @notice Calculate the price of a token in the pool with given\n * precision-adjusted balances and a particular D.\n *\n * @dev This is accomplished via solving the invariant iteratively.\n * See the StableSwap paper and Curve.fi implementation for further details.\n *\n * x_1**2 + x1 * (sum' - (A*n**n - 1) * D / (A * n**n)) = D ** (n + 1) / (n ** (2 * n) * prod' * A)\n * x_1**2 + b*x_1 = c\n * x_1 = (x_1**2 + c) / (2*x_1 + b)\n *\n * @param a the amplification coefficient * n * (n - 1). See the StableSwap paper for details.\n * @param tokenIndex Index of token we are calculating for.\n * @param xp a precision-adjusted set of pool balances. Array should be\n * the same cardinality as the pool.\n * @param d the stableswap invariant\n * @return the price of the token, in the same precision as in xp\n */\n function getYD(\n uint256 a,\n uint8 tokenIndex,\n uint256[] memory xp,\n uint256 d\n ) internal pure returns (uint256) {\n uint256 numTokens = xp.length;\n require(tokenIndex < numTokens, \"Token not found\");\n\n uint256 c = d;\n uint256 s;\n uint256 nA = a.mul(numTokens);\n\n for (uint256 i = 0; i < numTokens; i++) {\n if (i != tokenIndex) {\n s = s.add(xp[i]);\n c = c.mul(d).div(xp[i].mul(numTokens));\n // If we were to protect the division loss we would have to keep the denominator separate\n // and divide at the end. However this leads to overflow with large numTokens or/and D.\n // c = c * D * D * D * ... overflow!\n }\n }\n c = c.mul(d).mul(AmplificationUtils.A_PRECISION).div(nA.mul(numTokens));\n\n uint256 b = s.add(d.mul(AmplificationUtils.A_PRECISION).div(nA));\n uint256 yPrev;\n uint256 y = d;\n for (uint256 i = 0; i < MAX_LOOP_LIMIT; i++) {\n yPrev = y;\n y = y.mul(y).add(c).div(y.mul(2).add(b).sub(d));\n if (y.within1(yPrev)) {\n return y;\n }\n }\n revert(\"Approximation did not converge\");\n }\n\n /**\n * @notice Get D, the StableSwap invariant, based on a set of balances and a particular A.\n * @param xp a precision-adjusted set of pool balances. Array should be the same cardinality\n * as the pool.\n * @param a the amplification coefficient * n * (n - 1) in A_PRECISION.\n * See the StableSwap paper for details\n * @return the invariant, at the precision of the pool\n */\n function getD(uint256[] memory xp, uint256 a)\n internal\n pure\n returns (uint256)\n {\n uint256 numTokens = xp.length;\n uint256 s;\n for (uint256 i = 0; i < numTokens; i++) {\n s = s.add(xp[i]);\n }\n if (s == 0) {\n return 0;\n }\n\n uint256 prevD;\n uint256 d = s;\n uint256 nA = a.mul(numTokens);\n\n for (uint256 i = 0; i < MAX_LOOP_LIMIT; i++) {\n uint256 dP = d;\n for (uint256 j = 0; j < numTokens; j++) {\n dP = dP.mul(d).div(xp[j].mul(numTokens));\n // If we were to protect the division loss we would have to keep the denominator separate\n // and divide at the end. However this leads to overflow with large numTokens or/and D.\n // dP = dP * D * D * D * ... overflow!\n }\n prevD = d;\n d = nA\n .mul(s)\n .div(AmplificationUtils.A_PRECISION)\n .add(dP.mul(numTokens))\n .mul(d)\n .div(\n nA\n .sub(AmplificationUtils.A_PRECISION)\n .mul(d)\n .div(AmplificationUtils.A_PRECISION)\n .add(numTokens.add(1).mul(dP))\n );\n if (d.within1(prevD)) {\n return d;\n }\n }\n\n // Convergence should occur in 4 loops or less. If this is reached, there may be something wrong\n // with the pool. If this were to occur repeatedly, LPs should withdraw via `removeLiquidity()`\n // function which does not rely on D.\n revert(\"D does not converge\");\n }\n\n /**\n * @notice Given a set of balances and precision multipliers, return the\n * precision-adjusted balances.\n *\n * @param balances an array of token balances, in their native precisions.\n * These should generally correspond with pooled tokens.\n *\n * @param precisionMultipliers an array of multipliers, corresponding to\n * the amounts in the balances array. When multiplied together they\n * should yield amounts at the pool's precision.\n *\n * @return an array of amounts \"scaled\" to the pool's precision\n */\n function _xp(\n uint256[] memory balances,\n uint256[] memory precisionMultipliers\n ) internal pure returns (uint256[] memory) {\n uint256 numTokens = balances.length;\n require(\n numTokens == precisionMultipliers.length,\n \"Balances must match multipliers\"\n );\n uint256[] memory xp = new uint256[](numTokens);\n for (uint256 i = 0; i < numTokens; i++) {\n xp[i] = balances[i].mul(precisionMultipliers[i]);\n }\n return xp;\n }\n\n /**\n * @notice Return the precision-adjusted balances of all tokens in the pool\n * @param self Swap struct to read from\n * @return the pool balances \"scaled\" to the pool's precision, allowing\n * them to be more easily compared.\n */\n function _xp(Swap storage self) internal view returns (uint256[] memory) {\n return _xp(self.balances, self.tokenPrecisionMultipliers);\n }\n\n /**\n * @notice Get the virtual price, to help calculate profit\n * @param self Swap struct to read from\n * @return the virtual price, scaled to precision of POOL_PRECISION_DECIMALS\n */\n function getVirtualPrice(Swap storage self)\n external\n view\n returns (uint256)\n {\n uint256 d = getD(_xp(self), _getAPrecise(self));\n LPToken lpToken = self.lpToken;\n uint256 supply = lpToken.totalSupply();\n if (supply > 0) {\n return d.mul(10**uint256(POOL_PRECISION_DECIMALS)).div(supply);\n }\n return 0;\n }\n\n /**\n * @notice Calculate the new balances of the tokens given the indexes of the token\n * that is swapped from (FROM) and the token that is swapped to (TO).\n * This function is used as a helper function to calculate how much TO token\n * the user should receive on swap.\n *\n * @param preciseA precise form of amplification coefficient\n * @param tokenIndexFrom index of FROM token\n * @param tokenIndexTo index of TO token\n * @param x the new total amount of FROM token\n * @param xp balances of the tokens in the pool\n * @return the amount of TO token that should remain in the pool\n */\n function getY(\n uint256 preciseA,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 x,\n uint256[] memory xp\n ) internal pure returns (uint256) {\n uint256 numTokens = xp.length;\n require(\n tokenIndexFrom != tokenIndexTo,\n \"Can't compare token to itself\"\n );\n require(\n tokenIndexFrom < numTokens && tokenIndexTo < numTokens,\n \"Tokens must be in pool\"\n );\n\n uint256 d = getD(xp, preciseA);\n uint256 c = d;\n uint256 s;\n uint256 nA = numTokens.mul(preciseA);\n\n uint256 _x;\n for (uint256 i = 0; i < numTokens; i++) {\n if (i == tokenIndexFrom) {\n _x = x;\n } else if (i != tokenIndexTo) {\n _x = xp[i];\n } else {\n continue;\n }\n s = s.add(_x);\n c = c.mul(d).div(_x.mul(numTokens));\n // If we were to protect the division loss we would have to keep the denominator separate\n // and divide at the end. However this leads to overflow with large numTokens or/and D.\n // c = c * D * D * D * ... overflow!\n }\n c = c.mul(d).mul(AmplificationUtils.A_PRECISION).div(nA.mul(numTokens));\n uint256 b = s.add(d.mul(AmplificationUtils.A_PRECISION).div(nA));\n uint256 yPrev;\n uint256 y = d;\n\n // iterative approximation\n for (uint256 i = 0; i < MAX_LOOP_LIMIT; i++) {\n yPrev = y;\n y = y.mul(y).add(c).div(y.mul(2).add(b).sub(d));\n if (y.within1(yPrev)) {\n return y;\n }\n }\n revert(\"Approximation did not converge\");\n }\n\n /**\n * @notice Externally calculates a swap between two tokens.\n * @param self Swap struct to read from\n * @param tokenIndexFrom the token to sell\n * @param tokenIndexTo the token to buy\n * @param dx the number of tokens to sell. If the token charges a fee on transfers,\n * use the amount that gets transferred after the fee.\n * @return dy the number of tokens the user will get\n */\n function calculateSwap(\n Swap storage self,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx\n ) external view returns (uint256 dy) {\n (dy, ) = _calculateSwap(\n self,\n tokenIndexFrom,\n tokenIndexTo,\n dx,\n self.balances\n );\n }\n\n /**\n * @notice Internally calculates a swap between two tokens.\n *\n * @dev The caller is expected to transfer the actual amounts (dx and dy)\n * using the token contracts.\n *\n * @param self Swap struct to read from\n * @param tokenIndexFrom the token to sell\n * @param tokenIndexTo the token to buy\n * @param dx the number of tokens to sell. If the token charges a fee on transfers,\n * use the amount that gets transferred after the fee.\n * @return dy the number of tokens the user will get\n * @return dyFee the associated fee\n */\n function _calculateSwap(\n Swap storage self,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx,\n uint256[] memory balances\n ) internal view returns (uint256 dy, uint256 dyFee) {\n uint256[] memory multipliers = self.tokenPrecisionMultipliers;\n uint256[] memory xp = _xp(balances, multipliers);\n require(\n tokenIndexFrom < xp.length && tokenIndexTo < xp.length,\n \"Token index out of range\"\n );\n uint256 x = dx.mul(multipliers[tokenIndexFrom]).add(xp[tokenIndexFrom]);\n uint256 y = getY(\n _getAPrecise(self),\n tokenIndexFrom,\n tokenIndexTo,\n x,\n xp\n );\n dy = xp[tokenIndexTo].sub(y).sub(1);\n dyFee = dy.mul(self.swapFee).div(FEE_DENOMINATOR);\n dy = dy.sub(dyFee).div(multipliers[tokenIndexTo]);\n }\n\n /**\n * @notice A simple method to calculate amount of each underlying\n * tokens that is returned upon burning given amount of\n * LP tokens\n *\n * @param amount the amount of LP tokens that would to be burned on\n * withdrawal\n * @return array of amounts of tokens user will receive\n */\n function calculateRemoveLiquidity(Swap storage self, uint256 amount)\n external\n view\n returns (uint256[] memory)\n {\n return\n _calculateRemoveLiquidity(\n self.balances,\n amount,\n self.lpToken.totalSupply()\n );\n }\n\n function _calculateRemoveLiquidity(\n uint256[] memory balances,\n uint256 amount,\n uint256 totalSupply\n ) internal pure returns (uint256[] memory) {\n require(amount <= totalSupply, \"Cannot exceed total supply\");\n\n uint256[] memory amounts = new uint256[](balances.length);\n\n for (uint256 i = 0; i < balances.length; i++) {\n amounts[i] = balances[i].mul(amount).div(totalSupply);\n }\n return amounts;\n }\n\n /**\n * @notice A simple method to calculate prices from deposits or\n * withdrawals, excluding fees but including slippage. This is\n * helpful as an input into the various \"min\" parameters on calls\n * to fight front-running\n *\n * @dev This shouldn't be used outside frontends for user estimates.\n *\n * @param self Swap struct to read from\n * @param amounts an array of token amounts to deposit or withdrawal,\n * corresponding to pooledTokens. The amount should be in each\n * pooled token's native precision. If a token charges a fee on transfers,\n * use the amount that gets transferred after the fee.\n * @param deposit whether this is a deposit or a withdrawal\n * @return if deposit was true, total amount of lp token that will be minted and if\n * deposit was false, total amount of lp token that will be burned\n */\n function calculateTokenAmount(\n Swap storage self,\n uint256[] calldata amounts,\n bool deposit\n ) external view returns (uint256) {\n uint256 a = _getAPrecise(self);\n uint256[] memory balances = self.balances;\n uint256[] memory multipliers = self.tokenPrecisionMultipliers;\n\n uint256 d0 = getD(_xp(balances, multipliers), a);\n for (uint256 i = 0; i < balances.length; i++) {\n if (deposit) {\n balances[i] = balances[i].add(amounts[i]);\n } else {\n balances[i] = balances[i].sub(\n amounts[i],\n \"Cannot withdraw more than available\"\n );\n }\n }\n uint256 d1 = getD(_xp(balances, multipliers), a);\n uint256 totalSupply = self.lpToken.totalSupply();\n\n if (deposit) {\n return d1.sub(d0).mul(totalSupply).div(d0);\n } else {\n return d0.sub(d1).mul(totalSupply).div(d0);\n }\n }\n\n /**\n * @notice return accumulated amount of admin fees of the token with given index\n * @param self Swap struct to read from\n * @param index Index of the pooled token\n * @return admin balance in the token's precision\n */\n function getAdminBalance(Swap storage self, uint256 index)\n external\n view\n returns (uint256)\n {\n require(index < self.pooledTokens.length, \"Token index out of range\");\n return\n self.pooledTokens[index].balanceOf(address(this)).sub(\n self.balances[index]\n );\n }\n\n /**\n * @notice internal helper function to calculate fee per token multiplier used in\n * swap fee calculations\n * @param swapFee swap fee for the tokens\n * @param numTokens number of tokens pooled\n */\n function _feePerToken(uint256 swapFee, uint256 numTokens)\n internal\n pure\n returns (uint256)\n {\n return swapFee.mul(numTokens).div(numTokens.sub(1).mul(4));\n }\n\n /*** STATE MODIFYING FUNCTIONS ***/\n\n /**\n * @notice swap two tokens in the pool\n * @param self Swap struct to read from and write to\n * @param tokenIndexFrom the token the user wants to sell\n * @param tokenIndexTo the token the user wants to buy\n * @param dx the amount of tokens the user wants to sell\n * @param minDy the min amount the user would like to receive, or revert.\n * @return amount of token user received on swap\n */\n function swap(\n Swap storage self,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx,\n uint256 minDy\n ) external returns (uint256) {\n {\n IERC20 tokenFrom = self.pooledTokens[tokenIndexFrom];\n require(\n dx <= tokenFrom.balanceOf(msg.sender),\n \"Cannot swap more than you own\"\n );\n // Transfer tokens first to see if a fee was charged on transfer\n uint256 beforeBalance = tokenFrom.balanceOf(address(this));\n tokenFrom.safeTransferFrom(msg.sender, address(this), dx);\n\n // Use the actual transferred amount for AMM math\n dx = tokenFrom.balanceOf(address(this)).sub(beforeBalance);\n }\n\n uint256 dy;\n uint256 dyFee;\n uint256[] memory balances = self.balances;\n (dy, dyFee) = _calculateSwap(\n self,\n tokenIndexFrom,\n tokenIndexTo,\n dx,\n balances\n );\n require(dy >= minDy, \"Swap didn't result in min tokens\");\n\n uint256 dyAdminFee = dyFee.mul(self.adminFee).div(FEE_DENOMINATOR).div(\n self.tokenPrecisionMultipliers[tokenIndexTo]\n );\n\n self.balances[tokenIndexFrom] = balances[tokenIndexFrom].add(dx);\n self.balances[tokenIndexTo] = balances[tokenIndexTo].sub(dy).sub(\n dyAdminFee\n );\n\n self.pooledTokens[tokenIndexTo].safeTransfer(msg.sender, dy);\n\n emit TokenSwap(msg.sender, dx, dy, tokenIndexFrom, tokenIndexTo);\n\n return dy;\n }\n\n /**\n * @notice Add liquidity to the pool\n * @param self Swap struct to read from and write to\n * @param amounts the amounts of each token to add, in their native precision\n * @param minToMint the minimum LP tokens adding this amount of liquidity\n * should mint, otherwise revert. Handy for front-running mitigation\n * allowed addresses. If the pool is not in the guarded launch phase, this parameter will be ignored.\n * @return amount of LP token user received\n */\n function addLiquidity(\n Swap storage self,\n uint256[] memory amounts,\n uint256 minToMint\n ) external returns (uint256) {\n IERC20[] memory pooledTokens = self.pooledTokens;\n require(\n amounts.length == pooledTokens.length,\n \"Amounts must match pooled tokens\"\n );\n\n // current state\n ManageLiquidityInfo memory v = ManageLiquidityInfo(\n 0,\n 0,\n 0,\n _getAPrecise(self),\n self.lpToken,\n 0,\n self.balances,\n self.tokenPrecisionMultipliers\n );\n v.totalSupply = v.lpToken.totalSupply();\n\n if (v.totalSupply != 0) {\n v.d0 = getD(_xp(v.balances, v.multipliers), v.preciseA);\n }\n\n uint256[] memory newBalances = new uint256[](pooledTokens.length);\n\n for (uint256 i = 0; i < pooledTokens.length; i++) {\n require(\n v.totalSupply != 0 || amounts[i] > 0,\n \"Must supply all tokens in pool\"\n );\n\n // Transfer tokens first to see if a fee was charged on transfer\n if (amounts[i] != 0) {\n uint256 beforeBalance = pooledTokens[i].balanceOf(\n address(this)\n );\n pooledTokens[i].safeTransferFrom(\n msg.sender,\n address(this),\n amounts[i]\n );\n\n // Update the amounts[] with actual transfer amount\n amounts[i] = pooledTokens[i].balanceOf(address(this)).sub(\n beforeBalance\n );\n }\n\n newBalances[i] = v.balances[i].add(amounts[i]);\n }\n\n // invariant after change\n v.d1 = getD(_xp(newBalances, v.multipliers), v.preciseA);\n require(v.d1 > v.d0, \"D should increase\");\n\n // updated to reflect fees and calculate the user's LP tokens\n v.d2 = v.d1;\n uint256[] memory fees = new uint256[](pooledTokens.length);\n\n if (v.totalSupply != 0) {\n uint256 feePerToken = _feePerToken(\n self.swapFee,\n pooledTokens.length\n );\n for (uint256 i = 0; i < pooledTokens.length; i++) {\n uint256 idealBalance = v.d1.mul(v.balances[i]).div(v.d0);\n fees[i] = feePerToken\n .mul(idealBalance.difference(newBalances[i]))\n .div(FEE_DENOMINATOR);\n self.balances[i] = newBalances[i].sub(\n fees[i].mul(self.adminFee).div(FEE_DENOMINATOR)\n );\n newBalances[i] = newBalances[i].sub(fees[i]);\n }\n v.d2 = getD(_xp(newBalances, v.multipliers), v.preciseA);\n } else {\n // the initial depositor doesn't pay fees\n self.balances = newBalances;\n }\n\n uint256 toMint;\n if (v.totalSupply == 0) {\n toMint = v.d1;\n } else {\n toMint = v.d2.sub(v.d0).mul(v.totalSupply).div(v.d0);\n }\n\n require(toMint >= minToMint, \"Couldn't mint min requested\");\n\n // mint the user's LP tokens\n v.lpToken.mint(msg.sender, toMint);\n\n emit AddLiquidity(\n msg.sender,\n amounts,\n fees,\n v.d1,\n v.totalSupply.add(toMint)\n );\n\n return toMint;\n }\n\n /**\n * @notice Burn LP tokens to remove liquidity from the pool.\n * @dev Liquidity can always be removed, even when the pool is paused.\n * @param self Swap struct to read from and write to\n * @param amount the amount of LP tokens to burn\n * @param minAmounts the minimum amounts of each token in the pool\n * acceptable for this burn. Useful as a front-running mitigation\n * @return amounts of tokens the user received\n */\n function removeLiquidity(\n Swap storage self,\n uint256 amount,\n uint256[] calldata minAmounts\n ) external returns (uint256[] memory) {\n LPToken lpToken = self.lpToken;\n IERC20[] memory pooledTokens = self.pooledTokens;\n require(amount <= lpToken.balanceOf(msg.sender), \">LP.balanceOf\");\n require(\n minAmounts.length == pooledTokens.length,\n \"minAmounts must match poolTokens\"\n );\n\n uint256[] memory balances = self.balances;\n uint256 totalSupply = lpToken.totalSupply();\n\n uint256[] memory amounts = _calculateRemoveLiquidity(\n balances,\n amount,\n totalSupply\n );\n\n for (uint256 i = 0; i < amounts.length; i++) {\n require(amounts[i] >= minAmounts[i], \"amounts[i] < minAmounts[i]\");\n self.balances[i] = balances[i].sub(amounts[i]);\n pooledTokens[i].safeTransfer(msg.sender, amounts[i]);\n }\n\n lpToken.burnFrom(msg.sender, amount);\n\n emit RemoveLiquidity(msg.sender, amounts, totalSupply.sub(amount));\n\n return amounts;\n }\n\n /**\n * @notice Remove liquidity from the pool all in one token.\n * @param self Swap struct to read from and write to\n * @param tokenAmount the amount of the lp tokens to burn\n * @param tokenIndex the index of the token you want to receive\n * @param minAmount the minimum amount to withdraw, otherwise revert\n * @return amount chosen token that user received\n */\n function removeLiquidityOneToken(\n Swap storage self,\n uint256 tokenAmount,\n uint8 tokenIndex,\n uint256 minAmount\n ) external returns (uint256) {\n LPToken lpToken = self.lpToken;\n IERC20[] memory pooledTokens = self.pooledTokens;\n\n require(tokenAmount <= lpToken.balanceOf(msg.sender), \">LP.balanceOf\");\n require(tokenIndex < pooledTokens.length, \"Token not found\");\n\n uint256 totalSupply = lpToken.totalSupply();\n\n (uint256 dy, uint256 dyFee) = _calculateWithdrawOneToken(\n self,\n tokenAmount,\n tokenIndex,\n totalSupply\n );\n\n require(dy >= minAmount, \"dy < minAmount\");\n\n self.balances[tokenIndex] = self.balances[tokenIndex].sub(\n dy.add(dyFee.mul(self.adminFee).div(FEE_DENOMINATOR))\n );\n lpToken.burnFrom(msg.sender, tokenAmount);\n pooledTokens[tokenIndex].safeTransfer(msg.sender, dy);\n\n emit RemoveLiquidityOne(\n msg.sender,\n tokenAmount,\n totalSupply,\n tokenIndex,\n dy\n );\n\n return dy;\n }\n\n /**\n * @notice Remove liquidity from the pool, weighted differently than the\n * pool's current balances.\n *\n * @param self Swap struct to read from and write to\n * @param amounts how much of each token to withdraw\n * @param maxBurnAmount the max LP token provider is willing to pay to\n * remove liquidity. Useful as a front-running mitigation.\n * @return actual amount of LP tokens burned in the withdrawal\n */\n function removeLiquidityImbalance(\n Swap storage self,\n uint256[] memory amounts,\n uint256 maxBurnAmount\n ) public returns (uint256) {\n ManageLiquidityInfo memory v = ManageLiquidityInfo(\n 0,\n 0,\n 0,\n _getAPrecise(self),\n self.lpToken,\n 0,\n self.balances,\n self.tokenPrecisionMultipliers\n );\n v.totalSupply = v.lpToken.totalSupply();\n\n IERC20[] memory pooledTokens = self.pooledTokens;\n\n require(\n amounts.length == pooledTokens.length,\n \"Amounts should match pool tokens\"\n );\n\n require(\n maxBurnAmount <= v.lpToken.balanceOf(msg.sender) &&\n maxBurnAmount != 0,\n \">LP.balanceOf\"\n );\n\n uint256 feePerToken = _feePerToken(self.swapFee, pooledTokens.length);\n uint256[] memory fees = new uint256[](pooledTokens.length);\n {\n uint256[] memory balances1 = new uint256[](pooledTokens.length);\n v.d0 = getD(_xp(v.balances, v.multipliers), v.preciseA);\n for (uint256 i = 0; i < pooledTokens.length; i++) {\n balances1[i] = v.balances[i].sub(\n amounts[i],\n \"Cannot withdraw more than available\"\n );\n }\n v.d1 = getD(_xp(balances1, v.multipliers), v.preciseA);\n\n for (uint256 i = 0; i < pooledTokens.length; i++) {\n uint256 idealBalance = v.d1.mul(v.balances[i]).div(v.d0);\n uint256 difference = idealBalance.difference(balances1[i]);\n fees[i] = feePerToken.mul(difference).div(FEE_DENOMINATOR);\n self.balances[i] = balances1[i].sub(\n fees[i].mul(self.adminFee).div(FEE_DENOMINATOR)\n );\n balances1[i] = balances1[i].sub(fees[i]);\n }\n\n v.d2 = getD(_xp(balances1, v.multipliers), v.preciseA);\n }\n uint256 tokenAmount = v.d0.sub(v.d2).mul(v.totalSupply).div(v.d0);\n require(tokenAmount != 0, \"Burnt amount cannot be zero\");\n tokenAmount = tokenAmount.add(1);\n\n require(tokenAmount <= maxBurnAmount, \"tokenAmount > maxBurnAmount\");\n\n v.lpToken.burnFrom(msg.sender, tokenAmount);\n\n for (uint256 i = 0; i < pooledTokens.length; i++) {\n pooledTokens[i].safeTransfer(msg.sender, amounts[i]);\n }\n\n emit RemoveLiquidityImbalance(\n msg.sender,\n amounts,\n fees,\n v.d1,\n v.totalSupply.sub(tokenAmount)\n );\n\n return tokenAmount;\n }\n\n /**\n * @notice withdraw all admin fees to a given address\n * @param self Swap struct to withdraw fees from\n * @param to Address to send the fees to\n */\n function withdrawAdminFees(Swap storage self, address to) external {\n IERC20[] memory pooledTokens = self.pooledTokens;\n for (uint256 i = 0; i < pooledTokens.length; i++) {\n IERC20 token = pooledTokens[i];\n uint256 balance = token.balanceOf(address(this)).sub(\n self.balances[i]\n );\n if (balance != 0) {\n token.safeTransfer(to, balance);\n }\n }\n }\n\n /**\n * @notice Sets the admin fee\n * @dev adminFee cannot be higher than 100% of the swap fee\n * @param self Swap struct to update\n * @param newAdminFee new admin fee to be applied on future transactions\n */\n function setAdminFee(Swap storage self, uint256 newAdminFee) external {\n require(newAdminFee <= MAX_ADMIN_FEE, \"Fee is too high\");\n self.adminFee = newAdminFee;\n\n emit NewAdminFee(newAdminFee);\n }\n\n /**\n * @notice update the swap fee\n * @dev fee cannot be higher than 1% of each swap\n * @param self Swap struct to update\n * @param newSwapFee new swap fee to be applied on future transactions\n */\n function setSwapFee(Swap storage self, uint256 newSwapFee) external {\n require(newSwapFee <= MAX_SWAP_FEE, \"Fee is too high\");\n self.swapFee = newSwapFee;\n\n emit NewSwapFee(newSwapFee);\n }\n}\n" + }, + "contracts/amm/AmplificationUtils.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.6.12;\n\nimport \"@openzeppelin/contracts/token/ERC20/SafeERC20.sol\";\nimport \"./SwapUtils.sol\";\n\n/**\n * @title AmplificationUtils library\n * @notice A library to calculate and ramp the A parameter of a given `SwapUtils.Swap` struct.\n * This library assumes the struct is fully validated.\n */\nlibrary AmplificationUtils {\n using SafeMath for uint256;\n\n event RampA(\n uint256 oldA,\n uint256 newA,\n uint256 initialTime,\n uint256 futureTime\n );\n event StopRampA(uint256 currentA, uint256 time);\n\n // Constant values used in ramping A calculations\n uint256 public constant A_PRECISION = 100;\n uint256 public constant MAX_A = 10**6;\n uint256 private constant MAX_A_CHANGE = 2;\n uint256 private constant MIN_RAMP_TIME = 7 days;\n\n /**\n * @notice Return A, the amplification coefficient * n * (n - 1)\n * @dev See the StableSwap paper for details\n * @param self Swap struct to read from\n * @return A parameter\n */\n function getA(SwapUtils.Swap storage self) external view returns (uint256) {\n return _getAPrecise(self).div(A_PRECISION);\n }\n\n /**\n * @notice Return A in its raw precision\n * @dev See the StableSwap paper for details\n * @param self Swap struct to read from\n * @return A parameter in its raw precision form\n */\n function getAPrecise(SwapUtils.Swap storage self)\n external\n view\n returns (uint256)\n {\n return _getAPrecise(self);\n }\n\n /**\n * @notice Return A in its raw precision\n * @dev See the StableSwap paper for details\n * @param self Swap struct to read from\n * @return A parameter in its raw precision form\n */\n function _getAPrecise(SwapUtils.Swap storage self)\n internal\n view\n returns (uint256)\n {\n uint256 t1 = self.futureATime; // time when ramp is finished\n uint256 a1 = self.futureA; // final A value when ramp is finished\n\n if (block.timestamp < t1) {\n uint256 t0 = self.initialATime; // time when ramp is started\n uint256 a0 = self.initialA; // initial A value when ramp is started\n if (a1 > a0) {\n // a0 + (a1 - a0) * (block.timestamp - t0) / (t1 - t0)\n return\n a0.add(\n a1.sub(a0).mul(block.timestamp.sub(t0)).div(t1.sub(t0))\n );\n } else {\n // a0 - (a0 - a1) * (block.timestamp - t0) / (t1 - t0)\n return\n a0.sub(\n a0.sub(a1).mul(block.timestamp.sub(t0)).div(t1.sub(t0))\n );\n }\n } else {\n return a1;\n }\n }\n\n /**\n * @notice Start ramping up or down A parameter towards given futureA_ and futureTime_\n * Checks if the change is too rapid, and commits the new A value only when it falls under\n * the limit range.\n * @param self Swap struct to update\n * @param futureA_ the new A to ramp towards\n * @param futureTime_ timestamp when the new A should be reached\n */\n function rampA(\n SwapUtils.Swap storage self,\n uint256 futureA_,\n uint256 futureTime_\n ) external {\n require(\n block.timestamp >= self.initialATime.add(1 days),\n \"Wait 1 day before starting ramp\"\n );\n require(\n futureTime_ >= block.timestamp.add(MIN_RAMP_TIME),\n \"Insufficient ramp time\"\n );\n require(\n futureA_ > 0 && futureA_ < MAX_A,\n \"futureA_ must be > 0 and < MAX_A\"\n );\n\n uint256 initialAPrecise = _getAPrecise(self);\n uint256 futureAPrecise = futureA_.mul(A_PRECISION);\n\n if (futureAPrecise < initialAPrecise) {\n require(\n futureAPrecise.mul(MAX_A_CHANGE) >= initialAPrecise,\n \"futureA_ is too small\"\n );\n } else {\n require(\n futureAPrecise <= initialAPrecise.mul(MAX_A_CHANGE),\n \"futureA_ is too large\"\n );\n }\n\n self.initialA = initialAPrecise;\n self.futureA = futureAPrecise;\n self.initialATime = block.timestamp;\n self.futureATime = futureTime_;\n\n emit RampA(\n initialAPrecise,\n futureAPrecise,\n block.timestamp,\n futureTime_\n );\n }\n\n /**\n * @notice Stops ramping A immediately. Once this function is called, rampA()\n * cannot be called for another 24 hours\n * @param self Swap struct to update\n */\n function stopRampA(SwapUtils.Swap storage self) external {\n require(self.futureATime > block.timestamp, \"Ramp is already stopped\");\n\n uint256 currentA = _getAPrecise(self);\n self.initialA = currentA;\n self.futureA = currentA;\n self.initialATime = block.timestamp;\n self.futureATime = block.timestamp;\n\n emit StopRampA(currentA, block.timestamp);\n }\n}\n" + }, + "@openzeppelin/contracts/token/ERC20/IERC20.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <0.8.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" + }, + "@openzeppelin/contracts/utils/Address.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.2 <0.8.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" + }, + "@openzeppelin/contracts-upgradeable/proxy/Initializable.sol": { + "content": "// SPDX-License-Identifier: MIT\n\n// solhint-disable-next-line compiler-version\npragma solidity >=0.4.24 <0.8.0;\n\nimport \"../utils/AddressUpgradeable.sol\";\n\n/**\n * @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed\n * behind a proxy. Since a proxied contract can't have a constructor, it's common to move constructor logic to an\n * external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer\n * function so it can only be called once. The {initializer} modifier provided by this contract will have this effect.\n *\n * TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as\n * possible by providing the encoded function call as the `_data` argument to {UpgradeableProxy-constructor}.\n *\n * CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure\n * that all initializers are idempotent. This is not verified automatically as constructors are by Solidity.\n */\nabstract contract Initializable {\n\n /**\n * @dev Indicates that the contract has been initialized.\n */\n bool private _initialized;\n\n /**\n * @dev Indicates that the contract is in the process of being initialized.\n */\n bool private _initializing;\n\n /**\n * @dev Modifier to protect an initializer function from being invoked twice.\n */\n modifier initializer() {\n require(_initializing || _isConstructor() || !_initialized, \"Initializable: contract is already initialized\");\n\n bool isTopLevelCall = !_initializing;\n if (isTopLevelCall) {\n _initializing = true;\n _initialized = true;\n }\n\n _;\n\n if (isTopLevelCall) {\n _initializing = false;\n }\n }\n\n /// @dev Returns true if and only if the function is running in the constructor\n function _isConstructor() private view returns (bool) {\n return !AddressUpgradeable.isContract(address(this));\n }\n}\n" + }, + "@openzeppelin/contracts-upgradeable/utils/AddressUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.2 <0.8.0;\n\n/**\n * @dev Collection of functions related to the address type\n */\nlibrary AddressUpgradeable {\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 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" + }, + "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <0.8.0;\n\nimport \"../utils/ContextUpgradeable.sol\";\nimport \"../proxy/Initializable.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 OwnableUpgradeable is Initializable, ContextUpgradeable {\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 function __Ownable_init() internal initializer {\n __Context_init_unchained();\n __Ownable_init_unchained();\n }\n\n function __Ownable_init_unchained() internal initializer {\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 uint256[49] private __gap;\n}\n" + }, + "@openzeppelin/contracts-upgradeable/utils/PausableUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <0.8.0;\n\nimport \"./ContextUpgradeable.sol\";\nimport \"../proxy/Initializable.sol\";\n\n/**\n * @dev Contract module which allows children to implement an emergency stop\n * mechanism that can be triggered by an authorized account.\n *\n * This module is used through inheritance. It will make available the\n * modifiers `whenNotPaused` and `whenPaused`, which can be applied to\n * the functions of your contract. Note that they will not be pausable by\n * simply including this module, only once the modifiers are put in place.\n */\nabstract contract PausableUpgradeable is Initializable, ContextUpgradeable {\n /**\n * @dev Emitted when the pause is triggered by `account`.\n */\n event Paused(address account);\n\n /**\n * @dev Emitted when the pause is lifted by `account`.\n */\n event Unpaused(address account);\n\n bool private _paused;\n\n /**\n * @dev Initializes the contract in unpaused state.\n */\n function __Pausable_init() internal initializer {\n __Context_init_unchained();\n __Pausable_init_unchained();\n }\n\n function __Pausable_init_unchained() internal initializer {\n _paused = false;\n }\n\n /**\n * @dev Returns true if the contract is paused, and false otherwise.\n */\n function paused() public view virtual returns (bool) {\n return _paused;\n }\n\n /**\n * @dev Modifier to make a function callable only when the contract is not paused.\n *\n * Requirements:\n *\n * - The contract must not be paused.\n */\n modifier whenNotPaused() {\n require(!paused(), \"Pausable: paused\");\n _;\n }\n\n /**\n * @dev Modifier to make a function callable only when the contract is paused.\n *\n * Requirements:\n *\n * - The contract must be paused.\n */\n modifier whenPaused() {\n require(paused(), \"Pausable: not paused\");\n _;\n }\n\n /**\n * @dev Triggers stopped state.\n *\n * Requirements:\n *\n * - The contract must not be paused.\n */\n function _pause() internal virtual whenNotPaused {\n _paused = true;\n emit Paused(_msgSender());\n }\n\n /**\n * @dev Returns to normal state.\n *\n * Requirements:\n *\n * - The contract must be paused.\n */\n function _unpause() internal virtual whenPaused {\n _paused = false;\n emit Unpaused(_msgSender());\n }\n uint256[49] private __gap;\n}\n" + }, + "@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <0.8.0;\nimport \"../proxy/Initializable.sol\";\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 ContextUpgradeable is Initializable {\n function __Context_init() internal initializer {\n __Context_init_unchained();\n }\n\n function __Context_init_unchained() internal initializer {\n }\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 uint256[50] private __gap;\n}\n" + }, + "contracts/amm/LPToken.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.6.12;\n\nimport \"@openzeppelin/contracts-upgradeable/token/ERC20/ERC20BurnableUpgradeable.sol\";\nimport \"@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol\";\nimport \"./interfaces/ISwap.sol\";\n\n/**\n * @title Liquidity Provider Token\n * @notice This token is an ERC20 detailed token with added capability to be minted by the owner.\n * It is used to represent user's shares when providing liquidity to swap contracts.\n * @dev Only Swap contracts should initialize and own LPToken contracts.\n */\ncontract LPToken is ERC20BurnableUpgradeable, OwnableUpgradeable {\n using SafeMathUpgradeable for uint256;\n\n /**\n * @notice Initializes this LPToken contract with the given name and symbol\n * @dev The caller of this function will become the owner. A Swap contract should call this\n * in its initializer function.\n * @param name name of this token\n * @param symbol symbol of this token\n */\n function initialize(string memory name, string memory symbol)\n external\n initializer\n returns (bool)\n {\n __Context_init_unchained();\n __ERC20_init_unchained(name, symbol);\n __Ownable_init_unchained();\n return true;\n }\n\n /**\n * @notice Mints the given amount of LPToken to the recipient.\n * @dev only owner can call this mint function\n * @param recipient address of account to receive the tokens\n * @param amount amount of tokens to mint\n */\n function mint(address recipient, uint256 amount) external onlyOwner {\n require(amount != 0, \"LPToken: cannot mint 0\");\n _mint(recipient, amount);\n }\n\n /**\n * @dev Overrides ERC20._beforeTokenTransfer() which get called on every transfers including\n * minting and burning. * This assumes the owner is set to a Swap contract's address.\n */\n function _beforeTokenTransfer(\n address from,\n address to,\n uint256 amount\n ) internal virtual override(ERC20Upgradeable) {\n super._beforeTokenTransfer(from, to, amount);\n require(to != address(this), \"LPToken: cannot send to itself\");\n }\n}\n" + }, + "contracts/amm/MathUtils.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.6.12;\n\nimport \"@openzeppelin/contracts/math/SafeMath.sol\";\n\n/**\n * @title MathUtils library\n * @notice A library to be used in conjunction with SafeMath. Contains functions for calculating\n * differences between two uint256.\n */\nlibrary MathUtils {\n /**\n * @notice Compares a and b and returns true if the difference between a and b\n * is less than 1 or equal to each other.\n * @param a uint256 to compare with\n * @param b uint256 to compare with\n * @return True if the difference between a and b is less than 1 or equal,\n * otherwise return false\n */\n function within1(uint256 a, uint256 b) internal pure returns (bool) {\n return (difference(a, b) <= 1);\n }\n\n /**\n * @notice Calculates absolute difference between a and b\n * @param a uint256 to compare with\n * @param b uint256 to compare with\n * @return Difference between a and b\n */\n function difference(uint256 a, uint256 b) internal pure returns (uint256) {\n if (a > b) {\n return a - b;\n }\n return b - a;\n }\n}\n" + }, + "@openzeppelin/contracts-upgradeable/token/ERC20/ERC20BurnableUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <0.8.0;\n\nimport \"../../utils/ContextUpgradeable.sol\";\nimport \"./ERC20Upgradeable.sol\";\nimport \"../../proxy/Initializable.sol\";\n\n/**\n * @dev Extension of {ERC20} that allows token holders to destroy both their own\n * tokens and those that they have an allowance for, in a way that can be\n * recognized off-chain (via event analysis).\n */\nabstract contract ERC20BurnableUpgradeable is Initializable, ContextUpgradeable, ERC20Upgradeable {\n function __ERC20Burnable_init() internal initializer {\n __Context_init_unchained();\n __ERC20Burnable_init_unchained();\n }\n\n function __ERC20Burnable_init_unchained() internal initializer {\n }\n using SafeMathUpgradeable for uint256;\n\n /**\n * @dev Destroys `amount` tokens from the caller.\n *\n * See {ERC20-_burn}.\n */\n function burn(uint256 amount) public virtual {\n _burn(_msgSender(), amount);\n }\n\n /**\n * @dev Destroys `amount` tokens from `account`, deducting from the caller's\n * allowance.\n *\n * See {ERC20-_burn} and {ERC20-allowance}.\n *\n * Requirements:\n *\n * - the caller must have allowance for ``accounts``'s tokens of at least\n * `amount`.\n */\n function burnFrom(address account, uint256 amount) public virtual {\n uint256 decreasedAllowance = allowance(account, _msgSender()).sub(amount, \"ERC20: burn amount exceeds allowance\");\n\n _approve(account, _msgSender(), decreasedAllowance);\n _burn(account, amount);\n }\n uint256[50] private __gap;\n}\n" + }, + "contracts/amm/interfaces/ISwap.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.6.12;\n\nimport \"@openzeppelin/contracts/token/ERC20/ERC20.sol\";\n\ninterface ISwap {\n // pool data view functions\n function getA() external view returns (uint256);\n\n function getToken(uint8 index) external view returns (IERC20);\n\n function getTokenIndex(address tokenAddress) external view returns (uint8);\n\n function getTokenBalance(uint8 index) external view returns (uint256);\n\n function getVirtualPrice() external view returns (uint256);\n\n // min return calculation functions\n function calculateSwap(\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx\n ) external view returns (uint256);\n\n function calculateTokenAmount(uint256[] calldata amounts, bool deposit)\n external\n view\n returns (uint256);\n\n function calculateRemoveLiquidity(uint256 amount)\n external\n view\n returns (uint256[] memory);\n\n function calculateRemoveLiquidityOneToken(\n uint256 tokenAmount,\n uint8 tokenIndex\n ) external view returns (uint256 availableTokenAmount);\n\n // state modifying functions\n function initialize(\n IERC20[] memory pooledTokens,\n uint8[] memory decimals,\n string memory lpTokenName,\n string memory lpTokenSymbol,\n uint256 a,\n uint256 fee,\n uint256 adminFee,\n address lpTokenTargetAddress\n ) external;\n\n function swap(\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx,\n uint256 minDy,\n uint256 deadline\n ) external returns (uint256);\n\n function addLiquidity(\n uint256[] calldata amounts,\n uint256 minToMint,\n uint256 deadline\n ) external returns (uint256);\n\n function removeLiquidity(\n uint256 amount,\n uint256[] calldata minAmounts,\n uint256 deadline\n ) external returns (uint256[] memory);\n\n function removeLiquidityOneToken(\n uint256 tokenAmount,\n uint8 tokenIndex,\n uint256 minAmount,\n uint256 deadline\n ) external returns (uint256);\n\n function removeLiquidityImbalance(\n uint256[] calldata amounts,\n uint256 maxBurnAmount,\n uint256 deadline\n ) external returns (uint256);\n}\n" + }, + "@openzeppelin/contracts-upgradeable/token/ERC20/ERC20Upgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <0.8.0;\n\nimport \"../../utils/ContextUpgradeable.sol\";\nimport \"./IERC20Upgradeable.sol\";\nimport \"../../math/SafeMathUpgradeable.sol\";\nimport \"../../proxy/Initializable.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 ERC20Upgradeable is Initializable, ContextUpgradeable, IERC20Upgradeable {\n using SafeMathUpgradeable 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 function __ERC20_init(string memory name_, string memory symbol_) internal initializer {\n __Context_init_unchained();\n __ERC20_init_unchained(name_, symbol_);\n }\n\n function __ERC20_init_unchained(string memory name_, string memory symbol_) internal initializer {\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 uint256[44] private __gap;\n}\n" + }, + "@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <0.8.0;\n\n/**\n * @dev Interface of the ERC20 standard as defined in the EIP.\n */\ninterface IERC20Upgradeable {\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" + }, + "@openzeppelin/contracts-upgradeable/math/SafeMathUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <0.8.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 SafeMathUpgradeable {\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" + }, + "@openzeppelin/contracts/token/ERC20/ERC20.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <0.8.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_) public {\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" + }, + "@openzeppelin/contracts/utils/Context.sol": { + "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" + }, + "contracts/amm/SwapFlashLoan.sol": { + "content": "// SPDX-License-Identifier: MIT WITH AGPL-3.0-only\n\npragma solidity 0.6.12;\n\nimport \"./Swap.sol\";\nimport \"./interfaces/IFlashLoanReceiver.sol\";\n\n/**\n * @title Swap - A StableSwap implementation in solidity.\n * @notice This contract is responsible for custody of closely pegged assets (eg. group of stablecoins)\n * and automatic market making system. Users become an LP (Liquidity Provider) by depositing their tokens\n * in desired ratios for an exchange of the pool token that represents their share of the pool.\n * Users can burn pool tokens and withdraw their share of token(s).\n *\n * Each time a swap between the pooled tokens happens, a set fee incurs which effectively gets\n * distributed to the LPs.\n *\n * In case of emergencies, admin can pause additional deposits, swaps, or single-asset withdraws - which\n * stops the ratio of the tokens in the pool from changing.\n * Users can always withdraw their tokens via multi-asset withdraws.\n *\n * @dev Most of the logic is stored as a library `SwapUtils` for the sake of reducing contract's\n * deployment size.\n */\ncontract SwapFlashLoan is Swap {\n // Total fee that is charged on all flashloans in BPS. Borrowers must repay the amount plus the flash loan fee.\n // This fee is split between the protocol and the pool.\n uint256 public flashLoanFeeBPS;\n // Share of the flash loan fee that goes to the protocol in BPS. A portion of each flash loan fee is allocated\n // to the protocol rather than the pool.\n uint256 public protocolFeeShareBPS;\n // Max BPS for limiting flash loan fee settings.\n uint256 public constant MAX_BPS = 10000;\n\n /*** EVENTS ***/\n event FlashLoan(\n address indexed receiver,\n uint8 tokenIndex,\n uint256 amount,\n uint256 amountFee,\n uint256 protocolFee\n );\n\n /**\n * @notice Initializes this Swap contract with the given parameters.\n * This will also clone a LPToken contract that represents users'\n * LP positions. The owner of LPToken will be this contract - which means\n * only this contract is allowed to mint/burn tokens.\n *\n * @param _pooledTokens an array of ERC20s this pool will accept\n * @param decimals the decimals to use for each pooled token,\n * eg 8 for WBTC. Cannot be larger than POOL_PRECISION_DECIMALS\n * @param lpTokenName the long-form name of the token to be deployed\n * @param lpTokenSymbol the short symbol for the token to be deployed\n * @param _a the amplification coefficient * n * (n - 1). See the\n * StableSwap paper for details\n * @param _fee default swap fee to be initialized with\n * @param _adminFee default adminFee to be initialized with\n * @param lpTokenTargetAddress the address of an existing LPToken contract to use as a target\n */\n function initialize(\n IERC20[] memory _pooledTokens,\n uint8[] memory decimals,\n string memory lpTokenName,\n string memory lpTokenSymbol,\n uint256 _a,\n uint256 _fee,\n uint256 _adminFee,\n address lpTokenTargetAddress\n ) public virtual override initializer {\n Swap.initialize(\n _pooledTokens,\n decimals,\n lpTokenName,\n lpTokenSymbol,\n _a,\n _fee,\n _adminFee,\n lpTokenTargetAddress\n );\n flashLoanFeeBPS = 8; // 8 bps\n protocolFeeShareBPS = 0; // 0 bps\n }\n\n /*** STATE MODIFYING FUNCTIONS ***/\n\n /**\n * @notice Borrow the specified token from this pool for this transaction only. This function will call\n * `IFlashLoanReceiver(receiver).executeOperation` and the `receiver` must return the full amount of the token\n * and the associated fee by the end of the callback transaction. If the conditions are not met, this call\n * is reverted.\n * @param receiver the address of the receiver of the token. This address must implement the IFlashLoanReceiver\n * interface and the callback function `executeOperation`.\n * @param token the protocol fee in bps to be applied on the total flash loan fee\n * @param amount the total amount to borrow in this transaction\n * @param params optional data to pass along to the callback function\n */\n function flashLoan(\n address receiver,\n IERC20 token,\n uint256 amount,\n bytes memory params\n ) external nonReentrant {\n uint8 tokenIndex = getTokenIndex(address(token));\n uint256 availableLiquidityBefore = token.balanceOf(address(this));\n uint256 protocolBalanceBefore = availableLiquidityBefore.sub(\n swapStorage.balances[tokenIndex]\n );\n require(\n amount > 0 && availableLiquidityBefore >= amount,\n \"invalid amount\"\n );\n\n // Calculate the additional amount of tokens the pool should end up with\n uint256 amountFee = amount.mul(flashLoanFeeBPS).div(10000);\n // Calculate the portion of the fee that will go to the protocol\n uint256 protocolFee = amountFee.mul(protocolFeeShareBPS).div(10000);\n require(amountFee > 0, \"amount is small for a flashLoan\");\n\n // Transfer the requested amount of tokens\n token.safeTransfer(receiver, amount);\n\n // Execute callback function on receiver\n IFlashLoanReceiver(receiver).executeOperation(\n address(this),\n address(token),\n amount,\n amountFee,\n params\n );\n\n uint256 availableLiquidityAfter = token.balanceOf(address(this));\n require(\n availableLiquidityAfter >= availableLiquidityBefore.add(amountFee),\n \"flashLoan fee is not met\"\n );\n\n swapStorage.balances[tokenIndex] = availableLiquidityAfter\n .sub(protocolBalanceBefore)\n .sub(protocolFee);\n emit FlashLoan(receiver, tokenIndex, amount, amountFee, protocolFee);\n }\n\n /*** ADMIN FUNCTIONS ***/\n\n /**\n * @notice Updates the flash loan fee parameters. This function can only be called by the owner.\n * @param newFlashLoanFeeBPS the total fee in bps to be applied on future flash loans\n * @param newProtocolFeeShareBPS the protocol fee in bps to be applied on the total flash loan fee\n */\n function setFlashLoanFees(\n uint256 newFlashLoanFeeBPS,\n uint256 newProtocolFeeShareBPS\n ) external onlyOwner {\n require(\n newFlashLoanFeeBPS > 0 &&\n newFlashLoanFeeBPS <= MAX_BPS &&\n newProtocolFeeShareBPS <= MAX_BPS,\n \"fees are not in valid range\"\n );\n flashLoanFeeBPS = newFlashLoanFeeBPS;\n protocolFeeShareBPS = newProtocolFeeShareBPS;\n }\n}\n" + }, + "contracts/amm/interfaces/IFlashLoanReceiver.sol": { + "content": "// SPDX-License-Identifier: AGPL-3.0-only\n\npragma solidity 0.6.12;\n\n/**\n * @title IFlashLoanReceiver interface\n * @notice Interface for the Nerve fee IFlashLoanReceiver. Modified from Aave's IFlashLoanReceiver interface.\n * https://github.com/aave/aave-protocol/blob/4b4545fb583fd4f400507b10f3c3114f45b8a037/contracts/flashloan/interfaces/IFlashLoanReceiver.sol\n * @author Aave\n * @dev implement this interface to develop a flashloan-compatible flashLoanReceiver contract\n **/\ninterface IFlashLoanReceiver {\n function executeOperation(\n address pool,\n address token,\n uint256 amount,\n uint256 fee,\n bytes calldata params\n ) external;\n}\n" + }, + "contracts/amm/helper/FlashLoanBorrowerExample.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.6.12;\n\nimport \"@openzeppelin/contracts/math/SafeMath.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/SafeERC20.sol\";\nimport \"../interfaces/IFlashLoanReceiver.sol\";\nimport \"../interfaces/ISwapFlashLoan.sol\";\nimport \"hardhat/console.sol\";\n\ncontract FlashLoanBorrowerExample is IFlashLoanReceiver {\n using SafeMath for uint256;\n\n // Typical executeOperation function should do the 3 following actions\n // 1. Check if the flashLoan was successful\n // 2. Do actions with the borrowed tokens\n // 3. Repay the debt to the `pool`\n function executeOperation(\n address pool,\n address token,\n uint256 amount,\n uint256 fee,\n bytes calldata params\n ) external override {\n // 1. Check if the flashLoan was valid\n require(\n IERC20(token).balanceOf(address(this)) >= amount,\n \"flashloan is broken?\"\n );\n\n // 2. Do actions with the borrowed token\n bytes32 paramsHash = keccak256(params);\n if (paramsHash == keccak256(bytes(\"dontRepayDebt\"))) {\n return;\n } else if (paramsHash == keccak256(bytes(\"reentrancy_addLiquidity\"))) {\n ISwapFlashLoan(pool).addLiquidity(\n new uint256[](0),\n 0,\n block.timestamp\n );\n } else if (paramsHash == keccak256(bytes(\"reentrancy_swap\"))) {\n ISwapFlashLoan(pool).swap(1, 0, 1e6, 0, now);\n } else if (\n paramsHash == keccak256(bytes(\"reentrancy_removeLiquidity\"))\n ) {\n ISwapFlashLoan(pool).removeLiquidity(1e18, new uint256[](0), now);\n } else if (\n paramsHash == keccak256(bytes(\"reentrancy_removeLiquidityOneToken\"))\n ) {\n ISwapFlashLoan(pool).removeLiquidityOneToken(1e18, 0, 1e18, now);\n }\n\n // 3. Payback debt\n uint256 totalDebt = amount.add(fee);\n IERC20(token).transfer(pool, totalDebt);\n }\n\n function flashLoan(\n ISwapFlashLoan swap,\n IERC20 token,\n uint256 amount,\n bytes memory params\n ) external {\n swap.flashLoan(address(this), token, amount, params);\n }\n}\n" + }, + "contracts/amm/interfaces/ISwapFlashLoan.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.6.12;\n\nimport \"./ISwap.sol\";\n\ninterface ISwapFlashLoan is ISwap {\n function flashLoan(\n address receiver,\n IERC20 token,\n uint256 amount,\n bytes memory params\n ) external;\n}\n" + }, + "hardhat/console.sol": { + "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" + }, + "contracts/amm/helper/test/TestSwapReturnValues.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.6.12;\n\nimport \"../../interfaces/ISwap.sol\";\nimport \"hardhat/console.sol\";\n\ncontract TestSwapReturnValues {\n using SafeMath for uint256;\n\n ISwap public swap;\n IERC20 public lpToken;\n uint8 public n;\n\n uint256 public constant MAX_INT = 2**256 - 1;\n\n constructor(\n ISwap swapContract,\n IERC20 lpTokenContract,\n uint8 numOfTokens\n ) public {\n swap = swapContract;\n lpToken = lpTokenContract;\n n = numOfTokens;\n\n // Pre-approve tokens\n for (uint8 i; i < n; i++) {\n swap.getToken(i).approve(address(swap), MAX_INT);\n }\n lpToken.approve(address(swap), MAX_INT);\n }\n\n function test_swap(\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx,\n uint256 minDy\n ) public {\n uint256 balanceBefore =\n swap.getToken(tokenIndexTo).balanceOf(address(this));\n uint256 returnValue =\n swap.swap(tokenIndexFrom, tokenIndexTo, dx, minDy, block.timestamp);\n uint256 balanceAfter =\n swap.getToken(tokenIndexTo).balanceOf(address(this));\n\n console.log(\n \"swap: Expected %s, got %s\",\n balanceAfter.sub(balanceBefore),\n returnValue\n );\n\n require(\n returnValue == balanceAfter.sub(balanceBefore),\n \"swap()'s return value does not match received amount\"\n );\n }\n\n function test_addLiquidity(uint256[] calldata amounts, uint256 minToMint)\n public\n {\n uint256 balanceBefore = lpToken.balanceOf(address(this));\n uint256 returnValue = swap.addLiquidity(amounts, minToMint, MAX_INT);\n uint256 balanceAfter = lpToken.balanceOf(address(this));\n\n console.log(\n \"addLiquidity: Expected %s, got %s\",\n balanceAfter.sub(balanceBefore),\n returnValue\n );\n\n require(\n returnValue == balanceAfter.sub(balanceBefore),\n \"addLiquidity()'s return value does not match minted amount\"\n );\n }\n\n function test_removeLiquidity(uint256 amount, uint256[] memory minAmounts)\n public\n {\n uint256[] memory balanceBefore = new uint256[](n);\n uint256[] memory balanceAfter = new uint256[](n);\n\n for (uint8 i = 0; i < n; i++) {\n balanceBefore[i] = swap.getToken(i).balanceOf(address(this));\n }\n\n uint256[] memory returnValue =\n swap.removeLiquidity(amount, minAmounts, MAX_INT);\n\n for (uint8 i = 0; i < n; i++) {\n balanceAfter[i] = swap.getToken(i).balanceOf(address(this));\n console.log(\n \"removeLiquidity: Expected %s, got %s\",\n balanceAfter[i].sub(balanceBefore[i]),\n returnValue[i]\n );\n require(\n balanceAfter[i].sub(balanceBefore[i]) == returnValue[i],\n \"removeLiquidity()'s return value does not match received amounts of tokens\"\n );\n }\n }\n\n function test_removeLiquidityImbalance(\n uint256[] calldata amounts,\n uint256 maxBurnAmount\n ) public {\n uint256 balanceBefore = lpToken.balanceOf(address(this));\n uint256 returnValue =\n swap.removeLiquidityImbalance(amounts, maxBurnAmount, MAX_INT);\n uint256 balanceAfter = lpToken.balanceOf(address(this));\n\n console.log(\n \"removeLiquidityImbalance: Expected %s, got %s\",\n balanceBefore.sub(balanceAfter),\n returnValue\n );\n\n require(\n returnValue == balanceBefore.sub(balanceAfter),\n \"removeLiquidityImbalance()'s return value does not match burned lpToken amount\"\n );\n }\n\n function test_removeLiquidityOneToken(\n uint256 tokenAmount,\n uint8 tokenIndex,\n uint256 minAmount\n ) public {\n uint256 balanceBefore =\n swap.getToken(tokenIndex).balanceOf(address(this));\n uint256 returnValue =\n swap.removeLiquidityOneToken(\n tokenAmount,\n tokenIndex,\n minAmount,\n MAX_INT\n );\n uint256 balanceAfter =\n swap.getToken(tokenIndex).balanceOf(address(this));\n\n console.log(\n \"removeLiquidityOneToken: Expected %s, got %s\",\n balanceAfter.sub(balanceBefore),\n returnValue\n );\n\n require(\n returnValue == balanceAfter.sub(balanceBefore),\n \"removeLiquidityOneToken()'s return value does not match received token amount\"\n );\n }\n}\n" + }, + "contracts/amm/SwapDeployer.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.6.12;\n\nimport \"@openzeppelin/contracts/access/Ownable.sol\";\nimport \"@openzeppelin/contracts/proxy/Clones.sol\";\nimport \"./interfaces/ISwap.sol\";\n\ncontract SwapDeployer is Ownable {\n event NewSwapPool(\n address indexed deployer,\n address swapAddress,\n IERC20[] pooledTokens\n );\n\n constructor() public Ownable() {}\n\n function deploy(\n address swapAddress,\n IERC20[] memory _pooledTokens,\n uint8[] memory decimals,\n string memory lpTokenName,\n string memory lpTokenSymbol,\n uint256 _a,\n uint256 _fee,\n uint256 _adminFee,\n address lpTokenTargetAddress\n ) external returns (address) {\n address swapClone = Clones.clone(swapAddress);\n ISwap(swapClone).initialize(\n _pooledTokens,\n decimals,\n lpTokenName,\n lpTokenSymbol,\n _a,\n _fee,\n _adminFee,\n lpTokenTargetAddress\n );\n Ownable(swapClone).transferOwnership(owner());\n emit NewSwapPool(msg.sender, swapClone, _pooledTokens);\n return swapClone;\n }\n}\n" + }, + "@openzeppelin/contracts/access/Ownable.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <0.8.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 () internal {\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" + }, + "contracts/bridge/SynapseERC20Factory.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.6.12;\n\nimport \"@openzeppelin/contracts/access/Ownable.sol\";\nimport \"@openzeppelin/contracts/proxy/Clones.sol\";\nimport \"./interfaces/ISynapseERC20.sol\";\n\ncontract SynapseERC20Factory {\n constructor() public {}\n\n event SynapseERC20Created(address contractAddress);\n\n /**\n * @notice Deploys a new node\n * @param synapseERC20Address address of the synapseERC20Address contract to initialize with\n * @param name Token name\n * @param symbol Token symbol\n * @param decimals Token name\n * @param owner admin address to be initialized with\n * @return Address of the newest node management contract created\n **/\n function deploy(\n address synapseERC20Address,\n string memory name,\n string memory symbol,\n uint8 decimals,\n address owner\n ) external returns (address) {\n address synERC20Clone = Clones.clone(synapseERC20Address);\n ISynapseERC20(synERC20Clone).initialize(name, symbol, decimals, owner);\n\n emit SynapseERC20Created(synERC20Clone);\n\n return synERC20Clone;\n }\n}\n" + }, + "contracts/bridge/interfaces/ISynapseERC20.sol": { + "content": "// SPDX-License-Identifier: MIT\n\n\npragma solidity 0.6.12;\n\ninterface ISynapseERC20 { \n function initialize(\n string memory _name, string memory _symbol, uint8 _decimals, address owner) external;\n\n function mint(address to, uint256 amount) external;\n}\n\n" + }, + "contracts/bridge/wrappers/AvaxJewelMigration.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.6.12;\n\nimport \"@openzeppelin/contracts/token/ERC20/ERC20.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/SafeERC20.sol\";\nimport \"@openzeppelin/contracts/access/Ownable.sol\";\n\nimport \"../interfaces/ISynapseBridge.sol\";\n\ninterface IERC20Mintable is IERC20 {\n function mint(address to, uint256 amount) external;\n}\n\ncontract AvaxJewelMigration is Ownable {\n using SafeERC20 for IERC20;\n using SafeERC20 for IERC20Mintable;\n\n ISynapseBridge public constant SYNAPSE_BRIDGE =\n ISynapseBridge(0xC05e61d0E7a63D27546389B7aD62FdFf5A91aACE);\n // MULTICHAIN JEWEL\n IERC20 public constant LEGACY_TOKEN =\n IERC20(0x4f60a160D8C2DDdaAfe16FCC57566dB84D674BD6);\n // SYNAPSE JEWEL\n IERC20Mintable public constant NEW_TOKEN =\n IERC20Mintable(0x997Ddaa07d716995DE90577C123Db411584E5E46);\n uint256 private constant MAX_UINT256 = 2**256 - 1;\n\n constructor() public {\n NEW_TOKEN.safeApprove(address(SYNAPSE_BRIDGE), MAX_UINT256);\n }\n\n function migrate(uint256 amount) external {\n _migrate(amount, msg.sender);\n }\n\n function migrateAndBridge(\n uint256 amount,\n address to,\n uint256 chainId\n ) external {\n // First, mint new tokens to this contract, as Bridge burns tokens\n // from msg.sender, which would be AvaxJewelMigration\n _migrate(amount, address(this));\n // Initiate bridging and specify `to` as receiver on destination chain\n SYNAPSE_BRIDGE.redeem(to, chainId, NEW_TOKEN, amount);\n }\n\n /// @notice Pull old tokens from user and mint new ones to account\n function _migrate(uint256 amount, address account) internal {\n require(amount != 0, \"Amount must be greater than zero\");\n LEGACY_TOKEN.safeTransferFrom(msg.sender, address(this), amount);\n NEW_TOKEN.mint(account, amount);\n }\n\n function redeemLegacy() external onlyOwner {\n uint256 legacyBalance = LEGACY_TOKEN.balanceOf(address(this));\n LEGACY_TOKEN.safeTransfer(owner(), legacyBalance);\n }\n}\n" + }, + "contracts/bridge/interfaces/ISynapseBridge.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.6.12;\n\nimport '@openzeppelin/contracts/token/ERC20/SafeERC20.sol';\nimport '@openzeppelin/contracts/token/ERC20/ERC20Burnable.sol';\n\ninterface ISynapseBridge {\n using SafeERC20 for IERC20;\n\n function deposit(\n address to,\n uint256 chainId,\n IERC20 token,\n uint256 amount\n ) external;\n\n function depositAndSwap(\n address to,\n uint256 chainId,\n IERC20 token,\n uint256 amount,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 minDy,\n uint256 deadline\n ) external;\n\n function redeem(\n address to,\n uint256 chainId,\n IERC20 token,\n uint256 amount\n ) external;\n\n\n function redeemv2(\n bytes32 to,\n uint256 chainId,\n IERC20 token,\n uint256 amount\n ) external;\n\n\n function redeemAndSwap(\n address to,\n uint256 chainId,\n IERC20 token,\n uint256 amount,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 minDy,\n uint256 deadline\n ) external;\n\n function redeemAndRemove(\n address to,\n uint256 chainId,\n IERC20 token,\n uint256 amount,\n uint8 liqTokenIndex,\n uint256 liqMinAmount,\n uint256 liqDeadline\n ) external;\n}\n" + }, + "@openzeppelin/contracts/token/ERC20/ERC20Burnable.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <0.8.0;\n\nimport \"../../utils/Context.sol\";\nimport \"./ERC20.sol\";\n\n/**\n * @dev Extension of {ERC20} that allows token holders to destroy both their own\n * tokens and those that they have an allowance for, in a way that can be\n * recognized off-chain (via event analysis).\n */\nabstract contract ERC20Burnable is Context, ERC20 {\n using SafeMath for uint256;\n\n /**\n * @dev Destroys `amount` tokens from the caller.\n *\n * See {ERC20-_burn}.\n */\n function burn(uint256 amount) public virtual {\n _burn(_msgSender(), amount);\n }\n\n /**\n * @dev Destroys `amount` tokens from `account`, deducting from the caller's\n * allowance.\n *\n * See {ERC20-_burn} and {ERC20-allowance}.\n *\n * Requirements:\n *\n * - the caller must have allowance for ``accounts``'s tokens of at least\n * `amount`.\n */\n function burnFrom(address account, uint256 amount) public virtual {\n uint256 decreasedAllowance = allowance(account, _msgSender()).sub(amount, \"ERC20: burn amount exceeds allowance\");\n\n _approve(account, _msgSender(), decreasedAllowance);\n _burn(account, amount);\n }\n}\n" + }, + "contracts/bridge/wrappers/MoonriverBridgeZap.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.6.12;\n\nimport \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/SafeERC20.sol\";\nimport \"../interfaces/ISwap.sol\";\nimport \"../interfaces/ISynapseBridge.sol\";\nimport \"../interfaces/IWETH9.sol\";\n\ninterface IFrax {\n function exchangeCanonicalForOld(address bridge_token_address, uint256 token_amount) external returns (uint256);\n}\n\ncontract MoonriverBridgeZap {\n using SafeERC20 for IERC20;\n\n ISynapseBridge synapseBridge;\n address payable public immutable WETH_ADDRESS;\n IFrax private constant CANOLICAL_FRAX = IFrax(0x1A93B23281CC1CDE4C4741353F3064709A16197d);\n IERC20 private constant SYN_FRAX = IERC20(0xE96AC70907ffF3Efee79f502C985A7A21Bce407d);\n\n mapping(address => address) public swapMap;\n mapping(address => IERC20[]) public swapTokensMap;\n\n uint256 constant MAX_UINT256 = 2**256 - 1;\n\n constructor(\n address payable _wethAddress,\n address _swapOne,\n address tokenOne,\n address _swapTwo,\n address tokenTwo,\n ISynapseBridge _synapseBridge\n ) public {\n WETH_ADDRESS = _wethAddress;\n synapseBridge = _synapseBridge;\n swapMap[tokenOne] = _swapOne;\n swapMap[tokenTwo] = _swapTwo;\n IERC20(_wethAddress).safeIncreaseAllowance(address(_synapseBridge), MAX_UINT256);\n if (address(_swapOne) != address(0)) {\n {\n uint8 i;\n for (; i < 32; i++) {\n try ISwap(_swapOne).getToken(i) returns (\n IERC20 token\n ) {\n swapTokensMap[_swapOne].push(token);\n token.safeApprove(address(_swapOne), MAX_UINT256);\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n } catch {\n break;\n }\n }\n require(i > 1, \"swap must have at least 2 tokens\");\n }\n }\n if (address(_swapTwo) != address(0)) {\n {\n uint8 i;\n for (; i < 32; i++) {\n try ISwap(_swapTwo).getToken(i) returns (\n IERC20 token\n ) {\n swapTokensMap[_swapTwo].push(token);\n token.safeApprove(address(_swapTwo), MAX_UINT256);\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n } catch {\n break;\n }\n }\n require(i > 1, \"swap must have at least 2 tokens\");\n }\n }\n }\n\n /**\n * @notice Calculate amount of tokens you receive on swap\n * @param tokenIndexFrom the token the user wants to sell\n * @param tokenIndexTo the token the user wants to buy\n * @param dx the amount of tokens the user wants to sell. If the token charges\n * a fee on transfers, use the amount that gets transferred after the fee.\n * @return amount of tokens the user will receive\n */\n function calculateSwap(\n IERC20 token,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx\n ) external view virtual returns (uint256) {\n ISwap swap = ISwap(\n swapMap[address(token)]\n );\n return swap.calculateSwap(tokenIndexFrom, tokenIndexTo, dx);\n }\n\n function swapAndRedeem(\n address to,\n uint256 chainId,\n IERC20 token,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx,\n uint256 minDy,\n uint256 deadline\n ) external {\n ISwap swap = ISwap(swapMap[address(token)]);\n require(address(swap) != address(0), \"Swap is 0x00\");\n IERC20[] memory tokens = swapTokensMap[address(swap)];\n tokens[tokenIndexFrom].safeTransferFrom(\n msg.sender,\n address(this),\n dx\n );\n // swap\n\n uint256 swappedAmount = swap.swap(\n tokenIndexFrom,\n tokenIndexTo,\n dx,\n minDy,\n deadline\n );\n // deposit into bridge, gets nUSD\n if (\n token.allowance(address(this), address(synapseBridge)) <\n swappedAmount\n ) {\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n }\n synapseBridge.redeem(to, chainId, token, swappedAmount);\n }\n\n function swapAndRedeemAndSwap(\n address to,\n uint256 chainId,\n IERC20 token,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx,\n uint256 minDy,\n uint256 deadline,\n uint8 swapTokenIndexFrom,\n uint8 swapTokenIndexTo,\n uint256 swapMinDy,\n uint256 swapDeadline\n ) external {\n require(\n address(swapMap[address(token)]) != address(0),\n \"Swap is 0x00\"\n );\n IERC20[] memory tokens = swapTokensMap[\n swapMap[address(token)]\n ];\n tokens[tokenIndexFrom].safeTransferFrom(\n msg.sender,\n address(this),\n dx\n );\n // swap\n\n uint256 swappedAmount = ISwap(swapMap[address(token)]).swap(tokenIndexFrom, tokenIndexTo, dx, minDy, deadline);\n // deposit into bridge, gets nUSD\n if (\n token.allowance(address(this), address(synapseBridge)) <\n swappedAmount\n ) {\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n }\n synapseBridge.redeemAndSwap(\n to,\n chainId,\n token,\n swappedAmount,\n swapTokenIndexFrom,\n swapTokenIndexTo,\n swapMinDy,\n swapDeadline\n );\n }\n\n function swapAndRedeemAndRemove(\n address to,\n uint256 chainId,\n IERC20 token,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx,\n uint256 minDy,\n uint256 deadline,\n uint8 liqTokenIndex,\n uint256 liqMinAmount,\n uint256 liqDeadline\n ) external {\n ISwap swap = ISwap(swapMap[address(token)]);\n require(address(swap) != address(0), \"Swap is 0x00\");\n IERC20[] memory tokens = swapTokensMap[address(swap)];\n tokens[tokenIndexFrom].safeTransferFrom(\n msg.sender,\n address(this),\n dx\n );\n // swap\n\n uint256 swappedAmount = swap.swap(\n tokenIndexFrom,\n tokenIndexTo,\n dx,\n minDy,\n deadline\n );\n // deposit into bridge, gets nUSD\n if (\n token.allowance(address(this), address(synapseBridge)) <\n swappedAmount\n ) {\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n }\n synapseBridge.redeemAndRemove(\n to,\n chainId,\n token,\n swappedAmount,\n liqTokenIndex,\n liqMinAmount,\n liqDeadline\n );\n }\n\n /**\n * @notice wraps SynapseBridge redeem()\n * @param to address on other chain to redeem underlying assets to\n * @param chainId which underlying chain to bridge assets onto\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n **/\n function redeem(\n address to,\n uint256 chainId,\n IERC20 token,\n uint256 amount\n ) external {\n token.safeTransferFrom(msg.sender, address(this), amount);\n if (address(token) == address(CANOLICAL_FRAX)) {\n uint256 swappedAmount = CANOLICAL_FRAX.exchangeCanonicalForOld(address(SYN_FRAX), amount);\n if (SYN_FRAX.allowance(address(this), address(synapseBridge)) < amount) {\n SYN_FRAX.safeApprove(address(synapseBridge), MAX_UINT256);\n }\n synapseBridge.redeem(to, chainId, SYN_FRAX, swappedAmount);\n } else {\n if (token.allowance(address(this), address(synapseBridge)) < amount) {\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n }\n synapseBridge.redeem(to, chainId, token, amount);\n }\n }\n\n /**\n * @notice Wraps SynapseBridge redeemv2() function\n * @param to address on other chain to bridge assets to\n * @param chainId which chain to bridge assets onto\n * @param token ERC20 compatible token to redeem into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n **/\n function redeemv2(\n bytes32 to,\n uint256 chainId,\n IERC20 token,\n uint256 amount\n ) external {\n token.safeTransferFrom(msg.sender, address(this), amount);\n\n if (token.allowance(address(this), address(synapseBridge)) < amount) {\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n }\n synapseBridge.redeemv2(to, chainId, token, amount);\n }\n\n /**\n * @notice wraps SynapseBridge redeem()\n * @param to address on other chain to redeem underlying assets to\n * @param chainId which underlying chain to bridge assets onto\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n **/\n function deposit(\n address to,\n uint256 chainId,\n IERC20 token,\n uint256 amount\n ) external {\n token.safeTransferFrom(msg.sender, address(this), amount);\n if (token.allowance(address(this), address(synapseBridge)) < amount) {\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n }\n synapseBridge.deposit(to, chainId, token, amount);\n }\n\n /**\n * @notice Wraps SynapseBridge deposit() function to make it compatible w/ ETH -> WETH conversions\n * @param to address on other chain to bridge assets to\n * @param chainId which chain to bridge assets onto\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n **/\n function depositETH(\n address to,\n uint256 chainId,\n uint256 amount\n ) external payable {\n require(msg.value > 0 && msg.value == amount, 'INCORRECT MSG VALUE');\n IWETH9(WETH_ADDRESS).deposit{value: msg.value}();\n synapseBridge.deposit(to, chainId, IERC20(WETH_ADDRESS), amount);\n }\n\n\n\n function swapETHAndRedeem(\n address to,\n uint256 chainId,\n IERC20 token,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx,\n uint256 minDy,\n uint256 deadline\n ) external payable {\n require(WETH_ADDRESS != address(0), \"WETH 0\");\n require(msg.value > 0 && msg.value == dx, \"INCORRECT MSG VALUE\");\n ISwap swap = ISwap(swapMap[address(token)]);\n require(address(swap) != address(0), \"Swap is 0x00\");\n IWETH9(WETH_ADDRESS).deposit{value: msg.value}();\n\n // swap\n uint256 swappedAmount = swap.swap(\n tokenIndexFrom,\n tokenIndexTo,\n dx,\n minDy,\n deadline\n );\n synapseBridge.redeem(to, chainId, token, swappedAmount);\n }\n\n /**\n * @notice Wraps redeemAndSwap on SynapseBridge.sol\n * Relays to nodes that (typically) a wrapped synAsset ERC20 token has been burned and the underlying needs to be redeeemed on the native chain. This function indicates to the nodes that they should attempt to redeem the LP token for the underlying assets (E.g \"swap\" out of the LP token)\n * @param to address on other chain to redeem underlying assets to\n * @param chainId which underlying chain to bridge assets onto\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n * @param tokenIndexFrom the token the user wants to swap from\n * @param tokenIndexTo the token the user wants to swap to\n * @param minDy the min amount the user would like to receive, or revert to only minting the SynERC20 token crosschain.\n * @param deadline latest timestamp to accept this transaction\n **/\n function redeemAndSwap(\n address to,\n uint256 chainId,\n IERC20 token,\n uint256 amount,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 minDy,\n uint256 deadline\n ) external {\n token.safeTransferFrom(msg.sender, address(this), amount);\n if (token.allowance(address(this), address(synapseBridge)) < amount) {\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n }\n synapseBridge.redeemAndSwap(\n to,\n chainId,\n token,\n amount,\n tokenIndexFrom,\n tokenIndexTo,\n minDy,\n deadline\n );\n }\n\n /**\n * @notice Wraps redeemAndRemove on SynapseBridge\n * Relays to nodes that (typically) a wrapped synAsset ERC20 token has been burned and the underlying needs to be redeeemed on the native chain. This function indicates to the nodes that they should attempt to redeem the LP token for the underlying assets (E.g \"swap\" out of the LP token)\n * @param to address on other chain to redeem underlying assets to\n * @param chainId which underlying chain to bridge assets onto\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount of (typically) LP token to pass to the nodes to attempt to removeLiquidity() with to redeem for the underlying assets of the LP token\n * @param liqTokenIndex Specifies which of the underlying LP assets the nodes should attempt to redeem for\n * @param liqMinAmount Specifies the minimum amount of the underlying asset needed for the nodes to execute the redeem/swap\n * @param liqDeadline Specificies the deadline that the nodes are allowed to try to redeem/swap the LP token\n **/\n function redeemAndRemove(\n address to,\n uint256 chainId,\n IERC20 token,\n uint256 amount,\n uint8 liqTokenIndex,\n uint256 liqMinAmount,\n uint256 liqDeadline\n ) external {\n token.safeTransferFrom(msg.sender, address(this), amount);\n if (token.allowance(address(this), address(synapseBridge)) < amount) {\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n }\n synapseBridge.redeemAndRemove(\n to,\n chainId,\n token,\n amount,\n liqTokenIndex,\n liqMinAmount,\n liqDeadline\n );\n }\n}\n" + }, + "contracts/bridge/interfaces/ISwap.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.6.12;\n\nimport '@openzeppelin/contracts/token/ERC20/ERC20.sol';\n\ninterface ISwap {\n // pool data view functions\n function getA() external view returns (uint256);\n\n function getToken(uint8 index) external view returns (IERC20);\n\n function getTokenIndex(address tokenAddress) external view returns (uint8);\n\n function getTokenBalance(uint8 index) external view returns (uint256);\n\n function getVirtualPrice() external view returns (uint256);\n\n // min return calculation functions\n function calculateSwap(\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx\n ) external view returns (uint256);\n\n function calculateTokenAmount(uint256[] calldata amounts, bool deposit)\n external\n view\n returns (uint256);\n\n function calculateRemoveLiquidity(uint256 amount)\n external\n view\n returns (uint256[] memory);\n\n function calculateRemoveLiquidityOneToken(\n uint256 tokenAmount,\n uint8 tokenIndex\n ) external view returns (uint256 availableTokenAmount);\n\n // state modifying functions\n function initialize(\n IERC20[] memory pooledTokens,\n uint8[] memory decimals,\n string memory lpTokenName,\n string memory lpTokenSymbol,\n uint256 a,\n uint256 fee,\n uint256 adminFee,\n address lpTokenTargetAddress\n ) external;\n\n function swap(\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx,\n uint256 minDy,\n uint256 deadline\n ) external returns (uint256);\n\n function addLiquidity(\n uint256[] calldata amounts,\n uint256 minToMint,\n uint256 deadline\n ) external returns (uint256);\n\n function removeLiquidity(\n uint256 amount,\n uint256[] calldata minAmounts,\n uint256 deadline\n ) external returns (uint256[] memory);\n\n function removeLiquidityOneToken(\n uint256 tokenAmount,\n uint8 tokenIndex,\n uint256 minAmount,\n uint256 deadline\n ) external returns (uint256);\n\n function removeLiquidityImbalance(\n uint256[] calldata amounts,\n uint256 maxBurnAmount,\n uint256 deadline\n ) external returns (uint256);\n}\n" + }, + "contracts/bridge/interfaces/IWETH9.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.4.0;\n\ninterface IWETH9 {\n function name() external view returns (string memory);\n\n function symbol() external view returns (string memory);\n\n function decimals() external view returns (uint8);\n\n function balanceOf(address) external view returns (uint256);\n\n function allowance(address, address) external view returns (uint256);\n\n receive() external payable;\n\n function deposit() external payable;\n\n function withdraw(uint256 wad) external;\n\n function totalSupply() external view returns (uint256);\n\n function approve(address guy, uint256 wad) external returns (bool);\n\n function transfer(address dst, uint256 wad) external returns (bool);\n\n function transferFrom(\n address src,\n address dst,\n uint256 wad\n ) external returns (bool);\n}" + }, + "contracts/bridge/wrappers/L2BridgeZap.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.6.12;\n\nimport \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/SafeERC20.sol\";\nimport \"../interfaces/ISwap.sol\";\nimport \"../interfaces/ISynapseBridge.sol\";\nimport \"../interfaces/IWETH9.sol\";\n\ncontract L2BridgeZap {\n using SafeERC20 for IERC20;\n\n ISynapseBridge synapseBridge;\n address payable public immutable WETH_ADDRESS;\n\n mapping(address => address) public swapMap;\n mapping(address => IERC20[]) public swapTokensMap;\n\n uint256 constant MAX_UINT256 = 2**256 - 1;\n\n constructor(\n address payable _wethAddress,\n address _swapOne,\n address tokenOne,\n address _swapTwo,\n address tokenTwo,\n ISynapseBridge _synapseBridge\n ) public {\n WETH_ADDRESS = _wethAddress;\n synapseBridge = _synapseBridge;\n swapMap[tokenOne] = _swapOne;\n swapMap[tokenTwo] = _swapTwo;\n if (_wethAddress != address(0)) {\n IERC20(_wethAddress).safeIncreaseAllowance(address(_synapseBridge), MAX_UINT256);\n }\n if (address(_swapOne) != address(0)) {\n {\n uint8 i;\n for (; i < 32; i++) {\n try ISwap(_swapOne).getToken(i) returns (\n IERC20 token\n ) {\n swapTokensMap[_swapOne].push(token);\n token.safeApprove(address(_swapOne), MAX_UINT256);\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n } catch {\n break;\n }\n }\n require(i > 1, \"swap must have at least 2 tokens\");\n }\n }\n if (address(_swapTwo) != address(0)) {\n {\n uint8 i;\n for (; i < 32; i++) {\n try ISwap(_swapTwo).getToken(i) returns (\n IERC20 token\n ) {\n swapTokensMap[_swapTwo].push(token);\n token.safeApprove(address(_swapTwo), MAX_UINT256);\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n } catch {\n break;\n }\n }\n require(i > 1, \"swap must have at least 2 tokens\");\n }\n }\n }\n\n /**\n * @notice Calculate amount of tokens you receive on swap\n * @param tokenIndexFrom the token the user wants to sell\n * @param tokenIndexTo the token the user wants to buy\n * @param dx the amount of tokens the user wants to sell. If the token charges\n * a fee on transfers, use the amount that gets transferred after the fee.\n * @return amount of tokens the user will receive\n */\n function calculateSwap(\n IERC20 token,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx\n ) external view virtual returns (uint256) {\n ISwap swap = ISwap(\n swapMap[address(token)]\n );\n return swap.calculateSwap(tokenIndexFrom, tokenIndexTo, dx);\n }\n\n function swapAndRedeem(\n address to,\n uint256 chainId,\n IERC20 token,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx,\n uint256 minDy,\n uint256 deadline\n ) external {\n ISwap swap = ISwap(swapMap[address(token)]);\n require(address(swap) != address(0), \"Swap is 0x00\");\n IERC20[] memory tokens = swapTokensMap[address(swap)];\n tokens[tokenIndexFrom].safeTransferFrom(\n msg.sender,\n address(this),\n dx\n );\n // swap\n\n uint256 swappedAmount = swap.swap(\n tokenIndexFrom,\n tokenIndexTo,\n dx,\n minDy,\n deadline\n );\n // deposit into bridge, gets nUSD\n if (\n token.allowance(address(this), address(synapseBridge)) <\n swappedAmount\n ) {\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n }\n synapseBridge.redeem(to, chainId, token, swappedAmount);\n }\n\n function swapAndRedeemAndSwap(\n address to,\n uint256 chainId,\n IERC20 token,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx,\n uint256 minDy,\n uint256 deadline,\n uint8 swapTokenIndexFrom,\n uint8 swapTokenIndexTo,\n uint256 swapMinDy,\n uint256 swapDeadline\n ) external {\n require(\n address(swapMap[address(token)]) != address(0),\n \"Swap is 0x00\"\n );\n IERC20[] memory tokens = swapTokensMap[\n swapMap[address(token)]\n ];\n tokens[tokenIndexFrom].safeTransferFrom(\n msg.sender,\n address(this),\n dx\n );\n // swap\n\n uint256 swappedAmount = ISwap(swapMap[address(token)]).swap(tokenIndexFrom, tokenIndexTo, dx, minDy, deadline);\n // deposit into bridge, gets nUSD\n if (\n token.allowance(address(this), address(synapseBridge)) <\n swappedAmount\n ) {\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n }\n synapseBridge.redeemAndSwap(\n to,\n chainId,\n token,\n swappedAmount,\n swapTokenIndexFrom,\n swapTokenIndexTo,\n swapMinDy,\n swapDeadline\n );\n }\n\n function swapAndRedeemAndRemove(\n address to,\n uint256 chainId,\n IERC20 token,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx,\n uint256 minDy,\n uint256 deadline,\n uint8 liqTokenIndex,\n uint256 liqMinAmount,\n uint256 liqDeadline\n ) external {\n ISwap swap = ISwap(swapMap[address(token)]);\n require(address(swap) != address(0), \"Swap is 0x00\");\n IERC20[] memory tokens = swapTokensMap[address(swap)];\n tokens[tokenIndexFrom].safeTransferFrom(\n msg.sender,\n address(this),\n dx\n );\n // swap\n\n uint256 swappedAmount = swap.swap(\n tokenIndexFrom,\n tokenIndexTo,\n dx,\n minDy,\n deadline\n );\n // deposit into bridge, gets nUSD\n if (\n token.allowance(address(this), address(synapseBridge)) <\n swappedAmount\n ) {\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n }\n synapseBridge.redeemAndRemove(\n to,\n chainId,\n token,\n swappedAmount,\n liqTokenIndex,\n liqMinAmount,\n liqDeadline\n );\n }\n\n /**\n * @notice wraps SynapseBridge redeem()\n * @param to address on other chain to redeem underlying assets to\n * @param chainId which underlying chain to bridge assets onto\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n **/\n function redeem(\n address to,\n uint256 chainId,\n IERC20 token,\n uint256 amount\n ) external {\n token.safeTransferFrom(msg.sender, address(this), amount);\n if (token.allowance(address(this), address(synapseBridge)) < amount) {\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n }\n synapseBridge.redeem(to, chainId, token, amount);\n }\n\n /**\n * @notice wraps SynapseBridge redeem()\n * @param to address on other chain to redeem underlying assets to\n * @param chainId which underlying chain to bridge assets onto\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n **/\n function deposit(\n address to,\n uint256 chainId,\n IERC20 token,\n uint256 amount\n ) external {\n token.safeTransferFrom(msg.sender, address(this), amount);\n if (token.allowance(address(this), address(synapseBridge)) < amount) {\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n }\n synapseBridge.deposit(to, chainId, token, amount);\n }\n\n /**\n * @notice Wraps SynapseBridge deposit() function to make it compatible w/ ETH -> WETH conversions\n * @param to address on other chain to bridge assets to\n * @param chainId which chain to bridge assets onto\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n **/\n function depositETH(\n address to,\n uint256 chainId,\n uint256 amount\n ) external payable {\n require(msg.value > 0 && msg.value == amount, 'INCORRECT MSG VALUE');\n IWETH9(WETH_ADDRESS).deposit{value: msg.value}();\n synapseBridge.deposit(to, chainId, IERC20(WETH_ADDRESS), amount);\n }\n\n\n function swapETHAndRedeem(\n address to,\n uint256 chainId,\n IERC20 token,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx,\n uint256 minDy,\n uint256 deadline\n ) external payable {\n require(WETH_ADDRESS != address(0), \"WETH 0\");\n require(msg.value > 0 && msg.value == dx, \"INCORRECT MSG VALUE\");\n ISwap swap = ISwap(swapMap[address(token)]);\n require(address(swap) != address(0), \"Swap is 0x00\");\n IWETH9(WETH_ADDRESS).deposit{value: msg.value}();\n\n // swap\n uint256 swappedAmount = swap.swap(\n tokenIndexFrom,\n tokenIndexTo,\n dx,\n minDy,\n deadline\n );\n synapseBridge.redeem(to, chainId, token, swappedAmount);\n }\n\n\n function swapETHAndRedeemAndSwap(\n address to,\n uint256 chainId,\n IERC20 token,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx,\n uint256 minDy,\n uint256 deadline,\n uint8 swapTokenIndexFrom,\n uint8 swapTokenIndexTo,\n uint256 swapMinDy,\n uint256 swapDeadline\n ) external payable {\n require(WETH_ADDRESS != address(0), \"WETH 0\");\n require(msg.value > 0 && msg.value == dx, \"INCORRECT MSG VALUE\");\n ISwap swap = ISwap(swapMap[address(token)]);\n require(address(swap) != address(0), \"Swap is 0x00\");\n IWETH9(WETH_ADDRESS).deposit{value: msg.value}();\n\n // swap\n uint256 swappedAmount = swap.swap(\n tokenIndexFrom,\n tokenIndexTo,\n dx,\n minDy,\n deadline\n );\n synapseBridge.redeemAndSwap(to, chainId, token, swappedAmount,swapTokenIndexFrom,\n swapTokenIndexTo,\n swapMinDy,\n swapDeadline);\n }\n\n\n /**\n * @notice Wraps redeemAndSwap on SynapseBridge.sol\n * Relays to nodes that (typically) a wrapped synAsset ERC20 token has been burned and the underlying needs to be redeeemed on the native chain. This function indicates to the nodes that they should attempt to redeem the LP token for the underlying assets (E.g \"swap\" out of the LP token)\n * @param to address on other chain to redeem underlying assets to\n * @param chainId which underlying chain to bridge assets onto\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n * @param tokenIndexFrom the token the user wants to swap from\n * @param tokenIndexTo the token the user wants to swap to\n * @param minDy the min amount the user would like to receive, or revert to only minting the SynERC20 token crosschain.\n * @param deadline latest timestamp to accept this transaction\n **/\n function redeemAndSwap(\n address to,\n uint256 chainId,\n IERC20 token,\n uint256 amount,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 minDy,\n uint256 deadline\n ) external {\n token.safeTransferFrom(msg.sender, address(this), amount);\n if (token.allowance(address(this), address(synapseBridge)) < amount) {\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n }\n synapseBridge.redeemAndSwap(\n to,\n chainId,\n token,\n amount,\n tokenIndexFrom,\n tokenIndexTo,\n minDy,\n deadline\n );\n }\n\n /**\n * @notice Wraps redeemAndRemove on SynapseBridge\n * Relays to nodes that (typically) a wrapped synAsset ERC20 token has been burned and the underlying needs to be redeeemed on the native chain. This function indicates to the nodes that they should attempt to redeem the LP token for the underlying assets (E.g \"swap\" out of the LP token)\n * @param to address on other chain to redeem underlying assets to\n * @param chainId which underlying chain to bridge assets onto\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount of (typically) LP token to pass to the nodes to attempt to removeLiquidity() with to redeem for the underlying assets of the LP token\n * @param liqTokenIndex Specifies which of the underlying LP assets the nodes should attempt to redeem for\n * @param liqMinAmount Specifies the minimum amount of the underlying asset needed for the nodes to execute the redeem/swap\n * @param liqDeadline Specificies the deadline that the nodes are allowed to try to redeem/swap the LP token\n **/\n function redeemAndRemove(\n address to,\n uint256 chainId,\n IERC20 token,\n uint256 amount,\n uint8 liqTokenIndex,\n uint256 liqMinAmount,\n uint256 liqDeadline\n ) external {\n token.safeTransferFrom(msg.sender, address(this), amount);\n if (token.allowance(address(this), address(synapseBridge)) < amount) {\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n }\n synapseBridge.redeemAndRemove(\n to,\n chainId,\n token,\n amount,\n liqTokenIndex,\n liqMinAmount,\n liqDeadline\n );\n }\n\n /**\n * @notice Wraps SynapseBridge redeemv2() function\n * @param to address on other chain to bridge assets to\n * @param chainId which chain to bridge assets onto\n * @param token ERC20 compatible token to redeem into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n **/\n function redeemv2(\n bytes32 to,\n uint256 chainId,\n IERC20 token,\n uint256 amount\n ) external {\n token.safeTransferFrom(msg.sender, address(this), amount);\n\n if (token.allowance(address(this), address(synapseBridge)) < amount) {\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n }\n synapseBridge.redeemv2(to, chainId, token, amount);\n }\n}\n" + }, + "contracts/bridge/wrappers/L1BridgeZap.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.6.12;\n\nimport '@openzeppelin/contracts/token/ERC20/IERC20.sol';\nimport '@openzeppelin/contracts/token/ERC20/SafeERC20.sol';\nimport '../interfaces/ISwap.sol';\nimport '../interfaces/ISynapseBridge.sol';\nimport \"../interfaces/IWETH9.sol\";\n\n\n/**\n * @title L1BridgeZap\n * @notice This contract is responsible for handling user Zaps into the SynapseBridge contract, through the Synapse Swap contracts. It does so\n * It does so by combining the action of addLiquidity() to the base swap pool, and then calling either deposit() or depositAndSwap() on the bridge.\n * This is done in hopes of automating portions of the bridge user experience to users, while keeping the SynapseBridge contract logic small.\n *\n * @dev This contract should be deployed with a base Swap.sol address and a SynapseBridge.sol address, otherwise, it will not function.\n */\ncontract L1BridgeZap {\n using SafeERC20 for IERC20;\n\n uint256 constant MAX_UINT256 = 2**256 - 1;\n \n ISwap baseSwap;\n ISynapseBridge synapseBridge;\n IERC20[] public baseTokens;\n address payable public immutable WETH_ADDRESS;\n \n\n /**\n * @notice Constructs the contract, approves each token inside of baseSwap to be used by baseSwap (needed for addLiquidity())\n */\n constructor(address payable _wethAddress, ISwap _baseSwap, ISynapseBridge _synapseBridge) public {\n WETH_ADDRESS = _wethAddress;\n baseSwap = _baseSwap;\n synapseBridge = _synapseBridge;\n IERC20(_wethAddress).safeIncreaseAllowance(address(_synapseBridge), MAX_UINT256);\n if (address(_baseSwap) != address(0)) {\n {\n uint8 i;\n for (; i < 32; i++) {\n try _baseSwap.getToken(i) returns (IERC20 token) {\n baseTokens.push(token);\n token.safeIncreaseAllowance(address(_baseSwap), MAX_UINT256);\n } catch {\n break;\n }\n }\n require(i > 1, 'baseSwap must have at least 2 tokens');\n }\n }\n }\n \n /**\n * @notice Wraps SynapseBridge deposit() function to make it compatible w/ ETH -> WETH conversions\n * @param to address on other chain to bridge assets to\n * @param chainId which chain to bridge assets onto\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n **/\n function depositETH(\n address to,\n uint256 chainId,\n uint256 amount\n ) external payable {\n require(msg.value > 0 && msg.value == amount, 'INCORRECT MSG VALUE');\n IWETH9(WETH_ADDRESS).deposit{value: msg.value}();\n synapseBridge.deposit(to, chainId, IERC20(WETH_ADDRESS), amount);\n }\n\n /**\n * @notice Wraps SynapseBridge depositAndSwap() function to make it compatible w/ ETH -> WETH conversions\n * @param to address on other chain to bridge assets to\n * @param chainId which chain to bridge assets onto\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n * @param tokenIndexFrom the token the user wants to swap from\n * @param tokenIndexTo the token the user wants to swap to\n * @param minDy the min amount the user would like to receive, or revert to only minting the SynERC20 token crosschain.\n * @param deadline latest timestamp to accept this transaction\n **/\n function depositETHAndSwap(\n address to,\n uint256 chainId,\n uint256 amount,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 minDy,\n uint256 deadline\n ) external payable {\n require(msg.value > 0 && msg.value == amount, 'INCORRECT MSG VALUE');\n IWETH9(WETH_ADDRESS).deposit{value: msg.value}();\n synapseBridge.depositAndSwap(to, chainId, IERC20(WETH_ADDRESS), amount, tokenIndexFrom, tokenIndexTo, minDy, deadline);\n }\n\n\n /**\n * @notice A simple method to calculate prices from deposits or\n * withdrawals, excluding fees but including slippage. This is\n * helpful as an input into the various \"min\" parameters on calls\n * to fight front-running\n *\n * @dev This shouldn't be used outside frontends for user estimates.\n *\n * @param amounts an array of token amounts to deposit or withdrawal,\n * corresponding to pooledTokens. The amount should be in each\n * pooled token's native precision.\n * @param deposit whether this is a deposit or a withdrawal\n * @return token amount the user will receive\n */\n function calculateTokenAmount(uint256[] calldata amounts, bool deposit)\n external\n view\n virtual\n returns (uint256)\n {\n return baseSwap.calculateTokenAmount(amounts, deposit);\n }\n\n /**\n * @notice Calculate the amount of underlying token available to withdraw\n * when withdrawing via only single token\n * @param tokenAmount the amount of LP token to burn\n * @param tokenIndex index of which token will be withdrawn\n * @return availableTokenAmount calculated amount of underlying token\n * available to withdraw\n */\n function calculateRemoveLiquidityOneToken(\n uint256 tokenAmount,\n uint8 tokenIndex\n ) external view virtual returns (uint256 availableTokenAmount) {\n return baseSwap.calculateRemoveLiquidityOneToken(tokenAmount, tokenIndex);\n }\n\n\n /**\n * @notice Combines adding liquidity to the given Swap, and calls deposit() on the bridge using that LP token\n * @param to address on other chain to bridge assets to\n * @param chainId which chain to bridge assets onto\n * @param token ERC20 compatible token to deposit into the bridge\n * @param liquidityAmounts the amounts of each token to add, in their native precision\n * @param minToMint the minimum LP tokens adding this amount of liquidity\n * should mint, otherwise revert. Handy for front-running mitigation\n * @param deadline latest timestamp to accept this transaction\n **/\n function zapAndDeposit(\n address to,\n uint256 chainId,\n IERC20 token,\n uint256[] calldata liquidityAmounts,\n uint256 minToMint,\n uint256 deadline\n ) external {\n // add liquidity\n for (uint256 i = 0; i < baseTokens.length; i++) {\n if (liquidityAmounts[i] != 0) {\n baseTokens[i].safeTransferFrom(\n msg.sender,\n address(this),\n liquidityAmounts[i]\n );\n }\n }\n\n uint256 liqAdded = baseSwap.addLiquidity(\n liquidityAmounts,\n minToMint,\n deadline\n );\n // deposit into bridge, gets nUSD\n if (token.allowance(address(this), address(synapseBridge)) < liqAdded) {\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n }\n synapseBridge.deposit(to, chainId, token, liqAdded);\n }\n\n /**\n * @notice Combines adding liquidity to the given Swap, and calls depositAndSwap() on the bridge using that LP token\n * @param to address on other chain to bridge assets to\n * @param chainId which chain to bridge assets onto\n * @param token ERC20 compatible token to deposit into the bridge\n * @param liquidityAmounts the amounts of each token to add, in their native precision\n * @param minToMint the minimum LP tokens adding this amount of liquidity\n * should mint, otherwise revert. Handy for front-running mitigation\n * @param liqDeadline latest timestamp to accept this transaction\n * @param tokenIndexFrom the token the user wants to swap from\n * @param tokenIndexTo the token the user wants to swap to\n * @param minDy the min amount the user would like to receive, or revert to only minting the SynERC20 token crosschain.\n * @param swapDeadline latest timestamp to accept this transaction\n **/\n function zapAndDepositAndSwap(\n address to,\n uint256 chainId,\n IERC20 token,\n uint256[] calldata liquidityAmounts,\n uint256 minToMint,\n uint256 liqDeadline,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 minDy,\n uint256 swapDeadline\n ) external {\n // add liquidity\n for (uint256 i = 0; i < baseTokens.length; i++) {\n if (liquidityAmounts[i] != 0) {\n baseTokens[i].safeTransferFrom(\n msg.sender,\n address(this),\n liquidityAmounts[i]\n );\n }\n }\n\n uint256 liqAdded = baseSwap.addLiquidity(\n liquidityAmounts,\n minToMint,\n liqDeadline\n );\n // deposit into bridge, bridge attemps to swap into desired asset\n if (token.allowance(address(this), address(synapseBridge)) < liqAdded) {\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n }\n synapseBridge.depositAndSwap(\n to,\n chainId,\n token,\n liqAdded,\n tokenIndexFrom,\n tokenIndexTo,\n minDy,\n swapDeadline\n );\n }\n\n /**\n * @notice Wraps SynapseBridge deposit() function\n * @param to address on other chain to bridge assets to\n * @param chainId which chain to bridge assets onto\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n **/\n function deposit(\n address to,\n uint256 chainId,\n IERC20 token,\n uint256 amount\n ) external {\n token.safeTransferFrom(msg.sender, address(this), amount);\n\n if (token.allowance(address(this), address(synapseBridge)) < amount) {\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n }\n synapseBridge.deposit(to, chainId, token, amount);\n }\n \n /**\n * @notice Wraps SynapseBridge depositAndSwap() function\n * @param to address on other chain to bridge assets to\n * @param chainId which chain to bridge assets onto\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n * @param tokenIndexFrom the token the user wants to swap from\n * @param tokenIndexTo the token the user wants to swap to\n * @param minDy the min amount the user would like to receive, or revert to only minting the SynERC20 token crosschain.\n * @param deadline latest timestamp to accept this transaction\n **/\n function depositAndSwap(\n address to,\n uint256 chainId,\n IERC20 token,\n uint256 amount,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 minDy,\n uint256 deadline\n ) external {\n token.safeTransferFrom(msg.sender, address(this), amount);\n \n if (token.allowance(address(this), address(synapseBridge)) < amount) {\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n }\n synapseBridge.depositAndSwap(to, chainId, token, amount, tokenIndexFrom, tokenIndexTo, minDy, deadline);\n }\n\n\n /**\n * @notice Wraps SynapseBridge redeem() function\n * @param to address on other chain to bridge assets to\n * @param chainId which chain to bridge assets onto\n * @param token ERC20 compatible token to redeem into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n **/\n function redeem(\n address to,\n uint256 chainId,\n IERC20 token,\n uint256 amount\n ) external {\n token.safeTransferFrom(msg.sender, address(this), amount);\n\n if (token.allowance(address(this), address(synapseBridge)) < amount) {\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n }\n synapseBridge.redeem(to, chainId, token, amount);\n }\n\n /**\n * @notice Wraps redeemAndSwap on SynapseBridge.sol\n * Relays to nodes that (typically) a wrapped synAsset ERC20 token has been burned and the underlying needs to be redeeemed on the native chain. This function indicates to the nodes that they should attempt to redeem the LP token for the underlying assets (E.g \"swap\" out of the LP token)\n * @param to address on other chain to redeem underlying assets to\n * @param chainId which underlying chain to bridge assets onto\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n * @param tokenIndexFrom the token the user wants to swap from\n * @param tokenIndexTo the token the user wants to swap to\n * @param minDy the min amount the user would like to receive, or revert to only minting the SynERC20 token crosschain.\n * @param deadline latest timestamp to accept this transaction\n **/\n function redeemAndSwap(\n address to,\n uint256 chainId,\n IERC20 token,\n uint256 amount,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 minDy,\n uint256 deadline\n ) external {\n token.safeTransferFrom(msg.sender, address(this), amount);\n if (token.allowance(address(this), address(synapseBridge)) < amount) {\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n }\n synapseBridge.redeemAndSwap(\n to,\n chainId,\n token,\n amount,\n tokenIndexFrom,\n tokenIndexTo,\n minDy,\n deadline\n );\n }\n\n /**\n * @notice Wraps redeemAndRemove on SynapseBridge\n * Relays to nodes that (typically) a wrapped synAsset ERC20 token has been burned and the underlying needs to be redeeemed on the native chain. This function indicates to the nodes that they should attempt to redeem the LP token for the underlying assets (E.g \"swap\" out of the LP token)\n * @param to address on other chain to redeem underlying assets to\n * @param chainId which underlying chain to bridge assets onto\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount of (typically) LP token to pass to the nodes to attempt to removeLiquidity() with to redeem for the underlying assets of the LP token\n * @param liqTokenIndex Specifies which of the underlying LP assets the nodes should attempt to redeem for\n * @param liqMinAmount Specifies the minimum amount of the underlying asset needed for the nodes to execute the redeem/swap\n * @param liqDeadline Specificies the deadline that the nodes are allowed to try to redeem/swap the LP token\n **/\n function redeemAndRemove(\n address to,\n uint256 chainId,\n IERC20 token,\n uint256 amount,\n uint8 liqTokenIndex,\n uint256 liqMinAmount,\n uint256 liqDeadline\n ) external {\n token.safeTransferFrom(msg.sender, address(this), amount);\n if (token.allowance(address(this), address(synapseBridge)) < amount) {\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n }\n synapseBridge.redeemAndRemove(\n to,\n chainId,\n token,\n amount,\n liqTokenIndex,\n liqMinAmount,\n liqDeadline\n );\n }\n\n\n /**\n * @notice Wraps SynapseBridge redeemv2() function\n * @param to address on other chain to bridge assets to\n * @param chainId which chain to bridge assets onto\n * @param token ERC20 compatible token to redeem into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n **/\n function redeemv2(\n bytes32 to,\n uint256 chainId,\n IERC20 token,\n uint256 amount\n ) external {\n token.safeTransferFrom(msg.sender, address(this), amount);\n\n if (token.allowance(address(this), address(synapseBridge)) < amount) {\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n }\n synapseBridge.redeemv2(to, chainId, token, amount);\n }\n\n}\n" + }, + "contracts/bridge/wrappers/MigratorBridgeZap.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.6.12;\n\nimport '@openzeppelin/contracts/token/ERC20/IERC20.sol';\nimport '@openzeppelin/contracts/token/ERC20/SafeERC20.sol';\nimport '@openzeppelin/contracts/math/SafeMath.sol';\n\nimport '../interfaces/ISynapseBridge.sol';\nimport '../interfaces/IERC20Migrator.sol';\n\ncontract MigratorBridgeZap {\n using SafeERC20 for IERC20;\n using SafeMath for uint256;\n \n ISynapseBridge constant synapseBridge = ISynapseBridge(0xd123f70AE324d34A9E76b67a27bf77593bA8749f);\n IERC20Migrator constant erc20Migrator = IERC20Migrator(0xf0284FB86adA5E4D82555C529677eEA3B2C3E022); \n IERC20 constant legacyToken = IERC20(0x42F6f551ae042cBe50C739158b4f0CAC0Edb9096);\n IERC20 constant newToken = IERC20(0xa4080f1778e69467E905B8d6F72f6e441f9e9484);\n uint256 constant MAX_UINT256 = 2**256 - 1;\n\n constructor() public {\n legacyToken.safeApprove(address(erc20Migrator), MAX_UINT256);\n newToken.safeApprove(address(synapseBridge), MAX_UINT256);\n }\n\n function migrate(uint256 amount) external {\n legacyToken.safeTransferFrom(msg.sender, address(this), amount);\n erc20Migrator.migrate(amount);\n newToken.safeTransfer(msg.sender, amount.mul(5).div(2));\n }\n\n function migrateAndBridge(uint256 amount, address to, uint256 chainId) external {\n legacyToken.safeTransferFrom(msg.sender, address(this), amount);\n erc20Migrator.migrate(amount);\n synapseBridge.redeem(to, chainId, newToken, amount.mul(5).div(2));\n }\n}" + }, + "contracts/bridge/interfaces/IERC20Migrator.sol": { + "content": "// SPDX-License-Identifier: MIT\n\n\npragma solidity 0.6.12;\n\ninterface IERC20Migrator { \n function migrate(uint256 amount) external;\n}\n\n" + }, + "contracts/bridge/wrappers/GMXWrapper.sol": { + "content": "// SPDX-License-Identifier: MIT\n\nimport '@openzeppelin/contracts/math/SafeMath.sol';\n\npragma solidity 0.6.12;\n\ninterface IGMX {\n function burn(address _account, uint256 _amount) external;\n function balanceOf(address account) external view returns (uint256);\n function mint(address _account, uint256 _amount) external;\n}\n\ncontract GMXWrapper {\n using SafeMath for uint256;\n\n address constant public gmx = 0x62edc0692BD897D2295872a9FFCac5425011c661;\n address constant public bridge = 0xC05e61d0E7a63D27546389B7aD62FdFf5A91aACE;\n\n function transfer(address _recipient, uint256 _amount) external returns (bool) {\n require(msg.sender == bridge);\n _transfer(msg.sender, _recipient, _amount);\n return true;\n }\n\n function _transfer(address _sender, address _recipient, uint256 _amount) private {\n require(_sender != address(0), \"BaseToken: transfer from the zero address\");\n require(_recipient != address(0), \"BaseToken: transfer to the zero address\");\n IGMX(gmx).burn(_sender, _amount);\n IGMX(gmx).mint(_recipient, _amount);\n }\n\n function mint(address _addr, uint256 _amount) external {\n require(msg.sender == bridge);\n uint256 preMint = IGMX(gmx).balanceOf(_addr);\n IGMX(gmx).mint(_addr, _amount);\n uint256 postMint = IGMX(gmx).balanceOf(_addr);\n require(preMint.add(_amount) == postMint, \"Mint incomplete\");\n }\n\n function burnFrom(address _addr, uint256 _amount) external {\n require(msg.sender == bridge);\n uint256 preBurn = IGMX(gmx).balanceOf(_addr);\n IGMX(gmx).burn(_addr, _amount);\n uint256 postBurn = IGMX(gmx).balanceOf(_addr);\n require(postBurn.add(_amount) == preBurn, \"Burn incomplete\");\n }\n}" + }, + "@openzeppelin/contracts/utils/Counters.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <0.8.0;\n\nimport \"../math/SafeMath.sol\";\n\n/**\n * @title Counters\n * @author Matt Condon (@shrugs)\n * @dev Provides counters that can only be incremented or decremented by one. This can be used e.g. to track the number\n * of elements in a mapping, issuing ERC721 ids, or counting request ids.\n *\n * Include with `using Counters for Counters.Counter;`\n * Since it is not possible to overflow a 256 bit integer with increments of one, `increment` can skip the {SafeMath}\n * overflow check, thereby saving gas. This does assume however correct usage, in that the underlying `_value` is never\n * directly accessed.\n */\nlibrary Counters {\n using SafeMath for uint256;\n\n struct Counter {\n // This variable should never be directly accessed by users of the library: interactions must be restricted to\n // the library's function. As of Solidity v0.5.2, this cannot be enforced, though there is a proposal to add\n // this feature: see https://github.com/ethereum/solidity/issues/4637\n uint256 _value; // default: 0\n }\n\n function current(Counter storage counter) internal view returns (uint256) {\n return counter._value;\n }\n\n function increment(Counter storage counter) internal {\n // The {SafeMath} overflow check can be skipped here, see the comment at the top\n counter._value += 1;\n }\n\n function decrement(Counter storage counter) internal {\n counter._value = counter._value.sub(1);\n }\n}\n" + }, + "@openzeppelin/contracts/drafts/ERC20Permit.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.5 <0.8.0;\n\nimport \"../token/ERC20/ERC20.sol\";\nimport \"./IERC20Permit.sol\";\nimport \"../cryptography/ECDSA.sol\";\nimport \"../utils/Counters.sol\";\nimport \"./EIP712.sol\";\n\n/**\n * @dev Implementation of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in\n * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612].\n *\n * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by\n * presenting a message signed by the account. By not relying on `{IERC20-approve}`, the token holder account doesn't\n * need to send a transaction, and thus is not required to hold Ether at all.\n *\n * _Available since v3.4._\n */\nabstract contract ERC20Permit is ERC20, IERC20Permit, EIP712 {\n using Counters for Counters.Counter;\n\n mapping (address => Counters.Counter) private _nonces;\n\n // solhint-disable-next-line var-name-mixedcase\n bytes32 private immutable _PERMIT_TYPEHASH = keccak256(\"Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)\");\n\n /**\n * @dev Initializes the {EIP712} domain separator using the `name` parameter, and setting `version` to `\"1\"`.\n *\n * It's a good idea to use the same `name` that is defined as the ERC20 token name.\n */\n constructor(string memory name) internal EIP712(name, \"1\") {\n }\n\n /**\n * @dev See {IERC20Permit-permit}.\n */\n function permit(address owner, address spender, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s) public virtual override {\n // solhint-disable-next-line not-rely-on-time\n require(block.timestamp <= deadline, \"ERC20Permit: expired deadline\");\n\n bytes32 structHash = keccak256(\n abi.encode(\n _PERMIT_TYPEHASH,\n owner,\n spender,\n value,\n _nonces[owner].current(),\n deadline\n )\n );\n\n bytes32 hash = _hashTypedDataV4(structHash);\n\n address signer = ECDSA.recover(hash, v, r, s);\n require(signer == owner, \"ERC20Permit: invalid signature\");\n\n _nonces[owner].increment();\n _approve(owner, spender, value);\n }\n\n /**\n * @dev See {IERC20Permit-nonces}.\n */\n function nonces(address owner) public view override returns (uint256) {\n return _nonces[owner].current();\n }\n\n /**\n * @dev See {IERC20Permit-DOMAIN_SEPARATOR}.\n */\n // solhint-disable-next-line func-name-mixedcase\n function DOMAIN_SEPARATOR() external view override returns (bytes32) {\n return _domainSeparatorV4();\n }\n}\n" + }, + "@openzeppelin/contracts/drafts/IERC20Permit.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <0.8.0;\n\n/**\n * @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in\n * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612].\n *\n * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by\n * presenting a message signed by the account. By not relying on `{IERC20-approve}`, the token holder account doesn't\n * need to send a transaction, and thus is not required to hold Ether at all.\n */\ninterface IERC20Permit {\n /**\n * @dev Sets `value` as the allowance of `spender` over `owner`'s tokens,\n * given `owner`'s signed approval.\n *\n * IMPORTANT: The same issues {IERC20-approve} has related to transaction\n * ordering also apply here.\n *\n * Emits an {Approval} event.\n *\n * Requirements:\n *\n * - `spender` cannot be the zero address.\n * - `deadline` must be a timestamp in the future.\n * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner`\n * over the EIP712-formatted function arguments.\n * - the signature must use ``owner``'s current nonce (see {nonces}).\n *\n * For more information on the signature format, see the\n * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP\n * section].\n */\n function permit(address owner, address spender, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s) external;\n\n /**\n * @dev Returns the current nonce for `owner`. This value must be\n * included whenever a signature is generated for {permit}.\n *\n * Every successful call to {permit} increases ``owner``'s nonce by one. This\n * prevents a signature from being used multiple times.\n */\n function nonces(address owner) external view returns (uint256);\n\n /**\n * @dev Returns the domain separator used in the encoding of the signature for `permit`, as defined by {EIP712}.\n */\n // solhint-disable-next-line func-name-mixedcase\n function DOMAIN_SEPARATOR() external view returns (bytes32);\n}\n" + }, + "@openzeppelin/contracts/cryptography/ECDSA.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <0.8.0;\n\n/**\n * @dev Elliptic Curve Digital Signature Algorithm (ECDSA) operations.\n *\n * These functions can be used to verify that a message was signed by the holder\n * of the private keys of a given address.\n */\nlibrary ECDSA {\n /**\n * @dev Returns the address that signed a hashed message (`hash`) with\n * `signature`. This address can then be used for verification purposes.\n *\n * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:\n * this function rejects them by requiring the `s` value to be in the lower\n * half order, and the `v` value to be either 27 or 28.\n *\n * IMPORTANT: `hash` _must_ be the result of a hash operation for the\n * verification to be secure: it is possible to craft signatures that\n * recover to arbitrary addresses for non-hashed data. A safe way to ensure\n * this is by receiving a hash of the original message (which may otherwise\n * be too long), and then calling {toEthSignedMessageHash} on it.\n */\n function recover(bytes32 hash, bytes memory signature) internal pure returns (address) {\n // Check the signature length\n if (signature.length != 65) {\n revert(\"ECDSA: invalid signature length\");\n }\n\n // Divide the signature in r, s and v variables\n bytes32 r;\n bytes32 s;\n uint8 v;\n\n // ecrecover takes the signature parameters, and the only way to get them\n // currently is to use assembly.\n // solhint-disable-next-line no-inline-assembly\n assembly {\n r := mload(add(signature, 0x20))\n s := mload(add(signature, 0x40))\n v := byte(0, mload(add(signature, 0x60)))\n }\n\n return recover(hash, v, r, s);\n }\n\n /**\n * @dev Overload of {ECDSA-recover-bytes32-bytes-} that receives the `v`,\n * `r` and `s` signature fields separately.\n */\n function recover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) internal pure returns (address) {\n // EIP-2 still allows signature malleability for ecrecover(). Remove this possibility and make the signature\n // unique. Appendix F in the Ethereum Yellow paper (https://ethereum.github.io/yellowpaper/paper.pdf), defines\n // the valid range for s in (281): 0 < s < secp256k1n ÷ 2 + 1, and for v in (282): v ∈ {27, 28}. Most\n // signatures from current libraries generate a unique signature with an s-value in the lower half order.\n //\n // If your library generates malleable signatures, such as s-values in the upper range, calculate a new s-value\n // with 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 - s1 and flip v from 27 to 28 or\n // vice versa. If your library also generates signatures with 0/1 for v instead 27/28, add 27 to v to accept\n // these malleable signatures as well.\n require(uint256(s) <= 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0, \"ECDSA: invalid signature 's' value\");\n require(v == 27 || v == 28, \"ECDSA: invalid signature 'v' value\");\n\n // If the signature is valid (and not malleable), return the signer address\n address signer = ecrecover(hash, v, r, s);\n require(signer != address(0), \"ECDSA: invalid signature\");\n\n return signer;\n }\n\n /**\n * @dev Returns an Ethereum Signed Message, created from a `hash`. This\n * replicates the behavior of the\n * https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_sign[`eth_sign`]\n * JSON-RPC method.\n *\n * See {recover}.\n */\n function toEthSignedMessageHash(bytes32 hash) internal pure returns (bytes32) {\n // 32 is the length in bytes of hash,\n // enforced by the type signature above\n return keccak256(abi.encodePacked(\"\\x19Ethereum Signed Message:\\n32\", hash));\n }\n}\n" + }, + "@openzeppelin/contracts/drafts/EIP712.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <0.8.0;\n\n/**\n * @dev https://eips.ethereum.org/EIPS/eip-712[EIP 712] is a standard for hashing and signing of typed structured data.\n *\n * The encoding specified in the EIP is very generic, and such a generic implementation in Solidity is not feasible,\n * thus this contract does not implement the encoding itself. Protocols need to implement the type-specific encoding\n * they need in their contracts using a combination of `abi.encode` and `keccak256`.\n *\n * This contract implements the EIP 712 domain separator ({_domainSeparatorV4}) that is used as part of the encoding\n * scheme, and the final step of the encoding to obtain the message digest that is then signed via ECDSA\n * ({_hashTypedDataV4}).\n *\n * The implementation of the domain separator was designed to be as efficient as possible while still properly updating\n * the chain id to protect against replay attacks on an eventual fork of the chain.\n *\n * NOTE: This contract implements the version of the encoding known as \"v4\", as implemented by the JSON RPC method\n * https://docs.metamask.io/guide/signing-data.html[`eth_signTypedDataV4` in MetaMask].\n *\n * _Available since v3.4._\n */\nabstract contract EIP712 {\n /* solhint-disable var-name-mixedcase */\n // Cache the domain separator as an immutable value, but also store the chain id that it corresponds to, in order to\n // invalidate the cached domain separator if the chain id changes.\n bytes32 private immutable _CACHED_DOMAIN_SEPARATOR;\n uint256 private immutable _CACHED_CHAIN_ID;\n\n bytes32 private immutable _HASHED_NAME;\n bytes32 private immutable _HASHED_VERSION;\n bytes32 private immutable _TYPE_HASH;\n /* solhint-enable var-name-mixedcase */\n\n /**\n * @dev Initializes the domain separator and parameter caches.\n *\n * The meaning of `name` and `version` is specified in\n * https://eips.ethereum.org/EIPS/eip-712#definition-of-domainseparator[EIP 712]:\n *\n * - `name`: the user readable name of the signing domain, i.e. the name of the DApp or the protocol.\n * - `version`: the current major version of the signing domain.\n *\n * NOTE: These parameters cannot be changed except through a xref:learn::upgrading-smart-contracts.adoc[smart\n * contract upgrade].\n */\n constructor(string memory name, string memory version) internal {\n bytes32 hashedName = keccak256(bytes(name));\n bytes32 hashedVersion = keccak256(bytes(version));\n bytes32 typeHash = keccak256(\"EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)\");\n _HASHED_NAME = hashedName;\n _HASHED_VERSION = hashedVersion;\n _CACHED_CHAIN_ID = _getChainId();\n _CACHED_DOMAIN_SEPARATOR = _buildDomainSeparator(typeHash, hashedName, hashedVersion);\n _TYPE_HASH = typeHash;\n }\n\n /**\n * @dev Returns the domain separator for the current chain.\n */\n function _domainSeparatorV4() internal view virtual returns (bytes32) {\n if (_getChainId() == _CACHED_CHAIN_ID) {\n return _CACHED_DOMAIN_SEPARATOR;\n } else {\n return _buildDomainSeparator(_TYPE_HASH, _HASHED_NAME, _HASHED_VERSION);\n }\n }\n\n function _buildDomainSeparator(bytes32 typeHash, bytes32 name, bytes32 version) private view returns (bytes32) {\n return keccak256(\n abi.encode(\n typeHash,\n name,\n version,\n _getChainId(),\n address(this)\n )\n );\n }\n\n /**\n * @dev Given an already https://eips.ethereum.org/EIPS/eip-712#definition-of-hashstruct[hashed struct], this\n * function returns the hash of the fully encoded EIP712 message for this domain.\n *\n * This hash can be used together with {ECDSA-recover} to obtain the signer of a message. For example:\n *\n * ```solidity\n * bytes32 digest = _hashTypedDataV4(keccak256(abi.encode(\n * keccak256(\"Mail(address to,string contents)\"),\n * mailTo,\n * keccak256(bytes(mailContents))\n * )));\n * address signer = ECDSA.recover(digest, signature);\n * ```\n */\n function _hashTypedDataV4(bytes32 structHash) internal view virtual returns (bytes32) {\n return keccak256(abi.encodePacked(\"\\x19\\x01\", _domainSeparatorV4(), structHash));\n }\n\n function _getChainId() private view returns (uint256 chainId) {\n this; // silence state mutability warning without generating bytecode - see https://github.com/ethereum/solidity/issues/2691\n // solhint-disable-next-line no-inline-assembly\n assembly {\n chainId := chainid()\n }\n }\n}\n" + }, + "contracts/bridge/testing/SynapseToken.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity >=0.6.0 <0.8.0;\n\n\nimport \"@openzeppelin/contracts/token/ERC20/ERC20.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/ERC20Burnable.sol\";\nimport \"@openzeppelin/contracts/access/AccessControl.sol\";\nimport \"@openzeppelin/contracts/drafts/ERC20Permit.sol\";\n\ncontract Synapse is ERC20, ERC20Burnable, AccessControl, ERC20Permit {\n bytes32 public constant MINTER_ROLE = keccak256(\"MINTER_ROLE\");\n\n constructor() public ERC20(\"Synapse\", \"SYN\") ERC20Permit(\"Synapse\") {\n _setupRole(DEFAULT_ADMIN_ROLE, msg.sender);\n _setupRole(MINTER_ROLE, msg.sender);\n }\n\n function mint(address to, uint256 amount) external {\n require(hasRole(MINTER_ROLE, msg.sender));\n _mint(to, amount);\n }\n}" + }, + "@openzeppelin/contracts/access/AccessControl.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <0.8.0;\n\nimport \"../utils/EnumerableSet.sol\";\nimport \"../utils/Address.sol\";\nimport \"../utils/Context.sol\";\n\n/**\n * @dev Contract module that allows children to implement role-based access\n * control mechanisms.\n *\n * Roles are referred to by their `bytes32` identifier. These should be exposed\n * in the external API and be unique. The best way to achieve this is by\n * using `public constant` hash digests:\n *\n * ```\n * bytes32 public constant MY_ROLE = keccak256(\"MY_ROLE\");\n * ```\n *\n * Roles can be used to represent a set of permissions. To restrict access to a\n * function call, use {hasRole}:\n *\n * ```\n * function foo() public {\n * require(hasRole(MY_ROLE, msg.sender));\n * ...\n * }\n * ```\n *\n * Roles can be granted and revoked dynamically via the {grantRole} and\n * {revokeRole} functions. Each role has an associated admin role, and only\n * accounts that have a role's admin role can call {grantRole} and {revokeRole}.\n *\n * By default, the admin role for all roles is `DEFAULT_ADMIN_ROLE`, which means\n * that only accounts with this role will be able to grant or revoke other\n * roles. More complex role relationships can be created by using\n * {_setRoleAdmin}.\n *\n * WARNING: The `DEFAULT_ADMIN_ROLE` is also its own admin: it has permission to\n * grant and revoke this role. Extra precautions should be taken to secure\n * accounts that have been granted it.\n */\nabstract contract AccessControl is Context {\n using EnumerableSet for EnumerableSet.AddressSet;\n using Address for address;\n\n struct RoleData {\n EnumerableSet.AddressSet members;\n bytes32 adminRole;\n }\n\n mapping (bytes32 => RoleData) private _roles;\n\n bytes32 public constant DEFAULT_ADMIN_ROLE = 0x00;\n\n /**\n * @dev Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole`\n *\n * `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite\n * {RoleAdminChanged} not being emitted signaling this.\n *\n * _Available since v3.1._\n */\n event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole);\n\n /**\n * @dev Emitted when `account` is granted `role`.\n *\n * `sender` is the account that originated the contract call, an admin role\n * bearer except when using {_setupRole}.\n */\n event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender);\n\n /**\n * @dev Emitted when `account` is revoked `role`.\n *\n * `sender` is the account that originated the contract call:\n * - if using `revokeRole`, it is the admin role bearer\n * - if using `renounceRole`, it is the role bearer (i.e. `account`)\n */\n event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender);\n\n /**\n * @dev Returns `true` if `account` has been granted `role`.\n */\n function hasRole(bytes32 role, address account) public view returns (bool) {\n return _roles[role].members.contains(account);\n }\n\n /**\n * @dev Returns the number of accounts that have `role`. Can be used\n * together with {getRoleMember} to enumerate all bearers of a role.\n */\n function getRoleMemberCount(bytes32 role) public view returns (uint256) {\n return _roles[role].members.length();\n }\n\n /**\n * @dev Returns one of the accounts that have `role`. `index` must be a\n * value between 0 and {getRoleMemberCount}, non-inclusive.\n *\n * Role bearers are not sorted in any particular way, and their ordering may\n * change at any point.\n *\n * WARNING: When using {getRoleMember} and {getRoleMemberCount}, make sure\n * you perform all queries on the same block. See the following\n * https://forum.openzeppelin.com/t/iterating-over-elements-on-enumerableset-in-openzeppelin-contracts/2296[forum post]\n * for more information.\n */\n function getRoleMember(bytes32 role, uint256 index) public view returns (address) {\n return _roles[role].members.at(index);\n }\n\n /**\n * @dev Returns the admin role that controls `role`. See {grantRole} and\n * {revokeRole}.\n *\n * To change a role's admin, use {_setRoleAdmin}.\n */\n function getRoleAdmin(bytes32 role) public view returns (bytes32) {\n return _roles[role].adminRole;\n }\n\n /**\n * @dev Grants `role` to `account`.\n *\n * If `account` had not been already granted `role`, emits a {RoleGranted}\n * event.\n *\n * Requirements:\n *\n * - the caller must have ``role``'s admin role.\n */\n function grantRole(bytes32 role, address account) public virtual {\n require(hasRole(_roles[role].adminRole, _msgSender()), \"AccessControl: sender must be an admin to grant\");\n\n _grantRole(role, account);\n }\n\n /**\n * @dev Revokes `role` from `account`.\n *\n * If `account` had been granted `role`, emits a {RoleRevoked} event.\n *\n * Requirements:\n *\n * - the caller must have ``role``'s admin role.\n */\n function revokeRole(bytes32 role, address account) public virtual {\n require(hasRole(_roles[role].adminRole, _msgSender()), \"AccessControl: sender must be an admin to revoke\");\n\n _revokeRole(role, account);\n }\n\n /**\n * @dev Revokes `role` from the calling account.\n *\n * Roles are often managed via {grantRole} and {revokeRole}: this function's\n * purpose is to provide a mechanism for accounts to lose their privileges\n * if they are compromised (such as when a trusted device is misplaced).\n *\n * If the calling account had been granted `role`, emits a {RoleRevoked}\n * event.\n *\n * Requirements:\n *\n * - the caller must be `account`.\n */\n function renounceRole(bytes32 role, address account) public virtual {\n require(account == _msgSender(), \"AccessControl: can only renounce roles for self\");\n\n _revokeRole(role, account);\n }\n\n /**\n * @dev Grants `role` to `account`.\n *\n * If `account` had not been already granted `role`, emits a {RoleGranted}\n * event. Note that unlike {grantRole}, this function doesn't perform any\n * checks on the calling account.\n *\n * [WARNING]\n * ====\n * This function should only be called from the constructor when setting\n * up the initial roles for the system.\n *\n * Using this function in any other way is effectively circumventing the admin\n * system imposed by {AccessControl}.\n * ====\n */\n function _setupRole(bytes32 role, address account) internal virtual {\n _grantRole(role, account);\n }\n\n /**\n * @dev Sets `adminRole` as ``role``'s admin role.\n *\n * Emits a {RoleAdminChanged} event.\n */\n function _setRoleAdmin(bytes32 role, bytes32 adminRole) internal virtual {\n emit RoleAdminChanged(role, _roles[role].adminRole, adminRole);\n _roles[role].adminRole = adminRole;\n }\n\n function _grantRole(bytes32 role, address account) private {\n if (_roles[role].members.add(account)) {\n emit RoleGranted(role, account, _msgSender());\n }\n }\n\n function _revokeRole(bytes32 role, address account) private {\n if (_roles[role].members.remove(account)) {\n emit RoleRevoked(role, account, _msgSender());\n }\n }\n}\n" + }, + "@openzeppelin/contracts/utils/EnumerableSet.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <0.8.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" + }, + "contracts/bridge/testing/NodeEnv.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.6.12;\npragma experimental ABIEncoderV2;\n\nimport '@openzeppelin/contracts/access/AccessControl.sol';\nimport \"../utils/EnumerableStringMap.sol\";\n\n/**\n * @title NodeEnv contract\n * @author Synapse Authors\n * @notice This contract implements a key-value store for storing variables on which synapse nodes must coordinate\n * methods are purposely arbitrary to allow these fields to be defined in synapse improvement proposals.\n * @notice This token is used for configuring different tokens on the bridge and mapping them across chains.\n**/\ncontract NodeEnv is AccessControl {\n using EnumerableStringMap for EnumerableStringMap.StringToStringMap;\n // BRIDGEMANAGER_ROLE owns the bridge. They are the only user that can call setters on this contract\n bytes32 public constant BRIDGEMANAGER_ROLE = keccak256('BRIDGEMANAGER_ROLE');\n // _config stores the config\n EnumerableStringMap.StringToStringMap private _config; // key is tokenAddress,chainID\n\n // ConfigUpdate is emitted when the config is updated by the user\n event ConfigUpdate(\n string key\n );\n\n constructor() public {\n _setupRole(DEFAULT_ADMIN_ROLE, msg.sender);\n _setupRole(BRIDGEMANAGER_ROLE, msg.sender);\n }\n\n /**\n * @notice get the length of the config\n *\n * @dev this is useful for enumerating through all keys in the env\n */\n function keyCount()\n external\n view\n returns (uint256){\n return _config.length();\n }\n\n /**\n * @notice gets the key/value pair by it's index\n *\n * Requirements:\n *\n * - `index` must be strictly less than {length}.\n */\n function keyValueByIndex(uint256 index) external view returns(string memory, string memory){\n return _config.at(index);\n }\n\n /**\n * @notice gets the value associated with the key\n */\n function get(string calldata _key) external view returns(string memory){\n string memory key = _key;\n return _config.get(key);\n }\n\n /**\n * @notice sets the key\n *\n * @dev caller must have bridge manager role\n */\n function set(string calldata _key, string calldata _value) external returns(bool) {\n require(\n hasRole(BRIDGEMANAGER_ROLE, msg.sender),\n 'Caller is not Bridge Manager'\n );\n string memory key = _key;\n string memory value = _value;\n\n return _config.set(key, value);\n }\n}" + }, + "contracts/bridge/utils/EnumerableStringMap.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.6.12;\n\nimport \"@openzeppelin/contracts/utils/EnumerableSet.sol\";\n\n/**\n * @title EnumerableStringMap\n * @dev Library for managing an enumerable variant of Solidity's\n * https://solidity.readthedocs.io/en/latest/types.html#mapping-types[`mapping`]\n * type.\n *\n * Maps have the following properties:\n *\n * - Entries are added, removed, and checked for existence in constant time\n * (O(1)).\n * - Entries are enumerated in O(n). No guarantees are made on the ordering.\n *\n * this isn't a terribly gas efficient implementation because it emphasizes usability over gas efficiency\n * by allowing arbitrary length string memorys. If Gettetrs/Setters are going to be used frequently in contracts\n * consider using the OpenZeppeling Bytes32 implementation\n *\n * this also differs from the OpenZeppelin implementation by keccac256 hashing the string memorys\n * so we can use enumerable bytes32 set\n */\nlibrary EnumerableStringMap {\n using EnumerableSet for EnumerableSet.Bytes32Set;\n\n // To implement this library for multiple types with as little code\n // repetition as possible, we write it in terms of a generic Map type with\n // bytes32 keys and values.\n // The Map implementation uses private functions, and user-facing\n // implementations (such as Uint256ToAddressMap) are just wrappers around\n // the underlying Map.\n // This means that we can only create new EnumerableMaps for types that fit\n // in bytes32.\n\n struct Map {\n // Storage of keys as a set\n EnumerableSet.Bytes32Set _keys;\n // Mapping of keys to resulting values to allow key lookup in the set\n mapping(bytes32 => string) _hashKeyMap;\n // values\n mapping(bytes32 => string) _values;\n }\n\n /**\n * @dev Adds a key-value pair to a map, or updates the value for an existing\n * key. O(1).\n *\n * Returns true if the key was added to the map, that is if it was not\n * already present.\n */\n function _set(\n Map storage map,\n string memory key,\n string memory value\n ) private returns (bool) {\n bytes32 keyHash = keccak256(abi.encodePacked(key));\n map._values[keyHash] = value;\n map._hashKeyMap[keyHash] = key;\n return map._keys.add(keyHash);\n }\n\n /**\n * @dev Removes a key-value pair from a map. O(1).\n *\n * Returns true if the key was removed from the map, that is if it was present.\n */\n function _remove(Map storage map, bytes32 keyHash) private returns (bool) {\n delete map._values[keyHash];\n delete map._hashKeyMap[keyHash];\n return map._keys.remove(keyHash);\n }\n\n /**\n * @dev Returns true if the key is in the map. O(1).\n */\n function _contains(Map storage map, bytes32 keyHash) private view returns (bool) {\n return map._keys.contains(keyHash);\n }\n\n /**\n * @dev Returns the number of key-value pairs in the map. O(1).\n */\n function _length(Map storage map) private view returns (uint256) {\n return map._keys.length();\n }\n\n /**\n * @dev Returns the key-value pair stored at position `index` in the map. O(1).\n *\n * Note that there are no guarantees on the ordering of entries inside the\n * array, and it may change when more entries are added or removed.\n *\n * Requirements:\n *\n * - `index` must be strictly less than {length}.\n */\n function _at(Map storage map, uint256 index) private view returns (string memory, string memory) {\n bytes32 keyHash = map._keys.at(index);\n return (map._hashKeyMap[keyHash], map._values[keyHash]);\n }\n\n /**\n * @dev Tries to returns the value associated with `key`. O(1).\n * Does not revert if `key` is not in the map.\n */\n function _tryGet(Map storage map, bytes32 keyHash) private view returns (bool, string memory) {\n string memory value = map._values[keyHash];\n if (keccak256(bytes(value)) == keccak256(bytes(\"\"))) {\n return (_contains(map, keyHash), \"\");\n } else {\n return (true, value);\n }\n }\n\n /**\n * @dev Returns the value associated with `key`. O(1).\n *\n * Requirements:\n *\n * - `key` must be in the map.\n */\n function _get(Map storage map, bytes32 keyHash) private view returns (string memory) {\n string memory value = map._values[keyHash];\n require(_contains(map, keyHash), \"EnumerableMap: nonexistent key\");\n return value;\n }\n\n // StringToStringMap\n struct StringToStringMap {\n Map _inner;\n }\n\n /**\n * @dev Adds a key-value pair to a map, or updates the value for an existing\n * key. O(1).\n *\n * Returns true if the key was added to the map, that is if it was not\n * already present.\n */\n function set(\n StringToStringMap storage map,\n string memory key,\n string memory value\n ) internal returns (bool) {\n return _set(map._inner, key, value);\n }\n\n /**\n * @dev Removes a value from a set. O(1).\n *\n * Returns true if the key was removed from the map, that is if it was present.\n */\n function remove(StringToStringMap storage map, string memory key) internal returns (bool) {\n return _remove(map._inner, keccak256(abi.encodePacked(key)));\n }\n\n /**\n * @dev Returns true if the key is in the map. O(1).\n */\n function contains(StringToStringMap storage map, string memory key) internal view returns (bool) {\n return _contains(map._inner, keccak256(abi.encodePacked(key)));\n }\n\n /**\n * @dev Returns the number of elements in the map. O(1).\n */\n function length(StringToStringMap storage map) internal view returns (uint256) {\n return _length(map._inner);\n }\n\n /**\n * @dev Returns the element stored at position `index` in the set. O(1).\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(StringToStringMap storage map, uint256 index) internal view returns (string memory, string memory) {\n return _at(map._inner, index);\n }\n\n /**\n * @dev Tries to returns the value associated with `key`. O(1).\n * Does not revert if `key` is not in the map.\n *\n * _Available since v3.4._\n */\n function tryGet(StringToStringMap storage map, uint256 key) internal view returns (bool, string memory) {\n (bool success, string memory value) = _tryGet(map._inner, bytes32(key));\n return (success, value);\n }\n\n /**\n * @dev Returns the value associated with `key`. O(1).\n *\n * Requirements:\n *\n * - `key` must be in the map.\n */\n function get(StringToStringMap storage map, string memory key) internal view returns (string memory) {\n return _get(map._inner, keccak256(abi.encodePacked(key)));\n }\n}" + }, + "contracts/bridge/PoolConfig.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.6.12;\npragma experimental ABIEncoderV2;\n\nimport \"@openzeppelin/contracts/access/AccessControl.sol\";\n\ncontract PoolConfig is AccessControl {\n bytes32 public constant BRIDGEMANAGER_ROLE =\n keccak256(\"BRIDGEMANAGER_ROLE\");\n mapping(address => mapping(uint256 => Pool)) private _pool; // key is tokenAddress,chainID\n\n struct Pool {\n address tokenAddress;\n uint256 chainId;\n address poolAddress;\n bool metaswap;\n }\n\n constructor() public {\n _setupRole(DEFAULT_ADMIN_ROLE, msg.sender);\n _setupRole(BRIDGEMANAGER_ROLE, msg.sender);\n }\n\n function getPoolConfig(address tokenAddress, uint256 chainID)\n external\n view\n returns (Pool memory)\n {\n return _pool[tokenAddress][chainID];\n }\n\n function setPoolConfig(\n address tokenAddress,\n uint256 chainID,\n address poolAddress,\n bool metaswap\n ) external returns (Pool memory) {\n require(\n hasRole(BRIDGEMANAGER_ROLE, msg.sender),\n \"Caller is not Bridge Manager\"\n );\n Pool memory newPool = Pool(\n tokenAddress,\n chainID,\n poolAddress,\n metaswap\n );\n _pool[tokenAddress][chainID] = newPool;\n return newPool;\n }\n}\n" + }, + "contracts/bridge/SynapseBridge.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.6.12;\n\nimport \"@openzeppelin/contracts-upgradeable/proxy/Initializable.sol\";\nimport \"@openzeppelin/contracts-upgradeable/access/AccessControlUpgradeable.sol\";\nimport \"@openzeppelin/contracts-upgradeable/utils/ReentrancyGuardUpgradeable.sol\";\nimport \"@openzeppelin/contracts-upgradeable/utils/PausableUpgradeable.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/SafeERC20.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/ERC20Burnable.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport \"@openzeppelin/contracts/math/SafeMath.sol\";\n\nimport \"./interfaces/ISwap.sol\";\nimport \"./interfaces/IWETH9.sol\";\n\ninterface IERC20Mintable is IERC20 {\n function mint(address to, uint256 amount) external;\n}\n\ncontract SynapseBridge is\n Initializable,\n AccessControlUpgradeable,\n ReentrancyGuardUpgradeable,\n PausableUpgradeable\n{\n using SafeERC20 for IERC20;\n using SafeERC20 for IERC20Mintable;\n using SafeMath for uint256;\n\n bytes32 public constant NODEGROUP_ROLE = keccak256(\"NODEGROUP_ROLE\");\n bytes32 public constant GOVERNANCE_ROLE = keccak256(\"GOVERNANCE_ROLE\");\n\n mapping(address => uint256) private fees;\n\n uint256 public startBlockNumber;\n uint256 public constant bridgeVersion = 6;\n uint256 public chainGasAmount;\n address payable public WETH_ADDRESS;\n\n mapping(bytes32 => bool) private kappaMap;\n\n receive() external payable {}\n\n function initialize() external initializer {\n startBlockNumber = block.number;\n _setupRole(DEFAULT_ADMIN_ROLE, msg.sender);\n __AccessControl_init();\n }\n\n function setChainGasAmount(uint256 amount) external {\n require(hasRole(GOVERNANCE_ROLE, msg.sender), \"Not governance\");\n chainGasAmount = amount;\n }\n\n function setWethAddress(address payable _wethAddress) external {\n require(hasRole(DEFAULT_ADMIN_ROLE, msg.sender), \"Not admin\");\n WETH_ADDRESS = _wethAddress;\n }\n\n function addKappas(bytes32[] calldata kappas) external {\n require(hasRole(GOVERNANCE_ROLE, msg.sender), \"Not governance\");\n for (uint256 i = 0; i < kappas.length; ++i) {\n kappaMap[kappas[i]] = true;\n }\n }\n\n event TokenDeposit(\n address indexed to,\n uint256 chainId,\n IERC20 token,\n uint256 amount\n );\n event TokenRedeem(\n address indexed to,\n uint256 chainId,\n IERC20 token,\n uint256 amount\n );\n event TokenWithdraw(\n address indexed to,\n IERC20 token,\n uint256 amount,\n uint256 fee,\n bytes32 indexed kappa\n );\n event TokenMint(\n address indexed to,\n IERC20Mintable token,\n uint256 amount,\n uint256 fee,\n bytes32 indexed kappa\n );\n event TokenDepositAndSwap(\n address indexed to,\n uint256 chainId,\n IERC20 token,\n uint256 amount,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 minDy,\n uint256 deadline\n );\n event TokenMintAndSwap(\n address indexed to,\n IERC20Mintable token,\n uint256 amount,\n uint256 fee,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 minDy,\n uint256 deadline,\n bool swapSuccess,\n bytes32 indexed kappa\n );\n event TokenRedeemAndSwap(\n address indexed to,\n uint256 chainId,\n IERC20 token,\n uint256 amount,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 minDy,\n uint256 deadline\n );\n event TokenRedeemAndRemove(\n address indexed to,\n uint256 chainId,\n IERC20 token,\n uint256 amount,\n uint8 swapTokenIndex,\n uint256 swapMinAmount,\n uint256 swapDeadline\n );\n event TokenWithdrawAndRemove(\n address indexed to,\n IERC20 token,\n uint256 amount,\n uint256 fee,\n uint8 swapTokenIndex,\n uint256 swapMinAmount,\n uint256 swapDeadline,\n bool swapSuccess,\n bytes32 indexed kappa\n );\n\n // v2 events\n event TokenRedeemV2(\n bytes32 indexed to,\n uint256 chainId,\n IERC20 token,\n uint256 amount\n );\n\n // VIEW FUNCTIONS ***/\n function getFeeBalance(address tokenAddress)\n external\n view\n returns (uint256)\n {\n return fees[tokenAddress];\n }\n\n function kappaExists(bytes32 kappa) external view returns (bool) {\n return kappaMap[kappa];\n }\n\n // FEE FUNCTIONS ***/\n /**\n * * @notice withdraw specified ERC20 token fees to a given address\n * * @param token ERC20 token in which fees acccumulated to transfer\n * * @param to Address to send the fees to\n */\n function withdrawFees(IERC20 token, address to) external whenNotPaused {\n require(hasRole(GOVERNANCE_ROLE, msg.sender), \"Not governance\");\n require(to != address(0), \"Address is 0x000\");\n if (fees[address(token)] != 0) {\n token.safeTransfer(to, fees[address(token)]);\n fees[address(token)] = 0;\n }\n }\n\n // PAUSABLE FUNCTIONS ***/\n function pause() external {\n require(hasRole(GOVERNANCE_ROLE, msg.sender), \"Not governance\");\n _pause();\n }\n\n function unpause() external {\n require(hasRole(GOVERNANCE_ROLE, msg.sender), \"Not governance\");\n _unpause();\n }\n\n /**\n * @notice Relays to nodes to transfers an ERC20 token cross-chain\n * @param to address on other chain to bridge assets to\n * @param chainId which chain to bridge assets onto\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n **/\n function deposit(\n address to,\n uint256 chainId,\n IERC20 token,\n uint256 amount\n ) external nonReentrant whenNotPaused {\n emit TokenDeposit(to, chainId, token, amount);\n token.safeTransferFrom(msg.sender, address(this), amount);\n }\n\n /**\n * @notice Relays to nodes that (typically) a wrapped synAsset ERC20 token has been burned and the underlying needs to be redeeemed on the native chain\n * @param to address on other chain to redeem underlying assets to\n * @param chainId which underlying chain to bridge assets onto\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n **/\n function redeem(\n address to,\n uint256 chainId,\n ERC20Burnable token,\n uint256 amount\n ) external nonReentrant whenNotPaused {\n emit TokenRedeem(to, chainId, token, amount);\n token.burnFrom(msg.sender, amount);\n }\n\n /**\n * @notice Function to be called by the node group to withdraw the underlying assets from the contract\n * @param to address on chain to send underlying assets to\n * @param token ERC20 compatible token to withdraw from the bridge\n * @param amount Amount in native token decimals to withdraw\n * @param fee Amount in native token decimals to save to the contract as fees\n * @param kappa kappa\n **/\n function withdraw(\n address to,\n IERC20 token,\n uint256 amount,\n uint256 fee,\n bytes32 kappa\n ) external nonReentrant whenNotPaused {\n require(\n hasRole(NODEGROUP_ROLE, msg.sender),\n \"Caller is not a node group\"\n );\n require(amount > fee, \"Amount must be greater than fee\");\n require(!kappaMap[kappa], \"Kappa is already present\");\n kappaMap[kappa] = true;\n fees[address(token)] = fees[address(token)].add(fee);\n if (address(token) == WETH_ADDRESS && WETH_ADDRESS != address(0)) {\n IWETH9(WETH_ADDRESS).withdraw(amount.sub(fee));\n (bool success, ) = to.call{value: amount.sub(fee)}(\"\");\n require(success, \"ETH_TRANSFER_FAILED\");\n emit TokenWithdraw(to, token, amount, fee, kappa);\n } else {\n emit TokenWithdraw(to, token, amount, fee, kappa);\n token.safeTransfer(to, amount.sub(fee));\n }\n }\n\n /**\n * @notice Nodes call this function to mint a SynERC20 (or any asset that the bridge is given minter access to). This is called by the nodes after a TokenDeposit event is emitted.\n * @dev This means the SynapseBridge.sol contract must have minter access to the token attempting to be minted\n * @param to address on other chain to redeem underlying assets to\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain post-fees\n * @param fee Amount in native token decimals to save to the contract as fees\n * @param kappa kappa\n **/\n function mint(\n address payable to,\n IERC20Mintable token,\n uint256 amount,\n uint256 fee,\n bytes32 kappa\n ) external nonReentrant whenNotPaused {\n require(\n hasRole(NODEGROUP_ROLE, msg.sender),\n \"Caller is not a node group\"\n );\n require(amount > fee, \"Amount must be greater than fee\");\n require(!kappaMap[kappa], \"Kappa is already present\");\n kappaMap[kappa] = true;\n fees[address(token)] = fees[address(token)].add(fee);\n emit TokenMint(to, token, amount.sub(fee), fee, kappa);\n token.mint(address(this), amount);\n IERC20(token).safeTransfer(to, amount.sub(fee));\n if (chainGasAmount != 0 && address(this).balance > chainGasAmount) {\n to.call.value(chainGasAmount)(\"\");\n }\n }\n\n /**\n * @notice Relays to nodes to both transfer an ERC20 token cross-chain, and then have the nodes execute a swap through a liquidity pool on behalf of the user.\n * @param to address on other chain to bridge assets to\n * @param chainId which chain to bridge assets onto\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n * @param tokenIndexFrom the token the user wants to swap from\n * @param tokenIndexTo the token the user wants to swap to\n * @param minDy the min amount the user would like to receive, or revert to only minting the SynERC20 token crosschain.\n * @param deadline latest timestamp to accept this transaction\n **/\n function depositAndSwap(\n address to,\n uint256 chainId,\n IERC20 token,\n uint256 amount,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 minDy,\n uint256 deadline\n ) external nonReentrant whenNotPaused {\n emit TokenDepositAndSwap(\n to,\n chainId,\n token,\n amount,\n tokenIndexFrom,\n tokenIndexTo,\n minDy,\n deadline\n );\n token.safeTransferFrom(msg.sender, address(this), amount);\n }\n\n /**\n * @notice Relays to nodes that (typically) a wrapped synAsset ERC20 token has been burned and the underlying needs to be redeeemed on the native chain. This function indicates to the nodes that they should attempt to redeem the LP token for the underlying assets (E.g \"swap\" out of the LP token)\n * @param to address on other chain to redeem underlying assets to\n * @param chainId which underlying chain to bridge assets onto\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n * @param tokenIndexFrom the token the user wants to swap from\n * @param tokenIndexTo the token the user wants to swap to\n * @param minDy the min amount the user would like to receive, or revert to only minting the SynERC20 token crosschain.\n * @param deadline latest timestamp to accept this transaction\n **/\n function redeemAndSwap(\n address to,\n uint256 chainId,\n ERC20Burnable token,\n uint256 amount,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 minDy,\n uint256 deadline\n ) external nonReentrant whenNotPaused {\n emit TokenRedeemAndSwap(\n to,\n chainId,\n token,\n amount,\n tokenIndexFrom,\n tokenIndexTo,\n minDy,\n deadline\n );\n token.burnFrom(msg.sender, amount);\n }\n\n /**\n * @notice Relays to nodes that (typically) a wrapped synAsset ERC20 token has been burned and the underlying needs to be redeeemed on the native chain. This function indicates to the nodes that they should attempt to redeem the LP token for the underlying assets (E.g \"swap\" out of the LP token)\n * @param to address on other chain to redeem underlying assets to\n * @param chainId which underlying chain to bridge assets onto\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n * @param swapTokenIndex Specifies which of the underlying LP assets the nodes should attempt to redeem for\n * @param swapMinAmount Specifies the minimum amount of the underlying asset needed for the nodes to execute the redeem/swap\n * @param swapDeadline Specificies the deadline that the nodes are allowed to try to redeem/swap the LP token\n **/\n function redeemAndRemove(\n address to,\n uint256 chainId,\n ERC20Burnable token,\n uint256 amount,\n uint8 swapTokenIndex,\n uint256 swapMinAmount,\n uint256 swapDeadline\n ) external nonReentrant whenNotPaused {\n emit TokenRedeemAndRemove(\n to,\n chainId,\n token,\n amount,\n swapTokenIndex,\n swapMinAmount,\n swapDeadline\n );\n token.burnFrom(msg.sender, amount);\n }\n\n /**\n * @notice Nodes call this function to mint a SynERC20 (or any asset that the bridge is given minter access to), and then attempt to swap the SynERC20 into the desired destination asset. This is called by the nodes after a TokenDepositAndSwap event is emitted.\n * @dev This means the BridgeDeposit.sol contract must have minter access to the token attempting to be minted\n * @param to address on other chain to redeem underlying assets to\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain post-fees\n * @param fee Amount in native token decimals to save to the contract as fees\n * @param pool Destination chain's pool to use to swap SynERC20 -> Asset. The nodes determine this by using PoolConfig.sol.\n * @param tokenIndexFrom Index of the SynERC20 asset in the pool\n * @param tokenIndexTo Index of the desired final asset\n * @param minDy Minumum amount (in final asset decimals) that must be swapped for, otherwise the user will receive the SynERC20.\n * @param deadline Epoch time of the deadline that the swap is allowed to be executed.\n * @param kappa kappa\n **/\n function mintAndSwap(\n address payable to,\n IERC20Mintable token,\n uint256 amount,\n uint256 fee,\n ISwap pool,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 minDy,\n uint256 deadline,\n bytes32 kappa\n ) external nonReentrant whenNotPaused {\n require(\n hasRole(NODEGROUP_ROLE, msg.sender),\n \"Caller is not a node group\"\n );\n require(amount > fee, \"Amount must be greater than fee\");\n require(!kappaMap[kappa], \"Kappa is already present\");\n kappaMap[kappa] = true;\n fees[address(token)] = fees[address(token)].add(fee);\n // Transfer gas airdrop\n if (chainGasAmount != 0 && address(this).balance > chainGasAmount) {\n to.call.value(chainGasAmount)(\"\");\n }\n // first check to make sure more will be given than min amount required\n uint256 expectedOutput = ISwap(pool).calculateSwap(\n tokenIndexFrom,\n tokenIndexTo,\n amount.sub(fee)\n );\n\n if (expectedOutput >= minDy) {\n // proceed with swap\n token.mint(address(this), amount);\n token.safeIncreaseAllowance(address(pool), amount);\n try\n ISwap(pool).swap(\n tokenIndexFrom,\n tokenIndexTo,\n amount.sub(fee),\n minDy,\n deadline\n )\n returns (uint256 finalSwappedAmount) {\n // Swap succeeded, transfer swapped asset\n IERC20 swappedTokenTo = ISwap(pool).getToken(tokenIndexTo);\n if (\n address(swappedTokenTo) == WETH_ADDRESS &&\n WETH_ADDRESS != address(0)\n ) {\n IWETH9(WETH_ADDRESS).withdraw(finalSwappedAmount);\n (bool success, ) = to.call{value: finalSwappedAmount}(\"\");\n require(success, \"ETH_TRANSFER_FAILED\");\n emit TokenMintAndSwap(\n to,\n token,\n finalSwappedAmount,\n fee,\n tokenIndexFrom,\n tokenIndexTo,\n minDy,\n deadline,\n true,\n kappa\n );\n } else {\n swappedTokenTo.safeTransfer(to, finalSwappedAmount);\n emit TokenMintAndSwap(\n to,\n token,\n finalSwappedAmount,\n fee,\n tokenIndexFrom,\n tokenIndexTo,\n minDy,\n deadline,\n true,\n kappa\n );\n }\n } catch {\n IERC20(token).safeTransfer(to, amount.sub(fee));\n emit TokenMintAndSwap(\n to,\n token,\n amount.sub(fee),\n fee,\n tokenIndexFrom,\n tokenIndexTo,\n minDy,\n deadline,\n false,\n kappa\n );\n }\n } else {\n token.mint(address(this), amount);\n IERC20(token).safeTransfer(to, amount.sub(fee));\n emit TokenMintAndSwap(\n to,\n token,\n amount.sub(fee),\n fee,\n tokenIndexFrom,\n tokenIndexTo,\n minDy,\n deadline,\n false,\n kappa\n );\n }\n }\n\n /**\n * @notice Function to be called by the node group to withdraw the underlying assets from the contract\n * @param to address on chain to send underlying assets to\n * @param token ERC20 compatible token to withdraw from the bridge\n * @param amount Amount in native token decimals to withdraw\n * @param fee Amount in native token decimals to save to the contract as fees\n * @param pool Destination chain's pool to use to swap SynERC20 -> Asset. The nodes determine this by using PoolConfig.sol.\n * @param swapTokenIndex Specifies which of the underlying LP assets the nodes should attempt to redeem for\n * @param swapMinAmount Specifies the minimum amount of the underlying asset needed for the nodes to execute the redeem/swap\n * @param swapDeadline Specificies the deadline that the nodes are allowed to try to redeem/swap the LP token\n * @param kappa kappa\n **/\n function withdrawAndRemove(\n address to,\n IERC20 token,\n uint256 amount,\n uint256 fee,\n ISwap pool,\n uint8 swapTokenIndex,\n uint256 swapMinAmount,\n uint256 swapDeadline,\n bytes32 kappa\n ) external nonReentrant whenNotPaused {\n require(\n hasRole(NODEGROUP_ROLE, msg.sender),\n \"Caller is not a node group\"\n );\n require(amount > fee, \"Amount must be greater than fee\");\n require(!kappaMap[kappa], \"Kappa is already present\");\n kappaMap[kappa] = true;\n fees[address(token)] = fees[address(token)].add(fee);\n // first check to make sure more will be given than min amount required\n uint256 expectedOutput = ISwap(pool).calculateRemoveLiquidityOneToken(\n amount.sub(fee),\n swapTokenIndex\n );\n\n if (expectedOutput >= swapMinAmount) {\n token.safeIncreaseAllowance(address(pool), amount.sub(fee));\n try\n ISwap(pool).removeLiquidityOneToken(\n amount.sub(fee),\n swapTokenIndex,\n swapMinAmount,\n swapDeadline\n )\n returns (uint256 finalSwappedAmount) {\n // Swap succeeded, transfer swapped asset\n IERC20 swappedTokenTo = ISwap(pool).getToken(swapTokenIndex);\n swappedTokenTo.safeTransfer(to, finalSwappedAmount);\n emit TokenWithdrawAndRemove(\n to,\n token,\n finalSwappedAmount,\n fee,\n swapTokenIndex,\n swapMinAmount,\n swapDeadline,\n true,\n kappa\n );\n } catch {\n IERC20(token).safeTransfer(to, amount.sub(fee));\n emit TokenWithdrawAndRemove(\n to,\n token,\n amount.sub(fee),\n fee,\n swapTokenIndex,\n swapMinAmount,\n swapDeadline,\n false,\n kappa\n );\n }\n } else {\n token.safeTransfer(to, amount.sub(fee));\n emit TokenWithdrawAndRemove(\n to,\n token,\n amount.sub(fee),\n fee,\n swapTokenIndex,\n swapMinAmount,\n swapDeadline,\n false,\n kappa\n );\n }\n }\n\n // BRIDGE FUNCTIONS TO HANDLE DIFF ADDRESSES\n /**\n * @notice Relays to nodes that (typically) a wrapped synAsset ERC20 token has been burned and the underlying needs to be redeeemed on the native chain\n * @param to address on other chain to redeem underlying assets to\n * @param chainId which underlying chain to bridge assets onto\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n **/\n function redeemV2(\n bytes32 to,\n uint256 chainId,\n ERC20Burnable token,\n uint256 amount\n ) external nonReentrant whenNotPaused {\n emit TokenRedeemV2(to, chainId, token, amount);\n token.burnFrom(msg.sender, amount);\n }\n}\n" + }, + "@openzeppelin/contracts-upgradeable/access/AccessControlUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <0.8.0;\n\nimport \"../utils/EnumerableSetUpgradeable.sol\";\nimport \"../utils/AddressUpgradeable.sol\";\nimport \"../utils/ContextUpgradeable.sol\";\nimport \"../proxy/Initializable.sol\";\n\n/**\n * @dev Contract module that allows children to implement role-based access\n * control mechanisms.\n *\n * Roles are referred to by their `bytes32` identifier. These should be exposed\n * in the external API and be unique. The best way to achieve this is by\n * using `public constant` hash digests:\n *\n * ```\n * bytes32 public constant MY_ROLE = keccak256(\"MY_ROLE\");\n * ```\n *\n * Roles can be used to represent a set of permissions. To restrict access to a\n * function call, use {hasRole}:\n *\n * ```\n * function foo() public {\n * require(hasRole(MY_ROLE, msg.sender));\n * ...\n * }\n * ```\n *\n * Roles can be granted and revoked dynamically via the {grantRole} and\n * {revokeRole} functions. Each role has an associated admin role, and only\n * accounts that have a role's admin role can call {grantRole} and {revokeRole}.\n *\n * By default, the admin role for all roles is `DEFAULT_ADMIN_ROLE`, which means\n * that only accounts with this role will be able to grant or revoke other\n * roles. More complex role relationships can be created by using\n * {_setRoleAdmin}.\n *\n * WARNING: The `DEFAULT_ADMIN_ROLE` is also its own admin: it has permission to\n * grant and revoke this role. Extra precautions should be taken to secure\n * accounts that have been granted it.\n */\nabstract contract AccessControlUpgradeable is Initializable, ContextUpgradeable {\n function __AccessControl_init() internal initializer {\n __Context_init_unchained();\n __AccessControl_init_unchained();\n }\n\n function __AccessControl_init_unchained() internal initializer {\n }\n using EnumerableSetUpgradeable for EnumerableSetUpgradeable.AddressSet;\n using AddressUpgradeable for address;\n\n struct RoleData {\n EnumerableSetUpgradeable.AddressSet members;\n bytes32 adminRole;\n }\n\n mapping (bytes32 => RoleData) private _roles;\n\n bytes32 public constant DEFAULT_ADMIN_ROLE = 0x00;\n\n /**\n * @dev Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole`\n *\n * `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite\n * {RoleAdminChanged} not being emitted signaling this.\n *\n * _Available since v3.1._\n */\n event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole);\n\n /**\n * @dev Emitted when `account` is granted `role`.\n *\n * `sender` is the account that originated the contract call, an admin role\n * bearer except when using {_setupRole}.\n */\n event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender);\n\n /**\n * @dev Emitted when `account` is revoked `role`.\n *\n * `sender` is the account that originated the contract call:\n * - if using `revokeRole`, it is the admin role bearer\n * - if using `renounceRole`, it is the role bearer (i.e. `account`)\n */\n event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender);\n\n /**\n * @dev Returns `true` if `account` has been granted `role`.\n */\n function hasRole(bytes32 role, address account) public view returns (bool) {\n return _roles[role].members.contains(account);\n }\n\n /**\n * @dev Returns the number of accounts that have `role`. Can be used\n * together with {getRoleMember} to enumerate all bearers of a role.\n */\n function getRoleMemberCount(bytes32 role) public view returns (uint256) {\n return _roles[role].members.length();\n }\n\n /**\n * @dev Returns one of the accounts that have `role`. `index` must be a\n * value between 0 and {getRoleMemberCount}, non-inclusive.\n *\n * Role bearers are not sorted in any particular way, and their ordering may\n * change at any point.\n *\n * WARNING: When using {getRoleMember} and {getRoleMemberCount}, make sure\n * you perform all queries on the same block. See the following\n * https://forum.openzeppelin.com/t/iterating-over-elements-on-enumerableset-in-openzeppelin-contracts/2296[forum post]\n * for more information.\n */\n function getRoleMember(bytes32 role, uint256 index) public view returns (address) {\n return _roles[role].members.at(index);\n }\n\n /**\n * @dev Returns the admin role that controls `role`. See {grantRole} and\n * {revokeRole}.\n *\n * To change a role's admin, use {_setRoleAdmin}.\n */\n function getRoleAdmin(bytes32 role) public view returns (bytes32) {\n return _roles[role].adminRole;\n }\n\n /**\n * @dev Grants `role` to `account`.\n *\n * If `account` had not been already granted `role`, emits a {RoleGranted}\n * event.\n *\n * Requirements:\n *\n * - the caller must have ``role``'s admin role.\n */\n function grantRole(bytes32 role, address account) public virtual {\n require(hasRole(_roles[role].adminRole, _msgSender()), \"AccessControl: sender must be an admin to grant\");\n\n _grantRole(role, account);\n }\n\n /**\n * @dev Revokes `role` from `account`.\n *\n * If `account` had been granted `role`, emits a {RoleRevoked} event.\n *\n * Requirements:\n *\n * - the caller must have ``role``'s admin role.\n */\n function revokeRole(bytes32 role, address account) public virtual {\n require(hasRole(_roles[role].adminRole, _msgSender()), \"AccessControl: sender must be an admin to revoke\");\n\n _revokeRole(role, account);\n }\n\n /**\n * @dev Revokes `role` from the calling account.\n *\n * Roles are often managed via {grantRole} and {revokeRole}: this function's\n * purpose is to provide a mechanism for accounts to lose their privileges\n * if they are compromised (such as when a trusted device is misplaced).\n *\n * If the calling account had been granted `role`, emits a {RoleRevoked}\n * event.\n *\n * Requirements:\n *\n * - the caller must be `account`.\n */\n function renounceRole(bytes32 role, address account) public virtual {\n require(account == _msgSender(), \"AccessControl: can only renounce roles for self\");\n\n _revokeRole(role, account);\n }\n\n /**\n * @dev Grants `role` to `account`.\n *\n * If `account` had not been already granted `role`, emits a {RoleGranted}\n * event. Note that unlike {grantRole}, this function doesn't perform any\n * checks on the calling account.\n *\n * [WARNING]\n * ====\n * This function should only be called from the constructor when setting\n * up the initial roles for the system.\n *\n * Using this function in any other way is effectively circumventing the admin\n * system imposed by {AccessControl}.\n * ====\n */\n function _setupRole(bytes32 role, address account) internal virtual {\n _grantRole(role, account);\n }\n\n /**\n * @dev Sets `adminRole` as ``role``'s admin role.\n *\n * Emits a {RoleAdminChanged} event.\n */\n function _setRoleAdmin(bytes32 role, bytes32 adminRole) internal virtual {\n emit RoleAdminChanged(role, _roles[role].adminRole, adminRole);\n _roles[role].adminRole = adminRole;\n }\n\n function _grantRole(bytes32 role, address account) private {\n if (_roles[role].members.add(account)) {\n emit RoleGranted(role, account, _msgSender());\n }\n }\n\n function _revokeRole(bytes32 role, address account) private {\n if (_roles[role].members.remove(account)) {\n emit RoleRevoked(role, account, _msgSender());\n }\n }\n uint256[49] private __gap;\n}\n" + }, + "@openzeppelin/contracts-upgradeable/utils/EnumerableSetUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <0.8.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 EnumerableSetUpgradeable {\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" + }, + "contracts/bridge/wrappers/HarmonyBridgeZap.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.6.12;\n\nimport \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/SafeERC20.sol\";\nimport \"../interfaces/ISwap.sol\";\nimport \"../interfaces/ISynapseBridge.sol\";\nimport \"../interfaces/IWETH9.sol\";\n\ninterface IFrax {\n function exchangeCanonicalForOld(address bridge_token_address, uint256 token_amount) external returns (uint256);\n}\n\ncontract HarmonyBridgeZap {\n using SafeERC20 for IERC20;\n\n ISynapseBridge synapseBridge;\n address payable public immutable WETH_ADDRESS;\n IFrax private constant CANOLICAL_FRAX = IFrax(0xFa7191D292d5633f702B0bd7E3E3BcCC0e633200);\n IERC20 private constant SYN_FRAX = IERC20(0x1852F70512298d56e9c8FDd905e02581E04ddb2a);\n\n mapping(address => address) public swapMap;\n mapping(address => IERC20[]) public swapTokensMap;\n\n uint256 constant MAX_UINT256 = 2**256 - 1;\n\n constructor(\n address payable _wethAddress,\n address _swapOne,\n address tokenOne,\n address _swapTwo,\n address tokenTwo,\n ISynapseBridge _synapseBridge\n ) public {\n WETH_ADDRESS = _wethAddress;\n synapseBridge = _synapseBridge;\n swapMap[tokenOne] = _swapOne;\n swapMap[tokenTwo] = _swapTwo;\n\n if (address(_swapOne) != address(0)) {\n {\n uint8 i;\n for (; i < 32; i++) {\n try ISwap(_swapOne).getToken(i) returns (\n IERC20 token\n ) {\n swapTokensMap[_swapOne].push(token);\n token.safeApprove(address(_swapOne), MAX_UINT256);\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n } catch {\n break;\n }\n }\n require(i > 1, \"swap must have at least 2 tokens\");\n }\n }\n if (address(_swapTwo) != address(0)) {\n {\n uint8 i;\n for (; i < 32; i++) {\n try ISwap(_swapTwo).getToken(i) returns (\n IERC20 token\n ) {\n swapTokensMap[_swapTwo].push(token);\n token.safeApprove(address(_swapTwo), MAX_UINT256);\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n } catch {\n break;\n }\n }\n require(i > 1, \"swap must have at least 2 tokens\");\n }\n }\n }\n\n /**\n * @notice Calculate amount of tokens you receive on swap\n * @param tokenIndexFrom the token the user wants to sell\n * @param tokenIndexTo the token the user wants to buy\n * @param dx the amount of tokens the user wants to sell. If the token charges\n * a fee on transfers, use the amount that gets transferred after the fee.\n * @return amount of tokens the user will receive\n */\n function calculateSwap(\n IERC20 token,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx\n ) external view virtual returns (uint256) {\n ISwap swap = ISwap(\n swapMap[address(token)]\n );\n return swap.calculateSwap(tokenIndexFrom, tokenIndexTo, dx);\n }\n\n function swapAndRedeem(\n address to,\n uint256 chainId,\n IERC20 token,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx,\n uint256 minDy,\n uint256 deadline\n ) external {\n ISwap swap = ISwap(swapMap[address(token)]);\n require(address(swap) != address(0), \"Swap is 0x00\");\n IERC20[] memory tokens = swapTokensMap[address(swap)];\n tokens[tokenIndexFrom].safeTransferFrom(\n msg.sender,\n address(this),\n dx\n );\n // swap\n\n uint256 swappedAmount = swap.swap(\n tokenIndexFrom,\n tokenIndexTo,\n dx,\n minDy,\n deadline\n );\n // deposit into bridge, gets nUSD\n if (\n token.allowance(address(this), address(synapseBridge)) <\n swappedAmount\n ) {\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n }\n synapseBridge.redeem(to, chainId, token, swappedAmount);\n }\n\n function swapAndRedeemAndSwap(\n address to,\n uint256 chainId,\n IERC20 token,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx,\n uint256 minDy,\n uint256 deadline,\n uint8 swapTokenIndexFrom,\n uint8 swapTokenIndexTo,\n uint256 swapMinDy,\n uint256 swapDeadline\n ) external {\n require(\n address(swapMap[address(token)]) != address(0),\n \"Swap is 0x00\"\n );\n IERC20[] memory tokens = swapTokensMap[\n swapMap[address(token)]\n ];\n tokens[tokenIndexFrom].safeTransferFrom(\n msg.sender,\n address(this),\n dx\n );\n // swap\n\n uint256 swappedAmount = ISwap(swapMap[address(token)]).swap(tokenIndexFrom, tokenIndexTo, dx, minDy, deadline);\n // deposit into bridge, gets nUSD\n if (\n token.allowance(address(this), address(synapseBridge)) <\n swappedAmount\n ) {\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n }\n synapseBridge.redeemAndSwap(\n to,\n chainId,\n token,\n swappedAmount,\n swapTokenIndexFrom,\n swapTokenIndexTo,\n swapMinDy,\n swapDeadline\n );\n }\n\n function swapAndRedeemAndRemove(\n address to,\n uint256 chainId,\n IERC20 token,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx,\n uint256 minDy,\n uint256 deadline,\n uint8 liqTokenIndex,\n uint256 liqMinAmount,\n uint256 liqDeadline\n ) external {\n ISwap swap = ISwap(swapMap[address(token)]);\n require(address(swap) != address(0), \"Swap is 0x00\");\n IERC20[] memory tokens = swapTokensMap[address(swap)];\n tokens[tokenIndexFrom].safeTransferFrom(\n msg.sender,\n address(this),\n dx\n );\n // swap\n\n uint256 swappedAmount = swap.swap(\n tokenIndexFrom,\n tokenIndexTo,\n dx,\n minDy,\n deadline\n );\n // deposit into bridge, gets nUSD\n if (\n token.allowance(address(this), address(synapseBridge)) <\n swappedAmount\n ) {\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n }\n synapseBridge.redeemAndRemove(\n to,\n chainId,\n token,\n swappedAmount,\n liqTokenIndex,\n liqMinAmount,\n liqDeadline\n );\n }\n\n /**\n * @notice wraps SynapseBridge redeem()\n * @param to address on other chain to redeem underlying assets to\n * @param chainId which underlying chain to bridge assets onto\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n **/\n function redeem(\n address to,\n uint256 chainId,\n IERC20 token,\n uint256 amount\n ) external {\n token.safeTransferFrom(msg.sender, address(this), amount);\n if (address(token) == address(CANOLICAL_FRAX)) {\n uint256 swappedAmount = CANOLICAL_FRAX.exchangeCanonicalForOld(address(SYN_FRAX), amount);\n if (SYN_FRAX.allowance(address(this), address(synapseBridge)) < amount) {\n SYN_FRAX.safeApprove(address(synapseBridge), MAX_UINT256);\n }\n synapseBridge.redeem(to, chainId, SYN_FRAX, swappedAmount);\n } else {\n if (token.allowance(address(this), address(synapseBridge)) < amount) {\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n }\n synapseBridge.redeem(to, chainId, token, amount);\n }\n \n }\n\n /**\n * @notice Wraps SynapseBridge redeemv2() function\n * @param to address on other chain to bridge assets to\n * @param chainId which chain to bridge assets onto\n * @param token ERC20 compatible token to redeem into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n **/\n function redeemv2(\n bytes32 to,\n uint256 chainId,\n IERC20 token,\n uint256 amount\n ) external {\n token.safeTransferFrom(msg.sender, address(this), amount);\n\n if (token.allowance(address(this), address(synapseBridge)) < amount) {\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n }\n synapseBridge.redeemv2(to, chainId, token, amount);\n }\n\n /**\n * @notice wraps SynapseBridge redeem()\n * @param to address on other chain to redeem underlying assets to\n * @param chainId which underlying chain to bridge assets onto\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n **/\n function deposit(\n address to,\n uint256 chainId,\n IERC20 token,\n uint256 amount\n ) external {\n token.safeTransferFrom(msg.sender, address(this), amount);\n if (token.allowance(address(this), address(synapseBridge)) < amount) {\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n }\n synapseBridge.deposit(to, chainId, token, amount);\n }\n\n function swapETHAndRedeem(\n address to,\n uint256 chainId,\n IERC20 token,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx,\n uint256 minDy,\n uint256 deadline\n ) external payable {\n require(WETH_ADDRESS != address(0), \"WETH 0\");\n require(msg.value > 0 && msg.value == dx, \"INCORRECT MSG VALUE\");\n ISwap swap = ISwap(swapMap[address(token)]);\n require(address(swap) != address(0), \"Swap is 0x00\");\n IWETH9(WETH_ADDRESS).deposit{value: msg.value}();\n\n // swap\n uint256 swappedAmount = swap.swap(\n tokenIndexFrom,\n tokenIndexTo,\n dx,\n minDy,\n deadline\n );\n synapseBridge.redeem(to, chainId, token, swappedAmount);\n }\n\n /**\n * @notice Wraps redeemAndSwap on SynapseBridge.sol\n * Relays to nodes that (typically) a wrapped synAsset ERC20 token has been burned and the underlying needs to be redeeemed on the native chain. This function indicates to the nodes that they should attempt to redeem the LP token for the underlying assets (E.g \"swap\" out of the LP token)\n * @param to address on other chain to redeem underlying assets to\n * @param chainId which underlying chain to bridge assets onto\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n * @param tokenIndexFrom the token the user wants to swap from\n * @param tokenIndexTo the token the user wants to swap to\n * @param minDy the min amount the user would like to receive, or revert to only minting the SynERC20 token crosschain.\n * @param deadline latest timestamp to accept this transaction\n **/\n function redeemAndSwap(\n address to,\n uint256 chainId,\n IERC20 token,\n uint256 amount,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 minDy,\n uint256 deadline\n ) external {\n token.safeTransferFrom(msg.sender, address(this), amount);\n if (token.allowance(address(this), address(synapseBridge)) < amount) {\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n }\n synapseBridge.redeemAndSwap(\n to,\n chainId,\n token,\n amount,\n tokenIndexFrom,\n tokenIndexTo,\n minDy,\n deadline\n );\n }\n\n /**\n * @notice Wraps redeemAndRemove on SynapseBridge\n * Relays to nodes that (typically) a wrapped synAsset ERC20 token has been burned and the underlying needs to be redeeemed on the native chain. This function indicates to the nodes that they should attempt to redeem the LP token for the underlying assets (E.g \"swap\" out of the LP token)\n * @param to address on other chain to redeem underlying assets to\n * @param chainId which underlying chain to bridge assets onto\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount of (typically) LP token to pass to the nodes to attempt to removeLiquidity() with to redeem for the underlying assets of the LP token\n * @param liqTokenIndex Specifies which of the underlying LP assets the nodes should attempt to redeem for\n * @param liqMinAmount Specifies the minimum amount of the underlying asset needed for the nodes to execute the redeem/swap\n * @param liqDeadline Specificies the deadline that the nodes are allowed to try to redeem/swap the LP token\n **/\n function redeemAndRemove(\n address to,\n uint256 chainId,\n IERC20 token,\n uint256 amount,\n uint8 liqTokenIndex,\n uint256 liqMinAmount,\n uint256 liqDeadline\n ) external {\n token.safeTransferFrom(msg.sender, address(this), amount);\n if (token.allowance(address(this), address(synapseBridge)) < amount) {\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n }\n synapseBridge.redeemAndRemove(\n to,\n chainId,\n token,\n amount,\n liqTokenIndex,\n liqMinAmount,\n liqDeadline\n );\n }\n}\n" + }, + "contracts/bridge/MoonriverSynapseBridge.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.6.12;\n\nimport \"@openzeppelin/contracts-upgradeable/proxy/Initializable.sol\";\nimport \"@openzeppelin/contracts-upgradeable/access/AccessControlUpgradeable.sol\";\nimport \"@openzeppelin/contracts-upgradeable/utils/ReentrancyGuardUpgradeable.sol\";\nimport \"@openzeppelin/contracts-upgradeable/utils/PausableUpgradeable.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/SafeERC20.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/ERC20Burnable.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport \"@openzeppelin/contracts/math/SafeMath.sol\";\n\nimport \"./interfaces/ISwap.sol\";\nimport \"./interfaces/IWETH9.sol\";\n\ninterface IERC20Mintable is IERC20 {\n function mint(address to, uint256 amount) external;\n}\n\ninterface IFrax {\n function exchangeOldForCanonical(\n address bridge_token_address,\n uint256 token_amount\n ) external returns (uint256);\n}\n\ncontract MRSynapseBridge is\n Initializable,\n AccessControlUpgradeable,\n ReentrancyGuardUpgradeable,\n PausableUpgradeable\n{\n using SafeERC20 for IERC20;\n using SafeERC20 for IERC20Mintable;\n using SafeMath for uint256;\n\n bytes32 public constant NODEGROUP_ROLE = keccak256(\"NODEGROUP_ROLE\");\n bytes32 public constant GOVERNANCE_ROLE = keccak256(\"GOVERNANCE_ROLE\");\n\n mapping(address => uint256) private fees;\n\n uint256 public startBlockNumber;\n uint256 public constant bridgeVersion = 6;\n uint256 public chainGasAmount;\n address payable public WETH_ADDRESS;\n\n mapping(bytes32 => bool) private kappaMap;\n\n receive() external payable {}\n\n function initialize() external initializer {\n startBlockNumber = block.number;\n _setupRole(DEFAULT_ADMIN_ROLE, msg.sender);\n __AccessControl_init();\n }\n\n function setChainGasAmount(uint256 amount) external {\n require(hasRole(GOVERNANCE_ROLE, msg.sender), \"Not governance\");\n chainGasAmount = amount;\n }\n\n function setWethAddress(address payable _wethAddress) external {\n require(hasRole(DEFAULT_ADMIN_ROLE, msg.sender), \"Not admin\");\n WETH_ADDRESS = _wethAddress;\n }\n\n function addKappas(bytes32[] calldata kappas) external {\n require(hasRole(GOVERNANCE_ROLE, msg.sender), \"Not governance\");\n for (uint256 i = 0; i < kappas.length; ++i) {\n kappaMap[kappas[i]] = true;\n }\n }\n\n event TokenDeposit(\n address indexed to,\n uint256 chainId,\n IERC20 token,\n uint256 amount\n );\n event TokenRedeem(\n address indexed to,\n uint256 chainId,\n IERC20 token,\n uint256 amount\n );\n event TokenWithdraw(\n address indexed to,\n IERC20 token,\n uint256 amount,\n uint256 fee,\n bytes32 indexed kappa\n );\n event TokenMint(\n address indexed to,\n IERC20Mintable token,\n uint256 amount,\n uint256 fee,\n bytes32 indexed kappa\n );\n event TokenDepositAndSwap(\n address indexed to,\n uint256 chainId,\n IERC20 token,\n uint256 amount,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 minDy,\n uint256 deadline\n );\n event TokenMintAndSwap(\n address indexed to,\n IERC20Mintable token,\n uint256 amount,\n uint256 fee,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 minDy,\n uint256 deadline,\n bool swapSuccess,\n bytes32 indexed kappa\n );\n event TokenRedeemAndSwap(\n address indexed to,\n uint256 chainId,\n IERC20 token,\n uint256 amount,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 minDy,\n uint256 deadline\n );\n event TokenRedeemAndRemove(\n address indexed to,\n uint256 chainId,\n IERC20 token,\n uint256 amount,\n uint8 swapTokenIndex,\n uint256 swapMinAmount,\n uint256 swapDeadline\n );\n event TokenWithdrawAndRemove(\n address indexed to,\n IERC20 token,\n uint256 amount,\n uint256 fee,\n uint8 swapTokenIndex,\n uint256 swapMinAmount,\n uint256 swapDeadline,\n bool swapSuccess,\n bytes32 indexed kappa\n );\n\n // v2 events\n event TokenRedeemV2(\n bytes32 indexed to,\n uint256 chainId,\n IERC20 token,\n uint256 amount\n );\n\n // VIEW FUNCTIONS ***/\n function getFeeBalance(address tokenAddress)\n external\n view\n returns (uint256)\n {\n return fees[tokenAddress];\n }\n\n function kappaExists(bytes32 kappa) external view returns (bool) {\n return kappaMap[kappa];\n }\n\n // FEE FUNCTIONS ***/\n /**\n * * @notice withdraw specified ERC20 token fees to a given address\n * * @param token ERC20 token in which fees acccumulated to transfer\n * * @param to Address to send the fees to\n */\n function withdrawFees(IERC20 token, address to) external whenNotPaused {\n require(hasRole(GOVERNANCE_ROLE, msg.sender), \"Not governance\");\n require(to != address(0), \"Address is 0x000\");\n if (fees[address(token)] != 0) {\n token.safeTransfer(to, fees[address(token)]);\n fees[address(token)] = 0;\n }\n }\n\n // PAUSABLE FUNCTIONS ***/\n function pause() external {\n require(hasRole(GOVERNANCE_ROLE, msg.sender), \"Not governance\");\n _pause();\n }\n\n function unpause() external {\n require(hasRole(GOVERNANCE_ROLE, msg.sender), \"Not governance\");\n _unpause();\n }\n\n /**\n * @notice Relays to nodes to transfers an ERC20 token cross-chain\n * @param to address on other chain to bridge assets to\n * @param chainId which chain to bridge assets onto\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n **/\n function deposit(\n address to,\n uint256 chainId,\n IERC20 token,\n uint256 amount\n ) external nonReentrant whenNotPaused {\n emit TokenDeposit(to, chainId, token, amount);\n token.safeTransferFrom(msg.sender, address(this), amount);\n }\n\n /**\n * @notice Relays to nodes that (typically) a wrapped synAsset ERC20 token has been burned and the underlying needs to be redeeemed on the native chain\n * @param to address on other chain to redeem underlying assets to\n * @param chainId which underlying chain to bridge assets onto\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n **/\n function redeem(\n address to,\n uint256 chainId,\n ERC20Burnable token,\n uint256 amount\n ) external nonReentrant whenNotPaused {\n emit TokenRedeem(to, chainId, token, amount);\n token.burnFrom(msg.sender, amount);\n }\n\n /**\n * @notice Function to be called by the node group to withdraw the underlying assets from the contract\n * @param to address on chain to send underlying assets to\n * @param token ERC20 compatible token to withdraw from the bridge\n * @param amount Amount in native token decimals to withdraw\n * @param fee Amount in native token decimals to save to the contract as fees\n * @param kappa kappa\n **/\n function withdraw(\n address to,\n IERC20 token,\n uint256 amount,\n uint256 fee,\n bytes32 kappa\n ) external nonReentrant whenNotPaused {\n require(\n hasRole(NODEGROUP_ROLE, msg.sender),\n \"Caller is not a node group\"\n );\n require(amount > fee, \"Amount must be greater than fee\");\n require(!kappaMap[kappa], \"Kappa is already present\");\n kappaMap[kappa] = true;\n fees[address(token)] = fees[address(token)].add(fee);\n if (address(token) == WETH_ADDRESS && WETH_ADDRESS != address(0)) {\n IWETH9(WETH_ADDRESS).withdraw(amount.sub(fee));\n (bool success, ) = to.call{value: amount.sub(fee)}(\"\");\n require(success, \"ETH_TRANSFER_FAILED\");\n emit TokenWithdraw(to, token, amount, fee, kappa);\n } else {\n emit TokenWithdraw(to, token, amount, fee, kappa);\n token.safeTransfer(to, amount.sub(fee));\n }\n }\n\n /**\n * @notice Nodes call this function to mint a SynERC20 (or any asset that the bridge is given minter access to). This is called by the nodes after a TokenDeposit event is emitted.\n * @dev This means the SynapseBridge.sol contract must have minter access to the token attempting to be minted\n * @param to address on other chain to redeem underlying assets to\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain post-fees\n * @param fee Amount in native token decimals to save to the contract as fees\n * @param kappa kappa\n **/\n function mint(\n address payable to,\n IERC20Mintable token,\n uint256 amount,\n uint256 fee,\n bytes32 kappa\n ) external nonReentrant whenNotPaused {\n require(\n hasRole(NODEGROUP_ROLE, msg.sender),\n \"Caller is not a node group\"\n );\n require(amount > fee, \"Amount must be greater than fee\");\n require(!kappaMap[kappa], \"Kappa is already present\");\n kappaMap[kappa] = true;\n fees[address(token)] = fees[address(token)].add(fee);\n emit TokenMint(to, token, amount.sub(fee), fee, kappa);\n token.mint(address(this), amount);\n // checks if synFRAX\n if (address(token) == 0xE96AC70907ffF3Efee79f502C985A7A21Bce407d) {\n token.safeIncreaseAllowance(\n 0x1A93B23281CC1CDE4C4741353F3064709A16197d,\n amount.sub(fee)\n );\n try\n IFrax(0x1A93B23281CC1CDE4C4741353F3064709A16197d)\n .exchangeOldForCanonical(address(token), amount.sub(fee))\n returns (uint256 canolical_tokens_out) {\n IERC20(0x1A93B23281CC1CDE4C4741353F3064709A16197d).safeTransfer(\n to,\n canolical_tokens_out\n );\n } catch {\n IERC20(token).safeTransfer(to, amount.sub(fee));\n }\n } else {\n IERC20(token).safeTransfer(to, amount.sub(fee));\n }\n if (chainGasAmount != 0 && address(this).balance > chainGasAmount) {\n to.call.value(chainGasAmount)(\"\");\n }\n }\n\n /**\n * @notice Relays to nodes to both transfer an ERC20 token cross-chain, and then have the nodes execute a swap through a liquidity pool on behalf of the user.\n * @param to address on other chain to bridge assets to\n * @param chainId which chain to bridge assets onto\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n * @param tokenIndexFrom the token the user wants to swap from\n * @param tokenIndexTo the token the user wants to swap to\n * @param minDy the min amount the user would like to receive, or revert to only minting the SynERC20 token crosschain.\n * @param deadline latest timestamp to accept this transaction\n **/\n function depositAndSwap(\n address to,\n uint256 chainId,\n IERC20 token,\n uint256 amount,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 minDy,\n uint256 deadline\n ) external nonReentrant whenNotPaused {\n emit TokenDepositAndSwap(\n to,\n chainId,\n token,\n amount,\n tokenIndexFrom,\n tokenIndexTo,\n minDy,\n deadline\n );\n token.safeTransferFrom(msg.sender, address(this), amount);\n }\n\n /**\n * @notice Relays to nodes that (typically) a wrapped synAsset ERC20 token has been burned and the underlying needs to be redeeemed on the native chain. This function indicates to the nodes that they should attempt to redeem the LP token for the underlying assets (E.g \"swap\" out of the LP token)\n * @param to address on other chain to redeem underlying assets to\n * @param chainId which underlying chain to bridge assets onto\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n * @param tokenIndexFrom the token the user wants to swap from\n * @param tokenIndexTo the token the user wants to swap to\n * @param minDy the min amount the user would like to receive, or revert to only minting the SynERC20 token crosschain.\n * @param deadline latest timestamp to accept this transaction\n **/\n function redeemAndSwap(\n address to,\n uint256 chainId,\n ERC20Burnable token,\n uint256 amount,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 minDy,\n uint256 deadline\n ) external nonReentrant whenNotPaused {\n emit TokenRedeemAndSwap(\n to,\n chainId,\n token,\n amount,\n tokenIndexFrom,\n tokenIndexTo,\n minDy,\n deadline\n );\n token.burnFrom(msg.sender, amount);\n }\n\n /**\n * @notice Relays to nodes that (typically) a wrapped synAsset ERC20 token has been burned and the underlying needs to be redeeemed on the native chain. This function indicates to the nodes that they should attempt to redeem the LP token for the underlying assets (E.g \"swap\" out of the LP token)\n * @param to address on other chain to redeem underlying assets to\n * @param chainId which underlying chain to bridge assets onto\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n * @param swapTokenIndex Specifies which of the underlying LP assets the nodes should attempt to redeem for\n * @param swapMinAmount Specifies the minimum amount of the underlying asset needed for the nodes to execute the redeem/swap\n * @param swapDeadline Specificies the deadline that the nodes are allowed to try to redeem/swap the LP token\n **/\n function redeemAndRemove(\n address to,\n uint256 chainId,\n ERC20Burnable token,\n uint256 amount,\n uint8 swapTokenIndex,\n uint256 swapMinAmount,\n uint256 swapDeadline\n ) external nonReentrant whenNotPaused {\n emit TokenRedeemAndRemove(\n to,\n chainId,\n token,\n amount,\n swapTokenIndex,\n swapMinAmount,\n swapDeadline\n );\n token.burnFrom(msg.sender, amount);\n }\n\n /**\n * @notice Nodes call this function to mint a SynERC20 (or any asset that the bridge is given minter access to), and then attempt to swap the SynERC20 into the desired destination asset. This is called by the nodes after a TokenDepositAndSwap event is emitted.\n * @dev This means the BridgeDeposit.sol contract must have minter access to the token attempting to be minted\n * @param to address on other chain to redeem underlying assets to\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain post-fees\n * @param fee Amount in native token decimals to save to the contract as fees\n * @param pool Destination chain's pool to use to swap SynERC20 -> Asset. The nodes determine this by using PoolConfig.sol.\n * @param tokenIndexFrom Index of the SynERC20 asset in the pool\n * @param tokenIndexTo Index of the desired final asset\n * @param minDy Minumum amount (in final asset decimals) that must be swapped for, otherwise the user will receive the SynERC20.\n * @param deadline Epoch time of the deadline that the swap is allowed to be executed.\n * @param kappa kappa\n **/\n function mintAndSwap(\n address payable to,\n IERC20Mintable token,\n uint256 amount,\n uint256 fee,\n ISwap pool,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 minDy,\n uint256 deadline,\n bytes32 kappa\n ) external nonReentrant whenNotPaused {\n require(\n hasRole(NODEGROUP_ROLE, msg.sender),\n \"Caller is not a node group\"\n );\n require(amount > fee, \"Amount must be greater than fee\");\n require(!kappaMap[kappa], \"Kappa is already present\");\n kappaMap[kappa] = true;\n fees[address(token)] = fees[address(token)].add(fee);\n // Transfer gas airdrop\n if (chainGasAmount != 0 && address(this).balance > chainGasAmount) {\n to.call.value(chainGasAmount)(\"\");\n }\n // first check to make sure more will be given than min amount required\n uint256 expectedOutput = ISwap(pool).calculateSwap(\n tokenIndexFrom,\n tokenIndexTo,\n amount.sub(fee)\n );\n\n if (expectedOutput >= minDy) {\n // proceed with swap\n token.mint(address(this), amount);\n token.safeIncreaseAllowance(address(pool), amount);\n try\n ISwap(pool).swap(\n tokenIndexFrom,\n tokenIndexTo,\n amount.sub(fee),\n minDy,\n deadline\n )\n returns (uint256 finalSwappedAmount) {\n // Swap succeeded, transfer swapped asset\n IERC20 swappedTokenTo = ISwap(pool).getToken(tokenIndexTo);\n if (\n address(swappedTokenTo) == WETH_ADDRESS &&\n WETH_ADDRESS != address(0)\n ) {\n IWETH9(WETH_ADDRESS).withdraw(finalSwappedAmount);\n (bool success, ) = to.call{value: finalSwappedAmount}(\"\");\n require(success, \"ETH_TRANSFER_FAILED\");\n emit TokenMintAndSwap(\n to,\n token,\n finalSwappedAmount,\n fee,\n tokenIndexFrom,\n tokenIndexTo,\n minDy,\n deadline,\n true,\n kappa\n );\n } else {\n swappedTokenTo.safeTransfer(to, finalSwappedAmount);\n emit TokenMintAndSwap(\n to,\n token,\n finalSwappedAmount,\n fee,\n tokenIndexFrom,\n tokenIndexTo,\n minDy,\n deadline,\n true,\n kappa\n );\n }\n } catch {\n IERC20(token).safeTransfer(to, amount.sub(fee));\n emit TokenMintAndSwap(\n to,\n token,\n amount.sub(fee),\n fee,\n tokenIndexFrom,\n tokenIndexTo,\n minDy,\n deadline,\n false,\n kappa\n );\n }\n } else {\n token.mint(address(this), amount);\n IERC20(token).safeTransfer(to, amount.sub(fee));\n emit TokenMintAndSwap(\n to,\n token,\n amount.sub(fee),\n fee,\n tokenIndexFrom,\n tokenIndexTo,\n minDy,\n deadline,\n false,\n kappa\n );\n }\n }\n\n /**\n * @notice Function to be called by the node group to withdraw the underlying assets from the contract\n * @param to address on chain to send underlying assets to\n * @param token ERC20 compatible token to withdraw from the bridge\n * @param amount Amount in native token decimals to withdraw\n * @param fee Amount in native token decimals to save to the contract as fees\n * @param pool Destination chain's pool to use to swap SynERC20 -> Asset. The nodes determine this by using PoolConfig.sol.\n * @param swapTokenIndex Specifies which of the underlying LP assets the nodes should attempt to redeem for\n * @param swapMinAmount Specifies the minimum amount of the underlying asset needed for the nodes to execute the redeem/swap\n * @param swapDeadline Specificies the deadline that the nodes are allowed to try to redeem/swap the LP token\n * @param kappa kappa\n **/\n function withdrawAndRemove(\n address to,\n IERC20 token,\n uint256 amount,\n uint256 fee,\n ISwap pool,\n uint8 swapTokenIndex,\n uint256 swapMinAmount,\n uint256 swapDeadline,\n bytes32 kappa\n ) external nonReentrant whenNotPaused {\n require(\n hasRole(NODEGROUP_ROLE, msg.sender),\n \"Caller is not a node group\"\n );\n require(amount > fee, \"Amount must be greater than fee\");\n require(!kappaMap[kappa], \"Kappa is already present\");\n kappaMap[kappa] = true;\n fees[address(token)] = fees[address(token)].add(fee);\n // first check to make sure more will be given than min amount required\n uint256 expectedOutput = ISwap(pool).calculateRemoveLiquidityOneToken(\n amount.sub(fee),\n swapTokenIndex\n );\n\n if (expectedOutput >= swapMinAmount) {\n token.safeIncreaseAllowance(address(pool), amount.sub(fee));\n try\n ISwap(pool).removeLiquidityOneToken(\n amount.sub(fee),\n swapTokenIndex,\n swapMinAmount,\n swapDeadline\n )\n returns (uint256 finalSwappedAmount) {\n // Swap succeeded, transfer swapped asset\n IERC20 swappedTokenTo = ISwap(pool).getToken(swapTokenIndex);\n swappedTokenTo.safeTransfer(to, finalSwappedAmount);\n emit TokenWithdrawAndRemove(\n to,\n token,\n finalSwappedAmount,\n fee,\n swapTokenIndex,\n swapMinAmount,\n swapDeadline,\n true,\n kappa\n );\n } catch {\n IERC20(token).safeTransfer(to, amount.sub(fee));\n emit TokenWithdrawAndRemove(\n to,\n token,\n amount.sub(fee),\n fee,\n swapTokenIndex,\n swapMinAmount,\n swapDeadline,\n false,\n kappa\n );\n }\n } else {\n token.safeTransfer(to, amount.sub(fee));\n emit TokenWithdrawAndRemove(\n to,\n token,\n amount.sub(fee),\n fee,\n swapTokenIndex,\n swapMinAmount,\n swapDeadline,\n false,\n kappa\n );\n }\n }\n\n // BRIDGE FUNCTIONS TO HANDLE DIFF ADDRESSES\n /**\n * @notice Relays to nodes that (typically) a wrapped synAsset ERC20 token has been burned and the underlying needs to be redeeemed on the native chain\n * @param to address on other chain to redeem underlying assets to\n * @param chainId which underlying chain to bridge assets onto\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n **/\n function redeemV2(\n bytes32 to,\n uint256 chainId,\n ERC20Burnable token,\n uint256 amount\n ) external nonReentrant whenNotPaused {\n emit TokenRedeemV2(to, chainId, token, amount);\n token.burnFrom(msg.sender, amount);\n }\n}\n" + }, + "contracts/bridge/HarmonySynapseBridge.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.6.12;\n\nimport \"@openzeppelin/contracts-upgradeable/proxy/Initializable.sol\";\nimport \"@openzeppelin/contracts-upgradeable/access/AccessControlUpgradeable.sol\";\nimport \"@openzeppelin/contracts-upgradeable/utils/ReentrancyGuardUpgradeable.sol\";\nimport \"@openzeppelin/contracts-upgradeable/utils/PausableUpgradeable.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/SafeERC20.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/ERC20Burnable.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport \"@openzeppelin/contracts/math/SafeMath.sol\";\n\nimport \"./interfaces/ISwap.sol\";\nimport \"./interfaces/IWETH9.sol\";\n\ninterface IERC20Mintable is IERC20 {\n function mint(address to, uint256 amount) external;\n}\n\ninterface IFrax {\n function exchangeOldForCanonical(\n address bridge_token_address,\n uint256 token_amount\n ) external returns (uint256);\n}\n\ncontract HarmonySynapseBridge is\n Initializable,\n AccessControlUpgradeable,\n ReentrancyGuardUpgradeable,\n PausableUpgradeable\n{\n using SafeERC20 for IERC20;\n using SafeERC20 for IERC20Mintable;\n using SafeMath for uint256;\n\n bytes32 public constant NODEGROUP_ROLE = keccak256(\"NODEGROUP_ROLE\");\n bytes32 public constant GOVERNANCE_ROLE = keccak256(\"GOVERNANCE_ROLE\");\n\n mapping(address => uint256) private fees;\n\n uint256 public startBlockNumber;\n uint256 public constant bridgeVersion = 6;\n uint256 public chainGasAmount;\n address payable public WETH_ADDRESS;\n\n mapping(bytes32 => bool) private kappaMap;\n\n receive() external payable {}\n\n function initialize() external initializer {\n startBlockNumber = block.number;\n _setupRole(DEFAULT_ADMIN_ROLE, msg.sender);\n __AccessControl_init();\n }\n\n function setChainGasAmount(uint256 amount) external {\n require(hasRole(GOVERNANCE_ROLE, msg.sender), \"Not governance\");\n chainGasAmount = amount;\n }\n\n function setWethAddress(address payable _wethAddress) external {\n require(hasRole(DEFAULT_ADMIN_ROLE, msg.sender), \"Not admin\");\n WETH_ADDRESS = _wethAddress;\n }\n\n function addKappas(bytes32[] calldata kappas) external {\n require(hasRole(GOVERNANCE_ROLE, msg.sender), \"Not governance\");\n for (uint256 i = 0; i < kappas.length; ++i) {\n kappaMap[kappas[i]] = true;\n }\n }\n\n event TokenDeposit(\n address indexed to,\n uint256 chainId,\n IERC20 token,\n uint256 amount\n );\n event TokenRedeem(\n address indexed to,\n uint256 chainId,\n IERC20 token,\n uint256 amount\n );\n event TokenWithdraw(\n address indexed to,\n IERC20 token,\n uint256 amount,\n uint256 fee,\n bytes32 indexed kappa\n );\n event TokenMint(\n address indexed to,\n IERC20Mintable token,\n uint256 amount,\n uint256 fee,\n bytes32 indexed kappa\n );\n event TokenDepositAndSwap(\n address indexed to,\n uint256 chainId,\n IERC20 token,\n uint256 amount,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 minDy,\n uint256 deadline\n );\n event TokenMintAndSwap(\n address indexed to,\n IERC20Mintable token,\n uint256 amount,\n uint256 fee,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 minDy,\n uint256 deadline,\n bool swapSuccess,\n bytes32 indexed kappa\n );\n event TokenRedeemAndSwap(\n address indexed to,\n uint256 chainId,\n IERC20 token,\n uint256 amount,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 minDy,\n uint256 deadline\n );\n event TokenRedeemAndRemove(\n address indexed to,\n uint256 chainId,\n IERC20 token,\n uint256 amount,\n uint8 swapTokenIndex,\n uint256 swapMinAmount,\n uint256 swapDeadline\n );\n event TokenWithdrawAndRemove(\n address indexed to,\n IERC20 token,\n uint256 amount,\n uint256 fee,\n uint8 swapTokenIndex,\n uint256 swapMinAmount,\n uint256 swapDeadline,\n bool swapSuccess,\n bytes32 indexed kappa\n );\n\n // v2 events\n event TokenRedeemV2(\n bytes32 indexed to,\n uint256 chainId,\n IERC20 token,\n uint256 amount\n );\n\n // VIEW FUNCTIONS ***/\n function getFeeBalance(address tokenAddress)\n external\n view\n returns (uint256)\n {\n return fees[tokenAddress];\n }\n\n function kappaExists(bytes32 kappa) external view returns (bool) {\n return kappaMap[kappa];\n }\n\n // FEE FUNCTIONS ***/\n /**\n * * @notice withdraw specified ERC20 token fees to a given address\n * * @param token ERC20 token in which fees acccumulated to transfer\n * * @param to Address to send the fees to\n */\n function withdrawFees(IERC20 token, address to) external whenNotPaused {\n require(hasRole(GOVERNANCE_ROLE, msg.sender), \"Not governance\");\n require(to != address(0), \"Address is 0x000\");\n if (fees[address(token)] != 0) {\n token.safeTransfer(to, fees[address(token)]);\n fees[address(token)] = 0;\n }\n }\n\n // PAUSABLE FUNCTIONS ***/\n function pause() external {\n require(hasRole(GOVERNANCE_ROLE, msg.sender), \"Not governance\");\n _pause();\n }\n\n function unpause() external {\n require(hasRole(GOVERNANCE_ROLE, msg.sender), \"Not governance\");\n _unpause();\n }\n\n /**\n * @notice Relays to nodes to transfers an ERC20 token cross-chain\n * @param to address on other chain to bridge assets to\n * @param chainId which chain to bridge assets onto\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n **/\n function deposit(\n address to,\n uint256 chainId,\n IERC20 token,\n uint256 amount\n ) external nonReentrant whenNotPaused {\n emit TokenDeposit(to, chainId, token, amount);\n token.safeTransferFrom(msg.sender, address(this), amount);\n }\n\n /**\n * @notice Relays to nodes that (typically) a wrapped synAsset ERC20 token has been burned and the underlying needs to be redeeemed on the native chain\n * @param to address on other chain to redeem underlying assets to\n * @param chainId which underlying chain to bridge assets onto\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n **/\n function redeem(\n address to,\n uint256 chainId,\n ERC20Burnable token,\n uint256 amount\n ) external nonReentrant whenNotPaused {\n emit TokenRedeem(to, chainId, token, amount);\n token.burnFrom(msg.sender, amount);\n }\n\n /**\n * @notice Function to be called by the node group to withdraw the underlying assets from the contract\n * @param to address on chain to send underlying assets to\n * @param token ERC20 compatible token to withdraw from the bridge\n * @param amount Amount in native token decimals to withdraw\n * @param fee Amount in native token decimals to save to the contract as fees\n * @param kappa kappa\n **/\n function withdraw(\n address to,\n IERC20 token,\n uint256 amount,\n uint256 fee,\n bytes32 kappa\n ) external nonReentrant whenNotPaused {\n require(\n hasRole(NODEGROUP_ROLE, msg.sender),\n \"Caller is not a node group\"\n );\n require(amount > fee, \"Amount must be greater than fee\");\n require(!kappaMap[kappa], \"Kappa is already present\");\n kappaMap[kappa] = true;\n fees[address(token)] = fees[address(token)].add(fee);\n if (address(token) == WETH_ADDRESS && WETH_ADDRESS != address(0)) {\n IWETH9(WETH_ADDRESS).withdraw(amount.sub(fee));\n (bool success, ) = to.call{value: amount.sub(fee)}(\"\");\n require(success, \"ETH_TRANSFER_FAILED\");\n emit TokenWithdraw(to, token, amount, fee, kappa);\n } else {\n emit TokenWithdraw(to, token, amount, fee, kappa);\n token.safeTransfer(to, amount.sub(fee));\n }\n }\n\n /**\n * @notice Nodes call this function to mint a SynERC20 (or any asset that the bridge is given minter access to). This is called by the nodes after a TokenDeposit event is emitted.\n * @dev This means the SynapseBridge.sol contract must have minter access to the token attempting to be minted\n * @param to address on other chain to redeem underlying assets to\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain post-fees\n * @param fee Amount in native token decimals to save to the contract as fees\n * @param kappa kappa\n **/\n function mint(\n address payable to,\n IERC20Mintable token,\n uint256 amount,\n uint256 fee,\n bytes32 kappa\n ) external nonReentrant whenNotPaused {\n require(\n hasRole(NODEGROUP_ROLE, msg.sender),\n \"Caller is not a node group\"\n );\n require(amount > fee, \"Amount must be greater than fee\");\n require(!kappaMap[kappa], \"Kappa is already present\");\n kappaMap[kappa] = true;\n fees[address(token)] = fees[address(token)].add(fee);\n emit TokenMint(to, token, amount.sub(fee), fee, kappa);\n token.mint(address(this), amount);\n // checks if synFRAX\n if (address(token) == 0x1852F70512298d56e9c8FDd905e02581E04ddb2a) {\n if (\n token.allowance(\n address(this),\n 0xFa7191D292d5633f702B0bd7E3E3BcCC0e633200\n ) < amount.sub(fee)\n ) {\n token.safeApprove(\n address(0xFa7191D292d5633f702B0bd7E3E3BcCC0e633200),\n 0\n );\n token.safeApprove(\n address(0xFa7191D292d5633f702B0bd7E3E3BcCC0e633200),\n type(uint256).max\n );\n }\n try\n IFrax(0xFa7191D292d5633f702B0bd7E3E3BcCC0e633200)\n .exchangeOldForCanonical(address(token), amount.sub(fee))\n returns (uint256 canolical_tokens_out) {\n IERC20(0xFa7191D292d5633f702B0bd7E3E3BcCC0e633200).safeTransfer(\n to,\n canolical_tokens_out\n );\n } catch {\n IERC20(token).safeTransfer(to, amount.sub(fee));\n }\n } else {\n IERC20(token).safeTransfer(to, amount.sub(fee));\n }\n if (chainGasAmount != 0 && address(this).balance > chainGasAmount) {\n to.call.value(chainGasAmount)(\"\");\n }\n }\n\n /**\n * @notice Relays to nodes to both transfer an ERC20 token cross-chain, and then have the nodes execute a swap through a liquidity pool on behalf of the user.\n * @param to address on other chain to bridge assets to\n * @param chainId which chain to bridge assets onto\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n * @param tokenIndexFrom the token the user wants to swap from\n * @param tokenIndexTo the token the user wants to swap to\n * @param minDy the min amount the user would like to receive, or revert to only minting the SynERC20 token crosschain.\n * @param deadline latest timestamp to accept this transaction\n **/\n function depositAndSwap(\n address to,\n uint256 chainId,\n IERC20 token,\n uint256 amount,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 minDy,\n uint256 deadline\n ) external nonReentrant whenNotPaused {\n emit TokenDepositAndSwap(\n to,\n chainId,\n token,\n amount,\n tokenIndexFrom,\n tokenIndexTo,\n minDy,\n deadline\n );\n token.safeTransferFrom(msg.sender, address(this), amount);\n }\n\n /**\n * @notice Relays to nodes that (typically) a wrapped synAsset ERC20 token has been burned and the underlying needs to be redeeemed on the native chain. This function indicates to the nodes that they should attempt to redeem the LP token for the underlying assets (E.g \"swap\" out of the LP token)\n * @param to address on other chain to redeem underlying assets to\n * @param chainId which underlying chain to bridge assets onto\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n * @param tokenIndexFrom the token the user wants to swap from\n * @param tokenIndexTo the token the user wants to swap to\n * @param minDy the min amount the user would like to receive, or revert to only minting the SynERC20 token crosschain.\n * @param deadline latest timestamp to accept this transaction\n **/\n function redeemAndSwap(\n address to,\n uint256 chainId,\n ERC20Burnable token,\n uint256 amount,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 minDy,\n uint256 deadline\n ) external nonReentrant whenNotPaused {\n emit TokenRedeemAndSwap(\n to,\n chainId,\n token,\n amount,\n tokenIndexFrom,\n tokenIndexTo,\n minDy,\n deadline\n );\n token.burnFrom(msg.sender, amount);\n }\n\n /**\n * @notice Relays to nodes that (typically) a wrapped synAsset ERC20 token has been burned and the underlying needs to be redeeemed on the native chain. This function indicates to the nodes that they should attempt to redeem the LP token for the underlying assets (E.g \"swap\" out of the LP token)\n * @param to address on other chain to redeem underlying assets to\n * @param chainId which underlying chain to bridge assets onto\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n * @param swapTokenIndex Specifies which of the underlying LP assets the nodes should attempt to redeem for\n * @param swapMinAmount Specifies the minimum amount of the underlying asset needed for the nodes to execute the redeem/swap\n * @param swapDeadline Specificies the deadline that the nodes are allowed to try to redeem/swap the LP token\n **/\n function redeemAndRemove(\n address to,\n uint256 chainId,\n ERC20Burnable token,\n uint256 amount,\n uint8 swapTokenIndex,\n uint256 swapMinAmount,\n uint256 swapDeadline\n ) external nonReentrant whenNotPaused {\n emit TokenRedeemAndRemove(\n to,\n chainId,\n token,\n amount,\n swapTokenIndex,\n swapMinAmount,\n swapDeadline\n );\n token.burnFrom(msg.sender, amount);\n }\n\n /**\n * @notice Nodes call this function to mint a SynERC20 (or any asset that the bridge is given minter access to), and then attempt to swap the SynERC20 into the desired destination asset. This is called by the nodes after a TokenDepositAndSwap event is emitted.\n * @dev This means the BridgeDeposit.sol contract must have minter access to the token attempting to be minted\n * @param to address on other chain to redeem underlying assets to\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain post-fees\n * @param fee Amount in native token decimals to save to the contract as fees\n * @param pool Destination chain's pool to use to swap SynERC20 -> Asset. The nodes determine this by using PoolConfig.sol.\n * @param tokenIndexFrom Index of the SynERC20 asset in the pool\n * @param tokenIndexTo Index of the desired final asset\n * @param minDy Minumum amount (in final asset decimals) that must be swapped for, otherwise the user will receive the SynERC20.\n * @param deadline Epoch time of the deadline that the swap is allowed to be executed.\n * @param kappa kappa\n **/\n function mintAndSwap(\n address payable to,\n IERC20Mintable token,\n uint256 amount,\n uint256 fee,\n ISwap pool,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 minDy,\n uint256 deadline,\n bytes32 kappa\n ) external nonReentrant whenNotPaused {\n require(\n hasRole(NODEGROUP_ROLE, msg.sender),\n \"Caller is not a node group\"\n );\n require(amount > fee, \"Amount must be greater than fee\");\n require(!kappaMap[kappa], \"Kappa is already present\");\n kappaMap[kappa] = true;\n fees[address(token)] = fees[address(token)].add(fee);\n // Transfer gas airdrop\n if (chainGasAmount != 0 && address(this).balance > chainGasAmount) {\n to.call.value(chainGasAmount)(\"\");\n }\n // first check to make sure more will be given than min amount required\n uint256 expectedOutput = ISwap(pool).calculateSwap(\n tokenIndexFrom,\n tokenIndexTo,\n amount.sub(fee)\n );\n\n if (expectedOutput >= minDy) {\n // proceed with swap\n token.mint(address(this), amount);\n token.safeIncreaseAllowance(address(pool), amount);\n try\n ISwap(pool).swap(\n tokenIndexFrom,\n tokenIndexTo,\n amount.sub(fee),\n minDy,\n deadline\n )\n returns (uint256 finalSwappedAmount) {\n // Swap succeeded, transfer swapped asset\n IERC20 swappedTokenTo = ISwap(pool).getToken(tokenIndexTo);\n if (\n address(swappedTokenTo) == WETH_ADDRESS &&\n WETH_ADDRESS != address(0)\n ) {\n IWETH9(WETH_ADDRESS).withdraw(finalSwappedAmount);\n (bool success, ) = to.call{value: finalSwappedAmount}(\"\");\n require(success, \"ETH_TRANSFER_FAILED\");\n emit TokenMintAndSwap(\n to,\n token,\n finalSwappedAmount,\n fee,\n tokenIndexFrom,\n tokenIndexTo,\n minDy,\n deadline,\n true,\n kappa\n );\n } else {\n swappedTokenTo.safeTransfer(to, finalSwappedAmount);\n emit TokenMintAndSwap(\n to,\n token,\n finalSwappedAmount,\n fee,\n tokenIndexFrom,\n tokenIndexTo,\n minDy,\n deadline,\n true,\n kappa\n );\n }\n } catch {\n IERC20(token).safeTransfer(to, amount.sub(fee));\n emit TokenMintAndSwap(\n to,\n token,\n amount.sub(fee),\n fee,\n tokenIndexFrom,\n tokenIndexTo,\n minDy,\n deadline,\n false,\n kappa\n );\n }\n } else {\n token.mint(address(this), amount);\n IERC20(token).safeTransfer(to, amount.sub(fee));\n emit TokenMintAndSwap(\n to,\n token,\n amount.sub(fee),\n fee,\n tokenIndexFrom,\n tokenIndexTo,\n minDy,\n deadline,\n false,\n kappa\n );\n }\n }\n\n /**\n * @notice Function to be called by the node group to withdraw the underlying assets from the contract\n * @param to address on chain to send underlying assets to\n * @param token ERC20 compatible token to withdraw from the bridge\n * @param amount Amount in native token decimals to withdraw\n * @param fee Amount in native token decimals to save to the contract as fees\n * @param pool Destination chain's pool to use to swap SynERC20 -> Asset. The nodes determine this by using PoolConfig.sol.\n * @param swapTokenIndex Specifies which of the underlying LP assets the nodes should attempt to redeem for\n * @param swapMinAmount Specifies the minimum amount of the underlying asset needed for the nodes to execute the redeem/swap\n * @param swapDeadline Specificies the deadline that the nodes are allowed to try to redeem/swap the LP token\n * @param kappa kappa\n **/\n function withdrawAndRemove(\n address to,\n IERC20 token,\n uint256 amount,\n uint256 fee,\n ISwap pool,\n uint8 swapTokenIndex,\n uint256 swapMinAmount,\n uint256 swapDeadline,\n bytes32 kappa\n ) external nonReentrant whenNotPaused {\n require(\n hasRole(NODEGROUP_ROLE, msg.sender),\n \"Caller is not a node group\"\n );\n require(amount > fee, \"Amount must be greater than fee\");\n require(!kappaMap[kappa], \"Kappa is already present\");\n kappaMap[kappa] = true;\n fees[address(token)] = fees[address(token)].add(fee);\n // first check to make sure more will be given than min amount required\n uint256 expectedOutput = ISwap(pool).calculateRemoveLiquidityOneToken(\n amount.sub(fee),\n swapTokenIndex\n );\n\n if (expectedOutput >= swapMinAmount) {\n token.safeIncreaseAllowance(address(pool), amount.sub(fee));\n try\n ISwap(pool).removeLiquidityOneToken(\n amount.sub(fee),\n swapTokenIndex,\n swapMinAmount,\n swapDeadline\n )\n returns (uint256 finalSwappedAmount) {\n // Swap succeeded, transfer swapped asset\n IERC20 swappedTokenTo = ISwap(pool).getToken(swapTokenIndex);\n swappedTokenTo.safeTransfer(to, finalSwappedAmount);\n emit TokenWithdrawAndRemove(\n to,\n token,\n finalSwappedAmount,\n fee,\n swapTokenIndex,\n swapMinAmount,\n swapDeadline,\n true,\n kappa\n );\n } catch {\n IERC20(token).safeTransfer(to, amount.sub(fee));\n emit TokenWithdrawAndRemove(\n to,\n token,\n amount.sub(fee),\n fee,\n swapTokenIndex,\n swapMinAmount,\n swapDeadline,\n false,\n kappa\n );\n }\n } else {\n token.safeTransfer(to, amount.sub(fee));\n emit TokenWithdrawAndRemove(\n to,\n token,\n amount.sub(fee),\n fee,\n swapTokenIndex,\n swapMinAmount,\n swapDeadline,\n false,\n kappa\n );\n }\n }\n\n // BRIDGE FUNCTIONS TO HANDLE DIFF ADDRESSES\n /**\n * @notice Relays to nodes that (typically) a wrapped synAsset ERC20 token has been burned and the underlying needs to be redeeemed on the native chain\n * @param to address on other chain to redeem underlying assets to\n * @param chainId which underlying chain to bridge assets onto\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n **/\n function redeemV2(\n bytes32 to,\n uint256 chainId,\n ERC20Burnable token,\n uint256 amount\n ) external nonReentrant whenNotPaused {\n emit TokenRedeemV2(to, chainId, token, amount);\n token.burnFrom(msg.sender, amount);\n }\n}\n" + }, + "@openzeppelin/contracts-upgradeable/drafts/EIP712Upgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <0.8.0;\nimport \"../proxy/Initializable.sol\";\n\n/**\n * @dev https://eips.ethereum.org/EIPS/eip-712[EIP 712] is a standard for hashing and signing of typed structured data.\n *\n * The encoding specified in the EIP is very generic, and such a generic implementation in Solidity is not feasible,\n * thus this contract does not implement the encoding itself. Protocols need to implement the type-specific encoding\n * they need in their contracts using a combination of `abi.encode` and `keccak256`.\n *\n * This contract implements the EIP 712 domain separator ({_domainSeparatorV4}) that is used as part of the encoding\n * scheme, and the final step of the encoding to obtain the message digest that is then signed via ECDSA\n * ({_hashTypedDataV4}).\n *\n * The implementation of the domain separator was designed to be as efficient as possible while still properly updating\n * the chain id to protect against replay attacks on an eventual fork of the chain.\n *\n * NOTE: This contract implements the version of the encoding known as \"v4\", as implemented by the JSON RPC method\n * https://docs.metamask.io/guide/signing-data.html[`eth_signTypedDataV4` in MetaMask].\n *\n * _Available since v3.4._\n */\nabstract contract EIP712Upgradeable is Initializable {\n /* solhint-disable var-name-mixedcase */\n bytes32 private _HASHED_NAME;\n bytes32 private _HASHED_VERSION;\n bytes32 private constant _TYPE_HASH = keccak256(\"EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)\");\n /* solhint-enable var-name-mixedcase */\n\n /**\n * @dev Initializes the domain separator and parameter caches.\n *\n * The meaning of `name` and `version` is specified in\n * https://eips.ethereum.org/EIPS/eip-712#definition-of-domainseparator[EIP 712]:\n *\n * - `name`: the user readable name of the signing domain, i.e. the name of the DApp or the protocol.\n * - `version`: the current major version of the signing domain.\n *\n * NOTE: These parameters cannot be changed except through a xref:learn::upgrading-smart-contracts.adoc[smart\n * contract upgrade].\n */\n function __EIP712_init(string memory name, string memory version) internal initializer {\n __EIP712_init_unchained(name, version);\n }\n\n function __EIP712_init_unchained(string memory name, string memory version) internal initializer {\n bytes32 hashedName = keccak256(bytes(name));\n bytes32 hashedVersion = keccak256(bytes(version));\n _HASHED_NAME = hashedName;\n _HASHED_VERSION = hashedVersion;\n }\n\n /**\n * @dev Returns the domain separator for the current chain.\n */\n function _domainSeparatorV4() internal view returns (bytes32) {\n return _buildDomainSeparator(_TYPE_HASH, _EIP712NameHash(), _EIP712VersionHash());\n }\n\n function _buildDomainSeparator(bytes32 typeHash, bytes32 name, bytes32 version) private view returns (bytes32) {\n return keccak256(\n abi.encode(\n typeHash,\n name,\n version,\n _getChainId(),\n address(this)\n )\n );\n }\n\n /**\n * @dev Given an already https://eips.ethereum.org/EIPS/eip-712#definition-of-hashstruct[hashed struct], this\n * function returns the hash of the fully encoded EIP712 message for this domain.\n *\n * This hash can be used together with {ECDSA-recover} to obtain the signer of a message. For example:\n *\n * ```solidity\n * bytes32 digest = _hashTypedDataV4(keccak256(abi.encode(\n * keccak256(\"Mail(address to,string contents)\"),\n * mailTo,\n * keccak256(bytes(mailContents))\n * )));\n * address signer = ECDSA.recover(digest, signature);\n * ```\n */\n function _hashTypedDataV4(bytes32 structHash) internal view virtual returns (bytes32) {\n return keccak256(abi.encodePacked(\"\\x19\\x01\", _domainSeparatorV4(), structHash));\n }\n\n function _getChainId() private view returns (uint256 chainId) {\n this; // silence state mutability warning without generating bytecode - see https://github.com/ethereum/solidity/issues/2691\n // solhint-disable-next-line no-inline-assembly\n assembly {\n chainId := chainid()\n }\n }\n\n /**\n * @dev The hash of the name parameter for the EIP712 domain.\n *\n * NOTE: This function reads from storage by default, but can be redefined to return a constant value if gas costs\n * are a concern.\n */\n function _EIP712NameHash() internal virtual view returns (bytes32) {\n return _HASHED_NAME;\n }\n\n /**\n * @dev The hash of the version parameter for the EIP712 domain.\n *\n * NOTE: This function reads from storage by default, but can be redefined to return a constant value if gas costs\n * are a concern.\n */\n function _EIP712VersionHash() internal virtual view returns (bytes32) {\n return _HASHED_VERSION;\n }\n uint256[50] private __gap;\n}\n" + }, + "@openzeppelin/contracts-upgradeable/drafts/ERC20PermitUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.5 <0.8.0;\n\nimport \"../token/ERC20/ERC20Upgradeable.sol\";\nimport \"./IERC20PermitUpgradeable.sol\";\nimport \"../cryptography/ECDSAUpgradeable.sol\";\nimport \"../utils/CountersUpgradeable.sol\";\nimport \"./EIP712Upgradeable.sol\";\nimport \"../proxy/Initializable.sol\";\n\n/**\n * @dev Implementation of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in\n * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612].\n *\n * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by\n * presenting a message signed by the account. By not relying on `{IERC20-approve}`, the token holder account doesn't\n * need to send a transaction, and thus is not required to hold Ether at all.\n *\n * _Available since v3.4._\n */\nabstract contract ERC20PermitUpgradeable is Initializable, ERC20Upgradeable, IERC20PermitUpgradeable, EIP712Upgradeable {\n using CountersUpgradeable for CountersUpgradeable.Counter;\n\n mapping (address => CountersUpgradeable.Counter) private _nonces;\n\n // solhint-disable-next-line var-name-mixedcase\n bytes32 private _PERMIT_TYPEHASH;\n\n /**\n * @dev Initializes the {EIP712} domain separator using the `name` parameter, and setting `version` to `\"1\"`.\n *\n * It's a good idea to use the same `name` that is defined as the ERC20 token name.\n */\n function __ERC20Permit_init(string memory name) internal initializer {\n __Context_init_unchained();\n __EIP712_init_unchained(name, \"1\");\n __ERC20Permit_init_unchained(name);\n }\n\n function __ERC20Permit_init_unchained(string memory name) internal initializer {\n _PERMIT_TYPEHASH = keccak256(\"Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)\");\n }\n\n /**\n * @dev See {IERC20Permit-permit}.\n */\n function permit(address owner, address spender, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s) public virtual override {\n // solhint-disable-next-line not-rely-on-time\n require(block.timestamp <= deadline, \"ERC20Permit: expired deadline\");\n\n bytes32 structHash = keccak256(\n abi.encode(\n _PERMIT_TYPEHASH,\n owner,\n spender,\n value,\n _nonces[owner].current(),\n deadline\n )\n );\n\n bytes32 hash = _hashTypedDataV4(structHash);\n\n address signer = ECDSAUpgradeable.recover(hash, v, r, s);\n require(signer == owner, \"ERC20Permit: invalid signature\");\n\n _nonces[owner].increment();\n _approve(owner, spender, value);\n }\n\n /**\n * @dev See {IERC20Permit-nonces}.\n */\n function nonces(address owner) public view override returns (uint256) {\n return _nonces[owner].current();\n }\n\n /**\n * @dev See {IERC20Permit-DOMAIN_SEPARATOR}.\n */\n // solhint-disable-next-line func-name-mixedcase\n function DOMAIN_SEPARATOR() external view override returns (bytes32) {\n return _domainSeparatorV4();\n }\n uint256[49] private __gap;\n}\n" + }, + "@openzeppelin/contracts-upgradeable/drafts/IERC20PermitUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <0.8.0;\n\n/**\n * @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in\n * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612].\n *\n * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by\n * presenting a message signed by the account. By not relying on `{IERC20-approve}`, the token holder account doesn't\n * need to send a transaction, and thus is not required to hold Ether at all.\n */\ninterface IERC20PermitUpgradeable {\n /**\n * @dev Sets `value` as the allowance of `spender` over `owner`'s tokens,\n * given `owner`'s signed approval.\n *\n * IMPORTANT: The same issues {IERC20-approve} has related to transaction\n * ordering also apply here.\n *\n * Emits an {Approval} event.\n *\n * Requirements:\n *\n * - `spender` cannot be the zero address.\n * - `deadline` must be a timestamp in the future.\n * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner`\n * over the EIP712-formatted function arguments.\n * - the signature must use ``owner``'s current nonce (see {nonces}).\n *\n * For more information on the signature format, see the\n * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP\n * section].\n */\n function permit(address owner, address spender, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s) external;\n\n /**\n * @dev Returns the current nonce for `owner`. This value must be\n * included whenever a signature is generated for {permit}.\n *\n * Every successful call to {permit} increases ``owner``'s nonce by one. This\n * prevents a signature from being used multiple times.\n */\n function nonces(address owner) external view returns (uint256);\n\n /**\n * @dev Returns the domain separator used in the encoding of the signature for `permit`, as defined by {EIP712}.\n */\n // solhint-disable-next-line func-name-mixedcase\n function DOMAIN_SEPARATOR() external view returns (bytes32);\n}\n" + }, + "@openzeppelin/contracts-upgradeable/cryptography/ECDSAUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <0.8.0;\n\n/**\n * @dev Elliptic Curve Digital Signature Algorithm (ECDSA) operations.\n *\n * These functions can be used to verify that a message was signed by the holder\n * of the private keys of a given address.\n */\nlibrary ECDSAUpgradeable {\n /**\n * @dev Returns the address that signed a hashed message (`hash`) with\n * `signature`. This address can then be used for verification purposes.\n *\n * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:\n * this function rejects them by requiring the `s` value to be in the lower\n * half order, and the `v` value to be either 27 or 28.\n *\n * IMPORTANT: `hash` _must_ be the result of a hash operation for the\n * verification to be secure: it is possible to craft signatures that\n * recover to arbitrary addresses for non-hashed data. A safe way to ensure\n * this is by receiving a hash of the original message (which may otherwise\n * be too long), and then calling {toEthSignedMessageHash} on it.\n */\n function recover(bytes32 hash, bytes memory signature) internal pure returns (address) {\n // Check the signature length\n if (signature.length != 65) {\n revert(\"ECDSA: invalid signature length\");\n }\n\n // Divide the signature in r, s and v variables\n bytes32 r;\n bytes32 s;\n uint8 v;\n\n // ecrecover takes the signature parameters, and the only way to get them\n // currently is to use assembly.\n // solhint-disable-next-line no-inline-assembly\n assembly {\n r := mload(add(signature, 0x20))\n s := mload(add(signature, 0x40))\n v := byte(0, mload(add(signature, 0x60)))\n }\n\n return recover(hash, v, r, s);\n }\n\n /**\n * @dev Overload of {ECDSA-recover-bytes32-bytes-} that receives the `v`,\n * `r` and `s` signature fields separately.\n */\n function recover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) internal pure returns (address) {\n // EIP-2 still allows signature malleability for ecrecover(). Remove this possibility and make the signature\n // unique. Appendix F in the Ethereum Yellow paper (https://ethereum.github.io/yellowpaper/paper.pdf), defines\n // the valid range for s in (281): 0 < s < secp256k1n ÷ 2 + 1, and for v in (282): v ∈ {27, 28}. Most\n // signatures from current libraries generate a unique signature with an s-value in the lower half order.\n //\n // If your library generates malleable signatures, such as s-values in the upper range, calculate a new s-value\n // with 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 - s1 and flip v from 27 to 28 or\n // vice versa. If your library also generates signatures with 0/1 for v instead 27/28, add 27 to v to accept\n // these malleable signatures as well.\n require(uint256(s) <= 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0, \"ECDSA: invalid signature 's' value\");\n require(v == 27 || v == 28, \"ECDSA: invalid signature 'v' value\");\n\n // If the signature is valid (and not malleable), return the signer address\n address signer = ecrecover(hash, v, r, s);\n require(signer != address(0), \"ECDSA: invalid signature\");\n\n return signer;\n }\n\n /**\n * @dev Returns an Ethereum Signed Message, created from a `hash`. This\n * replicates the behavior of the\n * https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_sign[`eth_sign`]\n * JSON-RPC method.\n *\n * See {recover}.\n */\n function toEthSignedMessageHash(bytes32 hash) internal pure returns (bytes32) {\n // 32 is the length in bytes of hash,\n // enforced by the type signature above\n return keccak256(abi.encodePacked(\"\\x19Ethereum Signed Message:\\n32\", hash));\n }\n}\n" + }, + "@openzeppelin/contracts-upgradeable/utils/CountersUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <0.8.0;\n\nimport \"../math/SafeMathUpgradeable.sol\";\n\n/**\n * @title Counters\n * @author Matt Condon (@shrugs)\n * @dev Provides counters that can only be incremented or decremented by one. This can be used e.g. to track the number\n * of elements in a mapping, issuing ERC721 ids, or counting request ids.\n *\n * Include with `using Counters for Counters.Counter;`\n * Since it is not possible to overflow a 256 bit integer with increments of one, `increment` can skip the {SafeMath}\n * overflow check, thereby saving gas. This does assume however correct usage, in that the underlying `_value` is never\n * directly accessed.\n */\nlibrary CountersUpgradeable {\n using SafeMathUpgradeable for uint256;\n\n struct Counter {\n // This variable should never be directly accessed by users of the library: interactions must be restricted to\n // the library's function. As of Solidity v0.5.2, this cannot be enforced, though there is a proposal to add\n // this feature: see https://github.com/ethereum/solidity/issues/4637\n uint256 _value; // default: 0\n }\n\n function current(Counter storage counter) internal view returns (uint256) {\n return counter._value;\n }\n\n function increment(Counter storage counter) internal {\n // The {SafeMath} overflow check can be skipped here, see the comment at the top\n counter._value += 1;\n }\n\n function decrement(Counter storage counter) internal {\n counter._value = counter._value.sub(1);\n }\n}\n" + }, + "contracts/bridge/SynapseERC20.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.6.12;\n\nimport \"@openzeppelin/contracts-upgradeable/token/ERC20/ERC20Upgradeable.sol\";\nimport \"@openzeppelin/contracts-upgradeable/token/ERC20/ERC20BurnableUpgradeable.sol\";\nimport \"@openzeppelin/contracts-upgradeable/drafts/ERC20PermitUpgradeable.sol\";\nimport \"@openzeppelin/contracts-upgradeable/access/AccessControlUpgradeable.sol\";\nimport \"@openzeppelin/contracts-upgradeable/proxy/Initializable.sol\";\n\ncontract SynapseERC20 is\n Initializable,\n ContextUpgradeable,\n AccessControlUpgradeable,\n ERC20BurnableUpgradeable,\n ERC20PermitUpgradeable\n{\n bytes32 public constant MINTER_ROLE = keccak256(\"MINTER_ROLE\");\n\n /**\n * @notice Initializes this ERC20 contract with the given parameters.\n * @param name Token name\n * @param symbol Token symbol\n * @param decimals Token name\n * @param owner admin address to be initialized with\n */\n function initialize(\n string memory name,\n string memory symbol,\n uint8 decimals,\n address owner\n ) external initializer {\n __Context_init_unchained();\n __AccessControl_init_unchained();\n __ERC20_init_unchained(name, symbol);\n __ERC20Burnable_init_unchained();\n _setupDecimals(decimals);\n __ERC20Permit_init(name);\n _setupRole(DEFAULT_ADMIN_ROLE, owner);\n }\n\n function mint(address to, uint256 amount) external {\n require(hasRole(MINTER_ROLE, msg.sender), \"Not a minter\");\n _mint(to, amount);\n }\n}\n" + }, + "contracts/auxiliary/DummyWethProxy.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.6.12;\nimport \"@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol\";\nimport \"@openzeppelin/contracts-upgradeable/proxy/Initializable.sol\";\n\ninterface IWETH9 {\n function name() external view returns (string memory);\n\n function symbol() external view returns (string memory);\n\n function decimals() external view returns (uint8);\n\n function balanceOf(address) external view returns (uint256);\n\n function allowance(address, address) external view returns (uint256);\n\n receive() external payable;\n\n function deposit() external payable;\n\n function withdraw(uint256 wad) external;\n\n function totalSupply() external view returns (uint256);\n\n function approve(address guy, uint256 wad) external returns (bool);\n\n function transfer(address dst, uint256 wad) external returns (bool);\n\n function transferFrom(\n address src,\n address dst,\n uint256 wad\n ) external returns (bool);\n}\n\ncontract DummyWethProxy is Initializable, OwnableUpgradeable {\n function initialize() external initializer {\n __Ownable_init();\n }\n\n IWETH9 public WETH;\n\n function setWETHAddress(address payable _weth) external onlyOwner {\n WETH = IWETH9(_weth);\n }\n\n function withdrawToSelf(uint256 amount) external {\n WETH.withdraw(amount);\n }\n\n function rescue(uint256 amount) external onlyOwner {\n WETH.transfer(owner(), amount);\n }\n\n receive() external payable {}\n\n fallback() external payable {}\n}\n" + }, + "contracts/amm/helper/test/TestMathUtils.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.6.12;\n\nimport \"../../MathUtils.sol\";\n\ncontract TestMathUtils {\n using MathUtils for uint256;\n\n function difference(uint256 a, uint256 b) public pure returns (uint256) {\n return a.difference(b);\n }\n\n function within1(uint256 a, uint256 b) public pure returns (bool) {\n return a.within1(b);\n }\n}\n" + }, + "contracts/bridge/ERC20Migrator.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.6.12;\n\nimport \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/SafeERC20.sol\";\nimport \"@openzeppelin/contracts/math/SafeMath.sol\";\n\n/**\n * @title ERC20Migrator\n * @dev This contract can be used to migrate an ERC20 token from one\n * contract to another, where each token holder has to opt-in to the migration.\n * To opt-in, users must approve for this contract the number of tokens they\n * want to migrate. Once the allowance is set up, anyone can trigger the\n * migration to the new token contract. In this way, token holders \"turn in\"\n * their old balance and will be minted an equal amount in the new token.\n * The new token contract must be mintable.\n * ```\n */\n\ninterface IERC20Mintable is IERC20 {\n function mint(address to, uint256 amount) external;\n}\n\ncontract ERC20Migrator {\n using SafeERC20 for IERC20;\n using SafeMath for uint256;\n\n // Address of the old token contract\n IERC20 private _legacyToken;\n\n // Address of the new token contract\n IERC20Mintable private _newToken;\n\n /**\n * @param legacyToken address of the old token contract\n */\n constructor(IERC20 legacyToken, IERC20Mintable newToken) public {\n _legacyToken = legacyToken;\n _newToken = newToken;\n }\n\n /**\n * @dev Returns the legacy token that is being migrated.\n */\n function legacyToken() external view returns (IERC20) {\n return _legacyToken;\n }\n\n /**\n * @dev Returns the new token to which we are migrating.\n */\n function newToken() external view returns (IERC20) {\n return _newToken;\n }\n\n /**\n * @dev Transfers part of an account's balance in the old token to this\n * contract, and mints the same amount of new tokens for that account.\n * @param amount amount of tokens to be migrated\n */\n function migrate(uint256 amount) external {\n _legacyToken.safeTransferFrom(msg.sender, address(this), amount);\n uint256 amountToMint = amount.mul(5).div(2);\n _newToken.mint(msg.sender, amountToMint);\n }\n}\n" + }, + "contracts/bridge/ECDSANodeManagement.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.6.12;\n\nimport \"./utils/AddressArrayUtils.sol\";\nimport \"@openzeppelin/contracts/math/SafeMath.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/SafeERC20.sol\";\n\ncontract ECDSANodeManagement {\n using AddressArrayUtils for address[];\n using SafeMath for uint256;\n using SafeERC20 for IERC20;\n\n // Status of the keep.\n // Active means the keep is active.\n // Closed means the keep was closed happily.\n // Terminated means the keep was closed due to misbehavior.\n enum Status {\n Active,\n Closed,\n Terminated\n }\n\n // Address of the keep's owner.\n address public owner;\n\n // List of keep members' addresses.\n address[] public members;\n\n // Minimum number of honest keep members required to produce a signature.\n uint256 public honestThreshold;\n\n // Keep's ECDSA public key serialized to 64-bytes, where X and Y coordinates\n // are padded with zeros to 32-byte each.\n bytes public publicKey;\n\n // The timestamp at which keep has been created and key generation process\n // started.\n uint256 internal keyGenerationStartTimestamp;\n\n // Map stores public key by member addresses. All members should submit the\n // same public key.\n mapping(address => bytes) internal submittedPublicKeys;\n\n // The current status of the keep.\n // If the keep is Active members monitor it and support requests from the\n // keep owner.\n // If the owner decides to close the keep the flag is set to Closed.\n // If the owner seizes member bonds the flag is set to Terminated.\n Status internal status;\n\n // Flags execution of contract initialization.\n bool internal isInitialized;\n\n // Notification that the submitted public key does not match a key submitted\n // by other member. The event contains address of the member who tried to\n // submit a public key and a conflicting public key submitted already by other\n // member.\n event ConflictingPublicKeySubmitted(\n address indexed submittingMember,\n bytes conflictingPublicKey\n );\n\n // Notification that keep's ECDSA public key has been successfully established.\n event PublicKeyPublished(bytes publicKey);\n\n // Notification that the keep was closed by the owner.\n // Members no longer need to support this keep.\n event KeepClosed();\n\n // Notification that the keep has been terminated by the owner.\n // Members no longer need to support this keep.\n event KeepTerminated();\n\n /// @notice Returns keep's ECDSA public key.\n /// @return Keep's ECDSA public key.\n function getPublicKey() external view returns (bytes memory) {\n return publicKey;\n }\n\n /// @notice Submits a public key to the keep.\n /// @dev Public key is published successfully if all members submit the same\n /// value. In case of conflicts with others members submissions it will emit\n /// `ConflictingPublicKeySubmitted` event. When all submitted keys match\n /// it will store the key as keep's public key and emit a `PublicKeyPublished`\n /// event.\n /// @param _publicKey Signer's public key.\n function submitPublicKey(bytes calldata _publicKey) external onlyMember {\n require(\n !hasMemberSubmittedPublicKey(msg.sender),\n \"Member already submitted a public key\"\n );\n\n require(_publicKey.length == 64, \"Public key must be 64 bytes long\");\n\n submittedPublicKeys[msg.sender] = _publicKey;\n\n // Check if public keys submitted by all keep members are the same as\n // the currently submitted one.\n uint256 matchingPublicKeysCount = 0;\n for (uint256 i = 0; i < members.length; i++) {\n if (\n keccak256(submittedPublicKeys[members[i]]) !=\n keccak256(_publicKey)\n ) {\n // Emit an event only if compared member already submitted a value.\n if (hasMemberSubmittedPublicKey(members[i])) {\n emit ConflictingPublicKeySubmitted(\n msg.sender,\n submittedPublicKeys[members[i]]\n );\n }\n } else {\n matchingPublicKeysCount++;\n }\n }\n\n if (matchingPublicKeysCount != members.length) {\n return;\n }\n\n // All submitted signatures match.\n publicKey = _publicKey;\n emit PublicKeyPublished(_publicKey);\n }\n\n /// @notice Gets the owner of the keep.\n /// @return Address of the keep owner.\n function getOwner() external view returns (address) {\n return owner;\n }\n\n /// @notice Gets the timestamp the keep was opened at.\n /// @return Timestamp the keep was opened at.\n function getOpenedTimestamp() external view returns (uint256) {\n return keyGenerationStartTimestamp;\n }\n\n /// @notice Closes keep when owner decides that they no longer need it.\n /// Releases bonds to the keep members.\n /// @dev The function can be called only by the owner of the keep and only\n /// if the keep has not been already closed.\n function closeKeep() public onlyOwner onlyWhenActive {\n markAsClosed();\n }\n\n /// @notice Returns true if the keep is active.\n /// @return true if the keep is active, false otherwise.\n function isActive() public view returns (bool) {\n return status == Status.Active;\n }\n\n /// @notice Returns true if the keep is closed and members no longer support\n /// this keep.\n /// @return true if the keep is closed, false otherwise.\n function isClosed() public view returns (bool) {\n return status == Status.Closed;\n }\n\n /// @notice Returns true if the keep has been terminated.\n /// Keep is terminated when bonds are seized and members no longer support\n /// this keep.\n /// @return true if the keep has been terminated, false otherwise.\n function isTerminated() public view returns (bool) {\n return status == Status.Terminated;\n }\n\n /// @notice Returns members of the keep.\n /// @return List of the keep members' addresses.\n function getMembers() public view returns (address[] memory) {\n return members;\n }\n\n /// @notice Initialization function.\n /// @dev We use clone factory to create new keep. That is why this contract\n /// doesn't have a constructor. We provide keep parameters for each instance\n /// function after cloning instances from the master contract.\n /// Initialization must happen in the same transaction in which the clone is\n /// created.\n /// @param _owner Address of the keep owner.\n /// @param _members Addresses of the keep members.\n /// @param _honestThreshold Minimum number of honest keep members.\n function initialize(\n address _owner,\n address[] memory _members,\n uint256 _honestThreshold\n ) public {\n require(!isInitialized, \"Contract already initialized\");\n require(_owner != address(0));\n owner = _owner;\n members = _members;\n honestThreshold = _honestThreshold;\n\n status = Status.Active;\n isInitialized = true;\n\n /* solium-disable-next-line security/no-block-members*/\n keyGenerationStartTimestamp = block.timestamp;\n }\n\n /// @notice Checks if the member already submitted a public key.\n /// @param _member Address of the member.\n /// @return True if member already submitted a public key, else false.\n function hasMemberSubmittedPublicKey(address _member)\n internal\n view\n returns (bool)\n {\n return submittedPublicKeys[_member].length != 0;\n }\n\n /// @notice Marks the keep as closed.\n /// Keep can be marked as closed only when there is no signing in progress\n /// or the requested signing process has timed out.\n function markAsClosed() internal {\n status = Status.Closed;\n emit KeepClosed();\n }\n\n /// @notice Marks the keep as terminated.\n /// Keep can be marked as terminated only when there is no signing in progress\n /// or the requested signing process has timed out.\n function markAsTerminated() internal {\n status = Status.Terminated;\n emit KeepTerminated();\n }\n\n /// @notice Coverts a public key to an ethereum address.\n /// @param _publicKey Public key provided as 64-bytes concatenation of\n /// X and Y coordinates (32-bytes each).\n /// @return Ethereum address.\n function publicKeyToAddress(bytes memory _publicKey)\n internal\n pure\n returns (address)\n {\n // We hash the public key and then truncate last 20 bytes of the digest\n // which is the ethereum address.\n return address(uint160(uint256(keccak256(_publicKey))));\n }\n\n /// @notice Terminates the keep.\n function terminateKeep() internal {\n markAsTerminated();\n }\n\n /// @notice Checks if the caller is the keep's owner.\n /// @dev Throws an error if called by any account other than owner.\n modifier onlyOwner() {\n require(owner == msg.sender, \"Caller is not the keep owner\");\n _;\n }\n\n /// @notice Checks if the caller is a keep member.\n /// @dev Throws an error if called by any account other than one of the members.\n modifier onlyMember() {\n require(members.contains(msg.sender), \"Caller is not the keep member\");\n _;\n }\n\n /// @notice Checks if the keep is currently active.\n /// @dev Throws an error if called when the keep has been already closed.\n modifier onlyWhenActive() {\n require(isActive(), \"Keep is not active\");\n _;\n }\n}\n" + }, + "contracts/bridge/utils/AddressArrayUtils.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.6.12;\n\nlibrary AddressArrayUtils {\n function contains(address[] memory self, address _address)\n internal\n pure\n returns (bool)\n {\n for (uint256 i = 0; i < self.length; i++) {\n if (_address == self[i]) {\n return true;\n }\n }\n return false;\n }\n}" + }, + "contracts/bridge/BridgeConfigV3.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.6.12;\npragma experimental ABIEncoderV2;\n\nimport \"@openzeppelin/contracts/access/AccessControl.sol\";\nimport \"@openzeppelin/contracts/math/SafeMath.sol\";\n\n/**\n * @title BridgeConfig contract\n * @notice This token is used for configuring different tokens on the bridge and mapping them across chains.\n **/\n\ncontract BridgeConfigV3 is AccessControl {\n using SafeMath for uint256;\n bytes32 public constant BRIDGEMANAGER_ROLE =\n keccak256(\"BRIDGEMANAGER_ROLE\");\n bytes32[] private _allTokenIDs;\n mapping(bytes32 => Token[]) private _allTokens; // key is tokenID\n mapping(uint256 => mapping(string => bytes32)) private _tokenIDMap; // key is chainID,tokenAddress\n mapping(bytes32 => mapping(uint256 => Token)) private _tokens; // key is tokenID,chainID\n mapping(address => mapping(uint256 => Pool)) private _pool; // key is tokenAddress,chainID\n mapping(uint256 => uint256) private _maxGasPrice; // key is tokenID,chainID\n uint256 public constant bridgeConfigVersion = 3;\n\n // the denominator used to calculate fees. For example, an\n // LP fee might be something like tradeAmount.mul(fee).div(FEE_DENOMINATOR)\n uint256 private constant FEE_DENOMINATOR = 10**10;\n\n // this struct must be initialized using setTokenConfig for each token that directly interacts with the bridge\n struct Token {\n uint256 chainId;\n string tokenAddress;\n uint8 tokenDecimals;\n uint256 maxSwap;\n uint256 minSwap;\n uint256 swapFee;\n uint256 maxSwapFee;\n uint256 minSwapFee;\n bool hasUnderlying;\n bool isUnderlying;\n }\n\n struct Pool {\n address tokenAddress;\n uint256 chainId;\n address poolAddress;\n bool metaswap;\n }\n\n constructor() public {\n _setupRole(DEFAULT_ADMIN_ROLE, msg.sender);\n }\n\n /**\n * @notice Returns a list of all existing token IDs converted to strings\n */\n function getAllTokenIDs() public view returns (string[] memory result) {\n uint256 length = _allTokenIDs.length;\n result = new string[](length);\n for (uint256 i = 0; i < length; ++i) {\n result[i] = toString(_allTokenIDs[i]);\n }\n }\n\n function _getTokenID(string memory tokenAddress, uint256 chainID)\n internal\n view\n returns (string memory)\n {\n return toString(_tokenIDMap[chainID][tokenAddress]);\n }\n\n function getTokenID(string memory tokenAddress, uint256 chainID)\n public\n view\n returns (string memory)\n {\n return _getTokenID(_toLower(tokenAddress), chainID);\n }\n\n /**\n * @notice Returns the token ID (string) of the cross-chain token inputted\n * @param tokenAddress address of token to get ID for\n * @param chainID chainID of which to get token ID for\n */\n function getTokenID(address tokenAddress, uint256 chainID)\n public\n view\n returns (string memory)\n {\n return _getTokenID(_toLower(toString(tokenAddress)), chainID);\n }\n\n /**\n * @notice Returns the full token config struct\n * @param tokenID String input of the token ID for the token\n * @param chainID Chain ID of which token address + config to get\n */\n function getToken(string memory tokenID, uint256 chainID)\n public\n view\n returns (Token memory token)\n {\n return _tokens[toBytes32(tokenID)][chainID];\n }\n\n /**\n * @notice Returns the full token config struct\n * @param tokenID String input of the token ID for the token\n * @param chainID Chain ID of which token address + config to get\n */\n function getTokenByID(string memory tokenID, uint256 chainID)\n public\n view\n returns (Token memory token)\n {\n return _tokens[toBytes32(tokenID)][chainID];\n }\n\n /**\n * @notice Returns token config struct, given an address and chainID\n * @param tokenAddress Matches the token ID by using a combo of address + chain ID\n * @param chainID Chain ID of which token to get config for\n */\n function getTokenByAddress(string memory tokenAddress, uint256 chainID)\n public\n view\n returns (Token memory token)\n {\n return _tokens[_tokenIDMap[chainID][_toLower(tokenAddress)]][chainID];\n }\n\n function getTokenByEVMAddress(address tokenAddress, uint256 chainID)\n public\n view\n returns (Token memory token)\n {\n return\n _tokens[_tokenIDMap[chainID][_toLower(toString(tokenAddress))]][\n chainID\n ];\n }\n\n /**\n * @notice Returns true if the token has an underlying token -- meaning the token is deposited into the bridge\n * @param tokenID String to check if it is a withdraw/underlying token\n */\n function hasUnderlyingToken(string memory tokenID)\n public\n view\n returns (bool)\n {\n bytes32 bytesTokenID = toBytes32(tokenID);\n Token[] memory _mcTokens = _allTokens[bytesTokenID];\n for (uint256 i = 0; i < _mcTokens.length; ++i) {\n if (_mcTokens[i].hasUnderlying) {\n return true;\n }\n }\n return false;\n }\n\n /**\n * @notice Returns which token is the underlying token to withdraw\n * @param tokenID string token ID\n */\n function getUnderlyingToken(string memory tokenID)\n public\n view\n returns (Token memory token)\n {\n bytes32 bytesTokenID = toBytes32(tokenID);\n Token[] memory _mcTokens = _allTokens[bytesTokenID];\n for (uint256 i = 0; i < _mcTokens.length; ++i) {\n if (_mcTokens[i].isUnderlying) {\n return _mcTokens[i];\n }\n }\n }\n\n /**\n @notice Public function returning if token ID exists given a string\n */\n function isTokenIDExist(string memory tokenID) public view returns (bool) {\n return _isTokenIDExist(toBytes32(tokenID));\n }\n\n /**\n @notice Internal function returning if token ID exists given bytes32 version of the ID\n */\n function _isTokenIDExist(bytes32 tokenID) internal view returns (bool) {\n for (uint256 i = 0; i < _allTokenIDs.length; ++i) {\n if (_allTokenIDs[i] == tokenID) {\n return true;\n }\n }\n return false;\n }\n\n /**\n * @notice Internal function which handles logic of setting token ID and dealing with mappings\n * @param tokenID bytes32 version of ID\n * @param chainID which chain to set the token config for\n * @param tokenToAdd Token object to set the mapping to\n */\n function _setTokenConfig(\n bytes32 tokenID,\n uint256 chainID,\n Token memory tokenToAdd\n ) internal returns (bool) {\n _tokens[tokenID][chainID] = tokenToAdd;\n if (!_isTokenIDExist(tokenID)) {\n _allTokenIDs.push(tokenID);\n }\n\n Token[] storage _mcTokens = _allTokens[tokenID];\n for (uint256 i = 0; i < _mcTokens.length; ++i) {\n if (_mcTokens[i].chainId == chainID) {\n string memory oldToken = _mcTokens[i].tokenAddress;\n if (!compareStrings(tokenToAdd.tokenAddress, oldToken)) {\n _mcTokens[i].tokenAddress = tokenToAdd.tokenAddress;\n _tokenIDMap[chainID][oldToken] = keccak256(\"\");\n _tokenIDMap[chainID][tokenToAdd.tokenAddress] = tokenID;\n }\n }\n }\n _mcTokens.push(tokenToAdd);\n _tokenIDMap[chainID][tokenToAdd.tokenAddress] = tokenID;\n return true;\n }\n\n /**\n * @notice Main write function of this contract - Handles creating the struct and passing it to the internal logic function\n * @param tokenID string ID to set the token config object form\n * @param chainID chain ID to use for the token config object\n * @param tokenAddress token address of the token on the given chain\n * @param tokenDecimals decimals of token\n * @param maxSwap maximum amount of token allowed to be transferred at once - in native token decimals\n * @param minSwap minimum amount of token needed to be transferred at once - in native token decimals\n * @param swapFee percent based swap fee -- 10e6 == 10bps\n * @param maxSwapFee max swap fee to be charged - in native token decimals\n * @param minSwapFee min swap fee to be charged - in native token decimals - especially useful for mainnet ETH\n * @param hasUnderlying bool which represents whether this is a global mint token or one to withdraw()\n * @param isUnderlying bool which represents if this token is the one to withdraw on the given chain\n */\n function setTokenConfig(\n string calldata tokenID,\n uint256 chainID,\n address tokenAddress,\n uint8 tokenDecimals,\n uint256 maxSwap,\n uint256 minSwap,\n uint256 swapFee,\n uint256 maxSwapFee,\n uint256 minSwapFee,\n bool hasUnderlying,\n bool isUnderlying\n ) public returns (bool) {\n require(hasRole(BRIDGEMANAGER_ROLE, msg.sender));\n return\n setTokenConfig(\n tokenID,\n chainID,\n toString(tokenAddress),\n tokenDecimals,\n maxSwap,\n minSwap,\n swapFee,\n maxSwapFee,\n minSwapFee,\n hasUnderlying,\n isUnderlying\n );\n }\n\n /**\n * @notice Main write function of this contract - Handles creating the struct and passing it to the internal logic function\n * @param tokenID string ID to set the token config object form\n * @param chainID chain ID to use for the token config object\n * @param tokenAddress token address of the token on the given chain\n * @param tokenDecimals decimals of token\n * @param maxSwap maximum amount of token allowed to be transferred at once - in native token decimals\n * @param minSwap minimum amount of token needed to be transferred at once - in native token decimals\n * @param swapFee percent based swap fee -- 10e6 == 10bps\n * @param maxSwapFee max swap fee to be charged - in native token decimals\n * @param minSwapFee min swap fee to be charged - in native token decimals - especially useful for mainnet ETH\n * @param hasUnderlying bool which represents whether this is a global mint token or one to withdraw()\n * @param isUnderlying bool which represents if this token is the one to withdraw on the given chain\n */\n function setTokenConfig(\n string calldata tokenID,\n uint256 chainID,\n string memory tokenAddress,\n uint8 tokenDecimals,\n uint256 maxSwap,\n uint256 minSwap,\n uint256 swapFee,\n uint256 maxSwapFee,\n uint256 minSwapFee,\n bool hasUnderlying,\n bool isUnderlying\n ) public returns (bool) {\n require(hasRole(BRIDGEMANAGER_ROLE, msg.sender));\n Token memory tokenToAdd;\n tokenToAdd.tokenAddress = _toLower(tokenAddress);\n tokenToAdd.tokenDecimals = tokenDecimals;\n tokenToAdd.maxSwap = maxSwap;\n tokenToAdd.minSwap = minSwap;\n tokenToAdd.swapFee = swapFee;\n tokenToAdd.maxSwapFee = maxSwapFee;\n tokenToAdd.minSwapFee = minSwapFee;\n tokenToAdd.hasUnderlying = hasUnderlying;\n tokenToAdd.isUnderlying = isUnderlying;\n tokenToAdd.chainId = chainID;\n\n return _setTokenConfig(toBytes32(tokenID), chainID, tokenToAdd);\n }\n\n function _calculateSwapFee(\n string memory tokenAddress,\n uint256 chainID,\n uint256 amount\n ) internal view returns (uint256) {\n Token memory token = _tokens[_tokenIDMap[chainID][tokenAddress]][\n chainID\n ];\n uint256 calculatedSwapFee = amount.mul(token.swapFee).div(\n FEE_DENOMINATOR\n );\n if (\n calculatedSwapFee > token.minSwapFee &&\n calculatedSwapFee < token.maxSwapFee\n ) {\n return calculatedSwapFee;\n } else if (calculatedSwapFee > token.maxSwapFee) {\n return token.maxSwapFee;\n } else {\n return token.minSwapFee;\n }\n }\n\n /**\n * @notice Calculates bridge swap fee based on the destination chain's token transfer.\n * @dev This means the fee should be calculated based on the chain that the nodes emit a tx on\n * @param tokenAddress address of the destination token to query token config for\n * @param chainID destination chain ID to query the token config for\n * @param amount in native token decimals\n * @return Fee calculated in token decimals\n */\n function calculateSwapFee(\n string memory tokenAddress,\n uint256 chainID,\n uint256 amount\n ) external view returns (uint256) {\n return _calculateSwapFee(_toLower(tokenAddress), chainID, amount);\n }\n\n /**\n * @notice Calculates bridge swap fee based on the destination chain's token transfer.\n * @dev This means the fee should be calculated based on the chain that the nodes emit a tx on\n * @param tokenAddress address of the destination token to query token config for\n * @param chainID destination chain ID to query the token config for\n * @param amount in native token decimals\n * @return Fee calculated in token decimals\n */\n function calculateSwapFee(\n address tokenAddress,\n uint256 chainID,\n uint256 amount\n ) external view returns (uint256) {\n return\n _calculateSwapFee(\n _toLower(toString(tokenAddress)),\n chainID,\n amount\n );\n }\n\n // GAS PRICING\n\n /**\n * @notice sets the max gas price for a chain\n */\n function setMaxGasPrice(uint256 chainID, uint256 maxPrice) public {\n require(hasRole(BRIDGEMANAGER_ROLE, msg.sender));\n _maxGasPrice[chainID] = maxPrice;\n }\n\n /**\n * @notice gets the max gas price for a chain\n */\n function getMaxGasPrice(uint256 chainID) public view returns (uint256) {\n return _maxGasPrice[chainID];\n }\n\n // POOL CONFIG\n\n function getPoolConfig(address tokenAddress, uint256 chainID)\n external\n view\n returns (Pool memory)\n {\n return _pool[tokenAddress][chainID];\n }\n\n function setPoolConfig(\n address tokenAddress,\n uint256 chainID,\n address poolAddress,\n bool metaswap\n ) external returns (Pool memory) {\n require(\n hasRole(BRIDGEMANAGER_ROLE, msg.sender),\n \"Caller is not Bridge Manager\"\n );\n Pool memory newPool = Pool(\n tokenAddress,\n chainID,\n poolAddress,\n metaswap\n );\n _pool[tokenAddress][chainID] = newPool;\n return newPool;\n }\n\n // UTILITY FUNCTIONS\n\n function toString(bytes32 data) internal pure returns (string memory) {\n uint8 i = 0;\n while (i < 32 && data[i] != 0) {\n ++i;\n }\n bytes memory bs = new bytes(i);\n for (uint8 j = 0; j < i; ++j) {\n bs[j] = data[j];\n }\n return string(bs);\n }\n\n // toBytes32 converts a string to a bytes 32\n function toBytes32(string memory str)\n internal\n pure\n returns (bytes32 result)\n {\n require(bytes(str).length <= 32);\n assembly {\n result := mload(add(str, 32))\n }\n }\n\n function toString(address x) internal pure returns (string memory) {\n bytes memory s = new bytes(40);\n for (uint256 i = 0; i < 20; i++) {\n bytes1 b = bytes1(uint8(uint256(uint160(x)) / (2**(8 * (19 - i)))));\n bytes1 hi = bytes1(uint8(b) / 16);\n bytes1 lo = bytes1(uint8(b) - 16 * uint8(hi));\n s[2 * i] = char(hi);\n s[2 * i + 1] = char(lo);\n }\n\n string memory addrPrefix = \"0x\";\n\n return concat(addrPrefix, string(s));\n }\n\n function concat(string memory _x, string memory _y)\n internal\n pure\n returns (string memory)\n {\n bytes memory _xBytes = bytes(_x);\n bytes memory _yBytes = bytes(_y);\n\n string memory _tmpValue = new string(_xBytes.length + _yBytes.length);\n bytes memory _newValue = bytes(_tmpValue);\n\n uint256 i;\n uint256 j;\n\n for (i = 0; i < _xBytes.length; i++) {\n _newValue[j++] = _xBytes[i];\n }\n\n for (i = 0; i < _yBytes.length; i++) {\n _newValue[j++] = _yBytes[i];\n }\n\n return string(_newValue);\n }\n\n function char(bytes1 b) internal pure returns (bytes1 c) {\n if (uint8(b) < 10) {\n c = bytes1(uint8(b) + 0x30);\n } else {\n c = bytes1(uint8(b) + 0x57);\n }\n }\n\n function compareStrings(string memory a, string memory b)\n internal\n pure\n returns (bool)\n {\n return (keccak256(abi.encodePacked((a))) ==\n keccak256(abi.encodePacked((b))));\n }\n\n function _toLower(string memory str) internal pure returns (string memory) {\n bytes memory bStr = bytes(str);\n bytes memory bLower = new bytes(bStr.length);\n for (uint256 i = 0; i < bStr.length; i++) {\n // Uppercase character...\n if ((uint8(bStr[i]) >= 65) && (uint8(bStr[i]) <= 90)) {\n // So we add 32 to make it lowercase\n bLower[i] = bytes1(uint8(bStr[i]) + 32);\n } else {\n bLower[i] = bStr[i];\n }\n }\n return string(bLower);\n }\n}\n" + }, + "contracts/bridge/mocks/ERC20Mock.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.6.12;\n\nimport \"@openzeppelin/contracts/token/ERC20/ERC20.sol\";\n\ncontract ERC20Mock is ERC20 {\n constructor(\n string memory name,\n string memory symbol,\n uint256 supply\n ) public ERC20(name, symbol) {\n _mint(msg.sender, supply);\n }\n\n function mint(address to, uint256 amount) external {\n _mint(to, amount);\n }\n}" + }, + "contracts/bridge/interfaces/IMetaSwapDeposit.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.6.12;\nimport '@openzeppelin/contracts/token/ERC20/ERC20.sol';\n\n/**\n * @title IMetaSwapDeposit interface\n * @notice Interface for the meta swap contract.\n * @dev implement this interface to develop a a factory-patterned ECDSA node management contract\n **/\ninterface IMetaSwapDeposit {\n // min return calculation functions\n function calculateSwap(\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx\n ) external view returns (uint256);\n\n function swap(\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx,\n uint256 minDy,\n uint256 deadline\n ) external returns (uint256);\n\n function getToken(uint256 index) external view returns (IERC20);\n}\n" + }, + "contracts/amm/interfaces/IMetaSwapDeposit.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.6.12;\n\nimport \"@openzeppelin/contracts/token/ERC20/ERC20.sol\";\nimport \"./ISwap.sol\";\nimport \"./IMetaSwap.sol\";\n\ninterface IMetaSwapDeposit {\n function initialize(\n ISwap baseSwap_,\n IMetaSwap metaSwap_,\n IERC20 metaLPToken_\n ) external;\n}\n" + }, + "contracts/amm/interfaces/IMetaSwap.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.6.12;\n\nimport \"@openzeppelin/contracts/token/ERC20/ERC20.sol\";\n\ninterface IMetaSwap {\n // pool data view functions\n function getA() external view returns (uint256);\n\n function getToken(uint8 index) external view returns (IERC20);\n\n function getTokenIndex(address tokenAddress) external view returns (uint8);\n\n function getTokenBalance(uint8 index) external view returns (uint256);\n\n function getVirtualPrice() external view returns (uint256);\n\n function isGuarded() external view returns (bool);\n\n // min return calculation functions\n function calculateSwap(\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx\n ) external view returns (uint256);\n\n function calculateSwapUnderlying(\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx\n ) external view returns (uint256);\n\n function calculateTokenAmount(uint256[] calldata amounts, bool deposit)\n external\n view\n returns (uint256);\n\n function calculateRemoveLiquidity(uint256 amount)\n external\n view\n returns (uint256[] memory);\n\n function calculateRemoveLiquidityOneToken(\n uint256 tokenAmount,\n uint8 tokenIndex\n ) external view returns (uint256 availableTokenAmount);\n\n // state modifying functions\n function initializeMetaSwap(\n IERC20[] memory pooledTokens,\n uint8[] memory decimals,\n string memory lpTokenName,\n string memory lpTokenSymbol,\n uint256 a,\n uint256 fee,\n uint256 adminFee,\n address lpTokenTargetAddress,\n address baseSwap\n ) external;\n\n function swap(\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx,\n uint256 minDy,\n uint256 deadline\n ) external returns (uint256);\n\n function swapUnderlying(\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx,\n uint256 minDy,\n uint256 deadline\n ) external returns (uint256);\n\n function addLiquidity(\n uint256[] calldata amounts,\n uint256 minToMint,\n uint256 deadline\n ) external returns (uint256);\n\n function removeLiquidity(\n uint256 amount,\n uint256[] calldata minAmounts,\n uint256 deadline\n ) external returns (uint256[] memory);\n\n function removeLiquidityOneToken(\n uint256 tokenAmount,\n uint8 tokenIndex,\n uint256 minAmount,\n uint256 deadline\n ) external returns (uint256);\n\n function removeLiquidityImbalance(\n uint256[] calldata amounts,\n uint256 maxBurnAmount,\n uint256 deadline\n ) external returns (uint256);\n\n function swapStorage()\n external\n view\n returns (\n uint256 initialA,\n uint256 futureA,\n uint256 initialATime,\n uint256 futureATime,\n uint256 swapFee,\n uint256 adminFee,\n address lpToken\n );\n}\n" + }, + "contracts/amm/helper/GenericERC20.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.6.12;\n\nimport \"@openzeppelin/contracts/token/ERC20/ERC20.sol\";\nimport \"@openzeppelin/contracts/access/Ownable.sol\";\n\n/**\n * @title Generic ERC20 token\n * @notice This contract simulates a generic ERC20 token that is mintable and burnable.\n */\ncontract GenericERC20 is ERC20, Ownable {\n /**\n * @notice Deploy this contract with given name, symbol, and decimals\n * @dev the caller of this constructor will become the owner of this contract\n * @param name_ name of this token\n * @param symbol_ symbol of this token\n * @param decimals_ number of decimals this token will be based on\n */\n constructor(\n string memory name_,\n string memory symbol_,\n uint8 decimals_\n ) public ERC20(name_, symbol_) {\n _setupDecimals(decimals_);\n }\n\n /**\n * @notice Mints given amount of tokens to recipient\n * @dev only owner can call this mint function\n * @param recipient address of account to receive the tokens\n * @param amount amount of tokens to mint\n */\n function mint(address recipient, uint256 amount) external onlyOwner {\n require(amount != 0, \"amount == 0\");\n _mint(recipient, amount);\n }\n}\n" + }, + "contracts/amm/SwapEthWrapper.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.6.12;\n\nimport \"@openzeppelin/contracts/math/SafeMath.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/SafeERC20.sol\";\nimport \"./Swap.sol\";\nimport \"./interfaces/IWETH9.sol\";\n\n/**\n * @title SwapEthWrapper\n * @notice A wrapper contract for Swap contracts that have WETH as one of the pooled tokens.\n * @author Jongseung Lim (@weeb_mcgee)\n */\ncontract SwapEthWrapper {\n using SafeERC20 for IERC20;\n using SafeMath for uint256;\n\n // constants\n uint8 private constant MAX_UINT8 = 2**8 - 1;\n uint256 private constant MAX_UINT256 = 2**256 - 1;\n\n // immutables\n Swap public immutable SWAP;\n LPToken public immutable LP_TOKEN;\n address payable public immutable WETH_ADDRESS;\n address public immutable OWNER;\n uint8 public immutable WETH_INDEX;\n\n IERC20[] public pooledTokens;\n\n /**\n * @notice Deploys this contract with given WETH9 address and Swap address. It will attempt to\n * fetch information about the given Swap pool. If the Swap pool does not contain WETH9,\n * this call will be reverted. Owner address must be given so that `rescue()` function\n * can be limited.\n * @param wethAddress address to the WETH9 contract\n * @param swap address to the Swap contract that has WETH9 as one of the tokens\n * @param owner address that will be allowed to call `rescue()`\n */\n constructor(\n address payable wethAddress,\n Swap swap,\n address owner\n ) public {\n (, , , , , , LPToken lpToken) = swap.swapStorage();\n uint8 wethIndex = MAX_UINT8;\n\n for (uint8 i = 0; i < MAX_UINT8; i++) {\n try swap.getToken(i) returns (IERC20 token) {\n pooledTokens.push(token);\n if (address(token) == wethAddress) {\n wethIndex = i;\n }\n // Approve pooled tokens to be used by Swap\n token.approve(address(swap), MAX_UINT256);\n } catch {\n break;\n }\n }\n require(wethIndex != MAX_UINT8, \"WETH was not found in the swap pool\");\n\n // Set immutable variables\n WETH_INDEX = wethIndex;\n WETH_ADDRESS = wethAddress;\n SWAP = swap;\n LP_TOKEN = lpToken;\n OWNER = owner;\n\n // Approve LPToken to be used by Swap\n lpToken.approve(address(swap), MAX_UINT256);\n }\n\n /**\n * @notice Add liquidity to the pool with the given amounts of tokens.\n * @dev The msg.value of this call should match the value in amounts array\n * in position of WETH9.\n * @param amounts the amounts of each token to add, in their native precision\n * @param minToMint the minimum LP tokens adding this amount of liquidity\n * should mint, otherwise revert. Handy for front-running mitigation\n * @param deadline latest timestamp to accept this transaction\n * @return amount of LP token user minted and received\n */\n function addLiquidity(\n uint256[] memory amounts,\n uint256 minToMint,\n uint256 deadline\n ) external payable returns (uint256) {\n // If using ETH, deposit them to WETH.\n require(msg.value == amounts[WETH_INDEX], \"INCORRECT_MSG_VALUE\");\n if (msg.value > 0) {\n IWETH9(WETH_ADDRESS).deposit{value: msg.value}();\n }\n // Go through amounts array and transfer respective tokens to this contract.\n for (uint256 i = 0; i < amounts.length; i++) {\n uint256 amount = amounts[i];\n if (i != WETH_INDEX && amount > 0) {\n pooledTokens[i].safeTransferFrom(\n msg.sender,\n address(this),\n amount\n );\n }\n }\n // Add the assets to the pool\n uint256 lpTokenAmount = SWAP.addLiquidity(amounts, minToMint, deadline);\n // Send the LPToken to msg.sender\n IERC20(address(LP_TOKEN)).safeTransfer(msg.sender, lpTokenAmount);\n return lpTokenAmount;\n }\n\n /**\n * @notice Burn LP tokens to remove liquidity from the pool.\n * @dev Liquidity can always be removed, even when the pool is paused. Caller\n * will receive ETH instead of WETH9.\n * @param amount the amount of LP tokens to burn\n * @param minAmounts the minimum amounts of each token in the pool\n * acceptable for this burn. Useful as a front-running mitigation\n * @param deadline latest timestamp to accept this transaction\n * @return amounts of tokens user received\n */\n function removeLiquidity(\n uint256 amount,\n uint256[] calldata minAmounts,\n uint256 deadline\n ) external returns (uint256[] memory) {\n // Transfer LPToken from msg.sender to this contract.\n IERC20(address(LP_TOKEN)).safeTransferFrom(\n msg.sender,\n address(this),\n amount\n );\n // Remove liquidity\n uint256[] memory amounts = SWAP.removeLiquidity(\n amount,\n minAmounts,\n deadline\n );\n // Send the tokens back to the user\n for (uint256 i = 0; i < amounts.length; i++) {\n if (i != WETH_INDEX) {\n pooledTokens[i].safeTransfer(msg.sender, amounts[i]);\n } else {\n IWETH9(WETH_ADDRESS).withdraw(amounts[i]);\n // slither-disable-next-line arbitrary-send\n (bool success, ) = msg.sender.call{value: amounts[i]}(\"\");\n require(success, \"ETH_TRANSFER_FAILED\");\n }\n }\n return amounts;\n }\n\n /**\n * @notice Remove liquidity from the pool all in one token.\n * @dev Caller will receive ETH instead of WETH9.\n * @param tokenAmount the amount of the token you want to receive\n * @param tokenIndex the index of the token you want to receive\n * @param minAmount the minimum amount to withdraw, otherwise revert\n * @param deadline latest timestamp to accept this transaction\n * @return amount of chosen token user received\n */\n function removeLiquidityOneToken(\n uint256 tokenAmount,\n uint8 tokenIndex,\n uint256 minAmount,\n uint256 deadline\n ) external returns (uint256) {\n // Transfer LPToken from msg.sender to this contract.\n IERC20(address(LP_TOKEN)).safeTransferFrom(\n msg.sender,\n address(this),\n tokenAmount\n );\n // Withdraw via single token\n uint256 amount = SWAP.removeLiquidityOneToken(\n tokenAmount,\n tokenIndex,\n minAmount,\n deadline\n );\n // Transfer the token to msg.sender accordingly\n if (tokenIndex != WETH_INDEX) {\n pooledTokens[tokenIndex].safeTransfer(msg.sender, amount);\n } else {\n IWETH9(WETH_ADDRESS).withdraw(amount);\n // slither-disable-next-line arbitrary-send\n (bool success, ) = msg.sender.call{value: amount}(\"\");\n require(success, \"ETH_TRANSFER_FAILED\");\n }\n return amount;\n }\n\n /**\n * @notice Remove liquidity from the pool, weighted differently than the\n * pool's current balances.\n * @dev Caller will receive ETH instead of WETH9.\n * @param amounts how much of each token to withdraw\n * @param maxBurnAmount the max LP token provider is willing to pay to\n * remove liquidity. Useful as a front-running mitigation.\n * @param deadline latest timestamp to accept this transaction\n * @return amount of LP tokens burned\n */\n function removeLiquidityImbalance(\n uint256[] calldata amounts,\n uint256 maxBurnAmount,\n uint256 deadline\n ) external returns (uint256) {\n // Transfer LPToken from msg.sender to this contract.\n IERC20(address(LP_TOKEN)).safeTransferFrom(\n msg.sender,\n address(this),\n maxBurnAmount\n );\n // Withdraw in imbalanced ratio\n uint256 burnedLpTokenAmount = SWAP.removeLiquidityImbalance(\n amounts,\n maxBurnAmount,\n deadline\n );\n // Send the tokens back to the user\n for (uint256 i = 0; i < amounts.length; i++) {\n if (i != WETH_INDEX) {\n pooledTokens[i].safeTransfer(msg.sender, amounts[i]);\n } else {\n IWETH9(WETH_ADDRESS).withdraw(amounts[i]);\n // slither-disable-next-line arbitrary-send\n (bool success, ) = msg.sender.call{value: amounts[i]}(\"\");\n require(success, \"ETH_TRANSFER_FAILED\");\n }\n }\n // Send any extra LP tokens back as well\n uint256 extraLpTokenAmount = maxBurnAmount.sub(burnedLpTokenAmount);\n if (extraLpTokenAmount > 0) {\n IERC20(address(LP_TOKEN)).safeTransfer(\n msg.sender,\n extraLpTokenAmount\n );\n }\n return burnedLpTokenAmount;\n }\n\n /**\n * @notice Swap two tokens using the underlying pool. If tokenIndexFrom\n * represents WETH9 in the pool, the caller must set msg.value equal to dx.\n * If the user is swapping to WETH9 in the pool, the user will receive ETH instead.\n * @param tokenIndexFrom the token the user wants to swap from\n * @param tokenIndexTo the token the user wants to swap to\n * @param dx the amount of tokens the user wants to swap from\n * @param minDy the min amount the user would like to receive, or revert.\n * @param deadline latest timestamp to accept this transaction\n */\n function swap(\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx,\n uint256 minDy,\n uint256 deadline\n ) external payable returns (uint256) {\n // Transfer tokens from msg.sender to this contract\n if (tokenIndexFrom != WETH_INDEX) {\n IERC20(pooledTokens[tokenIndexFrom]).safeTransferFrom(\n msg.sender,\n address(this),\n dx\n );\n } else {\n require(msg.value == dx, \"INCORRECT_MSG_VALUE\");\n IWETH9(WETH_ADDRESS).deposit{value: msg.value}();\n }\n // Execute swap\n uint256 dy = SWAP.swap(\n tokenIndexFrom,\n tokenIndexTo,\n dx,\n minDy,\n deadline\n );\n // Transfer the swapped tokens to msg.sender\n if (tokenIndexTo != WETH_INDEX) {\n IERC20(pooledTokens[tokenIndexTo]).safeTransfer(msg.sender, dy);\n } else {\n IWETH9(WETH_ADDRESS).withdraw(dy);\n // slither-disable-next-line arbitrary-send\n (bool success, ) = msg.sender.call{value: dy}(\"\");\n require(success, \"ETH_TRANSFER_FAILED\");\n }\n return dy;\n }\n\n /**\n * @notice Rescues any of the ETH, the pooled tokens, or the LPToken that may be stuck\n * in this contract. Only the OWNER can call this function.\n */\n function rescue() external {\n require(msg.sender == OWNER, \"CALLED_BY_NON_OWNER\");\n IERC20[] memory tokens = pooledTokens;\n for (uint256 i = 0; i < tokens.length; i++) {\n tokens[i].safeTransfer(\n msg.sender,\n tokens[i].balanceOf(address(this))\n );\n }\n IERC20 lpToken_ = IERC20(address(LP_TOKEN));\n lpToken_.safeTransfer(msg.sender, lpToken_.balanceOf(address(this)));\n // slither-disable-next-line arbitrary-send\n (bool success, ) = msg.sender.call{value: address(this).balance}(\"\");\n require(success, \"ETH_TRANSFER_FAILED\");\n }\n\n receive() external payable {}\n\n // VIEW FUNCTIONS\n\n /**\n * @notice A simple method to calculate prices from deposits or\n * withdrawals, excluding fees but including slippage. This is\n * helpful as an input into the various \"min\" parameters on calls\n * to fight front-running\n *\n * @dev This shouldn't be used outside frontends for user estimates.\n *\n * @param amounts an array of token amounts to deposit or withdrawal,\n * corresponding to pooledTokens. The amount should be in each\n * pooled token's native precision. If a token charges a fee on transfers,\n * use the amount that gets transferred after the fee.\n * @param deposit whether this is a deposit or a withdrawal\n * @return token amount the user will receive\n */\n function calculateTokenAmount(uint256[] calldata amounts, bool deposit)\n external\n view\n returns (uint256)\n {\n return SWAP.calculateTokenAmount(amounts, deposit);\n }\n\n /**\n * @notice A simple method to calculate amount of each underlying\n * tokens that is returned upon burning given amount of LP tokens\n * @param amount the amount of LP tokens that would be burned on withdrawal\n * @return array of token balances that the user will receive\n */\n function calculateRemoveLiquidity(uint256 amount)\n external\n view\n returns (uint256[] memory)\n {\n return SWAP.calculateRemoveLiquidity(amount);\n }\n\n /**\n * @notice Calculate the amount of underlying token available to withdraw\n * when withdrawing via only single token\n * @param tokenAmount the amount of LP token to burn\n * @param tokenIndex index of which token will be withdrawn\n * @return availableTokenAmount calculated amount of underlying token\n * available to withdraw\n */\n function calculateRemoveLiquidityOneToken(\n uint256 tokenAmount,\n uint8 tokenIndex\n ) external view returns (uint256 availableTokenAmount) {\n return SWAP.calculateRemoveLiquidityOneToken(tokenAmount, tokenIndex);\n }\n}\n" + }, + "contracts/amm/interfaces/IWETH9.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.4.0;\n\ninterface IWETH9 {\n function name() external view returns (string memory);\n\n function symbol() external view returns (string memory);\n\n function decimals() external view returns (uint8);\n\n function balanceOf(address) external view returns (uint256);\n\n function allowance(address, address) external view returns (uint256);\n\n receive() external payable;\n\n function deposit() external payable;\n\n function withdraw(uint256 wad) external;\n\n function totalSupply() external view returns (uint256);\n\n function approve(address guy, uint256 wad) external returns (bool);\n\n function transfer(address dst, uint256 wad) external returns (bool);\n\n function transferFrom(\n address src,\n address dst,\n uint256 wad\n ) external returns (bool);\n}\n" + }, + "contracts/amm/helper/BaseSwapDeposit.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.6.12;\n\nimport \"@openzeppelin/contracts/math/SafeMath.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/SafeERC20.sol\";\nimport \"../interfaces/ISwap.sol\";\nimport \"@openzeppelin/contracts/utils/ReentrancyGuard.sol\";\n\ncontract BaseSwapDeposit is ReentrancyGuard {\n using SafeERC20 for IERC20;\n using SafeMath for uint256;\n\n ISwap public baseSwap;\n IERC20[] public baseTokens;\n\n uint256 constant MAX_UINT256 = 2**256 - 1;\n\n constructor(ISwap _baseSwap) public {\n baseSwap = _baseSwap;\n // Check and approve base level tokens to be deposited to the base Swap contract\n {\n uint8 i;\n for (; i < 32; i++) {\n try _baseSwap.getToken(i) returns (IERC20 token) {\n baseTokens.push(token);\n token.safeApprove(address(_baseSwap), MAX_UINT256);\n } catch {\n break;\n }\n }\n require(i > 1, \"baseSwap must have at least 2 tokens\");\n }\n }\n\n // Mutative functions\n\n /**\n * @notice Swap two underlying tokens using the meta pool and the base pool\n * @param tokenIndexFrom the token the user wants to swap from\n * @param tokenIndexTo the token the user wants to swap to\n * @param dx the amount of tokens the user wants to swap from\n * @param minDy the min amount the user would like to receive, or revert.\n * @param deadline latest timestamp to accept this transaction\n */\n function swap(\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx,\n uint256 minDy,\n uint256 deadline\n ) external nonReentrant returns (uint256) {\n baseTokens[tokenIndexFrom].safeTransferFrom(msg.sender, address(this), dx);\n uint256 tokenToAmount =\n baseSwap.swap(\n tokenIndexFrom,\n tokenIndexTo,\n dx,\n minDy,\n deadline\n );\n baseTokens[tokenIndexTo].safeTransfer(msg.sender, tokenToAmount);\n return tokenToAmount;\n }\n\n /**\n * @notice Calculate amount of tokens you receive on swap\n * @param tokenIndexFrom the token the user wants to sell\n * @param tokenIndexTo the token the user wants to buy\n * @param dx the amount of tokens the user wants to sell. If the token charges\n * a fee on transfers, use the amount that gets transferred after the fee.\n * @return amount of tokens the user will receive\n */\n function calculateSwap(\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx\n ) external view returns (uint256) {\n return\n baseSwap.calculateSwap(tokenIndexFrom, tokenIndexTo, dx);\n }\n\n /**\n * @notice Returns the address of the pooled token at given index. Reverts if tokenIndex is out of range.\n * @param index the index of the token\n * @return address of the token at given index\n */\n function getToken(uint256 index) external view returns (IERC20) {\n require(index < baseTokens.length, \"index out of range\");\n return baseTokens[index];\n }\n\n}" + }, + "@openzeppelin/contracts/utils/ReentrancyGuard.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <0.8.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 () internal {\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" + }, + "contracts/amm/AaveSwapWrapper.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.6.12;\n\nimport \"@openzeppelin/contracts/math/SafeMath.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/SafeERC20.sol\";\nimport \"./Swap.sol\";\n\ninterface ILendingPool {\n /**\n * @dev Deposits an `amount` of underlying asset into the reserve, receiving in return overlying aTokens.\n * - E.g. User deposits 100 USDC and gets in return 100 aUSDC\n * @param asset The address of the underlying asset to deposit\n * @param amount The amount to be deposited\n * @param onBehalfOf The address that will receive the aTokens, same as msg.sender if the user\n * wants to receive them on his own wallet, or a different address if the beneficiary of aTokens\n * is a different wallet\n * @param referralCode Code used to register the integrator originating the operation, for potential rewards.\n * 0 if the action is executed directly by the user, without any middle-man\n **/\n function deposit(\n address asset,\n uint256 amount,\n address onBehalfOf,\n uint16 referralCode\n ) external;\n\n /**\n * @dev Withdraws an `amount` of underlying asset from the reserve, burning the equivalent aTokens owned\n * E.g. User has 100 aUSDC, calls withdraw() and receives 100 USDC, burning the 100 aUSDC\n * @param asset The address of the underlying asset to withdraw\n * @param amount The underlying amount to be withdrawn\n * - Send the value type(uint256).max in order to withdraw the whole aToken balance\n * @param to Address that will receive the underlying, same as msg.sender if the user\n * wants to receive it on his own wallet, or a different address if the beneficiary is a\n * different wallet\n * @return The final amount withdrawn\n **/\n function withdraw(\n address asset,\n uint256 amount,\n address to\n ) external returns (uint256);\n}\n\n/**\n * @title AaveSwapWrapper\n * @notice A wrapper contract for interacting with aTokens\n */\ncontract AaveSwapWrapper {\n using SafeERC20 for IERC20;\n using SafeMath for uint256;\n mapping(uint8 => bool) private isUnderlyingIndex;\n\n // constants\n uint8 private constant MAX_UINT8 = 2**8 - 1;\n uint256 private constant MAX_UINT256 = 2**256 - 1;\n\n // immutables\n Swap public immutable SWAP;\n LPToken public immutable LP_TOKEN;\n address public immutable OWNER;\n IERC20[] public POOLED_TOKENS;\n IERC20[] public UNDERLYING_TOKENS;\n ILendingPool public LENDING_POOL;\n\n constructor(\n Swap swap,\n IERC20[] memory underlyingTokens,\n address lendingPool,\n address owner\n ) public {\n (, , , , , , LPToken lpToken) = swap.swapStorage();\n for (uint8 i = 0; i < MAX_UINT8; i++) {\n try swap.getToken(i) returns (IERC20 token) {\n POOLED_TOKENS.push(token);\n // Approve pooled tokens to be used by Swap\n token.approve(address(swap), MAX_UINT256);\n } catch {\n break;\n }\n }\n\n for (uint8 i = 0; i < POOLED_TOKENS.length; i++) {\n if (POOLED_TOKENS[i] == underlyingTokens[i]) {\n isUnderlyingIndex[i] = true;\n } else {\n isUnderlyingIndex[i] = false;\n underlyingTokens[i].approve(lendingPool, MAX_UINT256);\n }\n }\n\n // Set immutable variables\n SWAP = swap;\n LP_TOKEN = lpToken;\n OWNER = owner;\n UNDERLYING_TOKENS = underlyingTokens;\n LENDING_POOL = ILendingPool(lendingPool);\n\n // Approve LPToken to be used by Swap\n lpToken.approve(address(swap), MAX_UINT256);\n }\n\n /**\n * @notice Add liquidity to the pool with the given amounts of tokens.\n * @param amounts the amounts of each token to add, in their native precision\n * @param minToMint the minimum LP tokens adding this amount of liquidity\n * should mint, otherwise revert. Handy for front-running mitigation\n * @param deadline latest timestamp to accept this transaction\n * @return amount of LP token user minted and received\n */\n function addLiquidity(\n uint256[] memory amounts,\n uint256 minToMint,\n uint256 deadline\n ) external returns (uint256) {\n // Go through amounts array and transfer respective tokens to this contract.\n for (uint8 i = 0; i < amounts.length; i++) {\n uint256 amount = amounts[i];\n if (amount > 0) {\n UNDERLYING_TOKENS[i].safeTransferFrom(\n msg.sender,\n address(this),\n amount\n );\n if (isUnderlyingIndex[i] == false) {\n LENDING_POOL.deposit(\n address(UNDERLYING_TOKENS[i]),\n amount,\n address(this),\n 0\n );\n }\n }\n }\n\n // Add the assets to the pool\n uint256 lpTokenAmount = SWAP.addLiquidity(amounts, minToMint, deadline);\n // Send the LPToken to msg.sender\n IERC20(address(LP_TOKEN)).safeTransfer(msg.sender, lpTokenAmount);\n return lpTokenAmount;\n }\n\n /**\n * @notice Burn LP tokens to remove liquidity from the pool.\n * @dev Liquidity can always be removed, even when the pool is paused. Caller\n * will receive ETH instead of WETH9.\n * @param amount the amount of LP tokens to burn\n * @param minAmounts the minimum amounts of each token in the pool\n * acceptable for this burn. Useful as a front-running mitigation\n * @param deadline latest timestamp to accept this transaction\n * @return amounts of tokens user received\n */\n function removeLiquidity(\n uint256 amount,\n uint256[] calldata minAmounts,\n uint256 deadline\n ) external returns (uint256[] memory) {\n // Transfer LPToken from msg.sender to this contract.\n IERC20(address(LP_TOKEN)).safeTransferFrom(\n msg.sender,\n address(this),\n amount\n );\n // Remove liquidity\n uint256[] memory amounts = SWAP.removeLiquidity(\n amount,\n minAmounts,\n deadline\n );\n // Send the tokens back to the user\n for (uint8 i = 0; i < amounts.length; i++) {\n if (isUnderlyingIndex[i] == true) {\n UNDERLYING_TOKENS[i].safeTransfer(msg.sender, amounts[i]);\n } else {\n LENDING_POOL.withdraw(\n address(UNDERLYING_TOKENS[i]),\n amounts[i],\n msg.sender\n );\n // underlyingTokens[i].safeTransfer(msg.sender, amounts[i]);\n }\n }\n return amounts;\n }\n\n /**\n * @notice Remove liquidity from the pool all in one token.\n * @dev Caller will receive ETH instead of WETH9.\n * @param tokenAmount the amount of the token you want to receive\n * @param tokenIndex the index of the token you want to receive\n * @param minAmount the minimum amount to withdraw, otherwise revert\n * @param deadline latest timestamp to accept this transaction\n * @return amount of chosen token user received\n */\n function removeLiquidityOneToken(\n uint256 tokenAmount,\n uint8 tokenIndex,\n uint256 minAmount,\n uint256 deadline\n ) external returns (uint256) {\n // Transfer LPToken from msg.sender to this contract.\n IERC20(address(LP_TOKEN)).safeTransferFrom(\n msg.sender,\n address(this),\n tokenAmount\n );\n // Withdraw via single token\n uint256 amount = SWAP.removeLiquidityOneToken(\n tokenAmount,\n tokenIndex,\n minAmount,\n deadline\n );\n // Transfer the token to msg.sender accordingly\n if (isUnderlyingIndex[tokenIndex] == true) {\n UNDERLYING_TOKENS[tokenIndex].safeTransfer(msg.sender, amount);\n } else {\n LENDING_POOL.withdraw(\n address(UNDERLYING_TOKENS[tokenIndex]),\n amount,\n msg.sender\n );\n }\n return amount;\n }\n\n /**\n * @notice Swap two tokens using the underlying pool. If tokenIndexFrom\n * represents WETH9 in the pool, the caller must set msg.value equal to dx.\n * If the user is swapping to WETH9 in the pool, the user will receive ETH instead.\n * @param tokenIndexFrom the token the user wants to swap from\n * @param tokenIndexTo the token the user wants to swap to\n * @param dx the amount of tokens the user wants to swap from\n * @param minDy the min amount the user would like to receive, or revert.\n * @param deadline latest timestamp to accept this transaction\n */\n function swap(\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx,\n uint256 minDy,\n uint256 deadline\n ) external returns (uint256) {\n // Transfer tokens from msg.sender to this contract\n UNDERLYING_TOKENS[tokenIndexFrom].safeTransferFrom(\n msg.sender,\n address(this),\n dx\n );\n if (isUnderlyingIndex[tokenIndexFrom] == false) {\n LENDING_POOL.deposit(\n address(UNDERLYING_TOKENS[tokenIndexFrom]),\n dx,\n address(this),\n 0\n );\n }\n // Execute swap\n uint256 dy = SWAP.swap(\n tokenIndexFrom,\n tokenIndexTo,\n dx,\n minDy,\n deadline\n );\n // Transfer the swapped tokens to msg.sender\n if (isUnderlyingIndex[tokenIndexTo] == false) {\n LENDING_POOL.withdraw(\n address(UNDERLYING_TOKENS[tokenIndexTo]),\n dy,\n msg.sender\n );\n } else {\n UNDERLYING_TOKENS[tokenIndexTo].safeTransfer(msg.sender, dy);\n }\n return dy;\n }\n\n /**\n * @notice Rescues any of the ETH, the pooled tokens, or the LPToken that may be stuck\n * in this contract. Only the OWNER can call this function.\n */\n function rescue() external {\n require(msg.sender == OWNER, \"CALLED_BY_NON_OWNER\");\n IERC20[] memory tokens = POOLED_TOKENS;\n for (uint256 i = 0; i < tokens.length; i++) {\n tokens[i].safeTransfer(\n msg.sender,\n tokens[i].balanceOf(address(this))\n );\n }\n\n for (uint256 i = 0; i < UNDERLYING_TOKENS.length; i++) {\n UNDERLYING_TOKENS[i].safeTransfer(\n msg.sender,\n UNDERLYING_TOKENS[i].balanceOf(address(this))\n );\n }\n\n IERC20 lpToken_ = IERC20(address(LP_TOKEN));\n lpToken_.safeTransfer(msg.sender, lpToken_.balanceOf(address(this)));\n }\n\n // VIEW FUNCTIONS\n\n /**\n * @notice Calculate amount of tokens you receive on swap\n * @param tokenIndexFrom the token the user wants to sell\n * @param tokenIndexTo the token the user wants to buy\n * @param dx the amount of tokens the user wants to sell. If the token charges\n * a fee on transfers, use the amount that gets transferred after the fee.\n * @return amount of tokens the user will receive\n */\n function calculateSwap(\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx\n ) external view virtual returns (uint256) {\n return SWAP.calculateSwap(tokenIndexFrom, tokenIndexTo, dx);\n }\n\n /**\n * @notice A simple method to calculate prices from deposits or\n * withdrawals, excluding fees but including slippage. This is\n * helpful as an input into the various \"min\" parameters on calls\n * to fight front-running\n *\n * @dev This shouldn't be used outside frontends for user estimates.\n *\n * @param amounts an array of token amounts to deposit or withdrawal,\n * corresponding to pooledTokens. The amount should be in each\n * pooled token's native precision. If a token charges a fee on transfers,\n * use the amount that gets transferred after the fee.\n * @param deposit whether this is a deposit or a withdrawal\n * @return token amount the user will receive\n */\n function calculateTokenAmount(uint256[] calldata amounts, bool deposit)\n external\n view\n returns (uint256)\n {\n return SWAP.calculateTokenAmount(amounts, deposit);\n }\n\n /**\n * @notice A simple method to calculate amount of each underlying\n * tokens that is returned upon burning given amount of LP tokens\n * @param amount the amount of LP tokens that would be burned on withdrawal\n * @return array of token balances that the user will receive\n */\n function calculateRemoveLiquidity(uint256 amount)\n external\n view\n returns (uint256[] memory)\n {\n return SWAP.calculateRemoveLiquidity(amount);\n }\n\n /**\n * @notice Calculate the amount of underlying token available to withdraw\n * when withdrawing via only single token\n * @param tokenAmount the amount of LP token to burn\n * @param tokenIndex index of which token will be withdrawn\n * @return availableTokenAmount calculated amount of underlying token\n * available to withdraw\n */\n function calculateRemoveLiquidityOneToken(\n uint256 tokenAmount,\n uint8 tokenIndex\n ) external view returns (uint256 availableTokenAmount) {\n return SWAP.calculateRemoveLiquidityOneToken(tokenAmount, tokenIndex);\n }\n\n /**\n * @notice Return address of the pooled token at given index. Reverts if tokenIndex is out of range.\n * @param index the index of the token\n * @return address of the token at given index\n */\n function getToken(uint8 index) public view virtual returns (IERC20) {\n if (index < UNDERLYING_TOKENS.length) {\n return UNDERLYING_TOKENS[index];\n } else {\n revert();\n }\n }\n}\n" + }, + "contracts/bridge/ECDSAFactory.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.6.12;\n\nimport \"@openzeppelin/contracts/access/Ownable.sol\";\nimport \"@openzeppelin/contracts/proxy/Clones.sol\";\nimport \"./interfaces/IECDSANodeManagement.sol\";\n\ncontract ECDSAFactory is Ownable {\n event ECDSANodeGroupCreated(\n address indexed keepAddress,\n address[] members,\n address indexed owner,\n uint256 honestThreshold\n );\n\n struct LatestNodeGroup {\n address keepAddress;\n address[] members;\n address owner;\n uint256 honestThreshold;\n }\n\n LatestNodeGroup public latestNodeGroup;\n\n constructor() public Ownable() {}\n\n /// @notice Returns members of the keep.\n /// @return List of the keep members' addresses.\n function getMembers() public view returns (address[] memory) {\n return latestNodeGroup.members;\n }\n\n /**\n @notice Deploys a new node \n @param nodeMgmtAddress address of the ECDSANodeManagement contract to initialize with\n @param owner Owner of the ECDSANodeManagement contract who can determine if the node group is closed or active\n @param members Array of node group members addresses\n @param honestThreshold Number of signers to process a transaction \n @return Address of the newest node management contract created\n **/\n function deploy(\n address nodeMgmtAddress,\n address owner,\n address[] memory members,\n uint256 honestThreshold\n ) external onlyOwner returns (address) {\n address nodeClone = Clones.clone(nodeMgmtAddress);\n IECDSANodeManagement(nodeClone).initialize(\n owner,\n members,\n honestThreshold\n );\n\n latestNodeGroup.keepAddress = nodeClone;\n latestNodeGroup.members = members;\n latestNodeGroup.owner = owner;\n latestNodeGroup.honestThreshold = honestThreshold;\n\n emit ECDSANodeGroupCreated(nodeClone, members, owner, honestThreshold);\n return nodeClone;\n }\n}\n" + }, + "contracts/bridge/interfaces/IECDSANodeManagement.sol": { + "content": "// SPDX-License-Identifier: MIT\n\n\npragma solidity 0.6.12;\n\n/**\n * @title IECDSANodeManagement interface\n * @notice Interface for the ECDSA node management interface.\n * @dev implement this interface to develop a a factory-patterned ECDSA node management contract\n **/\ninterface IECDSANodeManagement { \n function initialize(\n address _owner,\n address[] memory _members,\n uint256 _honestThreshold) external;\n}\n\n" + }, + "contracts/auxiliary/DummyWeth.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.6.12;\nimport \"@openzeppelin/contracts/access/Ownable.sol\";\n\ninterface IWETH9 {\n function name() external view returns (string memory);\n\n function symbol() external view returns (string memory);\n\n function decimals() external view returns (uint8);\n\n function balanceOf(address) external view returns (uint256);\n\n function allowance(address, address) external view returns (uint256);\n\n receive() external payable;\n\n function deposit() external payable;\n\n function withdraw(uint256 wad) external;\n\n function totalSupply() external view returns (uint256);\n\n function approve(address guy, uint256 wad) external returns (bool);\n\n function transfer(address dst, uint256 wad) external returns (bool);\n\n function transferFrom(\n address src,\n address dst,\n uint256 wad\n ) external returns (bool);\n}\n\ncontract DummyWeth is Ownable {\n IWETH9 public WETH;\n\n function setWETHAddress(address payable _weth) external onlyOwner {\n WETH = IWETH9(_weth);\n }\n\n function withdrawToSelf(uint256 amount) external {\n WETH.withdraw(amount);\n }\n\n function rescue(uint256 amount) external onlyOwner {\n WETH.transfer(owner(), amount);\n }\n\n receive() external payable {}\n\n fallback() external payable {}\n}\n" + } + }, + "settings": { + "optimizer": { + "enabled": true, + "runs": 10000 + }, + "outputSelection": { + "*": { + "*": [ + "abi", + "evm.bytecode", + "evm.deployedBytecode", + "evm.methodIdentifiers", + "metadata", + "devdoc", + "userdoc", + "storageLayout", + "evm.gasEstimates", + "devdoc", + "userdoc" + ], + "": [ + "ast" + ] + } + }, + "metadata": { + "useLiteralContent": true + } + } +} \ No newline at end of file diff --git a/deployments/dfk/xJEWEL.json b/deployments/dfk/xJEWEL.json new file mode 100644 index 000000000..ed5ea4179 --- /dev/null +++ b/deployments/dfk/xJEWEL.json @@ -0,0 +1,668 @@ +{ + "address": "0x77f2656d04E158f915bC22f07B779D94c1DC47Ff", + "abi": [ + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "Approval", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "bytes32", + "name": "previousAdminRole", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "bytes32", + "name": "newAdminRole", + "type": "bytes32" + } + ], + "name": "RoleAdminChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "sender", + "type": "address" + } + ], + "name": "RoleGranted", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "sender", + "type": "address" + } + ], + "name": "RoleRevoked", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "Transfer", + "type": "event" + }, + { + "inputs": [], + "name": "DEFAULT_ADMIN_ROLE", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "DOMAIN_SEPARATOR", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "MINTER_ROLE", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "address", + "name": "spender", + "type": "address" + } + ], + "name": "allowance", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "approve", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "balanceOf", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "burn", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "burnFrom", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "decimals", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "subtractedValue", + "type": "uint256" + } + ], + "name": "decreaseAllowance", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + } + ], + "name": "getRoleAdmin", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "internalType": "uint256", + "name": "index", + "type": "uint256" + } + ], + "name": "getRoleMember", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + } + ], + "name": "getRoleMemberCount", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "grantRole", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "hasRole", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "addedValue", + "type": "uint256" + } + ], + "name": "increaseAllowance", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "name", + "type": "string" + }, + { + "internalType": "string", + "name": "symbol", + "type": "string" + }, + { + "internalType": "uint8", + "name": "decimals", + "type": "uint8" + }, + { + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "initialize", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "mint", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "name", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "nonces", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" + }, + { + "internalType": "uint8", + "name": "v", + "type": "uint8" + }, + { + "internalType": "bytes32", + "name": "r", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "s", + "type": "bytes32" + } + ], + "name": "permit", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "renounceRole", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "revokeRole", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "symbol", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "totalSupply", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "recipient", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "transfer", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "internalType": "address", + "name": "recipient", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "transferFrom", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + } + ] +} \ No newline at end of file diff --git a/deployments/harmony/AVAX.json b/deployments/harmony/AVAX.json new file mode 100644 index 000000000..44e5a76b1 --- /dev/null +++ b/deployments/harmony/AVAX.json @@ -0,0 +1,668 @@ +{ + "address": "0xD9eAA386cCD65F30b77FF175F6b52115FE454fD6", + "abi": [ + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "Approval", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "bytes32", + "name": "previousAdminRole", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "bytes32", + "name": "newAdminRole", + "type": "bytes32" + } + ], + "name": "RoleAdminChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "sender", + "type": "address" + } + ], + "name": "RoleGranted", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "sender", + "type": "address" + } + ], + "name": "RoleRevoked", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "Transfer", + "type": "event" + }, + { + "inputs": [], + "name": "DEFAULT_ADMIN_ROLE", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "DOMAIN_SEPARATOR", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "MINTER_ROLE", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "address", + "name": "spender", + "type": "address" + } + ], + "name": "allowance", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "approve", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "balanceOf", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "burn", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "burnFrom", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "decimals", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "subtractedValue", + "type": "uint256" + } + ], + "name": "decreaseAllowance", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + } + ], + "name": "getRoleAdmin", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "internalType": "uint256", + "name": "index", + "type": "uint256" + } + ], + "name": "getRoleMember", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + } + ], + "name": "getRoleMemberCount", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "grantRole", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "hasRole", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "addedValue", + "type": "uint256" + } + ], + "name": "increaseAllowance", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "name", + "type": "string" + }, + { + "internalType": "string", + "name": "symbol", + "type": "string" + }, + { + "internalType": "uint8", + "name": "decimals", + "type": "uint8" + }, + { + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "initialize", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "mint", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "name", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "nonces", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" + }, + { + "internalType": "uint8", + "name": "v", + "type": "uint8" + }, + { + "internalType": "bytes32", + "name": "r", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "s", + "type": "bytes32" + } + ], + "name": "permit", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "renounceRole", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "revokeRole", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "symbol", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "totalSupply", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "recipient", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "transfer", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "internalType": "address", + "name": "recipient", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "transferFrom", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + } + ] +} \ No newline at end of file diff --git a/deployments/harmony/BridgedAVAXPool.json b/deployments/harmony/BridgedAVAXPool.json new file mode 100644 index 000000000..00d90ba50 --- /dev/null +++ b/deployments/harmony/BridgedAVAXPool.json @@ -0,0 +1,1001 @@ +{ + "address": "0x00A4F57D926781f62D09bb05ec76e6D8aE4268da", + "abi": [ + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "provider", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256[]", + "name": "tokenAmounts", + "type": "uint256[]" + }, + { + "indexed": false, + "internalType": "uint256[]", + "name": "fees", + "type": "uint256[]" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "invariant", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "lpTokenSupply", + "type": "uint256" + } + ], + "name": "AddLiquidity", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "receiver", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint8", + "name": "tokenIndex", + "type": "uint8" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amountFee", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "protocolFee", + "type": "uint256" + } + ], + "name": "FlashLoan", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "newAdminFee", + "type": "uint256" + } + ], + "name": "NewAdminFee", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "newSwapFee", + "type": "uint256" + } + ], + "name": "NewSwapFee", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "previousOwner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "OwnershipTransferred", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "Paused", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "oldA", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newA", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "initialTime", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "futureTime", + "type": "uint256" + } + ], + "name": "RampA", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "provider", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256[]", + "name": "tokenAmounts", + "type": "uint256[]" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "lpTokenSupply", + "type": "uint256" + } + ], + "name": "RemoveLiquidity", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "provider", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256[]", + "name": "tokenAmounts", + "type": "uint256[]" + }, + { + "indexed": false, + "internalType": "uint256[]", + "name": "fees", + "type": "uint256[]" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "invariant", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "lpTokenSupply", + "type": "uint256" + } + ], + "name": "RemoveLiquidityImbalance", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "provider", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "lpTokenAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "lpTokenSupply", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "boughtId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "tokensBought", + "type": "uint256" + } + ], + "name": "RemoveLiquidityOne", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "currentA", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "time", + "type": "uint256" + } + ], + "name": "StopRampA", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "buyer", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "tokensSold", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "tokensBought", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint128", + "name": "soldId", + "type": "uint128" + }, + { + "indexed": false, + "internalType": "uint128", + "name": "boughtId", + "type": "uint128" + } + ], + "name": "TokenSwap", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "Unpaused", + "type": "event" + }, + { + "inputs": [], + "name": "MAX_BPS", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256[]", + "name": "amounts", + "type": "uint256[]" + }, + { + "internalType": "uint256", + "name": "minToMint", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" + } + ], + "name": "addLiquidity", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "calculateRemoveLiquidity", + "outputs": [ + { + "internalType": "uint256[]", + "name": "", + "type": "uint256[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "tokenAmount", + "type": "uint256" + }, + { + "internalType": "uint8", + "name": "tokenIndex", + "type": "uint8" + } + ], + "name": "calculateRemoveLiquidityOneToken", + "outputs": [ + { + "internalType": "uint256", + "name": "availableTokenAmount", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint8", + "name": "tokenIndexFrom", + "type": "uint8" + }, + { + "internalType": "uint8", + "name": "tokenIndexTo", + "type": "uint8" + }, + { + "internalType": "uint256", + "name": "dx", + "type": "uint256" + } + ], + "name": "calculateSwap", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256[]", + "name": "amounts", + "type": "uint256[]" + }, + { + "internalType": "bool", + "name": "deposit", + "type": "bool" + } + ], + "name": "calculateTokenAmount", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "receiver", + "type": "address" + }, + { + "internalType": "contract IERC20", + "name": "token", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "params", + "type": "bytes" + } + ], + "name": "flashLoan", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "flashLoanFeeBPS", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getA", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getAPrecise", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "index", + "type": "uint256" + } + ], + "name": "getAdminBalance", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint8", + "name": "index", + "type": "uint8" + } + ], + "name": "getToken", + "outputs": [ + { + "internalType": "contract IERC20", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint8", + "name": "index", + "type": "uint8" + } + ], + "name": "getTokenBalance", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "tokenAddress", + "type": "address" + } + ], + "name": "getTokenIndex", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getVirtualPrice", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract IERC20[]", + "name": "_pooledTokens", + "type": "address[]" + }, + { + "internalType": "uint8[]", + "name": "decimals", + "type": "uint8[]" + }, + { + "internalType": "string", + "name": "lpTokenName", + "type": "string" + }, + { + "internalType": "string", + "name": "lpTokenSymbol", + "type": "string" + }, + { + "internalType": "uint256", + "name": "_a", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_fee", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_adminFee", + "type": "uint256" + }, + { + "internalType": "address", + "name": "lpTokenTargetAddress", + "type": "address" + } + ], + "name": "initialize", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "pause", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "paused", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "protocolFeeShareBPS", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "futureA", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "futureTime", + "type": "uint256" + } + ], + "name": "rampA", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "internalType": "uint256[]", + "name": "minAmounts", + "type": "uint256[]" + }, + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" + } + ], + "name": "removeLiquidity", + "outputs": [ + { + "internalType": "uint256[]", + "name": "", + "type": "uint256[]" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256[]", + "name": "amounts", + "type": "uint256[]" + }, + { + "internalType": "uint256", + "name": "maxBurnAmount", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" + } + ], + "name": "removeLiquidityImbalance", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "tokenAmount", + "type": "uint256" + }, + { + "internalType": "uint8", + "name": "tokenIndex", + "type": "uint8" + }, + { + "internalType": "uint256", + "name": "minAmount", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" + } + ], + "name": "removeLiquidityOneToken", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "renounceOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "newAdminFee", + "type": "uint256" + } + ], + "name": "setAdminFee", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "newFlashLoanFeeBPS", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "newProtocolFeeShareBPS", + "type": "uint256" + } + ], + "name": "setFlashLoanFees", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "newSwapFee", + "type": "uint256" + } + ], + "name": "setSwapFee", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "stopRampA", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint8", + "name": "tokenIndexFrom", + "type": "uint8" + }, + { + "internalType": "uint8", + "name": "tokenIndexTo", + "type": "uint8" + }, + { + "internalType": "uint256", + "name": "dx", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "minDy", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" + } + ], + "name": "swap", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "swapStorage", + "outputs": [ + { + "internalType": "uint256", + "name": "initialA", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "futureA", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "initialATime", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "futureATime", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "swapFee", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "adminFee", + "type": "uint256" + }, + { + "internalType": "contract LPToken", + "name": "lpToken", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "unpause", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "withdrawAdminFees", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } + ] +} \ No newline at end of file diff --git a/deployments/harmony/BridgedAVAXPoolLPToken.json b/deployments/harmony/BridgedAVAXPoolLPToken.json new file mode 100644 index 000000000..b62ad0a0e --- /dev/null +++ b/deployments/harmony/BridgedAVAXPoolLPToken.json @@ -0,0 +1,225 @@ +{ + "address": "0x02f7D17f126BD54573c8EbAD9e05408A56f46452", + "abi": [ + { + "constant": true, + "inputs": [], + "name": "name", + "outputs": [ + { + "name": "", + "type": "string" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "name": "_spender", + "type": "address" + }, + { + "name": "_value", + "type": "uint256" + } + ], + "name": "approve", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "totalSupply", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "name": "_from", + "type": "address" + }, + { + "name": "_to", + "type": "address" + }, + { + "name": "_value", + "type": "uint256" + } + ], + "name": "transferFrom", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "decimals", + "outputs": [ + { + "name": "", + "type": "uint8" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "name": "_owner", + "type": "address" + } + ], + "name": "balanceOf", + "outputs": [ + { + "name": "balance", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "symbol", + "outputs": [ + { + "name": "", + "type": "string" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "name": "_to", + "type": "address" + }, + { + "name": "_value", + "type": "uint256" + } + ], + "name": "transfer", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "name": "_owner", + "type": "address" + }, + { + "name": "_spender", + "type": "address" + } + ], + "name": "allowance", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "payable": true, + "stateMutability": "payable", + "type": "fallback" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "name": "spender", + "type": "address" + }, + { + "indexed": false, + "name": "value", + "type": "uint256" + } + ], + "name": "Approval", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "name": "from", + "type": "address" + }, + { + "indexed": true, + "name": "to", + "type": "address" + }, + { + "indexed": false, + "name": "value", + "type": "uint256" + } + ], + "name": "Transfer", + "type": "event" + } + ] +} \ No newline at end of file diff --git a/deployments/harmony/JewelBridgeSwap.json b/deployments/harmony/JewelBridgeSwap.json new file mode 100644 index 000000000..28bff85d4 --- /dev/null +++ b/deployments/harmony/JewelBridgeSwap.json @@ -0,0 +1,260 @@ +{ + "address": "0x7bE461cce1501f07969BCE24Ccb2140fCA0a35b3", + "abi": [ + { + "inputs": [ + { + "internalType": "contract IERC20", + "name": "tokenA", + "type": "address" + }, + { + "internalType": "contract IERC20", + "name": "mintableTokenB", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [ + { + "internalType": "uint8", + "name": "tokenIndexFrom", + "type": "uint8" + }, + { + "internalType": "uint8", + "name": "tokenIndexTo", + "type": "uint8" + }, + { + "internalType": "uint256", + "name": "dx", + "type": "uint256" + } + ], + "name": "calculateSwap", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint8", + "name": "index", + "type": "uint8" + } + ], + "name": "getToken", + "outputs": [ + { + "internalType": "contract IERC20", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "tokenAddress", + "type": "address" + } + ], + "name": "getTokenIndex", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint8", + "name": "tokenIndexFrom", + "type": "uint8" + }, + { + "internalType": "uint8", + "name": "tokenIndexTo", + "type": "uint8" + }, + { + "internalType": "uint256", + "name": "dx", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "minDy", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" + } + ], + "name": "swap", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + } + ], + "transactionHash": "0x3f6974c3375eb055d4b3115895e42321897f162eabab0e2be1df48f07e3a9384", + "receipt": { + "to": null, + "from": "0x0AF91FA049A7e1894F480bFE5bBa20142C6c29a9", + "contractAddress": "0x7bE461cce1501f07969BCE24Ccb2140fCA0a35b3", + "transactionIndex": 8, + "gasUsed": "833355", + "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "blockHash": "0x9996b2283aef70f82f0d77a00c217a5acbcc26645284e2a2a6230dccc3f63bc9", + "transactionHash": "0x3f6974c3375eb055d4b3115895e42321897f162eabab0e2be1df48f07e3a9384", + "logs": [], + "blockNumber": 24549054, + "cumulativeGasUsed": "1523830", + "status": 1, + "byzantium": true + }, + "args": [ + "0x72Cb10C6bfA5624dD07Ef608027E366bd690048F", + "0x28b42698Caf46B4B012CF38b6C75867E0762186D" + ], + "solcInputHash": "95380060a7ec73498bb886cdc300b807", + "metadata": "{\"compiler\":{\"version\":\"0.6.12+commit.27d51765\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"contract IERC20\",\"name\":\"tokenA\",\"type\":\"address\"},{\"internalType\":\"contract IERC20\",\"name\":\"mintableTokenB\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"uint8\",\"name\":\"tokenIndexFrom\",\"type\":\"uint8\"},{\"internalType\":\"uint8\",\"name\":\"tokenIndexTo\",\"type\":\"uint8\"},{\"internalType\":\"uint256\",\"name\":\"dx\",\"type\":\"uint256\"}],\"name\":\"calculateSwap\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint8\",\"name\":\"index\",\"type\":\"uint8\"}],\"name\":\"getToken\",\"outputs\":[{\"internalType\":\"contract IERC20\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"tokenAddress\",\"type\":\"address\"}],\"name\":\"getTokenIndex\",\"outputs\":[{\"internalType\":\"uint8\",\"name\":\"\",\"type\":\"uint8\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint8\",\"name\":\"tokenIndexFrom\",\"type\":\"uint8\"},{\"internalType\":\"uint8\",\"name\":\"tokenIndexTo\",\"type\":\"uint8\"},{\"internalType\":\"uint256\",\"name\":\"dx\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"minDy\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"deadline\",\"type\":\"uint256\"}],\"name\":\"swap\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{\"calculateSwap(uint8,uint8,uint256)\":{\"params\":{\"dx\":\"the amount of tokens the user wants to swap. \",\"tokenIndexFrom\":\"the token the user wants to sell\",\"tokenIndexTo\":\"the token the user wants to buy\"},\"returns\":{\"_0\":\"amount of tokens the user will receive\"}},\"getToken(uint8)\":{\"params\":{\"index\":\"the index of the token\"},\"returns\":{\"_0\":\"address of the token at given index\"}},\"getTokenIndex(address)\":{\"params\":{\"tokenAddress\":\"address of the token\"},\"returns\":{\"_0\":\"the index of the given token address\"}},\"swap(uint8,uint8,uint256,uint256,uint256)\":{\"params\":{\"deadline\":\"latest timestamp to accept this transaction\",\"dx\":\"the amount of tokens the user wants to swap from\",\"minDy\":\"the min amount the user would like to receive, or revert.\",\"tokenIndexFrom\":\"the token the user wants to swap from\",\"tokenIndexTo\":\"the token the user wants to swap to\"}}},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{\"calculateSwap(uint8,uint8,uint256)\":{\"notice\":\"Calculate amount of tokens you receive on swap\"},\"getToken(uint8)\":{\"notice\":\"Return address of the pooled token at given index. Reverts if tokenIndex is out of range.\"},\"getTokenIndex(address)\":{\"notice\":\"Return the index of the given token address. Reverts if no matching token is found.\"},\"swap(uint8,uint8,uint256,uint256,uint256)\":{\"notice\":\"Swap two tokens using this pool\"}},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/bridge/wrappers/JewelBridgeSwap.sol\":\"JewelBridgeSwap\"},\"evmVersion\":\"istanbul\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":10000},\"remappings\":[]},\"sources\":{\"@openzeppelin/contracts/math/SafeMath.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity >=0.6.0 <0.8.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\",\"keccak256\":\"0xcc78a17dd88fa5a2edc60c8489e2f405c0913b377216a5b26b35656b2d0dab52\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/ERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity >=0.6.0 <0.8.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_) public {\\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\",\"keccak256\":\"0xca0c2396dbeb3503b51abf4248ebf77a1461edad513c01529df51850a012bee3\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/ERC20Burnable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity >=0.6.0 <0.8.0;\\n\\nimport \\\"../../utils/Context.sol\\\";\\nimport \\\"./ERC20.sol\\\";\\n\\n/**\\n * @dev Extension of {ERC20} that allows token holders to destroy both their own\\n * tokens and those that they have an allowance for, in a way that can be\\n * recognized off-chain (via event analysis).\\n */\\nabstract contract ERC20Burnable is Context, ERC20 {\\n using SafeMath for uint256;\\n\\n /**\\n * @dev Destroys `amount` tokens from the caller.\\n *\\n * See {ERC20-_burn}.\\n */\\n function burn(uint256 amount) public virtual {\\n _burn(_msgSender(), amount);\\n }\\n\\n /**\\n * @dev Destroys `amount` tokens from `account`, deducting from the caller's\\n * allowance.\\n *\\n * See {ERC20-_burn} and {ERC20-allowance}.\\n *\\n * Requirements:\\n *\\n * - the caller must have allowance for ``accounts``'s tokens of at least\\n * `amount`.\\n */\\n function burnFrom(address account, uint256 amount) public virtual {\\n uint256 decreasedAllowance = allowance(account, _msgSender()).sub(amount, \\\"ERC20: burn amount exceeds allowance\\\");\\n\\n _approve(account, _msgSender(), decreasedAllowance);\\n _burn(account, amount);\\n }\\n}\\n\",\"keccak256\":\"0x9c0eb3b0e11d2480d49991dc384f1e5f9c9b9967cc81944d50916a9b9c6c4984\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/IERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity >=0.6.0 <0.8.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\",\"keccak256\":\"0x5f02220344881ce43204ae4a6281145a67bc52c2bb1290a791857df3d19d78f5\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/SafeERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity >=0.6.0 <0.8.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\",\"keccak256\":\"0xf12dfbe97e6276980b83d2830bb0eb75e0cf4f3e626c2471137f82158ae6a0fc\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/Address.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity >=0.6.2 <0.8.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\",\"keccak256\":\"0x28911e614500ae7c607a432a709d35da25f3bc5ddc8bd12b278b66358070c0ea\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/Context.sol\":{\"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\",\"keccak256\":\"0x8d3cb350f04ff49cfb10aef08d87f19dcbaecc8027b0bed12f3275cd12f38cf0\",\"license\":\"MIT\"},\"contracts/bridge/wrappers/JewelBridgeSwap.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity 0.6.12;\\n\\nimport '@openzeppelin/contracts/token/ERC20/ERC20.sol';\\nimport \\\"@openzeppelin/contracts/token/ERC20/SafeERC20.sol\\\";\\nimport \\\"@openzeppelin/contracts/token/ERC20/ERC20Burnable.sol\\\";\\nimport \\\"@openzeppelin/contracts/math/SafeMath.sol\\\";\\n\\ninterface IERC20Mintable is IERC20 {\\n function mint(address to, uint256 amount) external;\\n}\\n\\ncontract JewelBridgeSwap {\\n using SafeERC20 for IERC20;\\n using SafeERC20 for IERC20Mintable;\\n using SafeMath for uint256;\\n\\n // Maps token address to an index in the pool. Used to prevent duplicate tokens in the pool.\\n // getTokenIndex function also relies on this mapping to retrieve token index.\\n mapping(address => uint8) private tokenIndexes;\\n IERC20[2] pooledTokens;\\n \\n constructor(IERC20 tokenA, IERC20 mintableTokenB) public {\\n pooledTokens[0] = tokenA;\\n pooledTokens[1] = mintableTokenB;\\n tokenIndexes[address(tokenA)] = 0;\\n tokenIndexes[address(mintableTokenB)] = 1;\\n }\\n\\n /**\\n * @notice Return address of the pooled token at given index. Reverts if tokenIndex is out of range.\\n * @param index the index of the token\\n * @return address of the token at given index\\n */\\n function getToken(uint8 index) public view returns (IERC20) {\\n require(index < pooledTokens.length, \\\"Out of range\\\");\\n return pooledTokens[index];\\n }\\n\\n /**\\n * @notice Return the index of the given token address. Reverts if no matching\\n * token is found.\\n * @param tokenAddress address of the token\\n * @return the index of the given token address\\n */\\n function getTokenIndex(address tokenAddress)\\n public\\n view\\n returns (uint8)\\n {\\n uint8 index = tokenIndexes[tokenAddress];\\n require(\\n address(getToken(index)) == tokenAddress,\\n \\\"Token does not exist\\\"\\n );\\n return index;\\n }\\n\\n /**\\n * @notice Calculate amount of tokens you receive on swap\\n * @param tokenIndexFrom the token the user wants to sell\\n * @param tokenIndexTo the token the user wants to buy\\n * @param dx the amount of tokens the user wants to swap. \\n * @return amount of tokens the user will receive\\n */\\n function calculateSwap(\\n uint8 tokenIndexFrom,\\n uint8 tokenIndexTo,\\n uint256 dx\\n ) external view returns (uint256) {\\n return dx;\\n }\\n\\n /**\\n * @notice Swap two tokens using this pool\\n * @param tokenIndexFrom the token the user wants to swap from\\n * @param tokenIndexTo the token the user wants to swap to\\n * @param dx the amount of tokens the user wants to swap from\\n * @param minDy the min amount the user would like to receive, or revert.\\n * @param deadline latest timestamp to accept this transaction\\n */\\n function swap(\\n uint8 tokenIndexFrom,\\n uint8 tokenIndexTo,\\n uint256 dx,\\n uint256 minDy,\\n uint256 deadline\\n )\\n external\\n returns (uint256)\\n {\\n {\\n IERC20 tokenFrom = pooledTokens[tokenIndexFrom];\\n require(\\n dx <= tokenFrom.balanceOf(msg.sender),\\n \\\"Cannot swap more than you own\\\"\\n );\\n // Transfer tokens first to see if a fee was charged on transfer\\n uint256 beforeBalance = tokenFrom.balanceOf(address(this));\\n tokenFrom.safeTransferFrom(msg.sender, address(this), dx);\\n\\n // Use the actual transferred amount for AMM math\\n dx = tokenFrom.balanceOf(address(this)).sub(beforeBalance);\\n }\\n\\n // redeem JEWEL for synJEWEL\\n if (tokenIndexFrom == 0 && tokenIndexTo == 1) {\\n IERC20Mintable(address(pooledTokens[tokenIndexTo])).mint(msg.sender, dx);\\n return dx;\\n // redeem synJEWEL for JEWEL\\n } else if (tokenIndexFrom == 1 && tokenIndexTo == 0) {\\n ERC20Burnable(address(pooledTokens[tokenIndexFrom])).burn(dx);\\n pooledTokens[tokenIndexTo].safeTransfer(msg.sender, dx);\\n return dx;\\n } else {\\n revert(\\\"Unsupported indexes\\\");\\n }\\n }\\n}\",\"keccak256\":\"0xa861a6b7588f0a74da67dd60b2cc7a83060592954d4aa48c0fcaad8c890cefbe\",\"license\":\"MIT\"}},\"version\":1}", + "bytecode": "0x608060405234801561001057600080fd5b50604051610da0380380610da08339818101604052604081101561003357600080fd5b508051602091820151600180546001600160a01b039384166001600160a01b03199182168117835560028054959094169490911684179092556000918252928190526040808220805460ff19908116909155928252812080549092169092179055610cfc9081906100a490396000f3fe608060405234801561001057600080fd5b506004361061004c5760003560e01c806366c0bd241461005157806382b866001461009a57806391695586146100e3578063a95b089f14610131575b600080fd5b6100846004803603602081101561006757600080fd5b503573ffffffffffffffffffffffffffffffffffffffff16610161565b6040805160ff9092168252519081900360200190f35b6100ba600480360360208110156100b057600080fd5b503560ff16610220565b6040805173ffffffffffffffffffffffffffffffffffffffff9092168252519081900360200190f35b61011f600480360360a08110156100f957600080fd5b5060ff8135811691602081013590911690604081013590606081013590608001356102c2565b60408051918252519081900360200190f35b61011f6004803603606081101561014757600080fd5b5060ff81358116916020810135909116906040013561075b565b73ffffffffffffffffffffffffffffffffffffffff8116600081815260208190526040812054909160ff9091169061019882610220565b73ffffffffffffffffffffffffffffffffffffffff161461021a57604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601460248201527f546f6b656e20646f6573206e6f74206578697374000000000000000000000000604482015290519081900360640190fd5b92915050565b600060028260ff161061029457604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f4f7574206f662072616e67650000000000000000000000000000000000000000604482015290519081900360640190fd5b60018260ff16600281106102a457fe5b015473ffffffffffffffffffffffffffffffffffffffff1692915050565b60008060018760ff16600281106102d557fe5b0154604080517f70a08231000000000000000000000000000000000000000000000000000000008152336004820152905173ffffffffffffffffffffffffffffffffffffffff909216925082916370a0823191602480820192602092909190829003018186803b15801561034857600080fd5b505afa15801561035c573d6000803e3d6000fd5b505050506040513d602081101561037257600080fd5b50518511156103e257604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f43616e6e6f742073776170206d6f7265207468616e20796f75206f776e000000604482015290519081900360640190fd5b60008173ffffffffffffffffffffffffffffffffffffffff166370a08231306040518263ffffffff1660e01b8152600401808273ffffffffffffffffffffffffffffffffffffffff16815260200191505060206040518083038186803b15801561044b57600080fd5b505afa15801561045f573d6000803e3d6000fd5b505050506040513d602081101561047557600080fd5b5051905061049b73ffffffffffffffffffffffffffffffffffffffff8316333089610764565b610538818373ffffffffffffffffffffffffffffffffffffffff166370a08231306040518263ffffffff1660e01b8152600401808273ffffffffffffffffffffffffffffffffffffffff16815260200191505060206040518083038186803b15801561050657600080fd5b505afa15801561051a573d6000803e3d6000fd5b505050506040513d602081101561053057600080fd5b5051906107ff565b9550505060ff861615801561055057508460ff166001145b156105fd5760018560ff166002811061056557fe5b0154604080517f40c10f1900000000000000000000000000000000000000000000000000000000815233600482015260248101879052905173ffffffffffffffffffffffffffffffffffffffff909216916340c10f199160448082019260009290919082900301818387803b1580156105dd57600080fd5b505af11580156105f1573d6000803e3d6000fd5b50505050839050610752565b8560ff166001148015610611575060ff8516155b156106eb5760018660ff166002811061062657fe5b0154604080517f42966c6800000000000000000000000000000000000000000000000000000000815260048101879052905173ffffffffffffffffffffffffffffffffffffffff909216916342966c689160248082019260009290919082900301818387803b15801561069857600080fd5b505af11580156106ac573d6000803e3d6000fd5b505050506106e4338560018860ff16600281106106c557fe5b015473ffffffffffffffffffffffffffffffffffffffff169190610876565b5082610752565b604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f556e737570706f7274656420696e646578657300000000000000000000000000604482015290519081900360640190fd5b95945050505050565b805b9392505050565b6040805173ffffffffffffffffffffffffffffffffffffffff80861660248301528416604482015260648082018490528251808303909101815260849091019091526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f23b872dd000000000000000000000000000000000000000000000000000000001790526107f9908590610908565b50505050565b60008282111561087057604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601e60248201527f536166654d6174683a207375627472616374696f6e206f766572666c6f770000604482015290519081900360640190fd5b50900390565b6040805173ffffffffffffffffffffffffffffffffffffffff8416602482015260448082018490528251808303909101815260649091019091526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fa9059cbb00000000000000000000000000000000000000000000000000000000179052610903908490610908565b505050565b606061096a826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff166109e09092919063ffffffff16565b8051909150156109035780806020019051602081101561098957600080fd5b5051610903576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602a815260200180610c9d602a913960400191505060405180910390fd5b60606109ef84846000856109f7565b949350505050565b606082471015610a52576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526026815260200180610c776026913960400191505060405180910390fd5b610a5b85610bb2565b610ac657604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000604482015290519081900360640190fd5b600060608673ffffffffffffffffffffffffffffffffffffffff1685876040518082805190602001908083835b60208310610b3057805182527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe09092019160209182019101610af3565b6001836020036101000a03801982511681845116808217855250505050505090500191505060006040518083038185875af1925050503d8060008114610b92576040519150601f19603f3d011682016040523d82523d6000602084013e610b97565b606091505b5091509150610ba7828286610bb8565b979650505050505050565b3b151590565b60608315610bc757508161075d565b825115610bd75782518084602001fd5b816040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825283818151815260200191508051906020019080838360005b83811015610c3b578181015183820152602001610c23565b50505050905090810190601f168015610c685780820380516001836020036101000a031916815260200191505b509250505060405180910390fdfe416464726573733a20696e73756666696369656e742062616c616e636520666f722063616c6c5361666545524332303a204552433230206f7065726174696f6e20646964206e6f742073756363656564a26469706673582212208d61e042f830e58f0680a2a6fb9a207cb685c0ce5979198456d025d18002398f64736f6c634300060c0033", + "deployedBytecode": "0x608060405234801561001057600080fd5b506004361061004c5760003560e01c806366c0bd241461005157806382b866001461009a57806391695586146100e3578063a95b089f14610131575b600080fd5b6100846004803603602081101561006757600080fd5b503573ffffffffffffffffffffffffffffffffffffffff16610161565b6040805160ff9092168252519081900360200190f35b6100ba600480360360208110156100b057600080fd5b503560ff16610220565b6040805173ffffffffffffffffffffffffffffffffffffffff9092168252519081900360200190f35b61011f600480360360a08110156100f957600080fd5b5060ff8135811691602081013590911690604081013590606081013590608001356102c2565b60408051918252519081900360200190f35b61011f6004803603606081101561014757600080fd5b5060ff81358116916020810135909116906040013561075b565b73ffffffffffffffffffffffffffffffffffffffff8116600081815260208190526040812054909160ff9091169061019882610220565b73ffffffffffffffffffffffffffffffffffffffff161461021a57604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601460248201527f546f6b656e20646f6573206e6f74206578697374000000000000000000000000604482015290519081900360640190fd5b92915050565b600060028260ff161061029457604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f4f7574206f662072616e67650000000000000000000000000000000000000000604482015290519081900360640190fd5b60018260ff16600281106102a457fe5b015473ffffffffffffffffffffffffffffffffffffffff1692915050565b60008060018760ff16600281106102d557fe5b0154604080517f70a08231000000000000000000000000000000000000000000000000000000008152336004820152905173ffffffffffffffffffffffffffffffffffffffff909216925082916370a0823191602480820192602092909190829003018186803b15801561034857600080fd5b505afa15801561035c573d6000803e3d6000fd5b505050506040513d602081101561037257600080fd5b50518511156103e257604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f43616e6e6f742073776170206d6f7265207468616e20796f75206f776e000000604482015290519081900360640190fd5b60008173ffffffffffffffffffffffffffffffffffffffff166370a08231306040518263ffffffff1660e01b8152600401808273ffffffffffffffffffffffffffffffffffffffff16815260200191505060206040518083038186803b15801561044b57600080fd5b505afa15801561045f573d6000803e3d6000fd5b505050506040513d602081101561047557600080fd5b5051905061049b73ffffffffffffffffffffffffffffffffffffffff8316333089610764565b610538818373ffffffffffffffffffffffffffffffffffffffff166370a08231306040518263ffffffff1660e01b8152600401808273ffffffffffffffffffffffffffffffffffffffff16815260200191505060206040518083038186803b15801561050657600080fd5b505afa15801561051a573d6000803e3d6000fd5b505050506040513d602081101561053057600080fd5b5051906107ff565b9550505060ff861615801561055057508460ff166001145b156105fd5760018560ff166002811061056557fe5b0154604080517f40c10f1900000000000000000000000000000000000000000000000000000000815233600482015260248101879052905173ffffffffffffffffffffffffffffffffffffffff909216916340c10f199160448082019260009290919082900301818387803b1580156105dd57600080fd5b505af11580156105f1573d6000803e3d6000fd5b50505050839050610752565b8560ff166001148015610611575060ff8516155b156106eb5760018660ff166002811061062657fe5b0154604080517f42966c6800000000000000000000000000000000000000000000000000000000815260048101879052905173ffffffffffffffffffffffffffffffffffffffff909216916342966c689160248082019260009290919082900301818387803b15801561069857600080fd5b505af11580156106ac573d6000803e3d6000fd5b505050506106e4338560018860ff16600281106106c557fe5b015473ffffffffffffffffffffffffffffffffffffffff169190610876565b5082610752565b604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f556e737570706f7274656420696e646578657300000000000000000000000000604482015290519081900360640190fd5b95945050505050565b805b9392505050565b6040805173ffffffffffffffffffffffffffffffffffffffff80861660248301528416604482015260648082018490528251808303909101815260849091019091526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f23b872dd000000000000000000000000000000000000000000000000000000001790526107f9908590610908565b50505050565b60008282111561087057604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601e60248201527f536166654d6174683a207375627472616374696f6e206f766572666c6f770000604482015290519081900360640190fd5b50900390565b6040805173ffffffffffffffffffffffffffffffffffffffff8416602482015260448082018490528251808303909101815260649091019091526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fa9059cbb00000000000000000000000000000000000000000000000000000000179052610903908490610908565b505050565b606061096a826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff166109e09092919063ffffffff16565b8051909150156109035780806020019051602081101561098957600080fd5b5051610903576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602a815260200180610c9d602a913960400191505060405180910390fd5b60606109ef84846000856109f7565b949350505050565b606082471015610a52576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526026815260200180610c776026913960400191505060405180910390fd5b610a5b85610bb2565b610ac657604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000604482015290519081900360640190fd5b600060608673ffffffffffffffffffffffffffffffffffffffff1685876040518082805190602001908083835b60208310610b3057805182527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe09092019160209182019101610af3565b6001836020036101000a03801982511681845116808217855250505050505090500191505060006040518083038185875af1925050503d8060008114610b92576040519150601f19603f3d011682016040523d82523d6000602084013e610b97565b606091505b5091509150610ba7828286610bb8565b979650505050505050565b3b151590565b60608315610bc757508161075d565b825115610bd75782518084602001fd5b816040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825283818151815260200191508051906020019080838360005b83811015610c3b578181015183820152602001610c23565b50505050905090810190601f168015610c685780820380516001836020036101000a031916815260200191505b509250505060405180910390fdfe416464726573733a20696e73756666696369656e742062616c616e636520666f722063616c6c5361666545524332303a204552433230206f7065726174696f6e20646964206e6f742073756363656564a26469706673582212208d61e042f830e58f0680a2a6fb9a207cb685c0ce5979198456d025d18002398f64736f6c634300060c0033", + "devdoc": { + "kind": "dev", + "methods": { + "calculateSwap(uint8,uint8,uint256)": { + "params": { + "dx": "the amount of tokens the user wants to swap. ", + "tokenIndexFrom": "the token the user wants to sell", + "tokenIndexTo": "the token the user wants to buy" + }, + "returns": { + "_0": "amount of tokens the user will receive" + } + }, + "getToken(uint8)": { + "params": { + "index": "the index of the token" + }, + "returns": { + "_0": "address of the token at given index" + } + }, + "getTokenIndex(address)": { + "params": { + "tokenAddress": "address of the token" + }, + "returns": { + "_0": "the index of the given token address" + } + }, + "swap(uint8,uint8,uint256,uint256,uint256)": { + "params": { + "deadline": "latest timestamp to accept this transaction", + "dx": "the amount of tokens the user wants to swap from", + "minDy": "the min amount the user would like to receive, or revert.", + "tokenIndexFrom": "the token the user wants to swap from", + "tokenIndexTo": "the token the user wants to swap to" + } + } + }, + "version": 1 + }, + "userdoc": { + "kind": "user", + "methods": { + "calculateSwap(uint8,uint8,uint256)": { + "notice": "Calculate amount of tokens you receive on swap" + }, + "getToken(uint8)": { + "notice": "Return address of the pooled token at given index. Reverts if tokenIndex is out of range." + }, + "getTokenIndex(address)": { + "notice": "Return the index of the given token address. Reverts if no matching token is found." + }, + "swap(uint8,uint8,uint256,uint256,uint256)": { + "notice": "Swap two tokens using this pool" + } + }, + "version": 1 + }, + "storageLayout": { + "storage": [ + { + "astId": 24454, + "contract": "contracts/bridge/wrappers/JewelBridgeSwap.sol:JewelBridgeSwap", + "label": "tokenIndexes", + "offset": 0, + "slot": "0", + "type": "t_mapping(t_address,t_uint8)" + }, + { + "astId": 24458, + "contract": "contracts/bridge/wrappers/JewelBridgeSwap.sol:JewelBridgeSwap", + "label": "pooledTokens", + "offset": 0, + "slot": "1", + "type": "t_array(t_contract(IERC20)4954)2_storage" + } + ], + "types": { + "t_address": { + "encoding": "inplace", + "label": "address", + "numberOfBytes": "20" + }, + "t_array(t_contract(IERC20)4954)2_storage": { + "base": "t_contract(IERC20)4954", + "encoding": "inplace", + "label": "contract IERC20[2]", + "numberOfBytes": "64" + }, + "t_contract(IERC20)4954": { + "encoding": "inplace", + "label": "contract IERC20", + "numberOfBytes": "20" + }, + "t_mapping(t_address,t_uint8)": { + "encoding": "mapping", + "key": "t_address", + "label": "mapping(address => uint8)", + "numberOfBytes": "32", + "value": "t_uint8" + }, + "t_uint8": { + "encoding": "inplace", + "label": "uint8", + "numberOfBytes": "1" + } + } + } +} \ No newline at end of file diff --git a/deployments/harmony/L2BridgeZap.json b/deployments/harmony/L2BridgeZap.json index f4999c8ee..c1b0a7df6 100644 --- a/deployments/harmony/L2BridgeZap.json +++ b/deployments/harmony/L2BridgeZap.json @@ -1,5 +1,5 @@ { - "address": "0xB729B5bAD4B42f3bDd4A3518a1Cc00178cb5920a", + "address": "0xB003e75f7E0B5365e814302192E99b4EE08c0DEd", "abi": [ { "inputs": [ @@ -28,6 +28,26 @@ "name": "tokenTwo", "type": "address" }, + { + "internalType": "address", + "name": "_swapThree", + "type": "address" + }, + { + "internalType": "address", + "name": "tokenThree", + "type": "address" + }, + { + "internalType": "address", + "name": "_swapFour", + "type": "address" + }, + { + "internalType": "address", + "name": "tokenFour", + "type": "address" + }, { "internalType": "contract ISynapseBridge", "name": "_synapseBridge", @@ -502,188 +522,300 @@ "type": "function" } ], - "transactionHash": "0x32ca3a2f7e348c7b914cb139850c57b106f80d6c70089b8730669c5376d97aa7", + "transactionHash": "0x7fc2bbfe8e811adaf1045e21718150bc315df59b926d045ab2f5aa3db6dc3df2", "receipt": { "to": null, "from": "0x0AF91FA049A7e1894F480bFE5bBa20142C6c29a9", - "contractAddress": "0xB729B5bAD4B42f3bDd4A3518a1Cc00178cb5920a", - "transactionIndex": 34, - "gasUsed": "2549013", - "logsBloom": "0x01000000000000000000000000020000400000000000000000000000004000000000000000000400000000000040000000000000000001000000000800200000000000000000000000000000000004000000200000082008000000100000004000000000000000000002000000000000000000000014000000000000000000004000000000000000000000000000000000000000000000000000000000000000020000000000200000000000000100000000000000000000000400000000000000000000000008000000000000000000400000002008020000000000000000000010000000000000000000000000000000000000000000400000000000080000", - "blockHash": "0xa0141a3119c6043994dc4530696008acd13923346876f8c1c521ddcc651da854", - "transactionHash": "0x32ca3a2f7e348c7b914cb139850c57b106f80d6c70089b8730669c5376d97aa7", + "contractAddress": "0xB003e75f7E0B5365e814302192E99b4EE08c0DEd", + "transactionIndex": 2, + "gasUsed": "3079209", + "logsBloom": "0x11000000002000000000000000020000400000004000000000000000004010000000000000000400000000000040000000000800000001000004000800200000000000000008000000000000000004000000200002082008000000000000004000000000800000000202000000000000000000000014000000000000000000006002020000000000000000000000000000000000000000000000000000000000020000040100200800000000000000000000000000000000000400000000000000000100000008000000000000200000400000002008020040080000000000000010000000000000000000000000000000000000000000400000000000000000", + "blockHash": "0x029abe103399a69026a20416a2b87c98c38328a8dc34c5d2da9c538d49aa3900", + "transactionHash": "0x7fc2bbfe8e811adaf1045e21718150bc315df59b926d045ab2f5aa3db6dc3df2", "logs": [ { - "transactionIndex": 34, - "blockNumber": 21385945, - "transactionHash": "0x32ca3a2f7e348c7b914cb139850c57b106f80d6c70089b8730669c5376d97aa7", + "transactionIndex": 2, + "blockNumber": 24804355, + "transactionHash": "0x7fc2bbfe8e811adaf1045e21718150bc315df59b926d045ab2f5aa3db6dc3df2", "address": "0xED2a7edd7413021d440b09D654f3b87712abAB66", "topics": [ "0x8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925", - "0x000000000000000000000000b729b5bad4b42f3bdd4a3518a1cc00178cb5920a", + "0x000000000000000000000000b003e75f7e0b5365e814302192e99b4ee08c0ded", "0x0000000000000000000000003ea9b0ab55f34fb188824ee288ceaefc63cf908e" ], "data": "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", - "logIndex": 107, - "blockHash": "0xa0141a3119c6043994dc4530696008acd13923346876f8c1c521ddcc651da854" + "logIndex": 9, + "blockHash": "0x029abe103399a69026a20416a2b87c98c38328a8dc34c5d2da9c538d49aa3900" }, { - "transactionIndex": 34, - "blockNumber": 21385945, - "transactionHash": "0x32ca3a2f7e348c7b914cb139850c57b106f80d6c70089b8730669c5376d97aa7", + "transactionIndex": 2, + "blockNumber": 24804355, + "transactionHash": "0x7fc2bbfe8e811adaf1045e21718150bc315df59b926d045ab2f5aa3db6dc3df2", "address": "0xED2a7edd7413021d440b09D654f3b87712abAB66", "topics": [ "0x8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925", - "0x000000000000000000000000b729b5bad4b42f3bdd4a3518a1cc00178cb5920a", + "0x000000000000000000000000b003e75f7e0b5365e814302192e99b4ee08c0ded", "0x000000000000000000000000af41a65f786339e7911f4acdad6bd49426f2dc6b" ], "data": "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", - "logIndex": 108, - "blockHash": "0xa0141a3119c6043994dc4530696008acd13923346876f8c1c521ddcc651da854" + "logIndex": 10, + "blockHash": "0x029abe103399a69026a20416a2b87c98c38328a8dc34c5d2da9c538d49aa3900" }, { - "transactionIndex": 34, - "blockNumber": 21385945, - "transactionHash": "0x32ca3a2f7e348c7b914cb139850c57b106f80d6c70089b8730669c5376d97aa7", + "transactionIndex": 2, + "blockNumber": 24804355, + "transactionHash": "0x7fc2bbfe8e811adaf1045e21718150bc315df59b926d045ab2f5aa3db6dc3df2", "address": "0xEf977d2f931C1978Db5F6747666fa1eACB0d0339", "topics": [ "0x8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925", - "0x000000000000000000000000b729b5bad4b42f3bdd4a3518a1cc00178cb5920a", + "0x000000000000000000000000b003e75f7e0b5365e814302192e99b4ee08c0ded", "0x0000000000000000000000003ea9b0ab55f34fb188824ee288ceaefc63cf908e" ], "data": "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", - "logIndex": 109, - "blockHash": "0xa0141a3119c6043994dc4530696008acd13923346876f8c1c521ddcc651da854" + "logIndex": 11, + "blockHash": "0x029abe103399a69026a20416a2b87c98c38328a8dc34c5d2da9c538d49aa3900" }, { - "transactionIndex": 34, - "blockNumber": 21385945, - "transactionHash": "0x32ca3a2f7e348c7b914cb139850c57b106f80d6c70089b8730669c5376d97aa7", + "transactionIndex": 2, + "blockNumber": 24804355, + "transactionHash": "0x7fc2bbfe8e811adaf1045e21718150bc315df59b926d045ab2f5aa3db6dc3df2", "address": "0xEf977d2f931C1978Db5F6747666fa1eACB0d0339", "topics": [ "0x8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925", - "0x000000000000000000000000b729b5bad4b42f3bdd4a3518a1cc00178cb5920a", + "0x000000000000000000000000b003e75f7e0b5365e814302192e99b4ee08c0ded", "0x000000000000000000000000af41a65f786339e7911f4acdad6bd49426f2dc6b" ], "data": "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", - "logIndex": 110, - "blockHash": "0xa0141a3119c6043994dc4530696008acd13923346876f8c1c521ddcc651da854" + "logIndex": 12, + "blockHash": "0x029abe103399a69026a20416a2b87c98c38328a8dc34c5d2da9c538d49aa3900" }, { - "transactionIndex": 34, - "blockNumber": 21385945, - "transactionHash": "0x32ca3a2f7e348c7b914cb139850c57b106f80d6c70089b8730669c5376d97aa7", + "transactionIndex": 2, + "blockNumber": 24804355, + "transactionHash": "0x7fc2bbfe8e811adaf1045e21718150bc315df59b926d045ab2f5aa3db6dc3df2", "address": "0x985458E523dB3d53125813eD68c274899e9DfAb4", "topics": [ "0x8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925", - "0x000000000000000000000000b729b5bad4b42f3bdd4a3518a1cc00178cb5920a", + "0x000000000000000000000000b003e75f7e0b5365e814302192e99b4ee08c0ded", "0x0000000000000000000000003ea9b0ab55f34fb188824ee288ceaefc63cf908e" ], "data": "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", - "logIndex": 111, - "blockHash": "0xa0141a3119c6043994dc4530696008acd13923346876f8c1c521ddcc651da854" + "logIndex": 13, + "blockHash": "0x029abe103399a69026a20416a2b87c98c38328a8dc34c5d2da9c538d49aa3900" }, { - "transactionIndex": 34, - "blockNumber": 21385945, - "transactionHash": "0x32ca3a2f7e348c7b914cb139850c57b106f80d6c70089b8730669c5376d97aa7", + "transactionIndex": 2, + "blockNumber": 24804355, + "transactionHash": "0x7fc2bbfe8e811adaf1045e21718150bc315df59b926d045ab2f5aa3db6dc3df2", "address": "0x985458E523dB3d53125813eD68c274899e9DfAb4", "topics": [ "0x8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925", - "0x000000000000000000000000b729b5bad4b42f3bdd4a3518a1cc00178cb5920a", + "0x000000000000000000000000b003e75f7e0b5365e814302192e99b4ee08c0ded", "0x000000000000000000000000af41a65f786339e7911f4acdad6bd49426f2dc6b" ], "data": "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", - "logIndex": 112, - "blockHash": "0xa0141a3119c6043994dc4530696008acd13923346876f8c1c521ddcc651da854" + "logIndex": 14, + "blockHash": "0x029abe103399a69026a20416a2b87c98c38328a8dc34c5d2da9c538d49aa3900" }, { - "transactionIndex": 34, - "blockNumber": 21385945, - "transactionHash": "0x32ca3a2f7e348c7b914cb139850c57b106f80d6c70089b8730669c5376d97aa7", + "transactionIndex": 2, + "blockNumber": 24804355, + "transactionHash": "0x7fc2bbfe8e811adaf1045e21718150bc315df59b926d045ab2f5aa3db6dc3df2", "address": "0x3C2B8Be99c50593081EAA2A724F0B8285F5aba8f", "topics": [ "0x8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925", - "0x000000000000000000000000b729b5bad4b42f3bdd4a3518a1cc00178cb5920a", + "0x000000000000000000000000b003e75f7e0b5365e814302192e99b4ee08c0ded", "0x0000000000000000000000003ea9b0ab55f34fb188824ee288ceaefc63cf908e" ], "data": "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", - "logIndex": 113, - "blockHash": "0xa0141a3119c6043994dc4530696008acd13923346876f8c1c521ddcc651da854" + "logIndex": 15, + "blockHash": "0x029abe103399a69026a20416a2b87c98c38328a8dc34c5d2da9c538d49aa3900" }, { - "transactionIndex": 34, - "blockNumber": 21385945, - "transactionHash": "0x32ca3a2f7e348c7b914cb139850c57b106f80d6c70089b8730669c5376d97aa7", + "transactionIndex": 2, + "blockNumber": 24804355, + "transactionHash": "0x7fc2bbfe8e811adaf1045e21718150bc315df59b926d045ab2f5aa3db6dc3df2", "address": "0x3C2B8Be99c50593081EAA2A724F0B8285F5aba8f", "topics": [ "0x8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925", - "0x000000000000000000000000b729b5bad4b42f3bdd4a3518a1cc00178cb5920a", + "0x000000000000000000000000b003e75f7e0b5365e814302192e99b4ee08c0ded", "0x000000000000000000000000af41a65f786339e7911f4acdad6bd49426f2dc6b" ], "data": "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", - "logIndex": 114, - "blockHash": "0xa0141a3119c6043994dc4530696008acd13923346876f8c1c521ddcc651da854" + "logIndex": 16, + "blockHash": "0x029abe103399a69026a20416a2b87c98c38328a8dc34c5d2da9c538d49aa3900" }, { - "transactionIndex": 34, - "blockNumber": 21385945, - "transactionHash": "0x32ca3a2f7e348c7b914cb139850c57b106f80d6c70089b8730669c5376d97aa7", + "transactionIndex": 2, + "blockNumber": 24804355, + "transactionHash": "0x7fc2bbfe8e811adaf1045e21718150bc315df59b926d045ab2f5aa3db6dc3df2", "address": "0x0b5740c6b4a97f90eF2F0220651Cca420B868FfB", "topics": [ "0x8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925", - "0x000000000000000000000000b729b5bad4b42f3bdd4a3518a1cc00178cb5920a", + "0x000000000000000000000000b003e75f7e0b5365e814302192e99b4ee08c0ded", "0x0000000000000000000000002913e812cf0dcca30fb28e6cac3d2dcff4497688" ], "data": "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", - "logIndex": 115, - "blockHash": "0xa0141a3119c6043994dc4530696008acd13923346876f8c1c521ddcc651da854" + "logIndex": 17, + "blockHash": "0x029abe103399a69026a20416a2b87c98c38328a8dc34c5d2da9c538d49aa3900" }, { - "transactionIndex": 34, - "blockNumber": 21385945, - "transactionHash": "0x32ca3a2f7e348c7b914cb139850c57b106f80d6c70089b8730669c5376d97aa7", + "transactionIndex": 2, + "blockNumber": 24804355, + "transactionHash": "0x7fc2bbfe8e811adaf1045e21718150bc315df59b926d045ab2f5aa3db6dc3df2", "address": "0x0b5740c6b4a97f90eF2F0220651Cca420B868FfB", "topics": [ "0x8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925", - "0x000000000000000000000000b729b5bad4b42f3bdd4a3518a1cc00178cb5920a", + "0x000000000000000000000000b003e75f7e0b5365e814302192e99b4ee08c0ded", "0x000000000000000000000000af41a65f786339e7911f4acdad6bd49426f2dc6b" ], "data": "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", - "logIndex": 116, - "blockHash": "0xa0141a3119c6043994dc4530696008acd13923346876f8c1c521ddcc651da854" + "logIndex": 18, + "blockHash": "0x029abe103399a69026a20416a2b87c98c38328a8dc34c5d2da9c538d49aa3900" }, { - "transactionIndex": 34, - "blockNumber": 21385945, - "transactionHash": "0x32ca3a2f7e348c7b914cb139850c57b106f80d6c70089b8730669c5376d97aa7", + "transactionIndex": 2, + "blockNumber": 24804355, + "transactionHash": "0x7fc2bbfe8e811adaf1045e21718150bc315df59b926d045ab2f5aa3db6dc3df2", "address": "0x6983D1E6DEf3690C4d616b13597A09e6193EA013", "topics": [ "0x8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925", - "0x000000000000000000000000b729b5bad4b42f3bdd4a3518a1cc00178cb5920a", + "0x000000000000000000000000b003e75f7e0b5365e814302192e99b4ee08c0ded", "0x0000000000000000000000002913e812cf0dcca30fb28e6cac3d2dcff4497688" ], "data": "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", - "logIndex": 117, - "blockHash": "0xa0141a3119c6043994dc4530696008acd13923346876f8c1c521ddcc651da854" + "logIndex": 19, + "blockHash": "0x029abe103399a69026a20416a2b87c98c38328a8dc34c5d2da9c538d49aa3900" }, { - "transactionIndex": 34, - "blockNumber": 21385945, - "transactionHash": "0x32ca3a2f7e348c7b914cb139850c57b106f80d6c70089b8730669c5376d97aa7", + "transactionIndex": 2, + "blockNumber": 24804355, + "transactionHash": "0x7fc2bbfe8e811adaf1045e21718150bc315df59b926d045ab2f5aa3db6dc3df2", "address": "0x6983D1E6DEf3690C4d616b13597A09e6193EA013", "topics": [ "0x8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925", - "0x000000000000000000000000b729b5bad4b42f3bdd4a3518a1cc00178cb5920a", + "0x000000000000000000000000b003e75f7e0b5365e814302192e99b4ee08c0ded", + "0x000000000000000000000000af41a65f786339e7911f4acdad6bd49426f2dc6b" + ], + "data": "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + "logIndex": 20, + "blockHash": "0x029abe103399a69026a20416a2b87c98c38328a8dc34c5d2da9c538d49aa3900" + }, + { + "transactionIndex": 2, + "blockNumber": 24804355, + "transactionHash": "0x7fc2bbfe8e811adaf1045e21718150bc315df59b926d045ab2f5aa3db6dc3df2", + "address": "0x72Cb10C6bfA5624dD07Ef608027E366bd690048F", + "topics": [ + "0x8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925", + "0x000000000000000000000000b003e75f7e0b5365e814302192e99b4ee08c0ded", + "0x0000000000000000000000007be461cce1501f07969bce24ccb2140fca0a35b3" + ], + "data": "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + "logIndex": 21, + "blockHash": "0x029abe103399a69026a20416a2b87c98c38328a8dc34c5d2da9c538d49aa3900" + }, + { + "transactionIndex": 2, + "blockNumber": 24804355, + "transactionHash": "0x7fc2bbfe8e811adaf1045e21718150bc315df59b926d045ab2f5aa3db6dc3df2", + "address": "0x72Cb10C6bfA5624dD07Ef608027E366bd690048F", + "topics": [ + "0x8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925", + "0x000000000000000000000000b003e75f7e0b5365e814302192e99b4ee08c0ded", + "0x000000000000000000000000af41a65f786339e7911f4acdad6bd49426f2dc6b" + ], + "data": "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + "logIndex": 22, + "blockHash": "0x029abe103399a69026a20416a2b87c98c38328a8dc34c5d2da9c538d49aa3900" + }, + { + "transactionIndex": 2, + "blockNumber": 24804355, + "transactionHash": "0x7fc2bbfe8e811adaf1045e21718150bc315df59b926d045ab2f5aa3db6dc3df2", + "address": "0x28b42698Caf46B4B012CF38b6C75867E0762186D", + "topics": [ + "0x8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925", + "0x000000000000000000000000b003e75f7e0b5365e814302192e99b4ee08c0ded", + "0x0000000000000000000000007be461cce1501f07969bce24ccb2140fca0a35b3" + ], + "data": "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + "logIndex": 23, + "blockHash": "0x029abe103399a69026a20416a2b87c98c38328a8dc34c5d2da9c538d49aa3900" + }, + { + "transactionIndex": 2, + "blockNumber": 24804355, + "transactionHash": "0x7fc2bbfe8e811adaf1045e21718150bc315df59b926d045ab2f5aa3db6dc3df2", + "address": "0x28b42698Caf46B4B012CF38b6C75867E0762186D", + "topics": [ + "0x8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925", + "0x000000000000000000000000b003e75f7e0b5365e814302192e99b4ee08c0ded", + "0x000000000000000000000000af41a65f786339e7911f4acdad6bd49426f2dc6b" + ], + "data": "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + "logIndex": 24, + "blockHash": "0x029abe103399a69026a20416a2b87c98c38328a8dc34c5d2da9c538d49aa3900" + }, + { + "transactionIndex": 2, + "blockNumber": 24804355, + "transactionHash": "0x7fc2bbfe8e811adaf1045e21718150bc315df59b926d045ab2f5aa3db6dc3df2", + "address": "0xD9eAA386cCD65F30b77FF175F6b52115FE454fD6", + "topics": [ + "0x8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925", + "0x000000000000000000000000b003e75f7e0b5365e814302192e99b4ee08c0ded", + "0x00000000000000000000000000a4f57d926781f62d09bb05ec76e6d8ae4268da" + ], + "data": "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + "logIndex": 25, + "blockHash": "0x029abe103399a69026a20416a2b87c98c38328a8dc34c5d2da9c538d49aa3900" + }, + { + "transactionIndex": 2, + "blockNumber": 24804355, + "transactionHash": "0x7fc2bbfe8e811adaf1045e21718150bc315df59b926d045ab2f5aa3db6dc3df2", + "address": "0xD9eAA386cCD65F30b77FF175F6b52115FE454fD6", + "topics": [ + "0x8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925", + "0x000000000000000000000000b003e75f7e0b5365e814302192e99b4ee08c0ded", + "0x000000000000000000000000af41a65f786339e7911f4acdad6bd49426f2dc6b" + ], + "data": "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + "logIndex": 26, + "blockHash": "0x029abe103399a69026a20416a2b87c98c38328a8dc34c5d2da9c538d49aa3900" + }, + { + "transactionIndex": 2, + "blockNumber": 24804355, + "transactionHash": "0x7fc2bbfe8e811adaf1045e21718150bc315df59b926d045ab2f5aa3db6dc3df2", + "address": "0xb12c13e66AdE1F72f71834f2FC5082Db8C091358", + "topics": [ + "0x8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925", + "0x000000000000000000000000b003e75f7e0b5365e814302192e99b4ee08c0ded", + "0x00000000000000000000000000a4f57d926781f62d09bb05ec76e6d8ae4268da" + ], + "data": "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + "logIndex": 27, + "blockHash": "0x029abe103399a69026a20416a2b87c98c38328a8dc34c5d2da9c538d49aa3900" + }, + { + "transactionIndex": 2, + "blockNumber": 24804355, + "transactionHash": "0x7fc2bbfe8e811adaf1045e21718150bc315df59b926d045ab2f5aa3db6dc3df2", + "address": "0xb12c13e66AdE1F72f71834f2FC5082Db8C091358", + "topics": [ + "0x8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925", + "0x000000000000000000000000b003e75f7e0b5365e814302192e99b4ee08c0ded", "0x000000000000000000000000af41a65f786339e7911f4acdad6bd49426f2dc6b" ], "data": "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", - "logIndex": 118, - "blockHash": "0xa0141a3119c6043994dc4530696008acd13923346876f8c1c521ddcc651da854" + "logIndex": 28, + "blockHash": "0x029abe103399a69026a20416a2b87c98c38328a8dc34c5d2da9c538d49aa3900" } ], - "blockNumber": 21385945, - "cumulativeGasUsed": "14057648", + "blockNumber": 24804355, + "cumulativeGasUsed": "3300631", "status": 1, "byzantium": true }, @@ -693,12 +825,16 @@ "0xED2a7edd7413021d440b09D654f3b87712abAB66", "0x2913E812Cf0dcCA30FB28E6Cac3d2DCFF4497688", "0x0b5740c6b4a97f90eF2F0220651Cca420B868FfB", + "0x7bE461cce1501f07969BCE24Ccb2140fCA0a35b3", + "0x28b42698Caf46B4B012CF38b6C75867E0762186D", + "0x00A4F57D926781f62D09bb05ec76e6D8aE4268da", + "0xD9eAA386cCD65F30b77FF175F6b52115FE454fD6", "0xAf41a65F786339e7911F4acDAD6BD49426F2Dc6b" ], - "solcInputHash": "035e670bc4ede9b753b567daabb2af5e", - "metadata": "{\"compiler\":{\"version\":\"0.6.12+commit.27d51765\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address payable\",\"name\":\"_wethAddress\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_swapOne\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenOne\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_swapTwo\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenTwo\",\"type\":\"address\"},{\"internalType\":\"contract ISynapseBridge\",\"name\":\"_synapseBridge\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"WETH_ADDRESS\",\"outputs\":[{\"internalType\":\"address payable\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contract IERC20\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint8\",\"name\":\"tokenIndexFrom\",\"type\":\"uint8\"},{\"internalType\":\"uint8\",\"name\":\"tokenIndexTo\",\"type\":\"uint8\"},{\"internalType\":\"uint256\",\"name\":\"dx\",\"type\":\"uint256\"}],\"name\":\"calculateSwap\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"chainId\",\"type\":\"uint256\"},{\"internalType\":\"contract IERC20\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"deposit\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"chainId\",\"type\":\"uint256\"},{\"internalType\":\"contract IERC20\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"redeem\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"chainId\",\"type\":\"uint256\"},{\"internalType\":\"contract IERC20\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"uint8\",\"name\":\"liqTokenIndex\",\"type\":\"uint8\"},{\"internalType\":\"uint256\",\"name\":\"liqMinAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"liqDeadline\",\"type\":\"uint256\"}],\"name\":\"redeemAndRemove\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"chainId\",\"type\":\"uint256\"},{\"internalType\":\"contract IERC20\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"uint8\",\"name\":\"tokenIndexFrom\",\"type\":\"uint8\"},{\"internalType\":\"uint8\",\"name\":\"tokenIndexTo\",\"type\":\"uint8\"},{\"internalType\":\"uint256\",\"name\":\"minDy\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"deadline\",\"type\":\"uint256\"}],\"name\":\"redeemAndSwap\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"chainId\",\"type\":\"uint256\"},{\"internalType\":\"contract IERC20\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint8\",\"name\":\"tokenIndexFrom\",\"type\":\"uint8\"},{\"internalType\":\"uint8\",\"name\":\"tokenIndexTo\",\"type\":\"uint8\"},{\"internalType\":\"uint256\",\"name\":\"dx\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"minDy\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"deadline\",\"type\":\"uint256\"}],\"name\":\"swapAndRedeem\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"chainId\",\"type\":\"uint256\"},{\"internalType\":\"contract IERC20\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint8\",\"name\":\"tokenIndexFrom\",\"type\":\"uint8\"},{\"internalType\":\"uint8\",\"name\":\"tokenIndexTo\",\"type\":\"uint8\"},{\"internalType\":\"uint256\",\"name\":\"dx\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"minDy\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"deadline\",\"type\":\"uint256\"},{\"internalType\":\"uint8\",\"name\":\"liqTokenIndex\",\"type\":\"uint8\"},{\"internalType\":\"uint256\",\"name\":\"liqMinAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"liqDeadline\",\"type\":\"uint256\"}],\"name\":\"swapAndRedeemAndRemove\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"chainId\",\"type\":\"uint256\"},{\"internalType\":\"contract IERC20\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint8\",\"name\":\"tokenIndexFrom\",\"type\":\"uint8\"},{\"internalType\":\"uint8\",\"name\":\"tokenIndexTo\",\"type\":\"uint8\"},{\"internalType\":\"uint256\",\"name\":\"dx\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"minDy\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"deadline\",\"type\":\"uint256\"},{\"internalType\":\"uint8\",\"name\":\"swapTokenIndexFrom\",\"type\":\"uint8\"},{\"internalType\":\"uint8\",\"name\":\"swapTokenIndexTo\",\"type\":\"uint8\"},{\"internalType\":\"uint256\",\"name\":\"swapMinDy\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"swapDeadline\",\"type\":\"uint256\"}],\"name\":\"swapAndRedeemAndSwap\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"chainId\",\"type\":\"uint256\"},{\"internalType\":\"contract IERC20\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint8\",\"name\":\"tokenIndexFrom\",\"type\":\"uint8\"},{\"internalType\":\"uint8\",\"name\":\"tokenIndexTo\",\"type\":\"uint8\"},{\"internalType\":\"uint256\",\"name\":\"dx\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"minDy\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"deadline\",\"type\":\"uint256\"}],\"name\":\"swapETHAndRedeem\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"swapMap\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"swapTokensMap\",\"outputs\":[{\"internalType\":\"contract IERC20\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{\"calculateSwap(address,uint8,uint8,uint256)\":{\"params\":{\"dx\":\"the amount of tokens the user wants to sell. If the token charges a fee on transfers, use the amount that gets transferred after the fee.\",\"tokenIndexFrom\":\"the token the user wants to sell\",\"tokenIndexTo\":\"the token the user wants to buy\"},\"returns\":{\"_0\":\"amount of tokens the user will receive\"}},\"deposit(address,uint256,address,uint256)\":{\"params\":{\"amount\":\"Amount in native token decimals to transfer cross-chain pre-fees*\",\"chainId\":\"which underlying chain to bridge assets onto\",\"to\":\"address on other chain to redeem underlying assets to\",\"token\":\"ERC20 compatible token to deposit into the bridge\"}},\"redeem(address,uint256,address,uint256)\":{\"params\":{\"amount\":\"Amount in native token decimals to transfer cross-chain pre-fees*\",\"chainId\":\"which underlying chain to bridge assets onto\",\"to\":\"address on other chain to redeem underlying assets to\",\"token\":\"ERC20 compatible token to deposit into the bridge\"}},\"redeemAndRemove(address,uint256,address,uint256,uint8,uint256,uint256)\":{\"params\":{\"amount\":\"Amount of (typically) LP token to pass to the nodes to attempt to removeLiquidity() with to redeem for the underlying assets of the LP token\",\"chainId\":\"which underlying chain to bridge assets onto\",\"liqDeadline\":\"Specificies the deadline that the nodes are allowed to try to redeem/swap the LP token*\",\"liqMinAmount\":\"Specifies the minimum amount of the underlying asset needed for the nodes to execute the redeem/swap\",\"liqTokenIndex\":\"Specifies which of the underlying LP assets the nodes should attempt to redeem for\",\"to\":\"address on other chain to redeem underlying assets to\",\"token\":\"ERC20 compatible token to deposit into the bridge\"}},\"redeemAndSwap(address,uint256,address,uint256,uint8,uint8,uint256,uint256)\":{\"params\":{\"amount\":\"Amount in native token decimals to transfer cross-chain pre-fees\",\"chainId\":\"which underlying chain to bridge assets onto\",\"deadline\":\"latest timestamp to accept this transaction*\",\"minDy\":\"the min amount the user would like to receive, or revert to only minting the SynERC20 token crosschain.\",\"to\":\"address on other chain to redeem underlying assets to\",\"token\":\"ERC20 compatible token to deposit into the bridge\",\"tokenIndexFrom\":\"the token the user wants to swap from\",\"tokenIndexTo\":\"the token the user wants to swap to\"}}},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{\"calculateSwap(address,uint8,uint8,uint256)\":{\"notice\":\"Calculate amount of tokens you receive on swap\"},\"deposit(address,uint256,address,uint256)\":{\"notice\":\"wraps SynapseBridge redeem()\"},\"redeem(address,uint256,address,uint256)\":{\"notice\":\"wraps SynapseBridge redeem()\"},\"redeemAndRemove(address,uint256,address,uint256,uint8,uint256,uint256)\":{\"notice\":\"Wraps redeemAndRemove on SynapseBridge Relays to nodes that (typically) a wrapped synAsset ERC20 token has been burned and the underlying needs to be redeeemed on the native chain. This function indicates to the nodes that they should attempt to redeem the LP token for the underlying assets (E.g \\\"swap\\\" out of the LP token)\"},\"redeemAndSwap(address,uint256,address,uint256,uint8,uint8,uint256,uint256)\":{\"notice\":\"Wraps redeemAndSwap on SynapseBridge.sol Relays to nodes that (typically) a wrapped synAsset ERC20 token has been burned and the underlying needs to be redeeemed on the native chain. This function indicates to the nodes that they should attempt to redeem the LP token for the underlying assets (E.g \\\"swap\\\" out of the LP token)\"}},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/bridge/wrappers/HarmonyBridgeZap.sol\":\"HarmonyBridgeZap\"},\"evmVersion\":\"istanbul\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":10000},\"remappings\":[]},\"sources\":{\"@openzeppelin/contracts/math/SafeMath.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity >=0.6.0 <0.8.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\",\"keccak256\":\"0xcc78a17dd88fa5a2edc60c8489e2f405c0913b377216a5b26b35656b2d0dab52\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/ERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity >=0.6.0 <0.8.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_) public {\\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\",\"keccak256\":\"0xca0c2396dbeb3503b51abf4248ebf77a1461edad513c01529df51850a012bee3\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/ERC20Burnable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity >=0.6.0 <0.8.0;\\n\\nimport \\\"../../utils/Context.sol\\\";\\nimport \\\"./ERC20.sol\\\";\\n\\n/**\\n * @dev Extension of {ERC20} that allows token holders to destroy both their own\\n * tokens and those that they have an allowance for, in a way that can be\\n * recognized off-chain (via event analysis).\\n */\\nabstract contract ERC20Burnable is Context, ERC20 {\\n using SafeMath for uint256;\\n\\n /**\\n * @dev Destroys `amount` tokens from the caller.\\n *\\n * See {ERC20-_burn}.\\n */\\n function burn(uint256 amount) public virtual {\\n _burn(_msgSender(), amount);\\n }\\n\\n /**\\n * @dev Destroys `amount` tokens from `account`, deducting from the caller's\\n * allowance.\\n *\\n * See {ERC20-_burn} and {ERC20-allowance}.\\n *\\n * Requirements:\\n *\\n * - the caller must have allowance for ``accounts``'s tokens of at least\\n * `amount`.\\n */\\n function burnFrom(address account, uint256 amount) public virtual {\\n uint256 decreasedAllowance = allowance(account, _msgSender()).sub(amount, \\\"ERC20: burn amount exceeds allowance\\\");\\n\\n _approve(account, _msgSender(), decreasedAllowance);\\n _burn(account, amount);\\n }\\n}\\n\",\"keccak256\":\"0x9c0eb3b0e11d2480d49991dc384f1e5f9c9b9967cc81944d50916a9b9c6c4984\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/IERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity >=0.6.0 <0.8.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\",\"keccak256\":\"0x5f02220344881ce43204ae4a6281145a67bc52c2bb1290a791857df3d19d78f5\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/SafeERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity >=0.6.0 <0.8.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\",\"keccak256\":\"0xf12dfbe97e6276980b83d2830bb0eb75e0cf4f3e626c2471137f82158ae6a0fc\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/Address.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity >=0.6.2 <0.8.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\",\"keccak256\":\"0x28911e614500ae7c607a432a709d35da25f3bc5ddc8bd12b278b66358070c0ea\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/Context.sol\":{\"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\",\"keccak256\":\"0x8d3cb350f04ff49cfb10aef08d87f19dcbaecc8027b0bed12f3275cd12f38cf0\",\"license\":\"MIT\"},\"contracts/bridge/interfaces/ISwap.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity 0.6.12;\\n\\nimport '@openzeppelin/contracts/token/ERC20/ERC20.sol';\\n\\ninterface ISwap {\\n // pool data view functions\\n function getA() external view returns (uint256);\\n\\n function getToken(uint8 index) external view returns (IERC20);\\n\\n function getTokenIndex(address tokenAddress) external view returns (uint8);\\n\\n function getTokenBalance(uint8 index) external view returns (uint256);\\n\\n function getVirtualPrice() external view returns (uint256);\\n\\n // min return calculation functions\\n function calculateSwap(\\n uint8 tokenIndexFrom,\\n uint8 tokenIndexTo,\\n uint256 dx\\n ) external view returns (uint256);\\n\\n function calculateTokenAmount(uint256[] calldata amounts, bool deposit)\\n external\\n view\\n returns (uint256);\\n\\n function calculateRemoveLiquidity(uint256 amount)\\n external\\n view\\n returns (uint256[] memory);\\n\\n function calculateRemoveLiquidityOneToken(\\n uint256 tokenAmount,\\n uint8 tokenIndex\\n ) external view returns (uint256 availableTokenAmount);\\n\\n // state modifying functions\\n function initialize(\\n IERC20[] memory pooledTokens,\\n uint8[] memory decimals,\\n string memory lpTokenName,\\n string memory lpTokenSymbol,\\n uint256 a,\\n uint256 fee,\\n uint256 adminFee,\\n address lpTokenTargetAddress\\n ) external;\\n\\n function swap(\\n uint8 tokenIndexFrom,\\n uint8 tokenIndexTo,\\n uint256 dx,\\n uint256 minDy,\\n uint256 deadline\\n ) external returns (uint256);\\n\\n function addLiquidity(\\n uint256[] calldata amounts,\\n uint256 minToMint,\\n uint256 deadline\\n ) external returns (uint256);\\n\\n function removeLiquidity(\\n uint256 amount,\\n uint256[] calldata minAmounts,\\n uint256 deadline\\n ) external returns (uint256[] memory);\\n\\n function removeLiquidityOneToken(\\n uint256 tokenAmount,\\n uint8 tokenIndex,\\n uint256 minAmount,\\n uint256 deadline\\n ) external returns (uint256);\\n\\n function removeLiquidityImbalance(\\n uint256[] calldata amounts,\\n uint256 maxBurnAmount,\\n uint256 deadline\\n ) external returns (uint256);\\n}\\n\",\"keccak256\":\"0xb51eb389637b2b595a09cd95ea4167a6d945719be1bc127eafae07c06abd8ca8\",\"license\":\"MIT\"},\"contracts/bridge/interfaces/ISynapseBridge.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity 0.6.12;\\n\\nimport '@openzeppelin/contracts/token/ERC20/SafeERC20.sol';\\nimport '@openzeppelin/contracts/token/ERC20/ERC20Burnable.sol';\\n\\ninterface ISynapseBridge {\\n using SafeERC20 for IERC20;\\n\\n function deposit(\\n address to,\\n uint256 chainId,\\n IERC20 token,\\n uint256 amount\\n ) external;\\n\\n function depositAndSwap(\\n address to,\\n uint256 chainId,\\n IERC20 token,\\n uint256 amount,\\n uint8 tokenIndexFrom,\\n uint8 tokenIndexTo,\\n uint256 minDy,\\n uint256 deadline\\n ) external;\\n\\n function redeem(\\n address to,\\n uint256 chainId,\\n IERC20 token,\\n uint256 amount\\n ) external;\\n\\n function redeemAndSwap(\\n address to,\\n uint256 chainId,\\n IERC20 token,\\n uint256 amount,\\n uint8 tokenIndexFrom,\\n uint8 tokenIndexTo,\\n uint256 minDy,\\n uint256 deadline\\n ) external;\\n\\n function redeemAndRemove(\\n address to,\\n uint256 chainId,\\n IERC20 token,\\n uint256 amount,\\n uint8 liqTokenIndex,\\n uint256 liqMinAmount,\\n uint256 liqDeadline\\n ) external;\\n}\\n\",\"keccak256\":\"0x481ef0dfbfdf319518480c86f83fe6caea352ced4aa05f26389285af5c7e4c19\",\"license\":\"MIT\"},\"contracts/bridge/interfaces/IWETH9.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity >=0.4.0;\\n\\ninterface IWETH9 {\\n function name() external view returns (string memory);\\n\\n function symbol() external view returns (string memory);\\n\\n function decimals() external view returns (uint8);\\n\\n function balanceOf(address) external view returns (uint256);\\n\\n function allowance(address, address) external view returns (uint256);\\n\\n receive() external payable;\\n\\n function deposit() external payable;\\n\\n function withdraw(uint256 wad) external;\\n\\n function totalSupply() external view returns (uint256);\\n\\n function approve(address guy, uint256 wad) external returns (bool);\\n\\n function transfer(address dst, uint256 wad) external returns (bool);\\n\\n function transferFrom(\\n address src,\\n address dst,\\n uint256 wad\\n ) external returns (bool);\\n}\",\"keccak256\":\"0x081ebde11dad2210d382564d40336f914d3d621750645f23707ca1a92139dbe2\",\"license\":\"MIT\"},\"contracts/bridge/wrappers/HarmonyBridgeZap.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.6.12;\\n\\nimport \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\nimport \\\"@openzeppelin/contracts/token/ERC20/SafeERC20.sol\\\";\\nimport \\\"../interfaces/ISwap.sol\\\";\\nimport \\\"../interfaces/ISynapseBridge.sol\\\";\\nimport \\\"../interfaces/IWETH9.sol\\\";\\n\\ninterface IFrax {\\n function exchangeCanonicalForOld(address bridge_token_address, uint256 token_amount) external returns (uint256);\\n}\\n\\ncontract HarmonyBridgeZap {\\n using SafeERC20 for IERC20;\\n\\n ISynapseBridge synapseBridge;\\n address payable public immutable WETH_ADDRESS;\\n IFrax private constant CANOLICAL_FRAX = IFrax(0xFa7191D292d5633f702B0bd7E3E3BcCC0e633200);\\n IERC20 private constant SYN_FRAX = IERC20(0x1852F70512298d56e9c8FDd905e02581E04ddb2a);\\n\\n mapping(address => address) public swapMap;\\n mapping(address => IERC20[]) public swapTokensMap;\\n\\n uint256 constant MAX_UINT256 = 2**256 - 1;\\n\\n constructor(\\n address payable _wethAddress,\\n address _swapOne,\\n address tokenOne,\\n address _swapTwo,\\n address tokenTwo,\\n ISynapseBridge _synapseBridge\\n ) public {\\n WETH_ADDRESS = _wethAddress;\\n synapseBridge = _synapseBridge;\\n swapMap[tokenOne] = _swapOne;\\n swapMap[tokenTwo] = _swapTwo;\\n\\n if (address(_swapOne) != address(0)) {\\n {\\n uint8 i;\\n for (; i < 32; i++) {\\n try ISwap(_swapOne).getToken(i) returns (\\n IERC20 token\\n ) {\\n swapTokensMap[_swapOne].push(token);\\n token.safeApprove(address(_swapOne), MAX_UINT256);\\n token.safeApprove(address(synapseBridge), MAX_UINT256);\\n } catch {\\n break;\\n }\\n }\\n require(i > 1, \\\"swap must have at least 2 tokens\\\");\\n }\\n }\\n if (address(_swapTwo) != address(0)) {\\n {\\n uint8 i;\\n for (; i < 32; i++) {\\n try ISwap(_swapTwo).getToken(i) returns (\\n IERC20 token\\n ) {\\n swapTokensMap[_swapTwo].push(token);\\n token.safeApprove(address(_swapTwo), MAX_UINT256);\\n token.safeApprove(address(synapseBridge), MAX_UINT256);\\n } catch {\\n break;\\n }\\n }\\n require(i > 1, \\\"swap must have at least 2 tokens\\\");\\n }\\n }\\n }\\n\\n /**\\n * @notice Calculate amount of tokens you receive on swap\\n * @param tokenIndexFrom the token the user wants to sell\\n * @param tokenIndexTo the token the user wants to buy\\n * @param dx the amount of tokens the user wants to sell. If the token charges\\n * a fee on transfers, use the amount that gets transferred after the fee.\\n * @return amount of tokens the user will receive\\n */\\n function calculateSwap(\\n IERC20 token,\\n uint8 tokenIndexFrom,\\n uint8 tokenIndexTo,\\n uint256 dx\\n ) external view virtual returns (uint256) {\\n ISwap swap = ISwap(\\n swapMap[address(token)]\\n );\\n return swap.calculateSwap(tokenIndexFrom, tokenIndexTo, dx);\\n }\\n\\n function swapAndRedeem(\\n address to,\\n uint256 chainId,\\n IERC20 token,\\n uint8 tokenIndexFrom,\\n uint8 tokenIndexTo,\\n uint256 dx,\\n uint256 minDy,\\n uint256 deadline\\n ) external {\\n ISwap swap = ISwap(swapMap[address(token)]);\\n require(address(swap) != address(0), \\\"Swap is 0x00\\\");\\n IERC20[] memory tokens = swapTokensMap[address(swap)];\\n tokens[tokenIndexFrom].safeTransferFrom(\\n msg.sender,\\n address(this),\\n dx\\n );\\n // swap\\n\\n uint256 swappedAmount = swap.swap(\\n tokenIndexFrom,\\n tokenIndexTo,\\n dx,\\n minDy,\\n deadline\\n );\\n // deposit into bridge, gets nUSD\\n if (\\n token.allowance(address(this), address(synapseBridge)) <\\n swappedAmount\\n ) {\\n token.safeApprove(address(synapseBridge), MAX_UINT256);\\n }\\n synapseBridge.redeem(to, chainId, token, swappedAmount);\\n }\\n\\n function swapAndRedeemAndSwap(\\n address to,\\n uint256 chainId,\\n IERC20 token,\\n uint8 tokenIndexFrom,\\n uint8 tokenIndexTo,\\n uint256 dx,\\n uint256 minDy,\\n uint256 deadline,\\n uint8 swapTokenIndexFrom,\\n uint8 swapTokenIndexTo,\\n uint256 swapMinDy,\\n uint256 swapDeadline\\n ) external {\\n require(\\n address(swapMap[address(token)]) != address(0),\\n \\\"Swap is 0x00\\\"\\n );\\n IERC20[] memory tokens = swapTokensMap[\\n swapMap[address(token)]\\n ];\\n tokens[tokenIndexFrom].safeTransferFrom(\\n msg.sender,\\n address(this),\\n dx\\n );\\n // swap\\n\\n uint256 swappedAmount = ISwap(swapMap[address(token)]).swap(tokenIndexFrom, tokenIndexTo, dx, minDy, deadline);\\n // deposit into bridge, gets nUSD\\n if (\\n token.allowance(address(this), address(synapseBridge)) <\\n swappedAmount\\n ) {\\n token.safeApprove(address(synapseBridge), MAX_UINT256);\\n }\\n synapseBridge.redeemAndSwap(\\n to,\\n chainId,\\n token,\\n swappedAmount,\\n swapTokenIndexFrom,\\n swapTokenIndexTo,\\n swapMinDy,\\n swapDeadline\\n );\\n }\\n\\n function swapAndRedeemAndRemove(\\n address to,\\n uint256 chainId,\\n IERC20 token,\\n uint8 tokenIndexFrom,\\n uint8 tokenIndexTo,\\n uint256 dx,\\n uint256 minDy,\\n uint256 deadline,\\n uint8 liqTokenIndex,\\n uint256 liqMinAmount,\\n uint256 liqDeadline\\n ) external {\\n ISwap swap = ISwap(swapMap[address(token)]);\\n require(address(swap) != address(0), \\\"Swap is 0x00\\\");\\n IERC20[] memory tokens = swapTokensMap[address(swap)];\\n tokens[tokenIndexFrom].safeTransferFrom(\\n msg.sender,\\n address(this),\\n dx\\n );\\n // swap\\n\\n uint256 swappedAmount = swap.swap(\\n tokenIndexFrom,\\n tokenIndexTo,\\n dx,\\n minDy,\\n deadline\\n );\\n // deposit into bridge, gets nUSD\\n if (\\n token.allowance(address(this), address(synapseBridge)) <\\n swappedAmount\\n ) {\\n token.safeApprove(address(synapseBridge), MAX_UINT256);\\n }\\n synapseBridge.redeemAndRemove(\\n to,\\n chainId,\\n token,\\n swappedAmount,\\n liqTokenIndex,\\n liqMinAmount,\\n liqDeadline\\n );\\n }\\n\\n /**\\n * @notice wraps SynapseBridge redeem()\\n * @param to address on other chain to redeem underlying assets to\\n * @param chainId which underlying chain to bridge assets onto\\n * @param token ERC20 compatible token to deposit into the bridge\\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\\n **/\\n function redeem(\\n address to,\\n uint256 chainId,\\n IERC20 token,\\n uint256 amount\\n ) external {\\n token.safeTransferFrom(msg.sender, address(this), amount);\\n if (address(token) == address(CANOLICAL_FRAX)) {\\n uint256 swappedAmount = CANOLICAL_FRAX.exchangeCanonicalForOld(address(SYN_FRAX), amount);\\n if (SYN_FRAX.allowance(address(this), address(synapseBridge)) < amount) {\\n SYN_FRAX.safeApprove(address(synapseBridge), MAX_UINT256);\\n }\\n synapseBridge.redeem(to, chainId, SYN_FRAX, swappedAmount);\\n } else {\\n if (token.allowance(address(this), address(synapseBridge)) < amount) {\\n token.safeApprove(address(synapseBridge), MAX_UINT256);\\n }\\n synapseBridge.redeem(to, chainId, token, amount);\\n }\\n \\n }\\n\\n /**\\n * @notice wraps SynapseBridge redeem()\\n * @param to address on other chain to redeem underlying assets to\\n * @param chainId which underlying chain to bridge assets onto\\n * @param token ERC20 compatible token to deposit into the bridge\\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\\n **/\\n function deposit(\\n address to,\\n uint256 chainId,\\n IERC20 token,\\n uint256 amount\\n ) external {\\n token.safeTransferFrom(msg.sender, address(this), amount);\\n if (token.allowance(address(this), address(synapseBridge)) < amount) {\\n token.safeApprove(address(synapseBridge), MAX_UINT256);\\n }\\n synapseBridge.deposit(to, chainId, token, amount);\\n }\\n\\n function swapETHAndRedeem(\\n address to,\\n uint256 chainId,\\n IERC20 token,\\n uint8 tokenIndexFrom,\\n uint8 tokenIndexTo,\\n uint256 dx,\\n uint256 minDy,\\n uint256 deadline\\n ) external payable {\\n require(WETH_ADDRESS != address(0), \\\"WETH 0\\\");\\n require(msg.value > 0 && msg.value == dx, \\\"INCORRECT MSG VALUE\\\");\\n ISwap swap = ISwap(swapMap[address(token)]);\\n require(address(swap) != address(0), \\\"Swap is 0x00\\\");\\n IWETH9(WETH_ADDRESS).deposit{value: msg.value}();\\n\\n // swap\\n uint256 swappedAmount = swap.swap(\\n tokenIndexFrom,\\n tokenIndexTo,\\n dx,\\n minDy,\\n deadline\\n );\\n synapseBridge.redeem(to, chainId, token, swappedAmount);\\n }\\n\\n /**\\n * @notice Wraps redeemAndSwap on SynapseBridge.sol\\n * Relays to nodes that (typically) a wrapped synAsset ERC20 token has been burned and the underlying needs to be redeeemed on the native chain. This function indicates to the nodes that they should attempt to redeem the LP token for the underlying assets (E.g \\\"swap\\\" out of the LP token)\\n * @param to address on other chain to redeem underlying assets to\\n * @param chainId which underlying chain to bridge assets onto\\n * @param token ERC20 compatible token to deposit into the bridge\\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\\n * @param tokenIndexFrom the token the user wants to swap from\\n * @param tokenIndexTo the token the user wants to swap to\\n * @param minDy the min amount the user would like to receive, or revert to only minting the SynERC20 token crosschain.\\n * @param deadline latest timestamp to accept this transaction\\n **/\\n function redeemAndSwap(\\n address to,\\n uint256 chainId,\\n IERC20 token,\\n uint256 amount,\\n uint8 tokenIndexFrom,\\n uint8 tokenIndexTo,\\n uint256 minDy,\\n uint256 deadline\\n ) external {\\n token.safeTransferFrom(msg.sender, address(this), amount);\\n if (token.allowance(address(this), address(synapseBridge)) < amount) {\\n token.safeApprove(address(synapseBridge), MAX_UINT256);\\n }\\n synapseBridge.redeemAndSwap(\\n to,\\n chainId,\\n token,\\n amount,\\n tokenIndexFrom,\\n tokenIndexTo,\\n minDy,\\n deadline\\n );\\n }\\n\\n /**\\n * @notice Wraps redeemAndRemove on SynapseBridge\\n * Relays to nodes that (typically) a wrapped synAsset ERC20 token has been burned and the underlying needs to be redeeemed on the native chain. This function indicates to the nodes that they should attempt to redeem the LP token for the underlying assets (E.g \\\"swap\\\" out of the LP token)\\n * @param to address on other chain to redeem underlying assets to\\n * @param chainId which underlying chain to bridge assets onto\\n * @param token ERC20 compatible token to deposit into the bridge\\n * @param amount Amount of (typically) LP token to pass to the nodes to attempt to removeLiquidity() with to redeem for the underlying assets of the LP token\\n * @param liqTokenIndex Specifies which of the underlying LP assets the nodes should attempt to redeem for\\n * @param liqMinAmount Specifies the minimum amount of the underlying asset needed for the nodes to execute the redeem/swap\\n * @param liqDeadline Specificies the deadline that the nodes are allowed to try to redeem/swap the LP token\\n **/\\n function redeemAndRemove(\\n address to,\\n uint256 chainId,\\n IERC20 token,\\n uint256 amount,\\n uint8 liqTokenIndex,\\n uint256 liqMinAmount,\\n uint256 liqDeadline\\n ) external {\\n token.safeTransferFrom(msg.sender, address(this), amount);\\n if (token.allowance(address(this), address(synapseBridge)) < amount) {\\n token.safeApprove(address(synapseBridge), MAX_UINT256);\\n }\\n synapseBridge.redeemAndRemove(\\n to,\\n chainId,\\n token,\\n amount,\\n liqTokenIndex,\\n liqMinAmount,\\n liqDeadline\\n );\\n }\\n}\\n\",\"keccak256\":\"0x3ab9e291088c26b85ea98b6808289af37b245f9dfb67e133565ba6f95355462f\",\"license\":\"MIT\"}},\"version\":1}", - "bytecode": "0x60a06040523480156200001157600080fd5b50604051620029fc380380620029fc833981810160405260c08110156200003757600080fd5b50805160208083015160408085015160608087015160808089015160a0909901519288901b6001600160601b0319169052600080546001600160a01b03199081166001600160a01b038086169190911783558086168352600190985285822080548216898916908117909155888b168352959091208054909116968216969096179095559495929490939291156200022d5760005b60208160ff161015620001e357856001600160a01b03166382b86600826040518263ffffffff1660e01b8152600401808260ff16815260200191505060206040518083038186803b1580156200012157600080fd5b505afa9250505080156200014857506040513d60208110156200014357600080fd5b505160015b6200015357620001e3565b6001600160a01b038781166000908152600260209081526040822080546001810182559083529181902090910180546001600160a01b0319169284169283179055620001af9190899060001990620003ad811b62001b5f17901c565b600054620001d9906001600160a01b038381169116600019620003ad602090811b62001b5f17901c565b50600101620000cc565b60018160ff16116200022b576040805162461bcd60e51b815260206004820181905260248201526000805160206200297c833981519152604482015290519081900360640190fd5b505b6001600160a01b03831615620003a15760005b60208160ff1610156200035757836001600160a01b03166382b86600826040518263ffffffff1660e01b8152600401808260ff16815260200191505060206040518083038186803b1580156200029557600080fd5b505afa925050508015620002bc57506040513d6020811015620002b757600080fd5b505160015b620002c75762000357565b6001600160a01b038581166000908152600260209081526040822080546001810182559083529181902090910180546001600160a01b0319169284169283179055620003239190879060001990620003ad811b62001b5f17901c565b6000546200034d906001600160a01b038381169116600019620003ad602090811b62001b5f17901c565b5060010162000240565b60018160ff16116200039f576040805162461bcd60e51b815260206004820181905260248201526000805160206200297c833981519152604482015290519081900360640190fd5b505b505050505050620007c0565b80158062000437575060408051636eb1769f60e11b81523060048201526001600160a01b03848116602483015291519185169163dd62ed3e91604480820192602092909190829003018186803b1580156200040757600080fd5b505afa1580156200041c573d6000803e3d6000fd5b505050506040513d60208110156200043357600080fd5b5051155b620004745760405162461bcd60e51b8152600401808060200182810382526036815260200180620029c66036913960400191505060405180910390fd5b604080516001600160a01b038416602482015260448082018490528251808303909101815260649091019091526020810180516001600160e01b0390811663095ea7b360e01b17909152620004cc918591620004d116565b505050565b60606200052d826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b03166200058d60201b62001cd8179092919060201c565b805190915015620004cc578080602001905160208110156200054e57600080fd5b5051620004cc5760405162461bcd60e51b815260040180806020018281038252602a8152602001806200299c602a913960400191505060405180910390fd5b60606200059e8484600085620005a8565b90505b9392505050565b606082471015620005eb5760405162461bcd60e51b8152600401808060200182810382526026815260200180620029566026913960400191505060405180910390fd5b620005f68562000710565b62000648576040805162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000604482015290519081900360640190fd5b60006060866001600160a01b031685876040518082805190602001908083835b60208310620006895780518252601f19909201916020918201910162000668565b6001836020036101000a03801982511681845116808217855250505050505090500191505060006040518083038185875af1925050503d8060008114620006ed576040519150601f19603f3d011682016040523d82523d6000602084013e620006f2565b606091505b5090925090506200070582828662000716565b979650505050505050565b3b151590565b6060831562000727575081620005a1565b825115620007385782518084602001fd5b8160405162461bcd60e51b81526004018080602001828103825283818151815260200191508051906020019080838360005b83811015620007845781810151838201526020016200076a565b50505050905090810190601f168015620007b25780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b60805160601c61216e620007e8600039806104e05280610d385280610ece525061216e6000f3fe6080604052600436106100c75760003560e01c8063798af7201161007457806390d250741161004e57806390d25074146103cb5780639f33072714610412578063f3f094a114610497576100c7565b8063798af720146102d3578063839ed90a1461033157806385528f0b14610398576100c7565b8063393494b8116100a5578063393494b8146101d95780634a517a551461021257806365749c9d14610279576100c7565b8063040141e5146100cc578063174dc952146100fd57806336e712ed1461017d575b600080fd5b3480156100d857600080fd5b506100e16104de565b604080516001600160a01b039092168252519081900360200190f35b34801561010957600080fd5b5061017b600480360361016081101561012157600080fd5b506001600160a01b0381358116916020810135916040820135169060ff6060820135811691608081013582169160a08201359160c08101359160e08201359161010081013590911690610120810135906101400135610502565b005b34801561018957600080fd5b5061017b600480360360e08110156101a057600080fd5b506001600160a01b0381358116916020810135916040820135169060608101359060ff6080820135169060a08101359060c00135610865565b3480156101e557600080fd5b506100e1600480360360408110156101fc57600080fd5b506001600160a01b0381351690602001356109e6565b34801561021e57600080fd5b5061017b600480360361010081101561023657600080fd5b506001600160a01b0381358116916020810135916040820135169060ff606082013581169160808101359091169060a08101359060c08101359060e00135610a1b565b61017b600480360361010081101561029057600080fd5b506001600160a01b0381358116916020810135916040820135169060ff606082013581169160808101359091169060a08101359060c08101359060e00135610d36565b3480156102df57600080fd5b5061031f600480360360808110156102f657600080fd5b506001600160a01b038135169060ff602082013581169160408101359091169060600135611090565b60408051918252519081900360200190f35b34801561033d57600080fd5b5061017b600480360361010081101561035557600080fd5b506001600160a01b0381358116916020810135916040820135169060608101359060ff608082013581169160a08101359091169060c08101359060e00135611149565b3480156103a457600080fd5b506100e1600480360360208110156103bb57600080fd5b50356001600160a01b03166112d4565b3480156103d757600080fd5b5061017b600480360360808110156103ee57600080fd5b506001600160a01b03813581169160208101359160408201351690606001356112ef565b34801561041e57600080fd5b5061017b600480360361018081101561043657600080fd5b506001600160a01b0381358116916020810135916040820135169060ff6060820135811691608081013582169160a08201359160c08101359160e0820135916101008101358216916101208201351690610140810135906101600135611456565b3480156104a357600080fd5b5061017b600480360360808110156104ba57600080fd5b506001600160a01b03813581169160208101359160408201351690606001356117aa565b7f000000000000000000000000000000000000000000000000000000000000000081565b6001600160a01b03808a16600090815260016020526040902054168061058957604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f5377617020697320307830300000000000000000000000000000000000000000604482015290519081900360640190fd5b6001600160a01b0381166000908152600260209081526040918290208054835181840281018401909452808452606093928301828280156105f357602002820191906000526020600020905b81546001600160a01b031681526001909101906020018083116105d5575b5050505050905061063033308a848e60ff168151811061060f57fe5b60200260200101516001600160a01b0316611cf1909392919063ffffffff16565b604080517f9169558600000000000000000000000000000000000000000000000000000000815260ff808d1660048301528b166024820152604481018a9052606481018990526084810188905290516000916001600160a01b0385169163916955869160a48082019260209290919082900301818787803b1580156106b457600080fd5b505af11580156106c8573d6000803e3d6000fd5b505050506040513d60208110156106de57600080fd5b5051600054604080517fdd62ed3e0000000000000000000000000000000000000000000000000000000081523060048201526001600160a01b03928316602482015290519293508392918f169163dd62ed3e91604480820192602092909190829003018186803b15801561075157600080fd5b505afa158015610765573d6000803e3d6000fd5b505050506040513d602081101561077b57600080fd5b5051101561079f5760005461079f906001600160a01b038e81169116600019611b5f565b60008054906101000a90046001600160a01b03166001600160a01b03166336e712ed8f8f8f858b8b8b6040518863ffffffff1660e01b815260040180886001600160a01b03168152602001878152602001866001600160a01b031681526020018581526020018460ff168152602001838152602001828152602001975050505050505050600060405180830381600087803b15801561083d57600080fd5b505af1158015610851573d6000803e3d6000fd5b505050505050505050505050505050505050565b61087a6001600160a01b038616333087611cf1565b600054604080517fdd62ed3e0000000000000000000000000000000000000000000000000000000081523060048201526001600160a01b0392831660248201529051869288169163dd62ed3e916044808301926020929190829003018186803b1580156108e657600080fd5b505afa1580156108fa573d6000803e3d6000fd5b505050506040513d602081101561091057600080fd5b5051101561093457600054610934906001600160a01b038781169116600019611b5f565b60008054604080517f36e712ed0000000000000000000000000000000000000000000000000000000081526001600160a01b038b81166004830152602482018b905289811660448301526064820189905260ff8816608483015260a4820187905260c48201869052915191909216926336e712ed9260e4808201939182900301818387803b1580156109c557600080fd5b505af11580156109d9573d6000803e3d6000fd5b5050505050505050505050565b600260205281600052604060002081815481106109ff57fe5b6000918252602090912001546001600160a01b03169150829050565b6001600160a01b038087166000908152600160205260409020541680610aa257604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f5377617020697320307830300000000000000000000000000000000000000000604482015290519081900360640190fd5b6001600160a01b038116600090815260026020908152604091829020805483518184028101840190945280845260609392830182828015610b0c57602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311610aee575b50505050509050610b28333087848b60ff168151811061060f57fe5b604080517f9169558600000000000000000000000000000000000000000000000000000000815260ff808a1660048301528816602482015260448101879052606481018690526084810185905290516000916001600160a01b0385169163916955869160a48082019260209290919082900301818787803b158015610bac57600080fd5b505af1158015610bc0573d6000803e3d6000fd5b505050506040513d6020811015610bd657600080fd5b5051600054604080517fdd62ed3e0000000000000000000000000000000000000000000000000000000081523060048201526001600160a01b03928316602482015290519293508392918c169163dd62ed3e91604480820192602092909190829003018186803b158015610c4957600080fd5b505afa158015610c5d573d6000803e3d6000fd5b505050506040513d6020811015610c7357600080fd5b50511015610c9757600054610c97906001600160a01b038b81169116600019611b5f565b60008054604080517ff3f094a10000000000000000000000000000000000000000000000000000000081526001600160a01b038f81166004830152602482018f90528d81166044830152606482018690529151919092169263f3f094a1926084808201939182900301818387803b158015610d1157600080fd5b505af1158015610d25573d6000803e3d6000fd5b505050505050505050505050505050565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316610dcb57604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600660248201527f5745544820300000000000000000000000000000000000000000000000000000604482015290519081900360640190fd5b600034118015610dda57508234145b610e4557604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f494e434f5252454354204d53472056414c554500000000000000000000000000604482015290519081900360640190fd5b6001600160a01b038087166000908152600160205260409020541680610ecc57604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f5377617020697320307830300000000000000000000000000000000000000000604482015290519081900360640190fd5b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663d0e30db0346040518263ffffffff1660e01b81526004016000604051808303818588803b158015610f2757600080fd5b505af1158015610f3b573d6000803e3d6000fd5b5050604080517f9169558600000000000000000000000000000000000000000000000000000000815260ff808c1660048301528a1660248201526044810189905260648101889052608481018790529051600094506001600160a01b03861693506391695586925060a480830192602092919082900301818787803b158015610fc357600080fd5b505af1158015610fd7573d6000803e3d6000fd5b505050506040513d6020811015610fed57600080fd5b505160008054604080517ff3f094a10000000000000000000000000000000000000000000000000000000081526001600160a01b038f81166004830152602482018f90528d8116604483015260648201869052915194955091169263f3f094a19260848084019391929182900301818387803b15801561106c57600080fd5b505af1158015611080573d6000803e3d6000fd5b5050505050505050505050505050565b6001600160a01b0380851660009081526001602090815260408083205481517fa95b089f00000000000000000000000000000000000000000000000000000000815260ff808a1660048301528816602482015260448101879052915193941692839263a95b089f9260648082019391829003018186803b15801561111357600080fd5b505afa158015611127573d6000803e3d6000fd5b505050506040513d602081101561113d57600080fd5b50519695505050505050565b61115e6001600160a01b038716333088611cf1565b600054604080517fdd62ed3e0000000000000000000000000000000000000000000000000000000081523060048201526001600160a01b0392831660248201529051879289169163dd62ed3e916044808301926020929190829003018186803b1580156111ca57600080fd5b505afa1580156111de573d6000803e3d6000fd5b505050506040513d60208110156111f457600080fd5b5051101561121857600054611218906001600160a01b038881169116600019611b5f565b60008054604080517f839ed90a0000000000000000000000000000000000000000000000000000000081526001600160a01b038c81166004830152602482018c90528a81166044830152606482018a905260ff808a166084840152881660a483015260c4820187905260e482018690529151919092169263839ed90a92610104808201939182900301818387803b1580156112b257600080fd5b505af11580156112c6573d6000803e3d6000fd5b505050505050505050505050565b6001602052600090815260409020546001600160a01b031681565b6113046001600160a01b038316333084611cf1565b600054604080517fdd62ed3e0000000000000000000000000000000000000000000000000000000081523060048201526001600160a01b0392831660248201529051839285169163dd62ed3e916044808301926020929190829003018186803b15801561137057600080fd5b505afa158015611384573d6000803e3d6000fd5b505050506040513d602081101561139a57600080fd5b505110156113be576000546113be906001600160a01b038481169116600019611b5f565b60008054604080517f90d250740000000000000000000000000000000000000000000000000000000081526001600160a01b03888116600483015260248201889052868116604483015260648201869052915191909216926390d25074926084808201939182900301818387803b15801561143857600080fd5b505af115801561144c573d6000803e3d6000fd5b5050505050505050565b6001600160a01b038a8116600090815260016020526040902054166114dc57604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f5377617020697320307830300000000000000000000000000000000000000000604482015290519081900360640190fd5b6001600160a01b03808b166000908152600160209081526040808320549093168252600281529082902080548351818402810184019094528084526060939283018282801561155457602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311611536575b5050505050905061157033308a848e60ff168151811061060f57fe5b6000600160008d6001600160a01b03166001600160a01b0316815260200190815260200160002060009054906101000a90046001600160a01b03166001600160a01b031663916955868c8c8c8c8c6040518663ffffffff1660e01b8152600401808660ff1681526020018560ff16815260200184815260200183815260200182815260200195505050505050602060405180830381600087803b15801561161657600080fd5b505af115801561162a573d6000803e3d6000fd5b505050506040513d602081101561164057600080fd5b5051600054604080517fdd62ed3e0000000000000000000000000000000000000000000000000000000081523060048201526001600160a01b03928316602482015290519293508392918f169163dd62ed3e91604480820192602092909190829003018186803b1580156116b357600080fd5b505afa1580156116c7573d6000803e3d6000fd5b505050506040513d60208110156116dd57600080fd5b5051101561170157600054611701906001600160a01b038e81169116600019611b5f565b60008054906101000a90046001600160a01b03166001600160a01b031663839ed90a8f8f8f858b8b8b8b6040518963ffffffff1660e01b815260040180896001600160a01b03168152602001888152602001876001600160a01b031681526020018681526020018560ff1681526020018460ff16815260200183815260200182815260200198505050505050505050600060405180830381600087803b15801561083d57600080fd5b6117bf6001600160a01b038316333084611cf1565b6001600160a01b03821673fa7191d292d5633f702b0bd7e3e3bccc0e6332001415611a2557604080517f280cf3ed000000000000000000000000000000000000000000000000000000008152731852f70512298d56e9c8fdd905e02581e04ddb2a600482015260248101839052905160009173fa7191d292d5633f702b0bd7e3e3bccc0e6332009163280cf3ed9160448082019260209290919082900301818787803b15801561186e57600080fd5b505af1158015611882573d6000803e3d6000fd5b505050506040513d602081101561189857600080fd5b5051600054604080517fdd62ed3e0000000000000000000000000000000000000000000000000000000081523060048201526001600160a01b039092166024830152519192508391731852f70512298d56e9c8fdd905e02581e04ddb2a9163dd62ed3e916044808301926020929190829003018186803b15801561191b57600080fd5b505afa15801561192f573d6000803e3d6000fd5b505050506040513d602081101561194557600080fd5b5051101561197b5760005461197b90731852f70512298d56e9c8fdd905e02581e04ddb2a906001600160a01b0316600019611b5f565b60008054604080517ff3f094a10000000000000000000000000000000000000000000000000000000081526001600160a01b03898116600483015260248201899052731852f70512298d56e9c8fdd905e02581e04ddb2a6044830152606482018690529151919092169263f3f094a1926084808201939182900301818387803b158015611a0757600080fd5b505af1158015611a1b573d6000803e3d6000fd5b5050505050611b59565b600054604080517fdd62ed3e0000000000000000000000000000000000000000000000000000000081523060048201526001600160a01b0392831660248201529051839285169163dd62ed3e916044808301926020929190829003018186803b158015611a9157600080fd5b505afa158015611aa5573d6000803e3d6000fd5b505050506040513d6020811015611abb57600080fd5b50511015611adf57600054611adf906001600160a01b038481169116600019611b5f565b60008054604080517ff3f094a10000000000000000000000000000000000000000000000000000000081526001600160a01b038881166004830152602482018890528681166044830152606482018690529151919092169263f3f094a1926084808201939182900301818387803b15801561143857600080fd5b50505050565b801580611bfe5750604080517fdd62ed3e0000000000000000000000000000000000000000000000000000000081523060048201526001600160a01b03848116602483015291519185169163dd62ed3e91604480820192602092909190829003018186803b158015611bd057600080fd5b505afa158015611be4573d6000803e3d6000fd5b505050506040513d6020811015611bfa57600080fd5b5051155b611c53576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260368152602001806121036036913960400191505060405180910390fd5b604080516001600160a01b038416602482015260448082018490528251808303909101815260649091019091526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f095ea7b300000000000000000000000000000000000000000000000000000000179052611cd3908490611d75565b505050565b6060611ce78484600085611e40565b90505b9392505050565b604080516001600160a01b0380861660248301528416604482015260648082018490528251808303909101815260849091019091526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f23b872dd00000000000000000000000000000000000000000000000000000000179052611b599085905b6060611dca826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b0316611cd89092919063ffffffff16565b805190915015611cd357808060200190516020811015611de957600080fd5b5051611cd3576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602a8152602001806120d9602a913960400191505060405180910390fd5b606082471015611e9b576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260268152602001806120b36026913960400191505060405180910390fd5b611ea485611fee565b611f0f57604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000604482015290519081900360640190fd5b60006060866001600160a01b031685876040518082805190602001908083835b60208310611f6c57805182527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe09092019160209182019101611f2f565b6001836020036101000a03801982511681845116808217855250505050505090500191505060006040518083038185875af1925050503d8060008114611fce576040519150601f19603f3d011682016040523d82523d6000602084013e611fd3565b606091505b5091509150611fe3828286611ff4565b979650505050505050565b3b151590565b60608315612003575081611cea565b8251156120135782518084602001fd5b816040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825283818151815260200191508051906020019080838360005b8381101561207757818101518382015260200161205f565b50505050905090810190601f1680156120a45780820380516001836020036101000a031916815260200191505b509250505060405180910390fdfe416464726573733a20696e73756666696369656e742062616c616e636520666f722063616c6c5361666545524332303a204552433230206f7065726174696f6e20646964206e6f7420737563636565645361666545524332303a20617070726f76652066726f6d206e6f6e2d7a65726f20746f206e6f6e2d7a65726f20616c6c6f77616e6365a2646970667358221220410c7c9dfa62a9716f4706a3683ee9f2ca020071ffa9f9552565a735e454c12a64736f6c634300060c0033416464726573733a20696e73756666696369656e742062616c616e636520666f722063616c6c73776170206d7573742068617665206174206c65617374203220746f6b656e735361666545524332303a204552433230206f7065726174696f6e20646964206e6f7420737563636565645361666545524332303a20617070726f76652066726f6d206e6f6e2d7a65726f20746f206e6f6e2d7a65726f20616c6c6f77616e6365", - "deployedBytecode": "0x6080604052600436106100c75760003560e01c8063798af7201161007457806390d250741161004e57806390d25074146103cb5780639f33072714610412578063f3f094a114610497576100c7565b8063798af720146102d3578063839ed90a1461033157806385528f0b14610398576100c7565b8063393494b8116100a5578063393494b8146101d95780634a517a551461021257806365749c9d14610279576100c7565b8063040141e5146100cc578063174dc952146100fd57806336e712ed1461017d575b600080fd5b3480156100d857600080fd5b506100e16104de565b604080516001600160a01b039092168252519081900360200190f35b34801561010957600080fd5b5061017b600480360361016081101561012157600080fd5b506001600160a01b0381358116916020810135916040820135169060ff6060820135811691608081013582169160a08201359160c08101359160e08201359161010081013590911690610120810135906101400135610502565b005b34801561018957600080fd5b5061017b600480360360e08110156101a057600080fd5b506001600160a01b0381358116916020810135916040820135169060608101359060ff6080820135169060a08101359060c00135610865565b3480156101e557600080fd5b506100e1600480360360408110156101fc57600080fd5b506001600160a01b0381351690602001356109e6565b34801561021e57600080fd5b5061017b600480360361010081101561023657600080fd5b506001600160a01b0381358116916020810135916040820135169060ff606082013581169160808101359091169060a08101359060c08101359060e00135610a1b565b61017b600480360361010081101561029057600080fd5b506001600160a01b0381358116916020810135916040820135169060ff606082013581169160808101359091169060a08101359060c08101359060e00135610d36565b3480156102df57600080fd5b5061031f600480360360808110156102f657600080fd5b506001600160a01b038135169060ff602082013581169160408101359091169060600135611090565b60408051918252519081900360200190f35b34801561033d57600080fd5b5061017b600480360361010081101561035557600080fd5b506001600160a01b0381358116916020810135916040820135169060608101359060ff608082013581169160a08101359091169060c08101359060e00135611149565b3480156103a457600080fd5b506100e1600480360360208110156103bb57600080fd5b50356001600160a01b03166112d4565b3480156103d757600080fd5b5061017b600480360360808110156103ee57600080fd5b506001600160a01b03813581169160208101359160408201351690606001356112ef565b34801561041e57600080fd5b5061017b600480360361018081101561043657600080fd5b506001600160a01b0381358116916020810135916040820135169060ff6060820135811691608081013582169160a08201359160c08101359160e0820135916101008101358216916101208201351690610140810135906101600135611456565b3480156104a357600080fd5b5061017b600480360360808110156104ba57600080fd5b506001600160a01b03813581169160208101359160408201351690606001356117aa565b7f000000000000000000000000000000000000000000000000000000000000000081565b6001600160a01b03808a16600090815260016020526040902054168061058957604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f5377617020697320307830300000000000000000000000000000000000000000604482015290519081900360640190fd5b6001600160a01b0381166000908152600260209081526040918290208054835181840281018401909452808452606093928301828280156105f357602002820191906000526020600020905b81546001600160a01b031681526001909101906020018083116105d5575b5050505050905061063033308a848e60ff168151811061060f57fe5b60200260200101516001600160a01b0316611cf1909392919063ffffffff16565b604080517f9169558600000000000000000000000000000000000000000000000000000000815260ff808d1660048301528b166024820152604481018a9052606481018990526084810188905290516000916001600160a01b0385169163916955869160a48082019260209290919082900301818787803b1580156106b457600080fd5b505af11580156106c8573d6000803e3d6000fd5b505050506040513d60208110156106de57600080fd5b5051600054604080517fdd62ed3e0000000000000000000000000000000000000000000000000000000081523060048201526001600160a01b03928316602482015290519293508392918f169163dd62ed3e91604480820192602092909190829003018186803b15801561075157600080fd5b505afa158015610765573d6000803e3d6000fd5b505050506040513d602081101561077b57600080fd5b5051101561079f5760005461079f906001600160a01b038e81169116600019611b5f565b60008054906101000a90046001600160a01b03166001600160a01b03166336e712ed8f8f8f858b8b8b6040518863ffffffff1660e01b815260040180886001600160a01b03168152602001878152602001866001600160a01b031681526020018581526020018460ff168152602001838152602001828152602001975050505050505050600060405180830381600087803b15801561083d57600080fd5b505af1158015610851573d6000803e3d6000fd5b505050505050505050505050505050505050565b61087a6001600160a01b038616333087611cf1565b600054604080517fdd62ed3e0000000000000000000000000000000000000000000000000000000081523060048201526001600160a01b0392831660248201529051869288169163dd62ed3e916044808301926020929190829003018186803b1580156108e657600080fd5b505afa1580156108fa573d6000803e3d6000fd5b505050506040513d602081101561091057600080fd5b5051101561093457600054610934906001600160a01b038781169116600019611b5f565b60008054604080517f36e712ed0000000000000000000000000000000000000000000000000000000081526001600160a01b038b81166004830152602482018b905289811660448301526064820189905260ff8816608483015260a4820187905260c48201869052915191909216926336e712ed9260e4808201939182900301818387803b1580156109c557600080fd5b505af11580156109d9573d6000803e3d6000fd5b5050505050505050505050565b600260205281600052604060002081815481106109ff57fe5b6000918252602090912001546001600160a01b03169150829050565b6001600160a01b038087166000908152600160205260409020541680610aa257604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f5377617020697320307830300000000000000000000000000000000000000000604482015290519081900360640190fd5b6001600160a01b038116600090815260026020908152604091829020805483518184028101840190945280845260609392830182828015610b0c57602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311610aee575b50505050509050610b28333087848b60ff168151811061060f57fe5b604080517f9169558600000000000000000000000000000000000000000000000000000000815260ff808a1660048301528816602482015260448101879052606481018690526084810185905290516000916001600160a01b0385169163916955869160a48082019260209290919082900301818787803b158015610bac57600080fd5b505af1158015610bc0573d6000803e3d6000fd5b505050506040513d6020811015610bd657600080fd5b5051600054604080517fdd62ed3e0000000000000000000000000000000000000000000000000000000081523060048201526001600160a01b03928316602482015290519293508392918c169163dd62ed3e91604480820192602092909190829003018186803b158015610c4957600080fd5b505afa158015610c5d573d6000803e3d6000fd5b505050506040513d6020811015610c7357600080fd5b50511015610c9757600054610c97906001600160a01b038b81169116600019611b5f565b60008054604080517ff3f094a10000000000000000000000000000000000000000000000000000000081526001600160a01b038f81166004830152602482018f90528d81166044830152606482018690529151919092169263f3f094a1926084808201939182900301818387803b158015610d1157600080fd5b505af1158015610d25573d6000803e3d6000fd5b505050505050505050505050505050565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316610dcb57604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600660248201527f5745544820300000000000000000000000000000000000000000000000000000604482015290519081900360640190fd5b600034118015610dda57508234145b610e4557604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f494e434f5252454354204d53472056414c554500000000000000000000000000604482015290519081900360640190fd5b6001600160a01b038087166000908152600160205260409020541680610ecc57604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f5377617020697320307830300000000000000000000000000000000000000000604482015290519081900360640190fd5b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663d0e30db0346040518263ffffffff1660e01b81526004016000604051808303818588803b158015610f2757600080fd5b505af1158015610f3b573d6000803e3d6000fd5b5050604080517f9169558600000000000000000000000000000000000000000000000000000000815260ff808c1660048301528a1660248201526044810189905260648101889052608481018790529051600094506001600160a01b03861693506391695586925060a480830192602092919082900301818787803b158015610fc357600080fd5b505af1158015610fd7573d6000803e3d6000fd5b505050506040513d6020811015610fed57600080fd5b505160008054604080517ff3f094a10000000000000000000000000000000000000000000000000000000081526001600160a01b038f81166004830152602482018f90528d8116604483015260648201869052915194955091169263f3f094a19260848084019391929182900301818387803b15801561106c57600080fd5b505af1158015611080573d6000803e3d6000fd5b5050505050505050505050505050565b6001600160a01b0380851660009081526001602090815260408083205481517fa95b089f00000000000000000000000000000000000000000000000000000000815260ff808a1660048301528816602482015260448101879052915193941692839263a95b089f9260648082019391829003018186803b15801561111357600080fd5b505afa158015611127573d6000803e3d6000fd5b505050506040513d602081101561113d57600080fd5b50519695505050505050565b61115e6001600160a01b038716333088611cf1565b600054604080517fdd62ed3e0000000000000000000000000000000000000000000000000000000081523060048201526001600160a01b0392831660248201529051879289169163dd62ed3e916044808301926020929190829003018186803b1580156111ca57600080fd5b505afa1580156111de573d6000803e3d6000fd5b505050506040513d60208110156111f457600080fd5b5051101561121857600054611218906001600160a01b038881169116600019611b5f565b60008054604080517f839ed90a0000000000000000000000000000000000000000000000000000000081526001600160a01b038c81166004830152602482018c90528a81166044830152606482018a905260ff808a166084840152881660a483015260c4820187905260e482018690529151919092169263839ed90a92610104808201939182900301818387803b1580156112b257600080fd5b505af11580156112c6573d6000803e3d6000fd5b505050505050505050505050565b6001602052600090815260409020546001600160a01b031681565b6113046001600160a01b038316333084611cf1565b600054604080517fdd62ed3e0000000000000000000000000000000000000000000000000000000081523060048201526001600160a01b0392831660248201529051839285169163dd62ed3e916044808301926020929190829003018186803b15801561137057600080fd5b505afa158015611384573d6000803e3d6000fd5b505050506040513d602081101561139a57600080fd5b505110156113be576000546113be906001600160a01b038481169116600019611b5f565b60008054604080517f90d250740000000000000000000000000000000000000000000000000000000081526001600160a01b03888116600483015260248201889052868116604483015260648201869052915191909216926390d25074926084808201939182900301818387803b15801561143857600080fd5b505af115801561144c573d6000803e3d6000fd5b5050505050505050565b6001600160a01b038a8116600090815260016020526040902054166114dc57604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f5377617020697320307830300000000000000000000000000000000000000000604482015290519081900360640190fd5b6001600160a01b03808b166000908152600160209081526040808320549093168252600281529082902080548351818402810184019094528084526060939283018282801561155457602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311611536575b5050505050905061157033308a848e60ff168151811061060f57fe5b6000600160008d6001600160a01b03166001600160a01b0316815260200190815260200160002060009054906101000a90046001600160a01b03166001600160a01b031663916955868c8c8c8c8c6040518663ffffffff1660e01b8152600401808660ff1681526020018560ff16815260200184815260200183815260200182815260200195505050505050602060405180830381600087803b15801561161657600080fd5b505af115801561162a573d6000803e3d6000fd5b505050506040513d602081101561164057600080fd5b5051600054604080517fdd62ed3e0000000000000000000000000000000000000000000000000000000081523060048201526001600160a01b03928316602482015290519293508392918f169163dd62ed3e91604480820192602092909190829003018186803b1580156116b357600080fd5b505afa1580156116c7573d6000803e3d6000fd5b505050506040513d60208110156116dd57600080fd5b5051101561170157600054611701906001600160a01b038e81169116600019611b5f565b60008054906101000a90046001600160a01b03166001600160a01b031663839ed90a8f8f8f858b8b8b8b6040518963ffffffff1660e01b815260040180896001600160a01b03168152602001888152602001876001600160a01b031681526020018681526020018560ff1681526020018460ff16815260200183815260200182815260200198505050505050505050600060405180830381600087803b15801561083d57600080fd5b6117bf6001600160a01b038316333084611cf1565b6001600160a01b03821673fa7191d292d5633f702b0bd7e3e3bccc0e6332001415611a2557604080517f280cf3ed000000000000000000000000000000000000000000000000000000008152731852f70512298d56e9c8fdd905e02581e04ddb2a600482015260248101839052905160009173fa7191d292d5633f702b0bd7e3e3bccc0e6332009163280cf3ed9160448082019260209290919082900301818787803b15801561186e57600080fd5b505af1158015611882573d6000803e3d6000fd5b505050506040513d602081101561189857600080fd5b5051600054604080517fdd62ed3e0000000000000000000000000000000000000000000000000000000081523060048201526001600160a01b039092166024830152519192508391731852f70512298d56e9c8fdd905e02581e04ddb2a9163dd62ed3e916044808301926020929190829003018186803b15801561191b57600080fd5b505afa15801561192f573d6000803e3d6000fd5b505050506040513d602081101561194557600080fd5b5051101561197b5760005461197b90731852f70512298d56e9c8fdd905e02581e04ddb2a906001600160a01b0316600019611b5f565b60008054604080517ff3f094a10000000000000000000000000000000000000000000000000000000081526001600160a01b03898116600483015260248201899052731852f70512298d56e9c8fdd905e02581e04ddb2a6044830152606482018690529151919092169263f3f094a1926084808201939182900301818387803b158015611a0757600080fd5b505af1158015611a1b573d6000803e3d6000fd5b5050505050611b59565b600054604080517fdd62ed3e0000000000000000000000000000000000000000000000000000000081523060048201526001600160a01b0392831660248201529051839285169163dd62ed3e916044808301926020929190829003018186803b158015611a9157600080fd5b505afa158015611aa5573d6000803e3d6000fd5b505050506040513d6020811015611abb57600080fd5b50511015611adf57600054611adf906001600160a01b038481169116600019611b5f565b60008054604080517ff3f094a10000000000000000000000000000000000000000000000000000000081526001600160a01b038881166004830152602482018890528681166044830152606482018690529151919092169263f3f094a1926084808201939182900301818387803b15801561143857600080fd5b50505050565b801580611bfe5750604080517fdd62ed3e0000000000000000000000000000000000000000000000000000000081523060048201526001600160a01b03848116602483015291519185169163dd62ed3e91604480820192602092909190829003018186803b158015611bd057600080fd5b505afa158015611be4573d6000803e3d6000fd5b505050506040513d6020811015611bfa57600080fd5b5051155b611c53576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260368152602001806121036036913960400191505060405180910390fd5b604080516001600160a01b038416602482015260448082018490528251808303909101815260649091019091526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f095ea7b300000000000000000000000000000000000000000000000000000000179052611cd3908490611d75565b505050565b6060611ce78484600085611e40565b90505b9392505050565b604080516001600160a01b0380861660248301528416604482015260648082018490528251808303909101815260849091019091526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f23b872dd00000000000000000000000000000000000000000000000000000000179052611b599085905b6060611dca826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b0316611cd89092919063ffffffff16565b805190915015611cd357808060200190516020811015611de957600080fd5b5051611cd3576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602a8152602001806120d9602a913960400191505060405180910390fd5b606082471015611e9b576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260268152602001806120b36026913960400191505060405180910390fd5b611ea485611fee565b611f0f57604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000604482015290519081900360640190fd5b60006060866001600160a01b031685876040518082805190602001908083835b60208310611f6c57805182527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe09092019160209182019101611f2f565b6001836020036101000a03801982511681845116808217855250505050505090500191505060006040518083038185875af1925050503d8060008114611fce576040519150601f19603f3d011682016040523d82523d6000602084013e611fd3565b606091505b5091509150611fe3828286611ff4565b979650505050505050565b3b151590565b60608315612003575081611cea565b8251156120135782518084602001fd5b816040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825283818151815260200191508051906020019080838360005b8381101561207757818101518382015260200161205f565b50505050905090810190601f1680156120a45780820380516001836020036101000a031916815260200191505b509250505060405180910390fdfe416464726573733a20696e73756666696369656e742062616c616e636520666f722063616c6c5361666545524332303a204552433230206f7065726174696f6e20646964206e6f7420737563636565645361666545524332303a20617070726f76652066726f6d206e6f6e2d7a65726f20746f206e6f6e2d7a65726f20616c6c6f77616e6365a2646970667358221220410c7c9dfa62a9716f4706a3683ee9f2ca020071ffa9f9552565a735e454c12a64736f6c634300060c0033", + "solcInputHash": "a0c105fd41656175868de59f7c100fca", + "metadata": "{\"compiler\":{\"version\":\"0.6.12+commit.27d51765\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address payable\",\"name\":\"_wethAddress\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_swapOne\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenOne\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_swapTwo\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenTwo\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_swapThree\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenThree\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_swapFour\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenFour\",\"type\":\"address\"},{\"internalType\":\"contract ISynapseBridge\",\"name\":\"_synapseBridge\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"WETH_ADDRESS\",\"outputs\":[{\"internalType\":\"address payable\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contract IERC20\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint8\",\"name\":\"tokenIndexFrom\",\"type\":\"uint8\"},{\"internalType\":\"uint8\",\"name\":\"tokenIndexTo\",\"type\":\"uint8\"},{\"internalType\":\"uint256\",\"name\":\"dx\",\"type\":\"uint256\"}],\"name\":\"calculateSwap\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"chainId\",\"type\":\"uint256\"},{\"internalType\":\"contract IERC20\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"deposit\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"chainId\",\"type\":\"uint256\"},{\"internalType\":\"contract IERC20\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"redeem\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"chainId\",\"type\":\"uint256\"},{\"internalType\":\"contract IERC20\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"uint8\",\"name\":\"liqTokenIndex\",\"type\":\"uint8\"},{\"internalType\":\"uint256\",\"name\":\"liqMinAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"liqDeadline\",\"type\":\"uint256\"}],\"name\":\"redeemAndRemove\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"chainId\",\"type\":\"uint256\"},{\"internalType\":\"contract IERC20\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"uint8\",\"name\":\"tokenIndexFrom\",\"type\":\"uint8\"},{\"internalType\":\"uint8\",\"name\":\"tokenIndexTo\",\"type\":\"uint8\"},{\"internalType\":\"uint256\",\"name\":\"minDy\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"deadline\",\"type\":\"uint256\"}],\"name\":\"redeemAndSwap\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"to\",\"type\":\"bytes32\"},{\"internalType\":\"uint256\",\"name\":\"chainId\",\"type\":\"uint256\"},{\"internalType\":\"contract IERC20\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"redeemv2\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"chainId\",\"type\":\"uint256\"},{\"internalType\":\"contract IERC20\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint8\",\"name\":\"tokenIndexFrom\",\"type\":\"uint8\"},{\"internalType\":\"uint8\",\"name\":\"tokenIndexTo\",\"type\":\"uint8\"},{\"internalType\":\"uint256\",\"name\":\"dx\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"minDy\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"deadline\",\"type\":\"uint256\"}],\"name\":\"swapAndRedeem\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"chainId\",\"type\":\"uint256\"},{\"internalType\":\"contract IERC20\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint8\",\"name\":\"tokenIndexFrom\",\"type\":\"uint8\"},{\"internalType\":\"uint8\",\"name\":\"tokenIndexTo\",\"type\":\"uint8\"},{\"internalType\":\"uint256\",\"name\":\"dx\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"minDy\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"deadline\",\"type\":\"uint256\"},{\"internalType\":\"uint8\",\"name\":\"liqTokenIndex\",\"type\":\"uint8\"},{\"internalType\":\"uint256\",\"name\":\"liqMinAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"liqDeadline\",\"type\":\"uint256\"}],\"name\":\"swapAndRedeemAndRemove\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"chainId\",\"type\":\"uint256\"},{\"internalType\":\"contract IERC20\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint8\",\"name\":\"tokenIndexFrom\",\"type\":\"uint8\"},{\"internalType\":\"uint8\",\"name\":\"tokenIndexTo\",\"type\":\"uint8\"},{\"internalType\":\"uint256\",\"name\":\"dx\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"minDy\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"deadline\",\"type\":\"uint256\"},{\"internalType\":\"uint8\",\"name\":\"swapTokenIndexFrom\",\"type\":\"uint8\"},{\"internalType\":\"uint8\",\"name\":\"swapTokenIndexTo\",\"type\":\"uint8\"},{\"internalType\":\"uint256\",\"name\":\"swapMinDy\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"swapDeadline\",\"type\":\"uint256\"}],\"name\":\"swapAndRedeemAndSwap\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"chainId\",\"type\":\"uint256\"},{\"internalType\":\"contract IERC20\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint8\",\"name\":\"tokenIndexFrom\",\"type\":\"uint8\"},{\"internalType\":\"uint8\",\"name\":\"tokenIndexTo\",\"type\":\"uint8\"},{\"internalType\":\"uint256\",\"name\":\"dx\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"minDy\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"deadline\",\"type\":\"uint256\"}],\"name\":\"swapETHAndRedeem\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"swapMap\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"swapTokensMap\",\"outputs\":[{\"internalType\":\"contract IERC20\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{\"calculateSwap(address,uint8,uint8,uint256)\":{\"params\":{\"dx\":\"the amount of tokens the user wants to sell. If the token charges a fee on transfers, use the amount that gets transferred after the fee.\",\"tokenIndexFrom\":\"the token the user wants to sell\",\"tokenIndexTo\":\"the token the user wants to buy\"},\"returns\":{\"_0\":\"amount of tokens the user will receive\"}},\"deposit(address,uint256,address,uint256)\":{\"params\":{\"amount\":\"Amount in native token decimals to transfer cross-chain pre-fees*\",\"chainId\":\"which underlying chain to bridge assets onto\",\"to\":\"address on other chain to redeem underlying assets to\",\"token\":\"ERC20 compatible token to deposit into the bridge\"}},\"redeem(address,uint256,address,uint256)\":{\"params\":{\"amount\":\"Amount in native token decimals to transfer cross-chain pre-fees*\",\"chainId\":\"which underlying chain to bridge assets onto\",\"to\":\"address on other chain to redeem underlying assets to\",\"token\":\"ERC20 compatible token to deposit into the bridge\"}},\"redeemAndRemove(address,uint256,address,uint256,uint8,uint256,uint256)\":{\"params\":{\"amount\":\"Amount of (typically) LP token to pass to the nodes to attempt to removeLiquidity() with to redeem for the underlying assets of the LP token\",\"chainId\":\"which underlying chain to bridge assets onto\",\"liqDeadline\":\"Specificies the deadline that the nodes are allowed to try to redeem/swap the LP token*\",\"liqMinAmount\":\"Specifies the minimum amount of the underlying asset needed for the nodes to execute the redeem/swap\",\"liqTokenIndex\":\"Specifies which of the underlying LP assets the nodes should attempt to redeem for\",\"to\":\"address on other chain to redeem underlying assets to\",\"token\":\"ERC20 compatible token to deposit into the bridge\"}},\"redeemAndSwap(address,uint256,address,uint256,uint8,uint8,uint256,uint256)\":{\"params\":{\"amount\":\"Amount in native token decimals to transfer cross-chain pre-fees\",\"chainId\":\"which underlying chain to bridge assets onto\",\"deadline\":\"latest timestamp to accept this transaction*\",\"minDy\":\"the min amount the user would like to receive, or revert to only minting the SynERC20 token crosschain.\",\"to\":\"address on other chain to redeem underlying assets to\",\"token\":\"ERC20 compatible token to deposit into the bridge\",\"tokenIndexFrom\":\"the token the user wants to swap from\",\"tokenIndexTo\":\"the token the user wants to swap to\"}},\"redeemv2(bytes32,uint256,address,uint256)\":{\"params\":{\"amount\":\"Amount in native token decimals to transfer cross-chain pre-fees*\",\"chainId\":\"which chain to bridge assets onto\",\"to\":\"address on other chain to bridge assets to\",\"token\":\"ERC20 compatible token to redeem into the bridge\"}}},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{\"calculateSwap(address,uint8,uint8,uint256)\":{\"notice\":\"Calculate amount of tokens you receive on swap\"},\"deposit(address,uint256,address,uint256)\":{\"notice\":\"wraps SynapseBridge redeem()\"},\"redeem(address,uint256,address,uint256)\":{\"notice\":\"wraps SynapseBridge redeem()\"},\"redeemAndRemove(address,uint256,address,uint256,uint8,uint256,uint256)\":{\"notice\":\"Wraps redeemAndRemove on SynapseBridge Relays to nodes that (typically) a wrapped synAsset ERC20 token has been burned and the underlying needs to be redeeemed on the native chain. This function indicates to the nodes that they should attempt to redeem the LP token for the underlying assets (E.g \\\"swap\\\" out of the LP token)\"},\"redeemAndSwap(address,uint256,address,uint256,uint8,uint8,uint256,uint256)\":{\"notice\":\"Wraps redeemAndSwap on SynapseBridge.sol Relays to nodes that (typically) a wrapped synAsset ERC20 token has been burned and the underlying needs to be redeeemed on the native chain. This function indicates to the nodes that they should attempt to redeem the LP token for the underlying assets (E.g \\\"swap\\\" out of the LP token)\"},\"redeemv2(bytes32,uint256,address,uint256)\":{\"notice\":\"Wraps SynapseBridge redeemv2() function\"}},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/bridge/wrappers/HarmonyBridgeZap.sol\":\"HarmonyBridgeZap\"},\"evmVersion\":\"istanbul\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":10000},\"remappings\":[]},\"sources\":{\"@openzeppelin/contracts/math/SafeMath.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity >=0.6.0 <0.8.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\",\"keccak256\":\"0xcc78a17dd88fa5a2edc60c8489e2f405c0913b377216a5b26b35656b2d0dab52\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/ERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity >=0.6.0 <0.8.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_) public {\\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\",\"keccak256\":\"0xca0c2396dbeb3503b51abf4248ebf77a1461edad513c01529df51850a012bee3\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/ERC20Burnable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity >=0.6.0 <0.8.0;\\n\\nimport \\\"../../utils/Context.sol\\\";\\nimport \\\"./ERC20.sol\\\";\\n\\n/**\\n * @dev Extension of {ERC20} that allows token holders to destroy both their own\\n * tokens and those that they have an allowance for, in a way that can be\\n * recognized off-chain (via event analysis).\\n */\\nabstract contract ERC20Burnable is Context, ERC20 {\\n using SafeMath for uint256;\\n\\n /**\\n * @dev Destroys `amount` tokens from the caller.\\n *\\n * See {ERC20-_burn}.\\n */\\n function burn(uint256 amount) public virtual {\\n _burn(_msgSender(), amount);\\n }\\n\\n /**\\n * @dev Destroys `amount` tokens from `account`, deducting from the caller's\\n * allowance.\\n *\\n * See {ERC20-_burn} and {ERC20-allowance}.\\n *\\n * Requirements:\\n *\\n * - the caller must have allowance for ``accounts``'s tokens of at least\\n * `amount`.\\n */\\n function burnFrom(address account, uint256 amount) public virtual {\\n uint256 decreasedAllowance = allowance(account, _msgSender()).sub(amount, \\\"ERC20: burn amount exceeds allowance\\\");\\n\\n _approve(account, _msgSender(), decreasedAllowance);\\n _burn(account, amount);\\n }\\n}\\n\",\"keccak256\":\"0x9c0eb3b0e11d2480d49991dc384f1e5f9c9b9967cc81944d50916a9b9c6c4984\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/IERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity >=0.6.0 <0.8.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\",\"keccak256\":\"0x5f02220344881ce43204ae4a6281145a67bc52c2bb1290a791857df3d19d78f5\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/SafeERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity >=0.6.0 <0.8.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\",\"keccak256\":\"0xf12dfbe97e6276980b83d2830bb0eb75e0cf4f3e626c2471137f82158ae6a0fc\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/Address.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity >=0.6.2 <0.8.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\",\"keccak256\":\"0x28911e614500ae7c607a432a709d35da25f3bc5ddc8bd12b278b66358070c0ea\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/Context.sol\":{\"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\",\"keccak256\":\"0x8d3cb350f04ff49cfb10aef08d87f19dcbaecc8027b0bed12f3275cd12f38cf0\",\"license\":\"MIT\"},\"contracts/bridge/interfaces/ISwap.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity 0.6.12;\\n\\nimport '@openzeppelin/contracts/token/ERC20/ERC20.sol';\\n\\ninterface ISwap {\\n // pool data view functions\\n function getA() external view returns (uint256);\\n\\n function getToken(uint8 index) external view returns (IERC20);\\n\\n function getTokenIndex(address tokenAddress) external view returns (uint8);\\n\\n function getTokenBalance(uint8 index) external view returns (uint256);\\n\\n function getVirtualPrice() external view returns (uint256);\\n\\n // min return calculation functions\\n function calculateSwap(\\n uint8 tokenIndexFrom,\\n uint8 tokenIndexTo,\\n uint256 dx\\n ) external view returns (uint256);\\n\\n function calculateTokenAmount(uint256[] calldata amounts, bool deposit)\\n external\\n view\\n returns (uint256);\\n\\n function calculateRemoveLiquidity(uint256 amount)\\n external\\n view\\n returns (uint256[] memory);\\n\\n function calculateRemoveLiquidityOneToken(\\n uint256 tokenAmount,\\n uint8 tokenIndex\\n ) external view returns (uint256 availableTokenAmount);\\n\\n // state modifying functions\\n function initialize(\\n IERC20[] memory pooledTokens,\\n uint8[] memory decimals,\\n string memory lpTokenName,\\n string memory lpTokenSymbol,\\n uint256 a,\\n uint256 fee,\\n uint256 adminFee,\\n address lpTokenTargetAddress\\n ) external;\\n\\n function swap(\\n uint8 tokenIndexFrom,\\n uint8 tokenIndexTo,\\n uint256 dx,\\n uint256 minDy,\\n uint256 deadline\\n ) external returns (uint256);\\n\\n function addLiquidity(\\n uint256[] calldata amounts,\\n uint256 minToMint,\\n uint256 deadline\\n ) external returns (uint256);\\n\\n function removeLiquidity(\\n uint256 amount,\\n uint256[] calldata minAmounts,\\n uint256 deadline\\n ) external returns (uint256[] memory);\\n\\n function removeLiquidityOneToken(\\n uint256 tokenAmount,\\n uint8 tokenIndex,\\n uint256 minAmount,\\n uint256 deadline\\n ) external returns (uint256);\\n\\n function removeLiquidityImbalance(\\n uint256[] calldata amounts,\\n uint256 maxBurnAmount,\\n uint256 deadline\\n ) external returns (uint256);\\n}\\n\",\"keccak256\":\"0xb51eb389637b2b595a09cd95ea4167a6d945719be1bc127eafae07c06abd8ca8\",\"license\":\"MIT\"},\"contracts/bridge/interfaces/ISynapseBridge.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity 0.6.12;\\n\\nimport '@openzeppelin/contracts/token/ERC20/SafeERC20.sol';\\nimport '@openzeppelin/contracts/token/ERC20/ERC20Burnable.sol';\\n\\ninterface ISynapseBridge {\\n using SafeERC20 for IERC20;\\n\\n function deposit(\\n address to,\\n uint256 chainId,\\n IERC20 token,\\n uint256 amount\\n ) external;\\n\\n function depositAndSwap(\\n address to,\\n uint256 chainId,\\n IERC20 token,\\n uint256 amount,\\n uint8 tokenIndexFrom,\\n uint8 tokenIndexTo,\\n uint256 minDy,\\n uint256 deadline\\n ) external;\\n\\n function redeem(\\n address to,\\n uint256 chainId,\\n IERC20 token,\\n uint256 amount\\n ) external;\\n\\n\\n function redeemv2(\\n bytes32 to,\\n uint256 chainId,\\n IERC20 token,\\n uint256 amount\\n ) external;\\n\\n\\n function redeemAndSwap(\\n address to,\\n uint256 chainId,\\n IERC20 token,\\n uint256 amount,\\n uint8 tokenIndexFrom,\\n uint8 tokenIndexTo,\\n uint256 minDy,\\n uint256 deadline\\n ) external;\\n\\n function redeemAndRemove(\\n address to,\\n uint256 chainId,\\n IERC20 token,\\n uint256 amount,\\n uint8 liqTokenIndex,\\n uint256 liqMinAmount,\\n uint256 liqDeadline\\n ) external;\\n}\\n\",\"keccak256\":\"0x9ae06bbed7d464faceb9c63e929171f422b5eaee1f6d653742ab97862bc6609a\",\"license\":\"MIT\"},\"contracts/bridge/interfaces/IWETH9.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity >=0.4.0;\\n\\ninterface IWETH9 {\\n function name() external view returns (string memory);\\n\\n function symbol() external view returns (string memory);\\n\\n function decimals() external view returns (uint8);\\n\\n function balanceOf(address) external view returns (uint256);\\n\\n function allowance(address, address) external view returns (uint256);\\n\\n receive() external payable;\\n\\n function deposit() external payable;\\n\\n function withdraw(uint256 wad) external;\\n\\n function totalSupply() external view returns (uint256);\\n\\n function approve(address guy, uint256 wad) external returns (bool);\\n\\n function transfer(address dst, uint256 wad) external returns (bool);\\n\\n function transferFrom(\\n address src,\\n address dst,\\n uint256 wad\\n ) external returns (bool);\\n}\",\"keccak256\":\"0x081ebde11dad2210d382564d40336f914d3d621750645f23707ca1a92139dbe2\",\"license\":\"MIT\"},\"contracts/bridge/wrappers/HarmonyBridgeZap.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.6.12;\\n\\nimport \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\nimport \\\"@openzeppelin/contracts/token/ERC20/SafeERC20.sol\\\";\\nimport \\\"../interfaces/ISwap.sol\\\";\\nimport \\\"../interfaces/ISynapseBridge.sol\\\";\\nimport \\\"../interfaces/IWETH9.sol\\\";\\n\\ninterface IFrax {\\n function exchangeCanonicalForOld(address bridge_token_address, uint256 token_amount) external returns (uint256);\\n}\\n\\ncontract HarmonyBridgeZap {\\n using SafeERC20 for IERC20;\\n\\n ISynapseBridge synapseBridge;\\n address payable public immutable WETH_ADDRESS;\\n IFrax private constant CANOLICAL_FRAX = IFrax(0xFa7191D292d5633f702B0bd7E3E3BcCC0e633200);\\n IERC20 private constant SYN_FRAX = IERC20(0x1852F70512298d56e9c8FDd905e02581E04ddb2a);\\n\\n mapping(address => address) public swapMap;\\n mapping(address => IERC20[]) public swapTokensMap;\\n\\n uint256 constant MAX_UINT256 = 2**256 - 1;\\n\\n constructor(\\n address payable _wethAddress,\\n address _swapOne,\\n address tokenOne,\\n address _swapTwo,\\n address tokenTwo,\\n address _swapThree,\\n address tokenThree,\\n address _swapFour,\\n address tokenFour,\\n ISynapseBridge _synapseBridge\\n ) public {\\n WETH_ADDRESS = _wethAddress;\\n synapseBridge = _synapseBridge;\\n swapMap[tokenOne] = _swapOne;\\n swapMap[tokenTwo] = _swapTwo;\\n swapMap[tokenThree] = _swapThree;\\n swapMap[tokenFour] = _swapFour;\\n\\n if (address(_swapOne) != address(0)) {\\n {\\n uint8 i;\\n for (; i < 32; i++) {\\n try ISwap(_swapOne).getToken(i) returns (\\n IERC20 token\\n ) {\\n swapTokensMap[_swapOne].push(token);\\n token.safeApprove(address(_swapOne), MAX_UINT256);\\n token.safeApprove(address(synapseBridge), MAX_UINT256);\\n } catch {\\n break;\\n }\\n }\\n require(i > 1, \\\"swap must have at least 2 tokens\\\");\\n }\\n }\\n if (address(_swapTwo) != address(0)) {\\n {\\n uint8 i;\\n for (; i < 32; i++) {\\n try ISwap(_swapTwo).getToken(i) returns (\\n IERC20 token\\n ) {\\n swapTokensMap[_swapTwo].push(token);\\n token.safeApprove(address(_swapTwo), MAX_UINT256);\\n token.safeApprove(address(synapseBridge), MAX_UINT256);\\n } catch {\\n break;\\n }\\n }\\n require(i > 1, \\\"swap must have at least 2 tokens\\\");\\n }\\n }\\n\\n if (address(_swapThree) != address(0)) {\\n {\\n uint8 i;\\n for (; i < 32; i++) {\\n try ISwap(_swapThree).getToken(i) returns (\\n IERC20 token\\n ) {\\n swapTokensMap[_swapThree].push(token);\\n token.safeApprove(address(_swapThree), MAX_UINT256);\\n token.safeApprove(address(synapseBridge), MAX_UINT256);\\n } catch {\\n break;\\n }\\n }\\n require(i > 1, \\\"swap must have at least 2 tokens\\\");\\n }\\n }\\n\\n if (address(_swapFour) != address(0)) {\\n {\\n uint8 i;\\n for (; i < 32; i++) {\\n try ISwap(_swapFour).getToken(i) returns (\\n IERC20 token\\n ) {\\n swapTokensMap[_swapFour].push(token);\\n token.safeApprove(address(_swapFour), MAX_UINT256);\\n token.safeApprove(address(synapseBridge), MAX_UINT256);\\n } catch {\\n break;\\n }\\n }\\n require(i > 1, \\\"swap must have at least 2 tokens\\\");\\n }\\n }\\n }\\n\\n /**\\n * @notice Calculate amount of tokens you receive on swap\\n * @param tokenIndexFrom the token the user wants to sell\\n * @param tokenIndexTo the token the user wants to buy\\n * @param dx the amount of tokens the user wants to sell. If the token charges\\n * a fee on transfers, use the amount that gets transferred after the fee.\\n * @return amount of tokens the user will receive\\n */\\n function calculateSwap(\\n IERC20 token,\\n uint8 tokenIndexFrom,\\n uint8 tokenIndexTo,\\n uint256 dx\\n ) external view virtual returns (uint256) {\\n ISwap swap = ISwap(\\n swapMap[address(token)]\\n );\\n return swap.calculateSwap(tokenIndexFrom, tokenIndexTo, dx);\\n }\\n\\n function swapAndRedeem(\\n address to,\\n uint256 chainId,\\n IERC20 token,\\n uint8 tokenIndexFrom,\\n uint8 tokenIndexTo,\\n uint256 dx,\\n uint256 minDy,\\n uint256 deadline\\n ) external {\\n ISwap swap = ISwap(swapMap[address(token)]);\\n require(address(swap) != address(0), \\\"Swap is 0x00\\\");\\n IERC20[] memory tokens = swapTokensMap[address(swap)];\\n tokens[tokenIndexFrom].safeTransferFrom(\\n msg.sender,\\n address(this),\\n dx\\n );\\n // swap\\n\\n uint256 swappedAmount = swap.swap(\\n tokenIndexFrom,\\n tokenIndexTo,\\n dx,\\n minDy,\\n deadline\\n );\\n // deposit into bridge, gets nUSD\\n if (\\n token.allowance(address(this), address(synapseBridge)) <\\n swappedAmount\\n ) {\\n token.safeApprove(address(synapseBridge), MAX_UINT256);\\n }\\n synapseBridge.redeem(to, chainId, token, swappedAmount);\\n }\\n\\n function swapAndRedeemAndSwap(\\n address to,\\n uint256 chainId,\\n IERC20 token,\\n uint8 tokenIndexFrom,\\n uint8 tokenIndexTo,\\n uint256 dx,\\n uint256 minDy,\\n uint256 deadline,\\n uint8 swapTokenIndexFrom,\\n uint8 swapTokenIndexTo,\\n uint256 swapMinDy,\\n uint256 swapDeadline\\n ) external {\\n require(\\n address(swapMap[address(token)]) != address(0),\\n \\\"Swap is 0x00\\\"\\n );\\n IERC20[] memory tokens = swapTokensMap[\\n swapMap[address(token)]\\n ];\\n tokens[tokenIndexFrom].safeTransferFrom(\\n msg.sender,\\n address(this),\\n dx\\n );\\n // swap\\n\\n uint256 swappedAmount = ISwap(swapMap[address(token)]).swap(tokenIndexFrom, tokenIndexTo, dx, minDy, deadline);\\n // deposit into bridge, gets nUSD\\n if (\\n token.allowance(address(this), address(synapseBridge)) <\\n swappedAmount\\n ) {\\n token.safeApprove(address(synapseBridge), MAX_UINT256);\\n }\\n synapseBridge.redeemAndSwap(\\n to,\\n chainId,\\n token,\\n swappedAmount,\\n swapTokenIndexFrom,\\n swapTokenIndexTo,\\n swapMinDy,\\n swapDeadline\\n );\\n }\\n\\n function swapAndRedeemAndRemove(\\n address to,\\n uint256 chainId,\\n IERC20 token,\\n uint8 tokenIndexFrom,\\n uint8 tokenIndexTo,\\n uint256 dx,\\n uint256 minDy,\\n uint256 deadline,\\n uint8 liqTokenIndex,\\n uint256 liqMinAmount,\\n uint256 liqDeadline\\n ) external {\\n ISwap swap = ISwap(swapMap[address(token)]);\\n require(address(swap) != address(0), \\\"Swap is 0x00\\\");\\n IERC20[] memory tokens = swapTokensMap[address(swap)];\\n tokens[tokenIndexFrom].safeTransferFrom(\\n msg.sender,\\n address(this),\\n dx\\n );\\n // swap\\n\\n uint256 swappedAmount = swap.swap(\\n tokenIndexFrom,\\n tokenIndexTo,\\n dx,\\n minDy,\\n deadline\\n );\\n // deposit into bridge, gets nUSD\\n if (\\n token.allowance(address(this), address(synapseBridge)) <\\n swappedAmount\\n ) {\\n token.safeApprove(address(synapseBridge), MAX_UINT256);\\n }\\n synapseBridge.redeemAndRemove(\\n to,\\n chainId,\\n token,\\n swappedAmount,\\n liqTokenIndex,\\n liqMinAmount,\\n liqDeadline\\n );\\n }\\n\\n /**\\n * @notice wraps SynapseBridge redeem()\\n * @param to address on other chain to redeem underlying assets to\\n * @param chainId which underlying chain to bridge assets onto\\n * @param token ERC20 compatible token to deposit into the bridge\\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\\n **/\\n function redeem(\\n address to,\\n uint256 chainId,\\n IERC20 token,\\n uint256 amount\\n ) external {\\n token.safeTransferFrom(msg.sender, address(this), amount);\\n if (address(token) == address(CANOLICAL_FRAX)) {\\n uint256 swappedAmount = CANOLICAL_FRAX.exchangeCanonicalForOld(address(SYN_FRAX), amount);\\n if (SYN_FRAX.allowance(address(this), address(synapseBridge)) < amount) {\\n SYN_FRAX.safeApprove(address(synapseBridge), MAX_UINT256);\\n }\\n synapseBridge.redeem(to, chainId, SYN_FRAX, swappedAmount);\\n } else {\\n if (token.allowance(address(this), address(synapseBridge)) < amount) {\\n token.safeApprove(address(synapseBridge), MAX_UINT256);\\n }\\n synapseBridge.redeem(to, chainId, token, amount);\\n }\\n \\n }\\n\\n /**\\n * @notice Wraps SynapseBridge redeemv2() function\\n * @param to address on other chain to bridge assets to\\n * @param chainId which chain to bridge assets onto\\n * @param token ERC20 compatible token to redeem into the bridge\\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\\n **/\\n function redeemv2(\\n bytes32 to,\\n uint256 chainId,\\n IERC20 token,\\n uint256 amount\\n ) external {\\n token.safeTransferFrom(msg.sender, address(this), amount);\\n\\n if (token.allowance(address(this), address(synapseBridge)) < amount) {\\n token.safeApprove(address(synapseBridge), MAX_UINT256);\\n }\\n synapseBridge.redeemv2(to, chainId, token, amount);\\n }\\n\\n /**\\n * @notice wraps SynapseBridge redeem()\\n * @param to address on other chain to redeem underlying assets to\\n * @param chainId which underlying chain to bridge assets onto\\n * @param token ERC20 compatible token to deposit into the bridge\\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\\n **/\\n function deposit(\\n address to,\\n uint256 chainId,\\n IERC20 token,\\n uint256 amount\\n ) external {\\n token.safeTransferFrom(msg.sender, address(this), amount);\\n if (token.allowance(address(this), address(synapseBridge)) < amount) {\\n token.safeApprove(address(synapseBridge), MAX_UINT256);\\n }\\n synapseBridge.deposit(to, chainId, token, amount);\\n }\\n\\n function swapETHAndRedeem(\\n address to,\\n uint256 chainId,\\n IERC20 token,\\n uint8 tokenIndexFrom,\\n uint8 tokenIndexTo,\\n uint256 dx,\\n uint256 minDy,\\n uint256 deadline\\n ) external payable {\\n require(WETH_ADDRESS != address(0), \\\"WETH 0\\\");\\n require(msg.value > 0 && msg.value == dx, \\\"INCORRECT MSG VALUE\\\");\\n ISwap swap = ISwap(swapMap[address(token)]);\\n require(address(swap) != address(0), \\\"Swap is 0x00\\\");\\n IWETH9(WETH_ADDRESS).deposit{value: msg.value}();\\n\\n // swap\\n uint256 swappedAmount = swap.swap(\\n tokenIndexFrom,\\n tokenIndexTo,\\n dx,\\n minDy,\\n deadline\\n );\\n synapseBridge.redeem(to, chainId, token, swappedAmount);\\n }\\n\\n /**\\n * @notice Wraps redeemAndSwap on SynapseBridge.sol\\n * Relays to nodes that (typically) a wrapped synAsset ERC20 token has been burned and the underlying needs to be redeeemed on the native chain. This function indicates to the nodes that they should attempt to redeem the LP token for the underlying assets (E.g \\\"swap\\\" out of the LP token)\\n * @param to address on other chain to redeem underlying assets to\\n * @param chainId which underlying chain to bridge assets onto\\n * @param token ERC20 compatible token to deposit into the bridge\\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\\n * @param tokenIndexFrom the token the user wants to swap from\\n * @param tokenIndexTo the token the user wants to swap to\\n * @param minDy the min amount the user would like to receive, or revert to only minting the SynERC20 token crosschain.\\n * @param deadline latest timestamp to accept this transaction\\n **/\\n function redeemAndSwap(\\n address to,\\n uint256 chainId,\\n IERC20 token,\\n uint256 amount,\\n uint8 tokenIndexFrom,\\n uint8 tokenIndexTo,\\n uint256 minDy,\\n uint256 deadline\\n ) external {\\n token.safeTransferFrom(msg.sender, address(this), amount);\\n if (token.allowance(address(this), address(synapseBridge)) < amount) {\\n token.safeApprove(address(synapseBridge), MAX_UINT256);\\n }\\n synapseBridge.redeemAndSwap(\\n to,\\n chainId,\\n token,\\n amount,\\n tokenIndexFrom,\\n tokenIndexTo,\\n minDy,\\n deadline\\n );\\n }\\n\\n /**\\n * @notice Wraps redeemAndRemove on SynapseBridge\\n * Relays to nodes that (typically) a wrapped synAsset ERC20 token has been burned and the underlying needs to be redeeemed on the native chain. This function indicates to the nodes that they should attempt to redeem the LP token for the underlying assets (E.g \\\"swap\\\" out of the LP token)\\n * @param to address on other chain to redeem underlying assets to\\n * @param chainId which underlying chain to bridge assets onto\\n * @param token ERC20 compatible token to deposit into the bridge\\n * @param amount Amount of (typically) LP token to pass to the nodes to attempt to removeLiquidity() with to redeem for the underlying assets of the LP token\\n * @param liqTokenIndex Specifies which of the underlying LP assets the nodes should attempt to redeem for\\n * @param liqMinAmount Specifies the minimum amount of the underlying asset needed for the nodes to execute the redeem/swap\\n * @param liqDeadline Specificies the deadline that the nodes are allowed to try to redeem/swap the LP token\\n **/\\n function redeemAndRemove(\\n address to,\\n uint256 chainId,\\n IERC20 token,\\n uint256 amount,\\n uint8 liqTokenIndex,\\n uint256 liqMinAmount,\\n uint256 liqDeadline\\n ) external {\\n token.safeTransferFrom(msg.sender, address(this), amount);\\n if (token.allowance(address(this), address(synapseBridge)) < amount) {\\n token.safeApprove(address(synapseBridge), MAX_UINT256);\\n }\\n synapseBridge.redeemAndRemove(\\n to,\\n chainId,\\n token,\\n amount,\\n liqTokenIndex,\\n liqMinAmount,\\n liqDeadline\\n );\\n }\\n}\\n\",\"keccak256\":\"0xcb72d17cdb6b3eb986351ef87603ab5c978f11aa57a6da9466a85abd69368038\",\"license\":\"MIT\"}},\"version\":1}", + "bytecode": "0x60a06040523480156200001157600080fd5b5060405162002ec538038062002ec583398181016040526101408110156200003857600080fd5b50805160208083015160408085015160608087015160808089015160a08a015160c08b015160e08c01516101008d0151610120909d0151968c901b6001600160601b031916909452600080546001600160a01b03199081166001600160a01b03808a16919091178355808a1683526001909c52898220805482168d8d169081179091558c861683528a8320805483168e8a161790558c841683528a8320805483168e87161790558c8f1683529990912080549091169a85169a909a17909955989996989497929690959293919290919015620002725760005b60208160ff1610156200022857896001600160a01b03166382b86600826040518263ffffffff1660e01b8152600401808260ff16815260200191505060206040518083038186803b1580156200016657600080fd5b505afa9250505080156200018d57506040513d60208110156200018857600080fd5b505160015b620001985762000228565b6001600160a01b038b81166000908152600260209081526040822080546001810182559083529181902090910180546001600160a01b0319169284169283179055620001f491908d9060001990620006de811b62001cf717901c565b6000546200021e906001600160a01b038381169116600019620006de602090811b62001cf717901c565b5060010162000111565b60018160ff161162000270576040805162461bcd60e51b8152602060048201819052602482015260008051602062002e45833981519152604482015290519081900360640190fd5b505b6001600160a01b03871615620003e65760005b60208160ff1610156200039c57876001600160a01b03166382b86600826040518263ffffffff1660e01b8152600401808260ff16815260200191505060206040518083038186803b158015620002da57600080fd5b505afa9250505080156200030157506040513d6020811015620002fc57600080fd5b505160015b6200030c576200039c565b6001600160a01b038981166000908152600260209081526040822080546001810182559083529181902090910180546001600160a01b03191692841692831790556200036891908b9060001990620006de811b62001cf717901c565b60005462000392906001600160a01b038381169116600019620006de602090811b62001cf717901c565b5060010162000285565b60018160ff1611620003e4576040805162461bcd60e51b8152602060048201819052602482015260008051602062002e45833981519152604482015290519081900360640190fd5b505b6001600160a01b038516156200055a5760005b60208160ff1610156200051057856001600160a01b03166382b86600826040518263ffffffff1660e01b8152600401808260ff16815260200191505060206040518083038186803b1580156200044e57600080fd5b505afa9250505080156200047557506040513d60208110156200047057600080fd5b505160015b620004805762000510565b6001600160a01b038781166000908152600260209081526040822080546001810182559083529181902090910180546001600160a01b0319169284169283179055620004dc9190899060001990620006de811b62001cf717901c565b60005462000506906001600160a01b038381169116600019620006de602090811b62001cf717901c565b50600101620003f9565b60018160ff161162000558576040805162461bcd60e51b8152602060048201819052602482015260008051602062002e45833981519152604482015290519081900360640190fd5b505b6001600160a01b03831615620006ce5760005b60208160ff1610156200068457836001600160a01b03166382b86600826040518263ffffffff1660e01b8152600401808260ff16815260200191505060206040518083038186803b158015620005c257600080fd5b505afa925050508015620005e957506040513d6020811015620005e457600080fd5b505160015b620005f45762000684565b6001600160a01b038581166000908152600260209081526040822080546001810182559083529181902090910180546001600160a01b0319169284169283179055620006509190879060001990620006de811b62001cf717901c565b6000546200067a906001600160a01b038381169116600019620006de602090811b62001cf717901c565b506001016200056d565b60018160ff1611620006cc576040805162461bcd60e51b8152602060048201819052602482015260008051602062002e45833981519152604482015290519081900360640190fd5b505b5050505050505050505062000af1565b80158062000768575060408051636eb1769f60e11b81523060048201526001600160a01b03848116602483015291519185169163dd62ed3e91604480820192602092909190829003018186803b1580156200073857600080fd5b505afa1580156200074d573d6000803e3d6000fd5b505050506040513d60208110156200076457600080fd5b5051155b620007a55760405162461bcd60e51b815260040180806020018281038252603681526020018062002e8f6036913960400191505060405180910390fd5b604080516001600160a01b038416602482015260448082018490528251808303909101815260649091019091526020810180516001600160e01b0390811663095ea7b360e01b17909152620007fd9185916200080216565b505050565b60606200085e826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b0316620008be60201b62001e70179092919060201c565b805190915015620007fd578080602001905160208110156200087f57600080fd5b5051620007fd5760405162461bcd60e51b815260040180806020018281038252602a81526020018062002e65602a913960400191505060405180910390fd5b6060620008cf8484600085620008d9565b90505b9392505050565b6060824710156200091c5760405162461bcd60e51b815260040180806020018281038252602681526020018062002e1f6026913960400191505060405180910390fd5b620009278562000a41565b62000979576040805162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000604482015290519081900360640190fd5b60006060866001600160a01b031685876040518082805190602001908083835b60208310620009ba5780518252601f19909201916020918201910162000999565b6001836020036101000a03801982511681845116808217855250505050505090500191505060006040518083038185875af1925050503d806000811462000a1e576040519150601f19603f3d011682016040523d82523d6000602084013e62000a23565b606091505b50909250905062000a3682828662000a47565b979650505050505050565b3b151590565b6060831562000a58575081620008d2565b82511562000a695782518084602001fd5b8160405162461bcd60e51b81526004018080602001828103825283818151815260200191508051906020019080838360005b8381101562000ab557818101518382015260200162000a9b565b50505050905090810190601f16801562000ae35780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b60805160601c61230662000b19600039806105305280610eee528061108452506123066000f3fe6080604052600436106100d25760003560e01c806365749c9d1161007f57806385528f0b1161005957806385528f0b146103e857806390d250741461041b5780639f33072714610462578063f3f094a1146104e7576100d2565b806365749c9d146102c9578063798af72014610323578063839ed90a14610381576100d2565b8063393494b8116100b0578063393494b8146101e457806349b7cf841461021d5780634a517a5514610262576100d2565b8063040141e5146100d7578063174dc9521461010857806336e712ed14610188575b600080fd5b3480156100e357600080fd5b506100ec61052e565b604080516001600160a01b039092168252519081900360200190f35b34801561011457600080fd5b50610186600480360361016081101561012c57600080fd5b506001600160a01b0381358116916020810135916040820135169060ff6060820135811691608081013582169160a08201359160c08101359160e08201359161010081013590911690610120810135906101400135610552565b005b34801561019457600080fd5b50610186600480360360e08110156101ab57600080fd5b506001600160a01b0381358116916020810135916040820135169060608101359060ff6080820135169060a08101359060c001356108b5565b3480156101f057600080fd5b506100ec6004803603604081101561020757600080fd5b506001600160a01b038135169060200135610a36565b34801561022957600080fd5b506101866004803603608081101561024057600080fd5b508035906020810135906001600160a01b036040820135169060600135610a6b565b34801561026e57600080fd5b50610186600480360361010081101561028657600080fd5b506001600160a01b0381358116916020810135916040820135169060ff606082013581169160808101359091169060a08101359060c08101359060e00135610bd1565b61018660048036036101008110156102e057600080fd5b506001600160a01b0381358116916020810135916040820135169060ff606082013581169160808101359091169060a08101359060c08101359060e00135610eec565b34801561032f57600080fd5b5061036f6004803603608081101561034657600080fd5b506001600160a01b038135169060ff602082013581169160408101359091169060600135611246565b60408051918252519081900360200190f35b34801561038d57600080fd5b5061018660048036036101008110156103a557600080fd5b506001600160a01b0381358116916020810135916040820135169060608101359060ff608082013581169160a08101359091169060c08101359060e001356112ff565b3480156103f457600080fd5b506100ec6004803603602081101561040b57600080fd5b50356001600160a01b031661148a565b34801561042757600080fd5b506101866004803603608081101561043e57600080fd5b506001600160a01b03813581169160208101359160408201351690606001356114a5565b34801561046e57600080fd5b50610186600480360361018081101561048657600080fd5b506001600160a01b0381358116916020810135916040820135169060ff6060820135811691608081013582169160a08201359160c08101359160e08201359161010081013582169161012082013516906101408101359061016001356115ee565b3480156104f357600080fd5b506101866004803603608081101561050a57600080fd5b506001600160a01b0381358116916020810135916040820135169060600135611942565b7f000000000000000000000000000000000000000000000000000000000000000081565b6001600160a01b03808a1660009081526001602052604090205416806105d957604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f5377617020697320307830300000000000000000000000000000000000000000604482015290519081900360640190fd5b6001600160a01b03811660009081526002602090815260409182902080548351818402810184019094528084526060939283018282801561064357602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311610625575b5050505050905061068033308a848e60ff168151811061065f57fe5b60200260200101516001600160a01b0316611e89909392919063ffffffff16565b604080517f9169558600000000000000000000000000000000000000000000000000000000815260ff808d1660048301528b166024820152604481018a9052606481018990526084810188905290516000916001600160a01b0385169163916955869160a48082019260209290919082900301818787803b15801561070457600080fd5b505af1158015610718573d6000803e3d6000fd5b505050506040513d602081101561072e57600080fd5b5051600054604080517fdd62ed3e0000000000000000000000000000000000000000000000000000000081523060048201526001600160a01b03928316602482015290519293508392918f169163dd62ed3e91604480820192602092909190829003018186803b1580156107a157600080fd5b505afa1580156107b5573d6000803e3d6000fd5b505050506040513d60208110156107cb57600080fd5b505110156107ef576000546107ef906001600160a01b038e81169116600019611cf7565b60008054906101000a90046001600160a01b03166001600160a01b03166336e712ed8f8f8f858b8b8b6040518863ffffffff1660e01b815260040180886001600160a01b03168152602001878152602001866001600160a01b031681526020018581526020018460ff168152602001838152602001828152602001975050505050505050600060405180830381600087803b15801561088d57600080fd5b505af11580156108a1573d6000803e3d6000fd5b505050505050505050505050505050505050565b6108ca6001600160a01b038616333087611e89565b600054604080517fdd62ed3e0000000000000000000000000000000000000000000000000000000081523060048201526001600160a01b0392831660248201529051869288169163dd62ed3e916044808301926020929190829003018186803b15801561093657600080fd5b505afa15801561094a573d6000803e3d6000fd5b505050506040513d602081101561096057600080fd5b5051101561098457600054610984906001600160a01b038781169116600019611cf7565b60008054604080517f36e712ed0000000000000000000000000000000000000000000000000000000081526001600160a01b038b81166004830152602482018b905289811660448301526064820189905260ff8816608483015260a4820187905260c48201869052915191909216926336e712ed9260e4808201939182900301818387803b158015610a1557600080fd5b505af1158015610a29573d6000803e3d6000fd5b5050505050505050505050565b60026020528160005260406000208181548110610a4f57fe5b6000918252602090912001546001600160a01b03169150829050565b610a806001600160a01b038316333084611e89565b600054604080517fdd62ed3e0000000000000000000000000000000000000000000000000000000081523060048201526001600160a01b0392831660248201529051839285169163dd62ed3e916044808301926020929190829003018186803b158015610aec57600080fd5b505afa158015610b00573d6000803e3d6000fd5b505050506040513d6020811015610b1657600080fd5b50511015610b3a57600054610b3a906001600160a01b038481169116600019611cf7565b60008054604080517f49b7cf8400000000000000000000000000000000000000000000000000000000815260048101889052602481018790526001600160a01b03868116604483015260648201869052915191909216926349b7cf84926084808201939182900301818387803b158015610bb357600080fd5b505af1158015610bc7573d6000803e3d6000fd5b5050505050505050565b6001600160a01b038087166000908152600160205260409020541680610c5857604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f5377617020697320307830300000000000000000000000000000000000000000604482015290519081900360640190fd5b6001600160a01b038116600090815260026020908152604091829020805483518184028101840190945280845260609392830182828015610cc257602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311610ca4575b50505050509050610cde333087848b60ff168151811061065f57fe5b604080517f9169558600000000000000000000000000000000000000000000000000000000815260ff808a1660048301528816602482015260448101879052606481018690526084810185905290516000916001600160a01b0385169163916955869160a48082019260209290919082900301818787803b158015610d6257600080fd5b505af1158015610d76573d6000803e3d6000fd5b505050506040513d6020811015610d8c57600080fd5b5051600054604080517fdd62ed3e0000000000000000000000000000000000000000000000000000000081523060048201526001600160a01b03928316602482015290519293508392918c169163dd62ed3e91604480820192602092909190829003018186803b158015610dff57600080fd5b505afa158015610e13573d6000803e3d6000fd5b505050506040513d6020811015610e2957600080fd5b50511015610e4d57600054610e4d906001600160a01b038b81169116600019611cf7565b60008054604080517ff3f094a10000000000000000000000000000000000000000000000000000000081526001600160a01b038f81166004830152602482018f90528d81166044830152606482018690529151919092169263f3f094a1926084808201939182900301818387803b158015610ec757600080fd5b505af1158015610edb573d6000803e3d6000fd5b505050505050505050505050505050565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316610f8157604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600660248201527f5745544820300000000000000000000000000000000000000000000000000000604482015290519081900360640190fd5b600034118015610f9057508234145b610ffb57604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f494e434f5252454354204d53472056414c554500000000000000000000000000604482015290519081900360640190fd5b6001600160a01b03808716600090815260016020526040902054168061108257604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f5377617020697320307830300000000000000000000000000000000000000000604482015290519081900360640190fd5b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663d0e30db0346040518263ffffffff1660e01b81526004016000604051808303818588803b1580156110dd57600080fd5b505af11580156110f1573d6000803e3d6000fd5b5050604080517f9169558600000000000000000000000000000000000000000000000000000000815260ff808c1660048301528a1660248201526044810189905260648101889052608481018790529051600094506001600160a01b03861693506391695586925060a480830192602092919082900301818787803b15801561117957600080fd5b505af115801561118d573d6000803e3d6000fd5b505050506040513d60208110156111a357600080fd5b505160008054604080517ff3f094a10000000000000000000000000000000000000000000000000000000081526001600160a01b038f81166004830152602482018f90528d8116604483015260648201869052915194955091169263f3f094a19260848084019391929182900301818387803b15801561122257600080fd5b505af1158015611236573d6000803e3d6000fd5b5050505050505050505050505050565b6001600160a01b0380851660009081526001602090815260408083205481517fa95b089f00000000000000000000000000000000000000000000000000000000815260ff808a1660048301528816602482015260448101879052915193941692839263a95b089f9260648082019391829003018186803b1580156112c957600080fd5b505afa1580156112dd573d6000803e3d6000fd5b505050506040513d60208110156112f357600080fd5b50519695505050505050565b6113146001600160a01b038716333088611e89565b600054604080517fdd62ed3e0000000000000000000000000000000000000000000000000000000081523060048201526001600160a01b0392831660248201529051879289169163dd62ed3e916044808301926020929190829003018186803b15801561138057600080fd5b505afa158015611394573d6000803e3d6000fd5b505050506040513d60208110156113aa57600080fd5b505110156113ce576000546113ce906001600160a01b038881169116600019611cf7565b60008054604080517f839ed90a0000000000000000000000000000000000000000000000000000000081526001600160a01b038c81166004830152602482018c90528a81166044830152606482018a905260ff808a166084840152881660a483015260c4820187905260e482018690529151919092169263839ed90a92610104808201939182900301818387803b15801561146857600080fd5b505af115801561147c573d6000803e3d6000fd5b505050505050505050505050565b6001602052600090815260409020546001600160a01b031681565b6114ba6001600160a01b038316333084611e89565b600054604080517fdd62ed3e0000000000000000000000000000000000000000000000000000000081523060048201526001600160a01b0392831660248201529051839285169163dd62ed3e916044808301926020929190829003018186803b15801561152657600080fd5b505afa15801561153a573d6000803e3d6000fd5b505050506040513d602081101561155057600080fd5b5051101561157457600054611574906001600160a01b038481169116600019611cf7565b60008054604080517f90d250740000000000000000000000000000000000000000000000000000000081526001600160a01b03888116600483015260248201889052868116604483015260648201869052915191909216926390d25074926084808201939182900301818387803b158015610bb357600080fd5b6001600160a01b038a81166000908152600160205260409020541661167457604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f5377617020697320307830300000000000000000000000000000000000000000604482015290519081900360640190fd5b6001600160a01b03808b16600090815260016020908152604080832054909316825260028152908290208054835181840281018401909452808452606093928301828280156116ec57602002820191906000526020600020905b81546001600160a01b031681526001909101906020018083116116ce575b5050505050905061170833308a848e60ff168151811061065f57fe5b6000600160008d6001600160a01b03166001600160a01b0316815260200190815260200160002060009054906101000a90046001600160a01b03166001600160a01b031663916955868c8c8c8c8c6040518663ffffffff1660e01b8152600401808660ff1681526020018560ff16815260200184815260200183815260200182815260200195505050505050602060405180830381600087803b1580156117ae57600080fd5b505af11580156117c2573d6000803e3d6000fd5b505050506040513d60208110156117d857600080fd5b5051600054604080517fdd62ed3e0000000000000000000000000000000000000000000000000000000081523060048201526001600160a01b03928316602482015290519293508392918f169163dd62ed3e91604480820192602092909190829003018186803b15801561184b57600080fd5b505afa15801561185f573d6000803e3d6000fd5b505050506040513d602081101561187557600080fd5b5051101561189957600054611899906001600160a01b038e81169116600019611cf7565b60008054906101000a90046001600160a01b03166001600160a01b031663839ed90a8f8f8f858b8b8b8b6040518963ffffffff1660e01b815260040180896001600160a01b03168152602001888152602001876001600160a01b031681526020018681526020018560ff1681526020018460ff16815260200183815260200182815260200198505050505050505050600060405180830381600087803b15801561088d57600080fd5b6119576001600160a01b038316333084611e89565b6001600160a01b03821673fa7191d292d5633f702b0bd7e3e3bccc0e6332001415611bbd57604080517f280cf3ed000000000000000000000000000000000000000000000000000000008152731852f70512298d56e9c8fdd905e02581e04ddb2a600482015260248101839052905160009173fa7191d292d5633f702b0bd7e3e3bccc0e6332009163280cf3ed9160448082019260209290919082900301818787803b158015611a0657600080fd5b505af1158015611a1a573d6000803e3d6000fd5b505050506040513d6020811015611a3057600080fd5b5051600054604080517fdd62ed3e0000000000000000000000000000000000000000000000000000000081523060048201526001600160a01b039092166024830152519192508391731852f70512298d56e9c8fdd905e02581e04ddb2a9163dd62ed3e916044808301926020929190829003018186803b158015611ab357600080fd5b505afa158015611ac7573d6000803e3d6000fd5b505050506040513d6020811015611add57600080fd5b50511015611b1357600054611b1390731852f70512298d56e9c8fdd905e02581e04ddb2a906001600160a01b0316600019611cf7565b60008054604080517ff3f094a10000000000000000000000000000000000000000000000000000000081526001600160a01b03898116600483015260248201899052731852f70512298d56e9c8fdd905e02581e04ddb2a6044830152606482018690529151919092169263f3f094a1926084808201939182900301818387803b158015611b9f57600080fd5b505af1158015611bb3573d6000803e3d6000fd5b5050505050611cf1565b600054604080517fdd62ed3e0000000000000000000000000000000000000000000000000000000081523060048201526001600160a01b0392831660248201529051839285169163dd62ed3e916044808301926020929190829003018186803b158015611c2957600080fd5b505afa158015611c3d573d6000803e3d6000fd5b505050506040513d6020811015611c5357600080fd5b50511015611c7757600054611c77906001600160a01b038481169116600019611cf7565b60008054604080517ff3f094a10000000000000000000000000000000000000000000000000000000081526001600160a01b038881166004830152602482018890528681166044830152606482018690529151919092169263f3f094a1926084808201939182900301818387803b158015610bb357600080fd5b50505050565b801580611d965750604080517fdd62ed3e0000000000000000000000000000000000000000000000000000000081523060048201526001600160a01b03848116602483015291519185169163dd62ed3e91604480820192602092909190829003018186803b158015611d6857600080fd5b505afa158015611d7c573d6000803e3d6000fd5b505050506040513d6020811015611d9257600080fd5b5051155b611deb576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252603681526020018061229b6036913960400191505060405180910390fd5b604080516001600160a01b038416602482015260448082018490528251808303909101815260649091019091526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f095ea7b300000000000000000000000000000000000000000000000000000000179052611e6b908490611f0d565b505050565b6060611e7f8484600085611fd8565b90505b9392505050565b604080516001600160a01b0380861660248301528416604482015260648082018490528251808303909101815260849091019091526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f23b872dd00000000000000000000000000000000000000000000000000000000179052611cf19085905b6060611f62826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b0316611e709092919063ffffffff16565b805190915015611e6b57808060200190516020811015611f8157600080fd5b5051611e6b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602a815260200180612271602a913960400191505060405180910390fd5b606082471015612033576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602681526020018061224b6026913960400191505060405180910390fd5b61203c85612186565b6120a757604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000604482015290519081900360640190fd5b60006060866001600160a01b031685876040518082805190602001908083835b6020831061210457805182527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe090920191602091820191016120c7565b6001836020036101000a03801982511681845116808217855250505050505090500191505060006040518083038185875af1925050503d8060008114612166576040519150601f19603f3d011682016040523d82523d6000602084013e61216b565b606091505b509150915061217b82828661218c565b979650505050505050565b3b151590565b6060831561219b575081611e82565b8251156121ab5782518084602001fd5b816040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825283818151815260200191508051906020019080838360005b8381101561220f5781810151838201526020016121f7565b50505050905090810190601f16801561223c5780820380516001836020036101000a031916815260200191505b509250505060405180910390fdfe416464726573733a20696e73756666696369656e742062616c616e636520666f722063616c6c5361666545524332303a204552433230206f7065726174696f6e20646964206e6f7420737563636565645361666545524332303a20617070726f76652066726f6d206e6f6e2d7a65726f20746f206e6f6e2d7a65726f20616c6c6f77616e6365a2646970667358221220a7c0a1b9f1445fd326f087dc180e3d2d0c3f9219c2a4dc6e1e08988d218de59064736f6c634300060c0033416464726573733a20696e73756666696369656e742062616c616e636520666f722063616c6c73776170206d7573742068617665206174206c65617374203220746f6b656e735361666545524332303a204552433230206f7065726174696f6e20646964206e6f7420737563636565645361666545524332303a20617070726f76652066726f6d206e6f6e2d7a65726f20746f206e6f6e2d7a65726f20616c6c6f77616e6365", + "deployedBytecode": "0x6080604052600436106100d25760003560e01c806365749c9d1161007f57806385528f0b1161005957806385528f0b146103e857806390d250741461041b5780639f33072714610462578063f3f094a1146104e7576100d2565b806365749c9d146102c9578063798af72014610323578063839ed90a14610381576100d2565b8063393494b8116100b0578063393494b8146101e457806349b7cf841461021d5780634a517a5514610262576100d2565b8063040141e5146100d7578063174dc9521461010857806336e712ed14610188575b600080fd5b3480156100e357600080fd5b506100ec61052e565b604080516001600160a01b039092168252519081900360200190f35b34801561011457600080fd5b50610186600480360361016081101561012c57600080fd5b506001600160a01b0381358116916020810135916040820135169060ff6060820135811691608081013582169160a08201359160c08101359160e08201359161010081013590911690610120810135906101400135610552565b005b34801561019457600080fd5b50610186600480360360e08110156101ab57600080fd5b506001600160a01b0381358116916020810135916040820135169060608101359060ff6080820135169060a08101359060c001356108b5565b3480156101f057600080fd5b506100ec6004803603604081101561020757600080fd5b506001600160a01b038135169060200135610a36565b34801561022957600080fd5b506101866004803603608081101561024057600080fd5b508035906020810135906001600160a01b036040820135169060600135610a6b565b34801561026e57600080fd5b50610186600480360361010081101561028657600080fd5b506001600160a01b0381358116916020810135916040820135169060ff606082013581169160808101359091169060a08101359060c08101359060e00135610bd1565b61018660048036036101008110156102e057600080fd5b506001600160a01b0381358116916020810135916040820135169060ff606082013581169160808101359091169060a08101359060c08101359060e00135610eec565b34801561032f57600080fd5b5061036f6004803603608081101561034657600080fd5b506001600160a01b038135169060ff602082013581169160408101359091169060600135611246565b60408051918252519081900360200190f35b34801561038d57600080fd5b5061018660048036036101008110156103a557600080fd5b506001600160a01b0381358116916020810135916040820135169060608101359060ff608082013581169160a08101359091169060c08101359060e001356112ff565b3480156103f457600080fd5b506100ec6004803603602081101561040b57600080fd5b50356001600160a01b031661148a565b34801561042757600080fd5b506101866004803603608081101561043e57600080fd5b506001600160a01b03813581169160208101359160408201351690606001356114a5565b34801561046e57600080fd5b50610186600480360361018081101561048657600080fd5b506001600160a01b0381358116916020810135916040820135169060ff6060820135811691608081013582169160a08201359160c08101359160e08201359161010081013582169161012082013516906101408101359061016001356115ee565b3480156104f357600080fd5b506101866004803603608081101561050a57600080fd5b506001600160a01b0381358116916020810135916040820135169060600135611942565b7f000000000000000000000000000000000000000000000000000000000000000081565b6001600160a01b03808a1660009081526001602052604090205416806105d957604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f5377617020697320307830300000000000000000000000000000000000000000604482015290519081900360640190fd5b6001600160a01b03811660009081526002602090815260409182902080548351818402810184019094528084526060939283018282801561064357602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311610625575b5050505050905061068033308a848e60ff168151811061065f57fe5b60200260200101516001600160a01b0316611e89909392919063ffffffff16565b604080517f9169558600000000000000000000000000000000000000000000000000000000815260ff808d1660048301528b166024820152604481018a9052606481018990526084810188905290516000916001600160a01b0385169163916955869160a48082019260209290919082900301818787803b15801561070457600080fd5b505af1158015610718573d6000803e3d6000fd5b505050506040513d602081101561072e57600080fd5b5051600054604080517fdd62ed3e0000000000000000000000000000000000000000000000000000000081523060048201526001600160a01b03928316602482015290519293508392918f169163dd62ed3e91604480820192602092909190829003018186803b1580156107a157600080fd5b505afa1580156107b5573d6000803e3d6000fd5b505050506040513d60208110156107cb57600080fd5b505110156107ef576000546107ef906001600160a01b038e81169116600019611cf7565b60008054906101000a90046001600160a01b03166001600160a01b03166336e712ed8f8f8f858b8b8b6040518863ffffffff1660e01b815260040180886001600160a01b03168152602001878152602001866001600160a01b031681526020018581526020018460ff168152602001838152602001828152602001975050505050505050600060405180830381600087803b15801561088d57600080fd5b505af11580156108a1573d6000803e3d6000fd5b505050505050505050505050505050505050565b6108ca6001600160a01b038616333087611e89565b600054604080517fdd62ed3e0000000000000000000000000000000000000000000000000000000081523060048201526001600160a01b0392831660248201529051869288169163dd62ed3e916044808301926020929190829003018186803b15801561093657600080fd5b505afa15801561094a573d6000803e3d6000fd5b505050506040513d602081101561096057600080fd5b5051101561098457600054610984906001600160a01b038781169116600019611cf7565b60008054604080517f36e712ed0000000000000000000000000000000000000000000000000000000081526001600160a01b038b81166004830152602482018b905289811660448301526064820189905260ff8816608483015260a4820187905260c48201869052915191909216926336e712ed9260e4808201939182900301818387803b158015610a1557600080fd5b505af1158015610a29573d6000803e3d6000fd5b5050505050505050505050565b60026020528160005260406000208181548110610a4f57fe5b6000918252602090912001546001600160a01b03169150829050565b610a806001600160a01b038316333084611e89565b600054604080517fdd62ed3e0000000000000000000000000000000000000000000000000000000081523060048201526001600160a01b0392831660248201529051839285169163dd62ed3e916044808301926020929190829003018186803b158015610aec57600080fd5b505afa158015610b00573d6000803e3d6000fd5b505050506040513d6020811015610b1657600080fd5b50511015610b3a57600054610b3a906001600160a01b038481169116600019611cf7565b60008054604080517f49b7cf8400000000000000000000000000000000000000000000000000000000815260048101889052602481018790526001600160a01b03868116604483015260648201869052915191909216926349b7cf84926084808201939182900301818387803b158015610bb357600080fd5b505af1158015610bc7573d6000803e3d6000fd5b5050505050505050565b6001600160a01b038087166000908152600160205260409020541680610c5857604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f5377617020697320307830300000000000000000000000000000000000000000604482015290519081900360640190fd5b6001600160a01b038116600090815260026020908152604091829020805483518184028101840190945280845260609392830182828015610cc257602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311610ca4575b50505050509050610cde333087848b60ff168151811061065f57fe5b604080517f9169558600000000000000000000000000000000000000000000000000000000815260ff808a1660048301528816602482015260448101879052606481018690526084810185905290516000916001600160a01b0385169163916955869160a48082019260209290919082900301818787803b158015610d6257600080fd5b505af1158015610d76573d6000803e3d6000fd5b505050506040513d6020811015610d8c57600080fd5b5051600054604080517fdd62ed3e0000000000000000000000000000000000000000000000000000000081523060048201526001600160a01b03928316602482015290519293508392918c169163dd62ed3e91604480820192602092909190829003018186803b158015610dff57600080fd5b505afa158015610e13573d6000803e3d6000fd5b505050506040513d6020811015610e2957600080fd5b50511015610e4d57600054610e4d906001600160a01b038b81169116600019611cf7565b60008054604080517ff3f094a10000000000000000000000000000000000000000000000000000000081526001600160a01b038f81166004830152602482018f90528d81166044830152606482018690529151919092169263f3f094a1926084808201939182900301818387803b158015610ec757600080fd5b505af1158015610edb573d6000803e3d6000fd5b505050505050505050505050505050565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316610f8157604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600660248201527f5745544820300000000000000000000000000000000000000000000000000000604482015290519081900360640190fd5b600034118015610f9057508234145b610ffb57604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f494e434f5252454354204d53472056414c554500000000000000000000000000604482015290519081900360640190fd5b6001600160a01b03808716600090815260016020526040902054168061108257604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f5377617020697320307830300000000000000000000000000000000000000000604482015290519081900360640190fd5b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663d0e30db0346040518263ffffffff1660e01b81526004016000604051808303818588803b1580156110dd57600080fd5b505af11580156110f1573d6000803e3d6000fd5b5050604080517f9169558600000000000000000000000000000000000000000000000000000000815260ff808c1660048301528a1660248201526044810189905260648101889052608481018790529051600094506001600160a01b03861693506391695586925060a480830192602092919082900301818787803b15801561117957600080fd5b505af115801561118d573d6000803e3d6000fd5b505050506040513d60208110156111a357600080fd5b505160008054604080517ff3f094a10000000000000000000000000000000000000000000000000000000081526001600160a01b038f81166004830152602482018f90528d8116604483015260648201869052915194955091169263f3f094a19260848084019391929182900301818387803b15801561122257600080fd5b505af1158015611236573d6000803e3d6000fd5b5050505050505050505050505050565b6001600160a01b0380851660009081526001602090815260408083205481517fa95b089f00000000000000000000000000000000000000000000000000000000815260ff808a1660048301528816602482015260448101879052915193941692839263a95b089f9260648082019391829003018186803b1580156112c957600080fd5b505afa1580156112dd573d6000803e3d6000fd5b505050506040513d60208110156112f357600080fd5b50519695505050505050565b6113146001600160a01b038716333088611e89565b600054604080517fdd62ed3e0000000000000000000000000000000000000000000000000000000081523060048201526001600160a01b0392831660248201529051879289169163dd62ed3e916044808301926020929190829003018186803b15801561138057600080fd5b505afa158015611394573d6000803e3d6000fd5b505050506040513d60208110156113aa57600080fd5b505110156113ce576000546113ce906001600160a01b038881169116600019611cf7565b60008054604080517f839ed90a0000000000000000000000000000000000000000000000000000000081526001600160a01b038c81166004830152602482018c90528a81166044830152606482018a905260ff808a166084840152881660a483015260c4820187905260e482018690529151919092169263839ed90a92610104808201939182900301818387803b15801561146857600080fd5b505af115801561147c573d6000803e3d6000fd5b505050505050505050505050565b6001602052600090815260409020546001600160a01b031681565b6114ba6001600160a01b038316333084611e89565b600054604080517fdd62ed3e0000000000000000000000000000000000000000000000000000000081523060048201526001600160a01b0392831660248201529051839285169163dd62ed3e916044808301926020929190829003018186803b15801561152657600080fd5b505afa15801561153a573d6000803e3d6000fd5b505050506040513d602081101561155057600080fd5b5051101561157457600054611574906001600160a01b038481169116600019611cf7565b60008054604080517f90d250740000000000000000000000000000000000000000000000000000000081526001600160a01b03888116600483015260248201889052868116604483015260648201869052915191909216926390d25074926084808201939182900301818387803b158015610bb357600080fd5b6001600160a01b038a81166000908152600160205260409020541661167457604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f5377617020697320307830300000000000000000000000000000000000000000604482015290519081900360640190fd5b6001600160a01b03808b16600090815260016020908152604080832054909316825260028152908290208054835181840281018401909452808452606093928301828280156116ec57602002820191906000526020600020905b81546001600160a01b031681526001909101906020018083116116ce575b5050505050905061170833308a848e60ff168151811061065f57fe5b6000600160008d6001600160a01b03166001600160a01b0316815260200190815260200160002060009054906101000a90046001600160a01b03166001600160a01b031663916955868c8c8c8c8c6040518663ffffffff1660e01b8152600401808660ff1681526020018560ff16815260200184815260200183815260200182815260200195505050505050602060405180830381600087803b1580156117ae57600080fd5b505af11580156117c2573d6000803e3d6000fd5b505050506040513d60208110156117d857600080fd5b5051600054604080517fdd62ed3e0000000000000000000000000000000000000000000000000000000081523060048201526001600160a01b03928316602482015290519293508392918f169163dd62ed3e91604480820192602092909190829003018186803b15801561184b57600080fd5b505afa15801561185f573d6000803e3d6000fd5b505050506040513d602081101561187557600080fd5b5051101561189957600054611899906001600160a01b038e81169116600019611cf7565b60008054906101000a90046001600160a01b03166001600160a01b031663839ed90a8f8f8f858b8b8b8b6040518963ffffffff1660e01b815260040180896001600160a01b03168152602001888152602001876001600160a01b031681526020018681526020018560ff1681526020018460ff16815260200183815260200182815260200198505050505050505050600060405180830381600087803b15801561088d57600080fd5b6119576001600160a01b038316333084611e89565b6001600160a01b03821673fa7191d292d5633f702b0bd7e3e3bccc0e6332001415611bbd57604080517f280cf3ed000000000000000000000000000000000000000000000000000000008152731852f70512298d56e9c8fdd905e02581e04ddb2a600482015260248101839052905160009173fa7191d292d5633f702b0bd7e3e3bccc0e6332009163280cf3ed9160448082019260209290919082900301818787803b158015611a0657600080fd5b505af1158015611a1a573d6000803e3d6000fd5b505050506040513d6020811015611a3057600080fd5b5051600054604080517fdd62ed3e0000000000000000000000000000000000000000000000000000000081523060048201526001600160a01b039092166024830152519192508391731852f70512298d56e9c8fdd905e02581e04ddb2a9163dd62ed3e916044808301926020929190829003018186803b158015611ab357600080fd5b505afa158015611ac7573d6000803e3d6000fd5b505050506040513d6020811015611add57600080fd5b50511015611b1357600054611b1390731852f70512298d56e9c8fdd905e02581e04ddb2a906001600160a01b0316600019611cf7565b60008054604080517ff3f094a10000000000000000000000000000000000000000000000000000000081526001600160a01b03898116600483015260248201899052731852f70512298d56e9c8fdd905e02581e04ddb2a6044830152606482018690529151919092169263f3f094a1926084808201939182900301818387803b158015611b9f57600080fd5b505af1158015611bb3573d6000803e3d6000fd5b5050505050611cf1565b600054604080517fdd62ed3e0000000000000000000000000000000000000000000000000000000081523060048201526001600160a01b0392831660248201529051839285169163dd62ed3e916044808301926020929190829003018186803b158015611c2957600080fd5b505afa158015611c3d573d6000803e3d6000fd5b505050506040513d6020811015611c5357600080fd5b50511015611c7757600054611c77906001600160a01b038481169116600019611cf7565b60008054604080517ff3f094a10000000000000000000000000000000000000000000000000000000081526001600160a01b038881166004830152602482018890528681166044830152606482018690529151919092169263f3f094a1926084808201939182900301818387803b158015610bb357600080fd5b50505050565b801580611d965750604080517fdd62ed3e0000000000000000000000000000000000000000000000000000000081523060048201526001600160a01b03848116602483015291519185169163dd62ed3e91604480820192602092909190829003018186803b158015611d6857600080fd5b505afa158015611d7c573d6000803e3d6000fd5b505050506040513d6020811015611d9257600080fd5b5051155b611deb576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252603681526020018061229b6036913960400191505060405180910390fd5b604080516001600160a01b038416602482015260448082018490528251808303909101815260649091019091526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f095ea7b300000000000000000000000000000000000000000000000000000000179052611e6b908490611f0d565b505050565b6060611e7f8484600085611fd8565b90505b9392505050565b604080516001600160a01b0380861660248301528416604482015260648082018490528251808303909101815260849091019091526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f23b872dd00000000000000000000000000000000000000000000000000000000179052611cf19085905b6060611f62826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b0316611e709092919063ffffffff16565b805190915015611e6b57808060200190516020811015611f8157600080fd5b5051611e6b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602a815260200180612271602a913960400191505060405180910390fd5b606082471015612033576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602681526020018061224b6026913960400191505060405180910390fd5b61203c85612186565b6120a757604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000604482015290519081900360640190fd5b60006060866001600160a01b031685876040518082805190602001908083835b6020831061210457805182527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe090920191602091820191016120c7565b6001836020036101000a03801982511681845116808217855250505050505090500191505060006040518083038185875af1925050503d8060008114612166576040519150601f19603f3d011682016040523d82523d6000602084013e61216b565b606091505b509150915061217b82828661218c565b979650505050505050565b3b151590565b6060831561219b575081611e82565b8251156121ab5782518084602001fd5b816040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825283818151815260200191508051906020019080838360005b8381101561220f5781810151838201526020016121f7565b50505050905090810190601f16801561223c5780820380516001836020036101000a031916815260200191505b509250505060405180910390fdfe416464726573733a20696e73756666696369656e742062616c616e636520666f722063616c6c5361666545524332303a204552433230206f7065726174696f6e20646964206e6f7420737563636565645361666545524332303a20617070726f76652066726f6d206e6f6e2d7a65726f20746f206e6f6e2d7a65726f20616c6c6f77616e6365a2646970667358221220a7c0a1b9f1445fd326f087dc180e3d2d0c3f9219c2a4dc6e1e08988d218de59064736f6c634300060c0033", "devdoc": { "kind": "dev", "methods": { diff --git a/deployments/harmony/multiAVAX.json b/deployments/harmony/multiAVAX.json new file mode 100644 index 000000000..bb7aef1b2 --- /dev/null +++ b/deployments/harmony/multiAVAX.json @@ -0,0 +1,226 @@ +{ + "abi": [ + { + "constant": true, + "inputs": [], + "name": "name", + "outputs": [ + { + "name": "", + "type": "string" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "name": "_spender", + "type": "address" + }, + { + "name": "_value", + "type": "uint256" + } + ], + "name": "approve", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "totalSupply", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "name": "_from", + "type": "address" + }, + { + "name": "_to", + "type": "address" + }, + { + "name": "_value", + "type": "uint256" + } + ], + "name": "transferFrom", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "decimals", + "outputs": [ + { + "name": "", + "type": "uint8" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "name": "_owner", + "type": "address" + } + ], + "name": "balanceOf", + "outputs": [ + { + "name": "balance", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "symbol", + "outputs": [ + { + "name": "", + "type": "string" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "name": "_to", + "type": "address" + }, + { + "name": "_value", + "type": "uint256" + } + ], + "name": "transfer", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "name": "_owner", + "type": "address" + }, + { + "name": "_spender", + "type": "address" + } + ], + "name": "allowance", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "payable": true, + "stateMutability": "payable", + "type": "fallback" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "name": "spender", + "type": "address" + }, + { + "indexed": false, + "name": "value", + "type": "uint256" + } + ], + "name": "Approval", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "name": "from", + "type": "address" + }, + { + "indexed": true, + "name": "to", + "type": "address" + }, + { + "indexed": false, + "name": "value", + "type": "uint256" + } + ], + "name": "Transfer", + "type": "event" + } + ], + "address": "0xb12c13e66ade1f72f71834f2fc5082db8c091358" + } + \ No newline at end of file diff --git a/deployments/harmony/solcInputs/a0c105fd41656175868de59f7c100fca.json b/deployments/harmony/solcInputs/a0c105fd41656175868de59f7c100fca.json new file mode 100644 index 000000000..a50a35dfc --- /dev/null +++ b/deployments/harmony/solcInputs/a0c105fd41656175868de59f7c100fca.json @@ -0,0 +1,304 @@ +{ + "language": "Solidity", + "sources": { + "contracts/amm/AaveSwap.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.6.12;\n\nimport \"./Swap.sol\";\n\n/**\n * @title AaveSwap - A StableSwap implementation in solidity, integrated with Aave.\n * @notice This contract is responsible for custody of closely pegged assets (eg. group of stablecoins)\n * and automatic market making system. Users become an LP (Liquidity Provider) by depositing their tokens\n * in desired ratios for an exchange of the pool token that represents their share of the pool.\n * Users can burn pool tokens and withdraw their share of token(s).\n *\n * Each time a swap between the pooled tokens happens, a set fee incurs which effectively gets\n * distributed to the LPs.\n *\n * In case of emergencies, admin can pause additional deposits, swaps, or single-asset withdraws - which\n * stops the ratio of the tokens in the pool from changing.\n * Users can always withdraw their tokens via multi-asset withdraws.\n *\n * @dev Most of the logic is stored as a library `SwapUtils` for the sake of reducing contract's\n * deployment size.\n */\n\ncontract AaveSwap is Swap {\n address internal AAVE_REWARDS;\n address internal AAVE_LENDING_POOL;\n address internal REWARD_TOKEN;\n address internal REWARD_RECEIVER;\n address[] internal AAVE_ASSETS;\n\n /**\n * @notice Initializes this Swap contract with the given parameters.\n * This will also clone a LPToken contract that represents users'\n * LP positions. The owner of LPToken will be this contract - which means\n * only this contract is allowed to mint/burn tokens.\n *\n * @param _pooledTokens an array of ERC20s this pool will accept\n * @param decimals the decimals to use for each pooled token,\n * eg 8 for WBTC. Cannot be larger than POOL_PRECISION_DECIMALS\n * @param lpTokenName the long-form name of the token to be deployed\n * @param lpTokenSymbol the short symbol for the token to be deployed\n * @param _a the amplification coefficient * n * (n - 1). See the\n * StableSwap paper for details\n * @param _fee default swap fee to be initialized with\n * @param _adminFee default adminFee to be initialized with\n * @param lpTokenTargetAddress the address of an existing LPToken contract to use as a target\n */\n function initialize(\n IERC20[] memory _pooledTokens,\n uint8[] memory decimals,\n string memory lpTokenName,\n string memory lpTokenSymbol,\n uint256 _a,\n uint256 _fee,\n uint256 _adminFee,\n address lpTokenTargetAddress\n ) public virtual override initializer {\n Swap.initialize(\n _pooledTokens,\n decimals,\n lpTokenName,\n lpTokenSymbol,\n _a,\n _fee,\n _adminFee,\n lpTokenTargetAddress\n );\n AAVE_REWARDS = 0x01D83Fe6A10D2f2B7AF17034343746188272cAc9;\n AAVE_LENDING_POOL = 0x4F01AeD16D97E3aB5ab2B501154DC9bb0F1A5A2C;\n REWARD_TOKEN = 0xB31f66AA3C1e785363F0875A1B74E27b85FD66c7;\n AAVE_ASSETS = [0x53f7c5869a859F0AeC3D334ee8B4Cf01E3492f21];\n REWARD_RECEIVER = msg.sender;\n }\n\n function setRewardReceiver(address _reward_receiver) external onlyOwner {\n REWARD_RECEIVER = _reward_receiver;\n }\n\n function claimAaveRewards() external {\n AAVE_REWARDS.call(\n abi.encodeWithSignature(\n \"claimRewards(address[],uint256,address)\",\n AAVE_ASSETS,\n type(uint256).max,\n REWARD_RECEIVER\n )\n );\n }\n}\n" + }, + "contracts/amm/Swap.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.6.12;\n\nimport \"@openzeppelin/contracts/math/SafeMath.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/SafeERC20.sol\";\nimport \"@openzeppelin/contracts/proxy/Clones.sol\";\nimport \"@openzeppelin/contracts-upgradeable/utils/ReentrancyGuardUpgradeable.sol\";\nimport \"./OwnerPausableUpgradeable.sol\";\nimport \"./SwapUtils.sol\";\nimport \"./AmplificationUtils.sol\";\n\n/**\n * @title Swap - A StableSwap implementation in solidity.\n * @notice This contract is responsible for custody of closely pegged assets (eg. group of stablecoins)\n * and automatic market making system. Users become an LP (Liquidity Provider) by depositing their tokens\n * in desired ratios for an exchange of the pool token that represents their share of the pool.\n * Users can burn pool tokens and withdraw their share of token(s).\n *\n * Each time a swap between the pooled tokens happens, a set fee incurs which effectively gets\n * distributed to the LPs.\n *\n * In case of emergencies, admin can pause additional deposits, swaps, or single-asset withdraws - which\n * stops the ratio of the tokens in the pool from changing.\n * Users can always withdraw their tokens via multi-asset withdraws.\n *\n * @dev Most of the logic is stored as a library `SwapUtils` for the sake of reducing contract's\n * deployment size.\n */\ncontract Swap is OwnerPausableUpgradeable, ReentrancyGuardUpgradeable {\n using SafeERC20 for IERC20;\n using SafeMath for uint256;\n using SwapUtils for SwapUtils.Swap;\n using AmplificationUtils for SwapUtils.Swap;\n\n // Struct storing data responsible for automatic market maker functionalities. In order to\n // access this data, this contract uses SwapUtils library. For more details, see SwapUtils.sol\n SwapUtils.Swap public swapStorage;\n\n // Maps token address to an index in the pool. Used to prevent duplicate tokens in the pool.\n // getTokenIndex function also relies on this mapping to retrieve token index.\n mapping(address => uint8) private tokenIndexes;\n\n /*** EVENTS ***/\n\n // events replicated from SwapUtils to make the ABI easier for dumb\n // clients\n event TokenSwap(\n address indexed buyer,\n uint256 tokensSold,\n uint256 tokensBought,\n uint128 soldId,\n uint128 boughtId\n );\n event AddLiquidity(\n address indexed provider,\n uint256[] tokenAmounts,\n uint256[] fees,\n uint256 invariant,\n uint256 lpTokenSupply\n );\n event RemoveLiquidity(\n address indexed provider,\n uint256[] tokenAmounts,\n uint256 lpTokenSupply\n );\n event RemoveLiquidityOne(\n address indexed provider,\n uint256 lpTokenAmount,\n uint256 lpTokenSupply,\n uint256 boughtId,\n uint256 tokensBought\n );\n event RemoveLiquidityImbalance(\n address indexed provider,\n uint256[] tokenAmounts,\n uint256[] fees,\n uint256 invariant,\n uint256 lpTokenSupply\n );\n event NewAdminFee(uint256 newAdminFee);\n event NewSwapFee(uint256 newSwapFee);\n event RampA(\n uint256 oldA,\n uint256 newA,\n uint256 initialTime,\n uint256 futureTime\n );\n event StopRampA(uint256 currentA, uint256 time);\n\n /**\n * @notice Initializes this Swap contract with the given parameters.\n * This will also clone a LPToken contract that represents users'\n * LP positions. The owner of LPToken will be this contract - which means\n * only this contract is allowed to mint/burn tokens.\n *\n * @param _pooledTokens an array of ERC20s this pool will accept\n * @param decimals the decimals to use for each pooled token,\n * eg 8 for WBTC. Cannot be larger than POOL_PRECISION_DECIMALS\n * @param lpTokenName the long-form name of the token to be deployed\n * @param lpTokenSymbol the short symbol for the token to be deployed\n * @param _a the amplification coefficient * n * (n - 1). See the\n * StableSwap paper for details\n * @param _fee default swap fee to be initialized with\n * @param _adminFee default adminFee to be initialized with\n * @param lpTokenTargetAddress the address of an existing LPToken contract to use as a target\n */\n function initialize(\n IERC20[] memory _pooledTokens,\n uint8[] memory decimals,\n string memory lpTokenName,\n string memory lpTokenSymbol,\n uint256 _a,\n uint256 _fee,\n uint256 _adminFee,\n address lpTokenTargetAddress\n ) public virtual initializer {\n __OwnerPausable_init();\n __ReentrancyGuard_init();\n // Check _pooledTokens and precisions parameter\n require(_pooledTokens.length > 1, \"_pooledTokens.length <= 1\");\n require(_pooledTokens.length <= 32, \"_pooledTokens.length > 32\");\n require(\n _pooledTokens.length == decimals.length,\n \"_pooledTokens decimals mismatch\"\n );\n\n uint256[] memory precisionMultipliers = new uint256[](decimals.length);\n\n for (uint8 i = 0; i < _pooledTokens.length; i++) {\n if (i > 0) {\n // Check if index is already used. Check if 0th element is a duplicate.\n require(\n tokenIndexes[address(_pooledTokens[i])] == 0 &&\n _pooledTokens[0] != _pooledTokens[i],\n \"Duplicate tokens\"\n );\n }\n require(\n address(_pooledTokens[i]) != address(0),\n \"The 0 address isn't an ERC-20\"\n );\n require(\n decimals[i] <= SwapUtils.POOL_PRECISION_DECIMALS,\n \"Token decimals exceeds max\"\n );\n precisionMultipliers[i] =\n 10 **\n uint256(SwapUtils.POOL_PRECISION_DECIMALS).sub(\n uint256(decimals[i])\n );\n tokenIndexes[address(_pooledTokens[i])] = i;\n }\n\n // Check _a, _fee, _adminFee parameters\n require(_a < AmplificationUtils.MAX_A, \"_a exceeds maximum\");\n require(_fee < SwapUtils.MAX_SWAP_FEE, \"_fee exceeds maximum\");\n require(\n _adminFee < SwapUtils.MAX_ADMIN_FEE,\n \"_adminFee exceeds maximum\"\n );\n\n // Clone and initialize a LPToken contract\n LPToken lpToken = LPToken(Clones.clone(lpTokenTargetAddress));\n require(\n lpToken.initialize(lpTokenName, lpTokenSymbol),\n \"could not init lpToken clone\"\n );\n\n // Initialize swapStorage struct\n swapStorage.lpToken = lpToken;\n swapStorage.pooledTokens = _pooledTokens;\n swapStorage.tokenPrecisionMultipliers = precisionMultipliers;\n swapStorage.balances = new uint256[](_pooledTokens.length);\n swapStorage.initialA = _a.mul(AmplificationUtils.A_PRECISION);\n swapStorage.futureA = _a.mul(AmplificationUtils.A_PRECISION);\n // swapStorage.initialATime = 0;\n // swapStorage.futureATime = 0;\n swapStorage.swapFee = _fee;\n swapStorage.adminFee = _adminFee;\n }\n\n /*** MODIFIERS ***/\n\n /**\n * @notice Modifier to check deadline against current timestamp\n * @param deadline latest timestamp to accept this transaction\n */\n modifier deadlineCheck(uint256 deadline) {\n require(block.timestamp <= deadline, \"Deadline not met\");\n _;\n }\n\n /*** VIEW FUNCTIONS ***/\n\n /**\n * @notice Return A, the amplification coefficient * n * (n - 1)\n * @dev See the StableSwap paper for details\n * @return A parameter\n */\n function getA() external view virtual returns (uint256) {\n return swapStorage.getA();\n }\n\n /**\n * @notice Return A in its raw precision form\n * @dev See the StableSwap paper for details\n * @return A parameter in its raw precision form\n */\n function getAPrecise() external view virtual returns (uint256) {\n return swapStorage.getAPrecise();\n }\n\n /**\n * @notice Return address of the pooled token at given index. Reverts if tokenIndex is out of range.\n * @param index the index of the token\n * @return address of the token at given index\n */\n function getToken(uint8 index) public view virtual returns (IERC20) {\n require(index < swapStorage.pooledTokens.length, \"Out of range\");\n return swapStorage.pooledTokens[index];\n }\n\n /**\n * @notice Return the index of the given token address. Reverts if no matching\n * token is found.\n * @param tokenAddress address of the token\n * @return the index of the given token address\n */\n function getTokenIndex(address tokenAddress)\n public\n view\n virtual\n returns (uint8)\n {\n uint8 index = tokenIndexes[tokenAddress];\n require(\n address(getToken(index)) == tokenAddress,\n \"Token does not exist\"\n );\n return index;\n }\n\n /**\n * @notice Return current balance of the pooled token at given index\n * @param index the index of the token\n * @return current balance of the pooled token at given index with token's native precision\n */\n function getTokenBalance(uint8 index)\n external\n view\n virtual\n returns (uint256)\n {\n require(index < swapStorage.pooledTokens.length, \"Index out of range\");\n return swapStorage.balances[index];\n }\n\n /**\n * @notice Get the virtual price, to help calculate profit\n * @return the virtual price, scaled to the POOL_PRECISION_DECIMALS\n */\n function getVirtualPrice() external view virtual returns (uint256) {\n return swapStorage.getVirtualPrice();\n }\n\n /**\n * @notice Calculate amount of tokens you receive on swap\n * @param tokenIndexFrom the token the user wants to sell\n * @param tokenIndexTo the token the user wants to buy\n * @param dx the amount of tokens the user wants to sell. If the token charges\n * a fee on transfers, use the amount that gets transferred after the fee.\n * @return amount of tokens the user will receive\n */\n function calculateSwap(\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx\n ) external view virtual returns (uint256) {\n return swapStorage.calculateSwap(tokenIndexFrom, tokenIndexTo, dx);\n }\n\n /**\n * @notice A simple method to calculate prices from deposits or\n * withdrawals, excluding fees but including slippage. This is\n * helpful as an input into the various \"min\" parameters on calls\n * to fight front-running\n *\n * @dev This shouldn't be used outside frontends for user estimates.\n *\n * @param amounts an array of token amounts to deposit or withdrawal,\n * corresponding to pooledTokens. The amount should be in each\n * pooled token's native precision. If a token charges a fee on transfers,\n * use the amount that gets transferred after the fee.\n * @param deposit whether this is a deposit or a withdrawal\n * @return token amount the user will receive\n */\n function calculateTokenAmount(uint256[] calldata amounts, bool deposit)\n external\n view\n virtual\n returns (uint256)\n {\n return swapStorage.calculateTokenAmount(amounts, deposit);\n }\n\n /**\n * @notice A simple method to calculate amount of each underlying\n * tokens that is returned upon burning given amount of LP tokens\n * @param amount the amount of LP tokens that would be burned on withdrawal\n * @return array of token balances that the user will receive\n */\n function calculateRemoveLiquidity(uint256 amount)\n external\n view\n virtual\n returns (uint256[] memory)\n {\n return swapStorage.calculateRemoveLiquidity(amount);\n }\n\n /**\n * @notice Calculate the amount of underlying token available to withdraw\n * when withdrawing via only single token\n * @param tokenAmount the amount of LP token to burn\n * @param tokenIndex index of which token will be withdrawn\n * @return availableTokenAmount calculated amount of underlying token\n * available to withdraw\n */\n function calculateRemoveLiquidityOneToken(\n uint256 tokenAmount,\n uint8 tokenIndex\n ) external view virtual returns (uint256 availableTokenAmount) {\n return swapStorage.calculateWithdrawOneToken(tokenAmount, tokenIndex);\n }\n\n /**\n * @notice This function reads the accumulated amount of admin fees of the token with given index\n * @param index Index of the pooled token\n * @return admin's token balance in the token's precision\n */\n function getAdminBalance(uint256 index)\n external\n view\n virtual\n returns (uint256)\n {\n return swapStorage.getAdminBalance(index);\n }\n\n /*** STATE MODIFYING FUNCTIONS ***/\n\n /**\n * @notice Swap two tokens using this pool\n * @param tokenIndexFrom the token the user wants to swap from\n * @param tokenIndexTo the token the user wants to swap to\n * @param dx the amount of tokens the user wants to swap from\n * @param minDy the min amount the user would like to receive, or revert.\n * @param deadline latest timestamp to accept this transaction\n */\n function swap(\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx,\n uint256 minDy,\n uint256 deadline\n )\n external\n virtual\n nonReentrant\n whenNotPaused\n deadlineCheck(deadline)\n returns (uint256)\n {\n return swapStorage.swap(tokenIndexFrom, tokenIndexTo, dx, minDy);\n }\n\n /**\n * @notice Add liquidity to the pool with the given amounts of tokens\n * @param amounts the amounts of each token to add, in their native precision\n * @param minToMint the minimum LP tokens adding this amount of liquidity\n * should mint, otherwise revert. Handy for front-running mitigation\n * @param deadline latest timestamp to accept this transaction\n * @return amount of LP token user minted and received\n */\n function addLiquidity(\n uint256[] calldata amounts,\n uint256 minToMint,\n uint256 deadline\n )\n external\n virtual\n nonReentrant\n whenNotPaused\n deadlineCheck(deadline)\n returns (uint256)\n {\n return swapStorage.addLiquidity(amounts, minToMint);\n }\n\n /**\n * @notice Burn LP tokens to remove liquidity from the pool. Withdraw fee that decays linearly\n * over period of 4 weeks since last deposit will apply.\n * @dev Liquidity can always be removed, even when the pool is paused.\n * @param amount the amount of LP tokens to burn\n * @param minAmounts the minimum amounts of each token in the pool\n * acceptable for this burn. Useful as a front-running mitigation\n * @param deadline latest timestamp to accept this transaction\n * @return amounts of tokens user received\n */\n function removeLiquidity(\n uint256 amount,\n uint256[] calldata minAmounts,\n uint256 deadline\n )\n external\n virtual\n nonReentrant\n deadlineCheck(deadline)\n returns (uint256[] memory)\n {\n return swapStorage.removeLiquidity(amount, minAmounts);\n }\n\n /**\n * @notice Remove liquidity from the pool all in one token. Withdraw fee that decays linearly\n * over period of 4 weeks since last deposit will apply.\n * @param tokenAmount the amount of the token you want to receive\n * @param tokenIndex the index of the token you want to receive\n * @param minAmount the minimum amount to withdraw, otherwise revert\n * @param deadline latest timestamp to accept this transaction\n * @return amount of chosen token user received\n */\n function removeLiquidityOneToken(\n uint256 tokenAmount,\n uint8 tokenIndex,\n uint256 minAmount,\n uint256 deadline\n )\n external\n virtual\n nonReentrant\n whenNotPaused\n deadlineCheck(deadline)\n returns (uint256)\n {\n return\n swapStorage.removeLiquidityOneToken(\n tokenAmount,\n tokenIndex,\n minAmount\n );\n }\n\n /**\n * @notice Remove liquidity from the pool, weighted differently than the\n * pool's current balances. Withdraw fee that decays linearly\n * over period of 4 weeks since last deposit will apply.\n * @param amounts how much of each token to withdraw\n * @param maxBurnAmount the max LP token provider is willing to pay to\n * remove liquidity. Useful as a front-running mitigation.\n * @param deadline latest timestamp to accept this transaction\n * @return amount of LP tokens burned\n */\n function removeLiquidityImbalance(\n uint256[] calldata amounts,\n uint256 maxBurnAmount,\n uint256 deadline\n )\n external\n virtual\n nonReentrant\n whenNotPaused\n deadlineCheck(deadline)\n returns (uint256)\n {\n return swapStorage.removeLiquidityImbalance(amounts, maxBurnAmount);\n }\n\n /*** ADMIN FUNCTIONS ***/\n\n /**\n * @notice Withdraw all admin fees to the contract owner\n */\n function withdrawAdminFees() external onlyOwner {\n swapStorage.withdrawAdminFees(owner());\n }\n\n /**\n * @notice Update the admin fee. Admin fee takes portion of the swap fee.\n * @param newAdminFee new admin fee to be applied on future transactions\n */\n function setAdminFee(uint256 newAdminFee) external onlyOwner {\n swapStorage.setAdminFee(newAdminFee);\n }\n\n /**\n * @notice Update the swap fee to be applied on swaps\n * @param newSwapFee new swap fee to be applied on future transactions\n */\n function setSwapFee(uint256 newSwapFee) external onlyOwner {\n swapStorage.setSwapFee(newSwapFee);\n }\n\n /**\n * @notice Start ramping up or down A parameter towards given futureA and futureTime\n * Checks if the change is too rapid, and commits the new A value only when it falls under\n * the limit range.\n * @param futureA the new A to ramp towards\n * @param futureTime timestamp when the new A should be reached\n */\n function rampA(uint256 futureA, uint256 futureTime) external onlyOwner {\n swapStorage.rampA(futureA, futureTime);\n }\n\n /**\n * @notice Stop ramping A immediately. Reverts if ramp A is already stopped.\n */\n function stopRampA() external onlyOwner {\n swapStorage.stopRampA();\n }\n}\n" + }, + "@openzeppelin/contracts/math/SafeMath.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <0.8.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" + }, + "@openzeppelin/contracts/token/ERC20/SafeERC20.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <0.8.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" + }, + "@openzeppelin/contracts/proxy/Clones.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <0.8.0;\n\n/**\n * @dev https://eips.ethereum.org/EIPS/eip-1167[EIP 1167] is a standard for\n * deploying minimal proxy contracts, also known as \"clones\".\n *\n * > To simply and cheaply clone contract functionality in an immutable way, this standard specifies\n * > a minimal bytecode implementation that delegates all calls to a known, fixed address.\n *\n * The library includes functions to deploy a proxy using either `create` (traditional deployment) or `create2`\n * (salted deterministic deployment). It also includes functions to predict the addresses of clones deployed using the\n * deterministic method.\n *\n * _Available since v3.4._\n */\nlibrary Clones {\n /**\n * @dev Deploys and returns the address of a clone that mimics the behaviour of `master`.\n *\n * This function uses the create opcode, which should never revert.\n */\n function clone(address master) internal returns (address instance) {\n // solhint-disable-next-line no-inline-assembly\n assembly {\n let ptr := mload(0x40)\n mstore(ptr, 0x3d602d80600a3d3981f3363d3d373d3d3d363d73000000000000000000000000)\n mstore(add(ptr, 0x14), shl(0x60, master))\n mstore(add(ptr, 0x28), 0x5af43d82803e903d91602b57fd5bf30000000000000000000000000000000000)\n instance := create(0, ptr, 0x37)\n }\n require(instance != address(0), \"ERC1167: create failed\");\n }\n\n /**\n * @dev Deploys and returns the address of a clone that mimics the behaviour of `master`.\n *\n * This function uses the create2 opcode and a `salt` to deterministically deploy\n * the clone. Using the same `master` and `salt` multiple time will revert, since\n * the clones cannot be deployed twice at the same address.\n */\n function cloneDeterministic(address master, bytes32 salt) internal returns (address instance) {\n // solhint-disable-next-line no-inline-assembly\n assembly {\n let ptr := mload(0x40)\n mstore(ptr, 0x3d602d80600a3d3981f3363d3d373d3d3d363d73000000000000000000000000)\n mstore(add(ptr, 0x14), shl(0x60, master))\n mstore(add(ptr, 0x28), 0x5af43d82803e903d91602b57fd5bf30000000000000000000000000000000000)\n instance := create2(0, ptr, 0x37, salt)\n }\n require(instance != address(0), \"ERC1167: create2 failed\");\n }\n\n /**\n * @dev Computes the address of a clone deployed using {Clones-cloneDeterministic}.\n */\n function predictDeterministicAddress(address master, bytes32 salt, address deployer) internal pure returns (address predicted) {\n // solhint-disable-next-line no-inline-assembly\n assembly {\n let ptr := mload(0x40)\n mstore(ptr, 0x3d602d80600a3d3981f3363d3d373d3d3d363d73000000000000000000000000)\n mstore(add(ptr, 0x14), shl(0x60, master))\n mstore(add(ptr, 0x28), 0x5af43d82803e903d91602b57fd5bf3ff00000000000000000000000000000000)\n mstore(add(ptr, 0x38), shl(0x60, deployer))\n mstore(add(ptr, 0x4c), salt)\n mstore(add(ptr, 0x6c), keccak256(ptr, 0x37))\n predicted := keccak256(add(ptr, 0x37), 0x55)\n }\n }\n\n /**\n * @dev Computes the address of a clone deployed using {Clones-cloneDeterministic}.\n */\n function predictDeterministicAddress(address master, bytes32 salt) internal view returns (address predicted) {\n return predictDeterministicAddress(master, salt, address(this));\n }\n}\n" + }, + "@openzeppelin/contracts-upgradeable/utils/ReentrancyGuardUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <0.8.0;\nimport \"../proxy/Initializable.sol\";\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 ReentrancyGuardUpgradeable is Initializable {\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 function __ReentrancyGuard_init() internal initializer {\n __ReentrancyGuard_init_unchained();\n }\n\n function __ReentrancyGuard_init_unchained() internal initializer {\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 uint256[49] private __gap;\n}\n" + }, + "contracts/amm/OwnerPausableUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.6.12;\n\nimport \"@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol\";\nimport \"@openzeppelin/contracts-upgradeable/utils/PausableUpgradeable.sol\";\n\n/**\n * @title OwnerPausable\n * @notice An ownable contract allows the owner to pause and unpause the\n * contract without a delay.\n * @dev Only methods using the provided modifiers will be paused.\n */\nabstract contract OwnerPausableUpgradeable is\n OwnableUpgradeable,\n PausableUpgradeable\n{\n function __OwnerPausable_init() internal initializer {\n __Context_init_unchained();\n __Ownable_init_unchained();\n __Pausable_init_unchained();\n }\n\n /**\n * @notice Pause the contract. Revert if already paused.\n */\n function pause() external onlyOwner {\n PausableUpgradeable._pause();\n }\n\n /**\n * @notice Unpause the contract. Revert if already unpaused.\n */\n function unpause() external onlyOwner {\n PausableUpgradeable._unpause();\n }\n}\n" + }, + "contracts/amm/SwapUtils.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.6.12;\n\nimport \"@openzeppelin/contracts/math/SafeMath.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/SafeERC20.sol\";\nimport \"./AmplificationUtils.sol\";\nimport \"./LPToken.sol\";\nimport \"./MathUtils.sol\";\n\n/**\n * @title SwapUtils library\n * @notice A library to be used within Swap.sol. Contains functions responsible for custody and AMM functionalities.\n * @dev Contracts relying on this library must initialize SwapUtils.Swap struct then use this library\n * for SwapUtils.Swap struct. Note that this library contains both functions called by users and admins.\n * Admin functions should be protected within contracts using this library.\n */\nlibrary SwapUtils {\n using SafeERC20 for IERC20;\n using SafeMath for uint256;\n using MathUtils for uint256;\n\n /*** EVENTS ***/\n\n event TokenSwap(\n address indexed buyer,\n uint256 tokensSold,\n uint256 tokensBought,\n uint128 soldId,\n uint128 boughtId\n );\n event AddLiquidity(\n address indexed provider,\n uint256[] tokenAmounts,\n uint256[] fees,\n uint256 invariant,\n uint256 lpTokenSupply\n );\n event RemoveLiquidity(\n address indexed provider,\n uint256[] tokenAmounts,\n uint256 lpTokenSupply\n );\n event RemoveLiquidityOne(\n address indexed provider,\n uint256 lpTokenAmount,\n uint256 lpTokenSupply,\n uint256 boughtId,\n uint256 tokensBought\n );\n event RemoveLiquidityImbalance(\n address indexed provider,\n uint256[] tokenAmounts,\n uint256[] fees,\n uint256 invariant,\n uint256 lpTokenSupply\n );\n event NewAdminFee(uint256 newAdminFee);\n event NewSwapFee(uint256 newSwapFee);\n\n struct Swap {\n // variables around the ramp management of A,\n // the amplification coefficient * n * (n - 1)\n // see https://www.curve.fi/stableswap-paper.pdf for details\n uint256 initialA;\n uint256 futureA;\n uint256 initialATime;\n uint256 futureATime;\n // fee calculation\n uint256 swapFee;\n uint256 adminFee;\n LPToken lpToken;\n // contract references for all tokens being pooled\n IERC20[] pooledTokens;\n // multipliers for each pooled token's precision to get to POOL_PRECISION_DECIMALS\n // for example, TBTC has 18 decimals, so the multiplier should be 1. WBTC\n // has 8, so the multiplier should be 10 ** 18 / 10 ** 8 => 10 ** 10\n uint256[] tokenPrecisionMultipliers;\n // the pool balance of each token, in the token's precision\n // the contract's actual token balance might differ\n uint256[] balances;\n }\n\n // Struct storing variables used in calculations in the\n // calculateWithdrawOneTokenDY function to avoid stack too deep errors\n struct CalculateWithdrawOneTokenDYInfo {\n uint256 d0;\n uint256 d1;\n uint256 newY;\n uint256 feePerToken;\n uint256 preciseA;\n }\n\n // Struct storing variables used in calculations in the\n // {add,remove}Liquidity functions to avoid stack too deep errors\n struct ManageLiquidityInfo {\n uint256 d0;\n uint256 d1;\n uint256 d2;\n uint256 preciseA;\n LPToken lpToken;\n uint256 totalSupply;\n uint256[] balances;\n uint256[] multipliers;\n }\n\n // the precision all pools tokens will be converted to\n uint8 public constant POOL_PRECISION_DECIMALS = 18;\n\n // the denominator used to calculate admin and LP fees. For example, an\n // LP fee might be something like tradeAmount.mul(fee).div(FEE_DENOMINATOR)\n uint256 private constant FEE_DENOMINATOR = 10**10;\n\n // Max swap fee is 1% or 100bps of each swap\n uint256 public constant MAX_SWAP_FEE = 10**8;\n\n // Max adminFee is 100% of the swapFee\n // adminFee does not add additional fee on top of swapFee\n // Instead it takes a certain % of the swapFee. Therefore it has no impact on the\n // users but only on the earnings of LPs\n uint256 public constant MAX_ADMIN_FEE = 10**10;\n\n // Constant value used as max loop limit\n uint256 private constant MAX_LOOP_LIMIT = 256;\n\n /*** VIEW & PURE FUNCTIONS ***/\n\n function _getAPrecise(Swap storage self) internal view returns (uint256) {\n return AmplificationUtils._getAPrecise(self);\n }\n\n /**\n * @notice Calculate the dy, the amount of selected token that user receives and\n * the fee of withdrawing in one token\n * @param tokenAmount the amount to withdraw in the pool's precision\n * @param tokenIndex which token will be withdrawn\n * @param self Swap struct to read from\n * @return the amount of token user will receive\n */\n function calculateWithdrawOneToken(\n Swap storage self,\n uint256 tokenAmount,\n uint8 tokenIndex\n ) external view returns (uint256) {\n (uint256 availableTokenAmount, ) = _calculateWithdrawOneToken(\n self,\n tokenAmount,\n tokenIndex,\n self.lpToken.totalSupply()\n );\n return availableTokenAmount;\n }\n\n function _calculateWithdrawOneToken(\n Swap storage self,\n uint256 tokenAmount,\n uint8 tokenIndex,\n uint256 totalSupply\n ) internal view returns (uint256, uint256) {\n uint256 dy;\n uint256 newY;\n uint256 currentY;\n\n (dy, newY, currentY) = calculateWithdrawOneTokenDY(\n self,\n tokenIndex,\n tokenAmount,\n totalSupply\n );\n\n // dy_0 (without fees)\n // dy, dy_0 - dy\n\n uint256 dySwapFee = currentY\n .sub(newY)\n .div(self.tokenPrecisionMultipliers[tokenIndex])\n .sub(dy);\n\n return (dy, dySwapFee);\n }\n\n /**\n * @notice Calculate the dy of withdrawing in one token\n * @param self Swap struct to read from\n * @param tokenIndex which token will be withdrawn\n * @param tokenAmount the amount to withdraw in the pools precision\n * @return the d and the new y after withdrawing one token\n */\n function calculateWithdrawOneTokenDY(\n Swap storage self,\n uint8 tokenIndex,\n uint256 tokenAmount,\n uint256 totalSupply\n )\n internal\n view\n returns (\n uint256,\n uint256,\n uint256\n )\n {\n // Get the current D, then solve the stableswap invariant\n // y_i for D - tokenAmount\n uint256[] memory xp = _xp(self);\n\n require(tokenIndex < xp.length, \"Token index out of range\");\n\n\n CalculateWithdrawOneTokenDYInfo memory v\n = CalculateWithdrawOneTokenDYInfo(0, 0, 0, 0, 0);\n v.preciseA = _getAPrecise(self);\n v.d0 = getD(xp, v.preciseA);\n v.d1 = v.d0.sub(tokenAmount.mul(v.d0).div(totalSupply));\n\n require(tokenAmount <= xp[tokenIndex], \"Withdraw exceeds available\");\n\n v.newY = getYD(v.preciseA, tokenIndex, xp, v.d1);\n\n uint256[] memory xpReduced = new uint256[](xp.length);\n\n v.feePerToken = _feePerToken(self.swapFee, xp.length);\n for (uint256 i = 0; i < xp.length; i++) {\n uint256 xpi = xp[i];\n // if i == tokenIndex, dxExpected = xp[i] * d1 / d0 - newY\n // else dxExpected = xp[i] - (xp[i] * d1 / d0)\n // xpReduced[i] -= dxExpected * fee / FEE_DENOMINATOR\n xpReduced[i] = xpi.sub(\n (\n (i == tokenIndex)\n ? xpi.mul(v.d1).div(v.d0).sub(v.newY)\n : xpi.sub(xpi.mul(v.d1).div(v.d0))\n )\n .mul(v.feePerToken)\n .div(FEE_DENOMINATOR)\n );\n }\n\n uint256 dy = xpReduced[tokenIndex].sub(\n getYD(v.preciseA, tokenIndex, xpReduced, v.d1)\n );\n dy = dy.sub(1).div(self.tokenPrecisionMultipliers[tokenIndex]);\n\n return (dy, v.newY, xp[tokenIndex]);\n }\n\n /**\n * @notice Calculate the price of a token in the pool with given\n * precision-adjusted balances and a particular D.\n *\n * @dev This is accomplished via solving the invariant iteratively.\n * See the StableSwap paper and Curve.fi implementation for further details.\n *\n * x_1**2 + x1 * (sum' - (A*n**n - 1) * D / (A * n**n)) = D ** (n + 1) / (n ** (2 * n) * prod' * A)\n * x_1**2 + b*x_1 = c\n * x_1 = (x_1**2 + c) / (2*x_1 + b)\n *\n * @param a the amplification coefficient * n * (n - 1). See the StableSwap paper for details.\n * @param tokenIndex Index of token we are calculating for.\n * @param xp a precision-adjusted set of pool balances. Array should be\n * the same cardinality as the pool.\n * @param d the stableswap invariant\n * @return the price of the token, in the same precision as in xp\n */\n function getYD(\n uint256 a,\n uint8 tokenIndex,\n uint256[] memory xp,\n uint256 d\n ) internal pure returns (uint256) {\n uint256 numTokens = xp.length;\n require(tokenIndex < numTokens, \"Token not found\");\n\n uint256 c = d;\n uint256 s;\n uint256 nA = a.mul(numTokens);\n\n for (uint256 i = 0; i < numTokens; i++) {\n if (i != tokenIndex) {\n s = s.add(xp[i]);\n c = c.mul(d).div(xp[i].mul(numTokens));\n // If we were to protect the division loss we would have to keep the denominator separate\n // and divide at the end. However this leads to overflow with large numTokens or/and D.\n // c = c * D * D * D * ... overflow!\n }\n }\n c = c.mul(d).mul(AmplificationUtils.A_PRECISION).div(nA.mul(numTokens));\n\n uint256 b = s.add(d.mul(AmplificationUtils.A_PRECISION).div(nA));\n uint256 yPrev;\n uint256 y = d;\n for (uint256 i = 0; i < MAX_LOOP_LIMIT; i++) {\n yPrev = y;\n y = y.mul(y).add(c).div(y.mul(2).add(b).sub(d));\n if (y.within1(yPrev)) {\n return y;\n }\n }\n revert(\"Approximation did not converge\");\n }\n\n /**\n * @notice Get D, the StableSwap invariant, based on a set of balances and a particular A.\n * @param xp a precision-adjusted set of pool balances. Array should be the same cardinality\n * as the pool.\n * @param a the amplification coefficient * n * (n - 1) in A_PRECISION.\n * See the StableSwap paper for details\n * @return the invariant, at the precision of the pool\n */\n function getD(uint256[] memory xp, uint256 a)\n internal\n pure\n returns (uint256)\n {\n uint256 numTokens = xp.length;\n uint256 s;\n for (uint256 i = 0; i < numTokens; i++) {\n s = s.add(xp[i]);\n }\n if (s == 0) {\n return 0;\n }\n\n uint256 prevD;\n uint256 d = s;\n uint256 nA = a.mul(numTokens);\n\n for (uint256 i = 0; i < MAX_LOOP_LIMIT; i++) {\n uint256 dP = d;\n for (uint256 j = 0; j < numTokens; j++) {\n dP = dP.mul(d).div(xp[j].mul(numTokens));\n // If we were to protect the division loss we would have to keep the denominator separate\n // and divide at the end. However this leads to overflow with large numTokens or/and D.\n // dP = dP * D * D * D * ... overflow!\n }\n prevD = d;\n d = nA\n .mul(s)\n .div(AmplificationUtils.A_PRECISION)\n .add(dP.mul(numTokens))\n .mul(d)\n .div(\n nA\n .sub(AmplificationUtils.A_PRECISION)\n .mul(d)\n .div(AmplificationUtils.A_PRECISION)\n .add(numTokens.add(1).mul(dP))\n );\n if (d.within1(prevD)) {\n return d;\n }\n }\n\n // Convergence should occur in 4 loops or less. If this is reached, there may be something wrong\n // with the pool. If this were to occur repeatedly, LPs should withdraw via `removeLiquidity()`\n // function which does not rely on D.\n revert(\"D does not converge\");\n }\n\n /**\n * @notice Given a set of balances and precision multipliers, return the\n * precision-adjusted balances.\n *\n * @param balances an array of token balances, in their native precisions.\n * These should generally correspond with pooled tokens.\n *\n * @param precisionMultipliers an array of multipliers, corresponding to\n * the amounts in the balances array. When multiplied together they\n * should yield amounts at the pool's precision.\n *\n * @return an array of amounts \"scaled\" to the pool's precision\n */\n function _xp(\n uint256[] memory balances,\n uint256[] memory precisionMultipliers\n ) internal pure returns (uint256[] memory) {\n uint256 numTokens = balances.length;\n require(\n numTokens == precisionMultipliers.length,\n \"Balances must match multipliers\"\n );\n uint256[] memory xp = new uint256[](numTokens);\n for (uint256 i = 0; i < numTokens; i++) {\n xp[i] = balances[i].mul(precisionMultipliers[i]);\n }\n return xp;\n }\n\n /**\n * @notice Return the precision-adjusted balances of all tokens in the pool\n * @param self Swap struct to read from\n * @return the pool balances \"scaled\" to the pool's precision, allowing\n * them to be more easily compared.\n */\n function _xp(Swap storage self) internal view returns (uint256[] memory) {\n return _xp(self.balances, self.tokenPrecisionMultipliers);\n }\n\n /**\n * @notice Get the virtual price, to help calculate profit\n * @param self Swap struct to read from\n * @return the virtual price, scaled to precision of POOL_PRECISION_DECIMALS\n */\n function getVirtualPrice(Swap storage self)\n external\n view\n returns (uint256)\n {\n uint256 d = getD(_xp(self), _getAPrecise(self));\n LPToken lpToken = self.lpToken;\n uint256 supply = lpToken.totalSupply();\n if (supply > 0) {\n return d.mul(10**uint256(POOL_PRECISION_DECIMALS)).div(supply);\n }\n return 0;\n }\n\n /**\n * @notice Calculate the new balances of the tokens given the indexes of the token\n * that is swapped from (FROM) and the token that is swapped to (TO).\n * This function is used as a helper function to calculate how much TO token\n * the user should receive on swap.\n *\n * @param preciseA precise form of amplification coefficient\n * @param tokenIndexFrom index of FROM token\n * @param tokenIndexTo index of TO token\n * @param x the new total amount of FROM token\n * @param xp balances of the tokens in the pool\n * @return the amount of TO token that should remain in the pool\n */\n function getY(\n uint256 preciseA,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 x,\n uint256[] memory xp\n ) internal pure returns (uint256) {\n uint256 numTokens = xp.length;\n require(\n tokenIndexFrom != tokenIndexTo,\n \"Can't compare token to itself\"\n );\n require(\n tokenIndexFrom < numTokens && tokenIndexTo < numTokens,\n \"Tokens must be in pool\"\n );\n\n uint256 d = getD(xp, preciseA);\n uint256 c = d;\n uint256 s;\n uint256 nA = numTokens.mul(preciseA);\n\n uint256 _x;\n for (uint256 i = 0; i < numTokens; i++) {\n if (i == tokenIndexFrom) {\n _x = x;\n } else if (i != tokenIndexTo) {\n _x = xp[i];\n } else {\n continue;\n }\n s = s.add(_x);\n c = c.mul(d).div(_x.mul(numTokens));\n // If we were to protect the division loss we would have to keep the denominator separate\n // and divide at the end. However this leads to overflow with large numTokens or/and D.\n // c = c * D * D * D * ... overflow!\n }\n c = c.mul(d).mul(AmplificationUtils.A_PRECISION).div(nA.mul(numTokens));\n uint256 b = s.add(d.mul(AmplificationUtils.A_PRECISION).div(nA));\n uint256 yPrev;\n uint256 y = d;\n\n // iterative approximation\n for (uint256 i = 0; i < MAX_LOOP_LIMIT; i++) {\n yPrev = y;\n y = y.mul(y).add(c).div(y.mul(2).add(b).sub(d));\n if (y.within1(yPrev)) {\n return y;\n }\n }\n revert(\"Approximation did not converge\");\n }\n\n /**\n * @notice Externally calculates a swap between two tokens.\n * @param self Swap struct to read from\n * @param tokenIndexFrom the token to sell\n * @param tokenIndexTo the token to buy\n * @param dx the number of tokens to sell. If the token charges a fee on transfers,\n * use the amount that gets transferred after the fee.\n * @return dy the number of tokens the user will get\n */\n function calculateSwap(\n Swap storage self,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx\n ) external view returns (uint256 dy) {\n (dy, ) = _calculateSwap(\n self,\n tokenIndexFrom,\n tokenIndexTo,\n dx,\n self.balances\n );\n }\n\n /**\n * @notice Internally calculates a swap between two tokens.\n *\n * @dev The caller is expected to transfer the actual amounts (dx and dy)\n * using the token contracts.\n *\n * @param self Swap struct to read from\n * @param tokenIndexFrom the token to sell\n * @param tokenIndexTo the token to buy\n * @param dx the number of tokens to sell. If the token charges a fee on transfers,\n * use the amount that gets transferred after the fee.\n * @return dy the number of tokens the user will get\n * @return dyFee the associated fee\n */\n function _calculateSwap(\n Swap storage self,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx,\n uint256[] memory balances\n ) internal view returns (uint256 dy, uint256 dyFee) {\n uint256[] memory multipliers = self.tokenPrecisionMultipliers;\n uint256[] memory xp = _xp(balances, multipliers);\n require(\n tokenIndexFrom < xp.length && tokenIndexTo < xp.length,\n \"Token index out of range\"\n );\n uint256 x = dx.mul(multipliers[tokenIndexFrom]).add(xp[tokenIndexFrom]);\n uint256 y = getY(\n _getAPrecise(self),\n tokenIndexFrom,\n tokenIndexTo,\n x,\n xp\n );\n dy = xp[tokenIndexTo].sub(y).sub(1);\n dyFee = dy.mul(self.swapFee).div(FEE_DENOMINATOR);\n dy = dy.sub(dyFee).div(multipliers[tokenIndexTo]);\n }\n\n /**\n * @notice A simple method to calculate amount of each underlying\n * tokens that is returned upon burning given amount of\n * LP tokens\n *\n * @param amount the amount of LP tokens that would to be burned on\n * withdrawal\n * @return array of amounts of tokens user will receive\n */\n function calculateRemoveLiquidity(Swap storage self, uint256 amount)\n external\n view\n returns (uint256[] memory)\n {\n return\n _calculateRemoveLiquidity(\n self.balances,\n amount,\n self.lpToken.totalSupply()\n );\n }\n\n function _calculateRemoveLiquidity(\n uint256[] memory balances,\n uint256 amount,\n uint256 totalSupply\n ) internal pure returns (uint256[] memory) {\n require(amount <= totalSupply, \"Cannot exceed total supply\");\n\n uint256[] memory amounts = new uint256[](balances.length);\n\n for (uint256 i = 0; i < balances.length; i++) {\n amounts[i] = balances[i].mul(amount).div(totalSupply);\n }\n return amounts;\n }\n\n /**\n * @notice A simple method to calculate prices from deposits or\n * withdrawals, excluding fees but including slippage. This is\n * helpful as an input into the various \"min\" parameters on calls\n * to fight front-running\n *\n * @dev This shouldn't be used outside frontends for user estimates.\n *\n * @param self Swap struct to read from\n * @param amounts an array of token amounts to deposit or withdrawal,\n * corresponding to pooledTokens. The amount should be in each\n * pooled token's native precision. If a token charges a fee on transfers,\n * use the amount that gets transferred after the fee.\n * @param deposit whether this is a deposit or a withdrawal\n * @return if deposit was true, total amount of lp token that will be minted and if\n * deposit was false, total amount of lp token that will be burned\n */\n function calculateTokenAmount(\n Swap storage self,\n uint256[] calldata amounts,\n bool deposit\n ) external view returns (uint256) {\n uint256 a = _getAPrecise(self);\n uint256[] memory balances = self.balances;\n uint256[] memory multipliers = self.tokenPrecisionMultipliers;\n\n uint256 d0 = getD(_xp(balances, multipliers), a);\n for (uint256 i = 0; i < balances.length; i++) {\n if (deposit) {\n balances[i] = balances[i].add(amounts[i]);\n } else {\n balances[i] = balances[i].sub(\n amounts[i],\n \"Cannot withdraw more than available\"\n );\n }\n }\n uint256 d1 = getD(_xp(balances, multipliers), a);\n uint256 totalSupply = self.lpToken.totalSupply();\n\n if (deposit) {\n return d1.sub(d0).mul(totalSupply).div(d0);\n } else {\n return d0.sub(d1).mul(totalSupply).div(d0);\n }\n }\n\n /**\n * @notice return accumulated amount of admin fees of the token with given index\n * @param self Swap struct to read from\n * @param index Index of the pooled token\n * @return admin balance in the token's precision\n */\n function getAdminBalance(Swap storage self, uint256 index)\n external\n view\n returns (uint256)\n {\n require(index < self.pooledTokens.length, \"Token index out of range\");\n return\n self.pooledTokens[index].balanceOf(address(this)).sub(\n self.balances[index]\n );\n }\n\n /**\n * @notice internal helper function to calculate fee per token multiplier used in\n * swap fee calculations\n * @param swapFee swap fee for the tokens\n * @param numTokens number of tokens pooled\n */\n function _feePerToken(uint256 swapFee, uint256 numTokens)\n internal\n pure\n returns (uint256)\n {\n return swapFee.mul(numTokens).div(numTokens.sub(1).mul(4));\n }\n\n /*** STATE MODIFYING FUNCTIONS ***/\n\n /**\n * @notice swap two tokens in the pool\n * @param self Swap struct to read from and write to\n * @param tokenIndexFrom the token the user wants to sell\n * @param tokenIndexTo the token the user wants to buy\n * @param dx the amount of tokens the user wants to sell\n * @param minDy the min amount the user would like to receive, or revert.\n * @return amount of token user received on swap\n */\n function swap(\n Swap storage self,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx,\n uint256 minDy\n ) external returns (uint256) {\n {\n IERC20 tokenFrom = self.pooledTokens[tokenIndexFrom];\n require(\n dx <= tokenFrom.balanceOf(msg.sender),\n \"Cannot swap more than you own\"\n );\n // Transfer tokens first to see if a fee was charged on transfer\n uint256 beforeBalance = tokenFrom.balanceOf(address(this));\n tokenFrom.safeTransferFrom(msg.sender, address(this), dx);\n\n // Use the actual transferred amount for AMM math\n dx = tokenFrom.balanceOf(address(this)).sub(beforeBalance);\n }\n\n uint256 dy;\n uint256 dyFee;\n uint256[] memory balances = self.balances;\n (dy, dyFee) = _calculateSwap(\n self,\n tokenIndexFrom,\n tokenIndexTo,\n dx,\n balances\n );\n require(dy >= minDy, \"Swap didn't result in min tokens\");\n\n uint256 dyAdminFee = dyFee.mul(self.adminFee).div(FEE_DENOMINATOR).div(\n self.tokenPrecisionMultipliers[tokenIndexTo]\n );\n\n self.balances[tokenIndexFrom] = balances[tokenIndexFrom].add(dx);\n self.balances[tokenIndexTo] = balances[tokenIndexTo].sub(dy).sub(\n dyAdminFee\n );\n\n self.pooledTokens[tokenIndexTo].safeTransfer(msg.sender, dy);\n\n emit TokenSwap(msg.sender, dx, dy, tokenIndexFrom, tokenIndexTo);\n\n return dy;\n }\n\n /**\n * @notice Add liquidity to the pool\n * @param self Swap struct to read from and write to\n * @param amounts the amounts of each token to add, in their native precision\n * @param minToMint the minimum LP tokens adding this amount of liquidity\n * should mint, otherwise revert. Handy for front-running mitigation\n * allowed addresses. If the pool is not in the guarded launch phase, this parameter will be ignored.\n * @return amount of LP token user received\n */\n function addLiquidity(\n Swap storage self,\n uint256[] memory amounts,\n uint256 minToMint\n ) external returns (uint256) {\n IERC20[] memory pooledTokens = self.pooledTokens;\n require(\n amounts.length == pooledTokens.length,\n \"Amounts must match pooled tokens\"\n );\n\n // current state\n ManageLiquidityInfo memory v = ManageLiquidityInfo(\n 0,\n 0,\n 0,\n _getAPrecise(self),\n self.lpToken,\n 0,\n self.balances,\n self.tokenPrecisionMultipliers\n );\n v.totalSupply = v.lpToken.totalSupply();\n\n if (v.totalSupply != 0) {\n v.d0 = getD(_xp(v.balances, v.multipliers), v.preciseA);\n }\n\n uint256[] memory newBalances = new uint256[](pooledTokens.length);\n\n for (uint256 i = 0; i < pooledTokens.length; i++) {\n require(\n v.totalSupply != 0 || amounts[i] > 0,\n \"Must supply all tokens in pool\"\n );\n\n // Transfer tokens first to see if a fee was charged on transfer\n if (amounts[i] != 0) {\n uint256 beforeBalance = pooledTokens[i].balanceOf(\n address(this)\n );\n pooledTokens[i].safeTransferFrom(\n msg.sender,\n address(this),\n amounts[i]\n );\n\n // Update the amounts[] with actual transfer amount\n amounts[i] = pooledTokens[i].balanceOf(address(this)).sub(\n beforeBalance\n );\n }\n\n newBalances[i] = v.balances[i].add(amounts[i]);\n }\n\n // invariant after change\n v.d1 = getD(_xp(newBalances, v.multipliers), v.preciseA);\n require(v.d1 > v.d0, \"D should increase\");\n\n // updated to reflect fees and calculate the user's LP tokens\n v.d2 = v.d1;\n uint256[] memory fees = new uint256[](pooledTokens.length);\n\n if (v.totalSupply != 0) {\n uint256 feePerToken = _feePerToken(\n self.swapFee,\n pooledTokens.length\n );\n for (uint256 i = 0; i < pooledTokens.length; i++) {\n uint256 idealBalance = v.d1.mul(v.balances[i]).div(v.d0);\n fees[i] = feePerToken\n .mul(idealBalance.difference(newBalances[i]))\n .div(FEE_DENOMINATOR);\n self.balances[i] = newBalances[i].sub(\n fees[i].mul(self.adminFee).div(FEE_DENOMINATOR)\n );\n newBalances[i] = newBalances[i].sub(fees[i]);\n }\n v.d2 = getD(_xp(newBalances, v.multipliers), v.preciseA);\n } else {\n // the initial depositor doesn't pay fees\n self.balances = newBalances;\n }\n\n uint256 toMint;\n if (v.totalSupply == 0) {\n toMint = v.d1;\n } else {\n toMint = v.d2.sub(v.d0).mul(v.totalSupply).div(v.d0);\n }\n\n require(toMint >= minToMint, \"Couldn't mint min requested\");\n\n // mint the user's LP tokens\n v.lpToken.mint(msg.sender, toMint);\n\n emit AddLiquidity(\n msg.sender,\n amounts,\n fees,\n v.d1,\n v.totalSupply.add(toMint)\n );\n\n return toMint;\n }\n\n /**\n * @notice Burn LP tokens to remove liquidity from the pool.\n * @dev Liquidity can always be removed, even when the pool is paused.\n * @param self Swap struct to read from and write to\n * @param amount the amount of LP tokens to burn\n * @param minAmounts the minimum amounts of each token in the pool\n * acceptable for this burn. Useful as a front-running mitigation\n * @return amounts of tokens the user received\n */\n function removeLiquidity(\n Swap storage self,\n uint256 amount,\n uint256[] calldata minAmounts\n ) external returns (uint256[] memory) {\n LPToken lpToken = self.lpToken;\n IERC20[] memory pooledTokens = self.pooledTokens;\n require(amount <= lpToken.balanceOf(msg.sender), \">LP.balanceOf\");\n require(\n minAmounts.length == pooledTokens.length,\n \"minAmounts must match poolTokens\"\n );\n\n uint256[] memory balances = self.balances;\n uint256 totalSupply = lpToken.totalSupply();\n\n uint256[] memory amounts = _calculateRemoveLiquidity(\n balances,\n amount,\n totalSupply\n );\n\n for (uint256 i = 0; i < amounts.length; i++) {\n require(amounts[i] >= minAmounts[i], \"amounts[i] < minAmounts[i]\");\n self.balances[i] = balances[i].sub(amounts[i]);\n pooledTokens[i].safeTransfer(msg.sender, amounts[i]);\n }\n\n lpToken.burnFrom(msg.sender, amount);\n\n emit RemoveLiquidity(msg.sender, amounts, totalSupply.sub(amount));\n\n return amounts;\n }\n\n /**\n * @notice Remove liquidity from the pool all in one token.\n * @param self Swap struct to read from and write to\n * @param tokenAmount the amount of the lp tokens to burn\n * @param tokenIndex the index of the token you want to receive\n * @param minAmount the minimum amount to withdraw, otherwise revert\n * @return amount chosen token that user received\n */\n function removeLiquidityOneToken(\n Swap storage self,\n uint256 tokenAmount,\n uint8 tokenIndex,\n uint256 minAmount\n ) external returns (uint256) {\n LPToken lpToken = self.lpToken;\n IERC20[] memory pooledTokens = self.pooledTokens;\n\n require(tokenAmount <= lpToken.balanceOf(msg.sender), \">LP.balanceOf\");\n require(tokenIndex < pooledTokens.length, \"Token not found\");\n\n uint256 totalSupply = lpToken.totalSupply();\n\n (uint256 dy, uint256 dyFee) = _calculateWithdrawOneToken(\n self,\n tokenAmount,\n tokenIndex,\n totalSupply\n );\n\n require(dy >= minAmount, \"dy < minAmount\");\n\n self.balances[tokenIndex] = self.balances[tokenIndex].sub(\n dy.add(dyFee.mul(self.adminFee).div(FEE_DENOMINATOR))\n );\n lpToken.burnFrom(msg.sender, tokenAmount);\n pooledTokens[tokenIndex].safeTransfer(msg.sender, dy);\n\n emit RemoveLiquidityOne(\n msg.sender,\n tokenAmount,\n totalSupply,\n tokenIndex,\n dy\n );\n\n return dy;\n }\n\n /**\n * @notice Remove liquidity from the pool, weighted differently than the\n * pool's current balances.\n *\n * @param self Swap struct to read from and write to\n * @param amounts how much of each token to withdraw\n * @param maxBurnAmount the max LP token provider is willing to pay to\n * remove liquidity. Useful as a front-running mitigation.\n * @return actual amount of LP tokens burned in the withdrawal\n */\n function removeLiquidityImbalance(\n Swap storage self,\n uint256[] memory amounts,\n uint256 maxBurnAmount\n ) public returns (uint256) {\n ManageLiquidityInfo memory v = ManageLiquidityInfo(\n 0,\n 0,\n 0,\n _getAPrecise(self),\n self.lpToken,\n 0,\n self.balances,\n self.tokenPrecisionMultipliers\n );\n v.totalSupply = v.lpToken.totalSupply();\n\n IERC20[] memory pooledTokens = self.pooledTokens;\n\n require(\n amounts.length == pooledTokens.length,\n \"Amounts should match pool tokens\"\n );\n\n require(\n maxBurnAmount <= v.lpToken.balanceOf(msg.sender) &&\n maxBurnAmount != 0,\n \">LP.balanceOf\"\n );\n\n uint256 feePerToken = _feePerToken(self.swapFee, pooledTokens.length);\n uint256[] memory fees = new uint256[](pooledTokens.length);\n {\n uint256[] memory balances1 = new uint256[](pooledTokens.length);\n v.d0 = getD(_xp(v.balances, v.multipliers), v.preciseA);\n for (uint256 i = 0; i < pooledTokens.length; i++) {\n balances1[i] = v.balances[i].sub(\n amounts[i],\n \"Cannot withdraw more than available\"\n );\n }\n v.d1 = getD(_xp(balances1, v.multipliers), v.preciseA);\n\n for (uint256 i = 0; i < pooledTokens.length; i++) {\n uint256 idealBalance = v.d1.mul(v.balances[i]).div(v.d0);\n uint256 difference = idealBalance.difference(balances1[i]);\n fees[i] = feePerToken.mul(difference).div(FEE_DENOMINATOR);\n self.balances[i] = balances1[i].sub(\n fees[i].mul(self.adminFee).div(FEE_DENOMINATOR)\n );\n balances1[i] = balances1[i].sub(fees[i]);\n }\n\n v.d2 = getD(_xp(balances1, v.multipliers), v.preciseA);\n }\n uint256 tokenAmount = v.d0.sub(v.d2).mul(v.totalSupply).div(v.d0);\n require(tokenAmount != 0, \"Burnt amount cannot be zero\");\n tokenAmount = tokenAmount.add(1);\n\n require(tokenAmount <= maxBurnAmount, \"tokenAmount > maxBurnAmount\");\n\n v.lpToken.burnFrom(msg.sender, tokenAmount);\n\n for (uint256 i = 0; i < pooledTokens.length; i++) {\n pooledTokens[i].safeTransfer(msg.sender, amounts[i]);\n }\n\n emit RemoveLiquidityImbalance(\n msg.sender,\n amounts,\n fees,\n v.d1,\n v.totalSupply.sub(tokenAmount)\n );\n\n return tokenAmount;\n }\n\n /**\n * @notice withdraw all admin fees to a given address\n * @param self Swap struct to withdraw fees from\n * @param to Address to send the fees to\n */\n function withdrawAdminFees(Swap storage self, address to) external {\n IERC20[] memory pooledTokens = self.pooledTokens;\n for (uint256 i = 0; i < pooledTokens.length; i++) {\n IERC20 token = pooledTokens[i];\n uint256 balance = token.balanceOf(address(this)).sub(\n self.balances[i]\n );\n if (balance != 0) {\n token.safeTransfer(to, balance);\n }\n }\n }\n\n /**\n * @notice Sets the admin fee\n * @dev adminFee cannot be higher than 100% of the swap fee\n * @param self Swap struct to update\n * @param newAdminFee new admin fee to be applied on future transactions\n */\n function setAdminFee(Swap storage self, uint256 newAdminFee) external {\n require(newAdminFee <= MAX_ADMIN_FEE, \"Fee is too high\");\n self.adminFee = newAdminFee;\n\n emit NewAdminFee(newAdminFee);\n }\n\n /**\n * @notice update the swap fee\n * @dev fee cannot be higher than 1% of each swap\n * @param self Swap struct to update\n * @param newSwapFee new swap fee to be applied on future transactions\n */\n function setSwapFee(Swap storage self, uint256 newSwapFee) external {\n require(newSwapFee <= MAX_SWAP_FEE, \"Fee is too high\");\n self.swapFee = newSwapFee;\n\n emit NewSwapFee(newSwapFee);\n }\n}\n" + }, + "contracts/amm/AmplificationUtils.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.6.12;\n\nimport \"@openzeppelin/contracts/token/ERC20/SafeERC20.sol\";\nimport \"./SwapUtils.sol\";\n\n/**\n * @title AmplificationUtils library\n * @notice A library to calculate and ramp the A parameter of a given `SwapUtils.Swap` struct.\n * This library assumes the struct is fully validated.\n */\nlibrary AmplificationUtils {\n using SafeMath for uint256;\n\n event RampA(\n uint256 oldA,\n uint256 newA,\n uint256 initialTime,\n uint256 futureTime\n );\n event StopRampA(uint256 currentA, uint256 time);\n\n // Constant values used in ramping A calculations\n uint256 public constant A_PRECISION = 100;\n uint256 public constant MAX_A = 10**6;\n uint256 private constant MAX_A_CHANGE = 2;\n uint256 private constant MIN_RAMP_TIME = 7 days;\n\n /**\n * @notice Return A, the amplification coefficient * n * (n - 1)\n * @dev See the StableSwap paper for details\n * @param self Swap struct to read from\n * @return A parameter\n */\n function getA(SwapUtils.Swap storage self) external view returns (uint256) {\n return _getAPrecise(self).div(A_PRECISION);\n }\n\n /**\n * @notice Return A in its raw precision\n * @dev See the StableSwap paper for details\n * @param self Swap struct to read from\n * @return A parameter in its raw precision form\n */\n function getAPrecise(SwapUtils.Swap storage self)\n external\n view\n returns (uint256)\n {\n return _getAPrecise(self);\n }\n\n /**\n * @notice Return A in its raw precision\n * @dev See the StableSwap paper for details\n * @param self Swap struct to read from\n * @return A parameter in its raw precision form\n */\n function _getAPrecise(SwapUtils.Swap storage self)\n internal\n view\n returns (uint256)\n {\n uint256 t1 = self.futureATime; // time when ramp is finished\n uint256 a1 = self.futureA; // final A value when ramp is finished\n\n if (block.timestamp < t1) {\n uint256 t0 = self.initialATime; // time when ramp is started\n uint256 a0 = self.initialA; // initial A value when ramp is started\n if (a1 > a0) {\n // a0 + (a1 - a0) * (block.timestamp - t0) / (t1 - t0)\n return\n a0.add(\n a1.sub(a0).mul(block.timestamp.sub(t0)).div(t1.sub(t0))\n );\n } else {\n // a0 - (a0 - a1) * (block.timestamp - t0) / (t1 - t0)\n return\n a0.sub(\n a0.sub(a1).mul(block.timestamp.sub(t0)).div(t1.sub(t0))\n );\n }\n } else {\n return a1;\n }\n }\n\n /**\n * @notice Start ramping up or down A parameter towards given futureA_ and futureTime_\n * Checks if the change is too rapid, and commits the new A value only when it falls under\n * the limit range.\n * @param self Swap struct to update\n * @param futureA_ the new A to ramp towards\n * @param futureTime_ timestamp when the new A should be reached\n */\n function rampA(\n SwapUtils.Swap storage self,\n uint256 futureA_,\n uint256 futureTime_\n ) external {\n require(\n block.timestamp >= self.initialATime.add(1 days),\n \"Wait 1 day before starting ramp\"\n );\n require(\n futureTime_ >= block.timestamp.add(MIN_RAMP_TIME),\n \"Insufficient ramp time\"\n );\n require(\n futureA_ > 0 && futureA_ < MAX_A,\n \"futureA_ must be > 0 and < MAX_A\"\n );\n\n uint256 initialAPrecise = _getAPrecise(self);\n uint256 futureAPrecise = futureA_.mul(A_PRECISION);\n\n if (futureAPrecise < initialAPrecise) {\n require(\n futureAPrecise.mul(MAX_A_CHANGE) >= initialAPrecise,\n \"futureA_ is too small\"\n );\n } else {\n require(\n futureAPrecise <= initialAPrecise.mul(MAX_A_CHANGE),\n \"futureA_ is too large\"\n );\n }\n\n self.initialA = initialAPrecise;\n self.futureA = futureAPrecise;\n self.initialATime = block.timestamp;\n self.futureATime = futureTime_;\n\n emit RampA(\n initialAPrecise,\n futureAPrecise,\n block.timestamp,\n futureTime_\n );\n }\n\n /**\n * @notice Stops ramping A immediately. Once this function is called, rampA()\n * cannot be called for another 24 hours\n * @param self Swap struct to update\n */\n function stopRampA(SwapUtils.Swap storage self) external {\n require(self.futureATime > block.timestamp, \"Ramp is already stopped\");\n\n uint256 currentA = _getAPrecise(self);\n self.initialA = currentA;\n self.futureA = currentA;\n self.initialATime = block.timestamp;\n self.futureATime = block.timestamp;\n\n emit StopRampA(currentA, block.timestamp);\n }\n}\n" + }, + "@openzeppelin/contracts/token/ERC20/IERC20.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <0.8.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" + }, + "@openzeppelin/contracts/utils/Address.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.2 <0.8.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" + }, + "@openzeppelin/contracts-upgradeable/proxy/Initializable.sol": { + "content": "// SPDX-License-Identifier: MIT\n\n// solhint-disable-next-line compiler-version\npragma solidity >=0.4.24 <0.8.0;\n\nimport \"../utils/AddressUpgradeable.sol\";\n\n/**\n * @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed\n * behind a proxy. Since a proxied contract can't have a constructor, it's common to move constructor logic to an\n * external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer\n * function so it can only be called once. The {initializer} modifier provided by this contract will have this effect.\n *\n * TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as\n * possible by providing the encoded function call as the `_data` argument to {UpgradeableProxy-constructor}.\n *\n * CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure\n * that all initializers are idempotent. This is not verified automatically as constructors are by Solidity.\n */\nabstract contract Initializable {\n\n /**\n * @dev Indicates that the contract has been initialized.\n */\n bool private _initialized;\n\n /**\n * @dev Indicates that the contract is in the process of being initialized.\n */\n bool private _initializing;\n\n /**\n * @dev Modifier to protect an initializer function from being invoked twice.\n */\n modifier initializer() {\n require(_initializing || _isConstructor() || !_initialized, \"Initializable: contract is already initialized\");\n\n bool isTopLevelCall = !_initializing;\n if (isTopLevelCall) {\n _initializing = true;\n _initialized = true;\n }\n\n _;\n\n if (isTopLevelCall) {\n _initializing = false;\n }\n }\n\n /// @dev Returns true if and only if the function is running in the constructor\n function _isConstructor() private view returns (bool) {\n return !AddressUpgradeable.isContract(address(this));\n }\n}\n" + }, + "@openzeppelin/contracts-upgradeable/utils/AddressUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.2 <0.8.0;\n\n/**\n * @dev Collection of functions related to the address type\n */\nlibrary AddressUpgradeable {\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 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" + }, + "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <0.8.0;\n\nimport \"../utils/ContextUpgradeable.sol\";\nimport \"../proxy/Initializable.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 OwnableUpgradeable is Initializable, ContextUpgradeable {\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 function __Ownable_init() internal initializer {\n __Context_init_unchained();\n __Ownable_init_unchained();\n }\n\n function __Ownable_init_unchained() internal initializer {\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 uint256[49] private __gap;\n}\n" + }, + "@openzeppelin/contracts-upgradeable/utils/PausableUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <0.8.0;\n\nimport \"./ContextUpgradeable.sol\";\nimport \"../proxy/Initializable.sol\";\n\n/**\n * @dev Contract module which allows children to implement an emergency stop\n * mechanism that can be triggered by an authorized account.\n *\n * This module is used through inheritance. It will make available the\n * modifiers `whenNotPaused` and `whenPaused`, which can be applied to\n * the functions of your contract. Note that they will not be pausable by\n * simply including this module, only once the modifiers are put in place.\n */\nabstract contract PausableUpgradeable is Initializable, ContextUpgradeable {\n /**\n * @dev Emitted when the pause is triggered by `account`.\n */\n event Paused(address account);\n\n /**\n * @dev Emitted when the pause is lifted by `account`.\n */\n event Unpaused(address account);\n\n bool private _paused;\n\n /**\n * @dev Initializes the contract in unpaused state.\n */\n function __Pausable_init() internal initializer {\n __Context_init_unchained();\n __Pausable_init_unchained();\n }\n\n function __Pausable_init_unchained() internal initializer {\n _paused = false;\n }\n\n /**\n * @dev Returns true if the contract is paused, and false otherwise.\n */\n function paused() public view virtual returns (bool) {\n return _paused;\n }\n\n /**\n * @dev Modifier to make a function callable only when the contract is not paused.\n *\n * Requirements:\n *\n * - The contract must not be paused.\n */\n modifier whenNotPaused() {\n require(!paused(), \"Pausable: paused\");\n _;\n }\n\n /**\n * @dev Modifier to make a function callable only when the contract is paused.\n *\n * Requirements:\n *\n * - The contract must be paused.\n */\n modifier whenPaused() {\n require(paused(), \"Pausable: not paused\");\n _;\n }\n\n /**\n * @dev Triggers stopped state.\n *\n * Requirements:\n *\n * - The contract must not be paused.\n */\n function _pause() internal virtual whenNotPaused {\n _paused = true;\n emit Paused(_msgSender());\n }\n\n /**\n * @dev Returns to normal state.\n *\n * Requirements:\n *\n * - The contract must be paused.\n */\n function _unpause() internal virtual whenPaused {\n _paused = false;\n emit Unpaused(_msgSender());\n }\n uint256[49] private __gap;\n}\n" + }, + "@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <0.8.0;\nimport \"../proxy/Initializable.sol\";\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 ContextUpgradeable is Initializable {\n function __Context_init() internal initializer {\n __Context_init_unchained();\n }\n\n function __Context_init_unchained() internal initializer {\n }\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 uint256[50] private __gap;\n}\n" + }, + "contracts/amm/LPToken.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.6.12;\n\nimport \"@openzeppelin/contracts-upgradeable/token/ERC20/ERC20BurnableUpgradeable.sol\";\nimport \"@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol\";\nimport \"./interfaces/ISwap.sol\";\n\n/**\n * @title Liquidity Provider Token\n * @notice This token is an ERC20 detailed token with added capability to be minted by the owner.\n * It is used to represent user's shares when providing liquidity to swap contracts.\n * @dev Only Swap contracts should initialize and own LPToken contracts.\n */\ncontract LPToken is ERC20BurnableUpgradeable, OwnableUpgradeable {\n using SafeMathUpgradeable for uint256;\n\n /**\n * @notice Initializes this LPToken contract with the given name and symbol\n * @dev The caller of this function will become the owner. A Swap contract should call this\n * in its initializer function.\n * @param name name of this token\n * @param symbol symbol of this token\n */\n function initialize(string memory name, string memory symbol)\n external\n initializer\n returns (bool)\n {\n __Context_init_unchained();\n __ERC20_init_unchained(name, symbol);\n __Ownable_init_unchained();\n return true;\n }\n\n /**\n * @notice Mints the given amount of LPToken to the recipient.\n * @dev only owner can call this mint function\n * @param recipient address of account to receive the tokens\n * @param amount amount of tokens to mint\n */\n function mint(address recipient, uint256 amount) external onlyOwner {\n require(amount != 0, \"LPToken: cannot mint 0\");\n _mint(recipient, amount);\n }\n\n /**\n * @dev Overrides ERC20._beforeTokenTransfer() which get called on every transfers including\n * minting and burning. * This assumes the owner is set to a Swap contract's address.\n */\n function _beforeTokenTransfer(\n address from,\n address to,\n uint256 amount\n ) internal virtual override(ERC20Upgradeable) {\n super._beforeTokenTransfer(from, to, amount);\n require(to != address(this), \"LPToken: cannot send to itself\");\n }\n}\n" + }, + "contracts/amm/MathUtils.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.6.12;\n\nimport \"@openzeppelin/contracts/math/SafeMath.sol\";\n\n/**\n * @title MathUtils library\n * @notice A library to be used in conjunction with SafeMath. Contains functions for calculating\n * differences between two uint256.\n */\nlibrary MathUtils {\n /**\n * @notice Compares a and b and returns true if the difference between a and b\n * is less than 1 or equal to each other.\n * @param a uint256 to compare with\n * @param b uint256 to compare with\n * @return True if the difference between a and b is less than 1 or equal,\n * otherwise return false\n */\n function within1(uint256 a, uint256 b) internal pure returns (bool) {\n return (difference(a, b) <= 1);\n }\n\n /**\n * @notice Calculates absolute difference between a and b\n * @param a uint256 to compare with\n * @param b uint256 to compare with\n * @return Difference between a and b\n */\n function difference(uint256 a, uint256 b) internal pure returns (uint256) {\n if (a > b) {\n return a - b;\n }\n return b - a;\n }\n}\n" + }, + "@openzeppelin/contracts-upgradeable/token/ERC20/ERC20BurnableUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <0.8.0;\n\nimport \"../../utils/ContextUpgradeable.sol\";\nimport \"./ERC20Upgradeable.sol\";\nimport \"../../proxy/Initializable.sol\";\n\n/**\n * @dev Extension of {ERC20} that allows token holders to destroy both their own\n * tokens and those that they have an allowance for, in a way that can be\n * recognized off-chain (via event analysis).\n */\nabstract contract ERC20BurnableUpgradeable is Initializable, ContextUpgradeable, ERC20Upgradeable {\n function __ERC20Burnable_init() internal initializer {\n __Context_init_unchained();\n __ERC20Burnable_init_unchained();\n }\n\n function __ERC20Burnable_init_unchained() internal initializer {\n }\n using SafeMathUpgradeable for uint256;\n\n /**\n * @dev Destroys `amount` tokens from the caller.\n *\n * See {ERC20-_burn}.\n */\n function burn(uint256 amount) public virtual {\n _burn(_msgSender(), amount);\n }\n\n /**\n * @dev Destroys `amount` tokens from `account`, deducting from the caller's\n * allowance.\n *\n * See {ERC20-_burn} and {ERC20-allowance}.\n *\n * Requirements:\n *\n * - the caller must have allowance for ``accounts``'s tokens of at least\n * `amount`.\n */\n function burnFrom(address account, uint256 amount) public virtual {\n uint256 decreasedAllowance = allowance(account, _msgSender()).sub(amount, \"ERC20: burn amount exceeds allowance\");\n\n _approve(account, _msgSender(), decreasedAllowance);\n _burn(account, amount);\n }\n uint256[50] private __gap;\n}\n" + }, + "contracts/amm/interfaces/ISwap.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.6.12;\n\nimport \"@openzeppelin/contracts/token/ERC20/ERC20.sol\";\n\ninterface ISwap {\n // pool data view functions\n function getA() external view returns (uint256);\n\n function getToken(uint8 index) external view returns (IERC20);\n\n function getTokenIndex(address tokenAddress) external view returns (uint8);\n\n function getTokenBalance(uint8 index) external view returns (uint256);\n\n function getVirtualPrice() external view returns (uint256);\n\n // min return calculation functions\n function calculateSwap(\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx\n ) external view returns (uint256);\n\n function calculateTokenAmount(uint256[] calldata amounts, bool deposit)\n external\n view\n returns (uint256);\n\n function calculateRemoveLiquidity(uint256 amount)\n external\n view\n returns (uint256[] memory);\n\n function calculateRemoveLiquidityOneToken(\n uint256 tokenAmount,\n uint8 tokenIndex\n ) external view returns (uint256 availableTokenAmount);\n\n // state modifying functions\n function initialize(\n IERC20[] memory pooledTokens,\n uint8[] memory decimals,\n string memory lpTokenName,\n string memory lpTokenSymbol,\n uint256 a,\n uint256 fee,\n uint256 adminFee,\n address lpTokenTargetAddress\n ) external;\n\n function swap(\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx,\n uint256 minDy,\n uint256 deadline\n ) external returns (uint256);\n\n function addLiquidity(\n uint256[] calldata amounts,\n uint256 minToMint,\n uint256 deadline\n ) external returns (uint256);\n\n function removeLiquidity(\n uint256 amount,\n uint256[] calldata minAmounts,\n uint256 deadline\n ) external returns (uint256[] memory);\n\n function removeLiquidityOneToken(\n uint256 tokenAmount,\n uint8 tokenIndex,\n uint256 minAmount,\n uint256 deadline\n ) external returns (uint256);\n\n function removeLiquidityImbalance(\n uint256[] calldata amounts,\n uint256 maxBurnAmount,\n uint256 deadline\n ) external returns (uint256);\n}\n" + }, + "@openzeppelin/contracts-upgradeable/token/ERC20/ERC20Upgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <0.8.0;\n\nimport \"../../utils/ContextUpgradeable.sol\";\nimport \"./IERC20Upgradeable.sol\";\nimport \"../../math/SafeMathUpgradeable.sol\";\nimport \"../../proxy/Initializable.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 ERC20Upgradeable is Initializable, ContextUpgradeable, IERC20Upgradeable {\n using SafeMathUpgradeable 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 function __ERC20_init(string memory name_, string memory symbol_) internal initializer {\n __Context_init_unchained();\n __ERC20_init_unchained(name_, symbol_);\n }\n\n function __ERC20_init_unchained(string memory name_, string memory symbol_) internal initializer {\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 uint256[44] private __gap;\n}\n" + }, + "@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <0.8.0;\n\n/**\n * @dev Interface of the ERC20 standard as defined in the EIP.\n */\ninterface IERC20Upgradeable {\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" + }, + "@openzeppelin/contracts-upgradeable/math/SafeMathUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <0.8.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 SafeMathUpgradeable {\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" + }, + "@openzeppelin/contracts/token/ERC20/ERC20.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <0.8.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_) public {\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" + }, + "@openzeppelin/contracts/utils/Context.sol": { + "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" + }, + "contracts/amm/SwapFlashLoan.sol": { + "content": "// SPDX-License-Identifier: MIT WITH AGPL-3.0-only\n\npragma solidity 0.6.12;\n\nimport \"./Swap.sol\";\nimport \"./interfaces/IFlashLoanReceiver.sol\";\n\n/**\n * @title Swap - A StableSwap implementation in solidity.\n * @notice This contract is responsible for custody of closely pegged assets (eg. group of stablecoins)\n * and automatic market making system. Users become an LP (Liquidity Provider) by depositing their tokens\n * in desired ratios for an exchange of the pool token that represents their share of the pool.\n * Users can burn pool tokens and withdraw their share of token(s).\n *\n * Each time a swap between the pooled tokens happens, a set fee incurs which effectively gets\n * distributed to the LPs.\n *\n * In case of emergencies, admin can pause additional deposits, swaps, or single-asset withdraws - which\n * stops the ratio of the tokens in the pool from changing.\n * Users can always withdraw their tokens via multi-asset withdraws.\n *\n * @dev Most of the logic is stored as a library `SwapUtils` for the sake of reducing contract's\n * deployment size.\n */\ncontract SwapFlashLoan is Swap {\n // Total fee that is charged on all flashloans in BPS. Borrowers must repay the amount plus the flash loan fee.\n // This fee is split between the protocol and the pool.\n uint256 public flashLoanFeeBPS;\n // Share of the flash loan fee that goes to the protocol in BPS. A portion of each flash loan fee is allocated\n // to the protocol rather than the pool.\n uint256 public protocolFeeShareBPS;\n // Max BPS for limiting flash loan fee settings.\n uint256 public constant MAX_BPS = 10000;\n\n /*** EVENTS ***/\n event FlashLoan(\n address indexed receiver,\n uint8 tokenIndex,\n uint256 amount,\n uint256 amountFee,\n uint256 protocolFee\n );\n\n /**\n * @notice Initializes this Swap contract with the given parameters.\n * This will also clone a LPToken contract that represents users'\n * LP positions. The owner of LPToken will be this contract - which means\n * only this contract is allowed to mint/burn tokens.\n *\n * @param _pooledTokens an array of ERC20s this pool will accept\n * @param decimals the decimals to use for each pooled token,\n * eg 8 for WBTC. Cannot be larger than POOL_PRECISION_DECIMALS\n * @param lpTokenName the long-form name of the token to be deployed\n * @param lpTokenSymbol the short symbol for the token to be deployed\n * @param _a the amplification coefficient * n * (n - 1). See the\n * StableSwap paper for details\n * @param _fee default swap fee to be initialized with\n * @param _adminFee default adminFee to be initialized with\n * @param lpTokenTargetAddress the address of an existing LPToken contract to use as a target\n */\n function initialize(\n IERC20[] memory _pooledTokens,\n uint8[] memory decimals,\n string memory lpTokenName,\n string memory lpTokenSymbol,\n uint256 _a,\n uint256 _fee,\n uint256 _adminFee,\n address lpTokenTargetAddress\n ) public virtual override initializer {\n Swap.initialize(\n _pooledTokens,\n decimals,\n lpTokenName,\n lpTokenSymbol,\n _a,\n _fee,\n _adminFee,\n lpTokenTargetAddress\n );\n flashLoanFeeBPS = 8; // 8 bps\n protocolFeeShareBPS = 0; // 0 bps\n }\n\n /*** STATE MODIFYING FUNCTIONS ***/\n\n /**\n * @notice Borrow the specified token from this pool for this transaction only. This function will call\n * `IFlashLoanReceiver(receiver).executeOperation` and the `receiver` must return the full amount of the token\n * and the associated fee by the end of the callback transaction. If the conditions are not met, this call\n * is reverted.\n * @param receiver the address of the receiver of the token. This address must implement the IFlashLoanReceiver\n * interface and the callback function `executeOperation`.\n * @param token the protocol fee in bps to be applied on the total flash loan fee\n * @param amount the total amount to borrow in this transaction\n * @param params optional data to pass along to the callback function\n */\n function flashLoan(\n address receiver,\n IERC20 token,\n uint256 amount,\n bytes memory params\n ) external nonReentrant {\n uint8 tokenIndex = getTokenIndex(address(token));\n uint256 availableLiquidityBefore = token.balanceOf(address(this));\n uint256 protocolBalanceBefore = availableLiquidityBefore.sub(\n swapStorage.balances[tokenIndex]\n );\n require(\n amount > 0 && availableLiquidityBefore >= amount,\n \"invalid amount\"\n );\n\n // Calculate the additional amount of tokens the pool should end up with\n uint256 amountFee = amount.mul(flashLoanFeeBPS).div(10000);\n // Calculate the portion of the fee that will go to the protocol\n uint256 protocolFee = amountFee.mul(protocolFeeShareBPS).div(10000);\n require(amountFee > 0, \"amount is small for a flashLoan\");\n\n // Transfer the requested amount of tokens\n token.safeTransfer(receiver, amount);\n\n // Execute callback function on receiver\n IFlashLoanReceiver(receiver).executeOperation(\n address(this),\n address(token),\n amount,\n amountFee,\n params\n );\n\n uint256 availableLiquidityAfter = token.balanceOf(address(this));\n require(\n availableLiquidityAfter >= availableLiquidityBefore.add(amountFee),\n \"flashLoan fee is not met\"\n );\n\n swapStorage.balances[tokenIndex] = availableLiquidityAfter\n .sub(protocolBalanceBefore)\n .sub(protocolFee);\n emit FlashLoan(receiver, tokenIndex, amount, amountFee, protocolFee);\n }\n\n /*** ADMIN FUNCTIONS ***/\n\n /**\n * @notice Updates the flash loan fee parameters. This function can only be called by the owner.\n * @param newFlashLoanFeeBPS the total fee in bps to be applied on future flash loans\n * @param newProtocolFeeShareBPS the protocol fee in bps to be applied on the total flash loan fee\n */\n function setFlashLoanFees(\n uint256 newFlashLoanFeeBPS,\n uint256 newProtocolFeeShareBPS\n ) external onlyOwner {\n require(\n newFlashLoanFeeBPS > 0 &&\n newFlashLoanFeeBPS <= MAX_BPS &&\n newProtocolFeeShareBPS <= MAX_BPS,\n \"fees are not in valid range\"\n );\n flashLoanFeeBPS = newFlashLoanFeeBPS;\n protocolFeeShareBPS = newProtocolFeeShareBPS;\n }\n}\n" + }, + "contracts/amm/interfaces/IFlashLoanReceiver.sol": { + "content": "// SPDX-License-Identifier: AGPL-3.0-only\n\npragma solidity 0.6.12;\n\n/**\n * @title IFlashLoanReceiver interface\n * @notice Interface for the Nerve fee IFlashLoanReceiver. Modified from Aave's IFlashLoanReceiver interface.\n * https://github.com/aave/aave-protocol/blob/4b4545fb583fd4f400507b10f3c3114f45b8a037/contracts/flashloan/interfaces/IFlashLoanReceiver.sol\n * @author Aave\n * @dev implement this interface to develop a flashloan-compatible flashLoanReceiver contract\n **/\ninterface IFlashLoanReceiver {\n function executeOperation(\n address pool,\n address token,\n uint256 amount,\n uint256 fee,\n bytes calldata params\n ) external;\n}\n" + }, + "contracts/amm/helper/FlashLoanBorrowerExample.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.6.12;\n\nimport \"@openzeppelin/contracts/math/SafeMath.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/SafeERC20.sol\";\nimport \"../interfaces/IFlashLoanReceiver.sol\";\nimport \"../interfaces/ISwapFlashLoan.sol\";\nimport \"hardhat/console.sol\";\n\ncontract FlashLoanBorrowerExample is IFlashLoanReceiver {\n using SafeMath for uint256;\n\n // Typical executeOperation function should do the 3 following actions\n // 1. Check if the flashLoan was successful\n // 2. Do actions with the borrowed tokens\n // 3. Repay the debt to the `pool`\n function executeOperation(\n address pool,\n address token,\n uint256 amount,\n uint256 fee,\n bytes calldata params\n ) external override {\n // 1. Check if the flashLoan was valid\n require(\n IERC20(token).balanceOf(address(this)) >= amount,\n \"flashloan is broken?\"\n );\n\n // 2. Do actions with the borrowed token\n bytes32 paramsHash = keccak256(params);\n if (paramsHash == keccak256(bytes(\"dontRepayDebt\"))) {\n return;\n } else if (paramsHash == keccak256(bytes(\"reentrancy_addLiquidity\"))) {\n ISwapFlashLoan(pool).addLiquidity(\n new uint256[](0),\n 0,\n block.timestamp\n );\n } else if (paramsHash == keccak256(bytes(\"reentrancy_swap\"))) {\n ISwapFlashLoan(pool).swap(1, 0, 1e6, 0, now);\n } else if (\n paramsHash == keccak256(bytes(\"reentrancy_removeLiquidity\"))\n ) {\n ISwapFlashLoan(pool).removeLiquidity(1e18, new uint256[](0), now);\n } else if (\n paramsHash == keccak256(bytes(\"reentrancy_removeLiquidityOneToken\"))\n ) {\n ISwapFlashLoan(pool).removeLiquidityOneToken(1e18, 0, 1e18, now);\n }\n\n // 3. Payback debt\n uint256 totalDebt = amount.add(fee);\n IERC20(token).transfer(pool, totalDebt);\n }\n\n function flashLoan(\n ISwapFlashLoan swap,\n IERC20 token,\n uint256 amount,\n bytes memory params\n ) external {\n swap.flashLoan(address(this), token, amount, params);\n }\n}\n" + }, + "contracts/amm/interfaces/ISwapFlashLoan.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.6.12;\n\nimport \"./ISwap.sol\";\n\ninterface ISwapFlashLoan is ISwap {\n function flashLoan(\n address receiver,\n IERC20 token,\n uint256 amount,\n bytes memory params\n ) external;\n}\n" + }, + "hardhat/console.sol": { + "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" + }, + "contracts/amm/helper/test/TestSwapReturnValues.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.6.12;\n\nimport \"../../interfaces/ISwap.sol\";\nimport \"hardhat/console.sol\";\n\ncontract TestSwapReturnValues {\n using SafeMath for uint256;\n\n ISwap public swap;\n IERC20 public lpToken;\n uint8 public n;\n\n uint256 public constant MAX_INT = 2**256 - 1;\n\n constructor(\n ISwap swapContract,\n IERC20 lpTokenContract,\n uint8 numOfTokens\n ) public {\n swap = swapContract;\n lpToken = lpTokenContract;\n n = numOfTokens;\n\n // Pre-approve tokens\n for (uint8 i; i < n; i++) {\n swap.getToken(i).approve(address(swap), MAX_INT);\n }\n lpToken.approve(address(swap), MAX_INT);\n }\n\n function test_swap(\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx,\n uint256 minDy\n ) public {\n uint256 balanceBefore =\n swap.getToken(tokenIndexTo).balanceOf(address(this));\n uint256 returnValue =\n swap.swap(tokenIndexFrom, tokenIndexTo, dx, minDy, block.timestamp);\n uint256 balanceAfter =\n swap.getToken(tokenIndexTo).balanceOf(address(this));\n\n console.log(\n \"swap: Expected %s, got %s\",\n balanceAfter.sub(balanceBefore),\n returnValue\n );\n\n require(\n returnValue == balanceAfter.sub(balanceBefore),\n \"swap()'s return value does not match received amount\"\n );\n }\n\n function test_addLiquidity(uint256[] calldata amounts, uint256 minToMint)\n public\n {\n uint256 balanceBefore = lpToken.balanceOf(address(this));\n uint256 returnValue = swap.addLiquidity(amounts, minToMint, MAX_INT);\n uint256 balanceAfter = lpToken.balanceOf(address(this));\n\n console.log(\n \"addLiquidity: Expected %s, got %s\",\n balanceAfter.sub(balanceBefore),\n returnValue\n );\n\n require(\n returnValue == balanceAfter.sub(balanceBefore),\n \"addLiquidity()'s return value does not match minted amount\"\n );\n }\n\n function test_removeLiquidity(uint256 amount, uint256[] memory minAmounts)\n public\n {\n uint256[] memory balanceBefore = new uint256[](n);\n uint256[] memory balanceAfter = new uint256[](n);\n\n for (uint8 i = 0; i < n; i++) {\n balanceBefore[i] = swap.getToken(i).balanceOf(address(this));\n }\n\n uint256[] memory returnValue =\n swap.removeLiquidity(amount, minAmounts, MAX_INT);\n\n for (uint8 i = 0; i < n; i++) {\n balanceAfter[i] = swap.getToken(i).balanceOf(address(this));\n console.log(\n \"removeLiquidity: Expected %s, got %s\",\n balanceAfter[i].sub(balanceBefore[i]),\n returnValue[i]\n );\n require(\n balanceAfter[i].sub(balanceBefore[i]) == returnValue[i],\n \"removeLiquidity()'s return value does not match received amounts of tokens\"\n );\n }\n }\n\n function test_removeLiquidityImbalance(\n uint256[] calldata amounts,\n uint256 maxBurnAmount\n ) public {\n uint256 balanceBefore = lpToken.balanceOf(address(this));\n uint256 returnValue =\n swap.removeLiquidityImbalance(amounts, maxBurnAmount, MAX_INT);\n uint256 balanceAfter = lpToken.balanceOf(address(this));\n\n console.log(\n \"removeLiquidityImbalance: Expected %s, got %s\",\n balanceBefore.sub(balanceAfter),\n returnValue\n );\n\n require(\n returnValue == balanceBefore.sub(balanceAfter),\n \"removeLiquidityImbalance()'s return value does not match burned lpToken amount\"\n );\n }\n\n function test_removeLiquidityOneToken(\n uint256 tokenAmount,\n uint8 tokenIndex,\n uint256 minAmount\n ) public {\n uint256 balanceBefore =\n swap.getToken(tokenIndex).balanceOf(address(this));\n uint256 returnValue =\n swap.removeLiquidityOneToken(\n tokenAmount,\n tokenIndex,\n minAmount,\n MAX_INT\n );\n uint256 balanceAfter =\n swap.getToken(tokenIndex).balanceOf(address(this));\n\n console.log(\n \"removeLiquidityOneToken: Expected %s, got %s\",\n balanceAfter.sub(balanceBefore),\n returnValue\n );\n\n require(\n returnValue == balanceAfter.sub(balanceBefore),\n \"removeLiquidityOneToken()'s return value does not match received token amount\"\n );\n }\n}\n" + }, + "contracts/amm/SwapDeployer.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.6.12;\n\nimport \"@openzeppelin/contracts/access/Ownable.sol\";\nimport \"@openzeppelin/contracts/proxy/Clones.sol\";\nimport \"./interfaces/ISwap.sol\";\n\ncontract SwapDeployer is Ownable {\n event NewSwapPool(\n address indexed deployer,\n address swapAddress,\n IERC20[] pooledTokens\n );\n\n constructor() public Ownable() {}\n\n function deploy(\n address swapAddress,\n IERC20[] memory _pooledTokens,\n uint8[] memory decimals,\n string memory lpTokenName,\n string memory lpTokenSymbol,\n uint256 _a,\n uint256 _fee,\n uint256 _adminFee,\n address lpTokenTargetAddress\n ) external returns (address) {\n address swapClone = Clones.clone(swapAddress);\n ISwap(swapClone).initialize(\n _pooledTokens,\n decimals,\n lpTokenName,\n lpTokenSymbol,\n _a,\n _fee,\n _adminFee,\n lpTokenTargetAddress\n );\n Ownable(swapClone).transferOwnership(owner());\n emit NewSwapPool(msg.sender, swapClone, _pooledTokens);\n return swapClone;\n }\n}\n" + }, + "@openzeppelin/contracts/access/Ownable.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <0.8.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 () internal {\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" + }, + "contracts/bridge/SynapseERC20Factory.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.6.12;\n\nimport \"@openzeppelin/contracts/access/Ownable.sol\";\nimport \"@openzeppelin/contracts/proxy/Clones.sol\";\nimport \"./interfaces/ISynapseERC20.sol\";\n\ncontract SynapseERC20Factory {\n constructor() public {}\n\n event SynapseERC20Created(address contractAddress);\n\n /**\n * @notice Deploys a new node\n * @param synapseERC20Address address of the synapseERC20Address contract to initialize with\n * @param name Token name\n * @param symbol Token symbol\n * @param decimals Token name\n * @param owner admin address to be initialized with\n * @return Address of the newest node management contract created\n **/\n function deploy(\n address synapseERC20Address,\n string memory name,\n string memory symbol,\n uint8 decimals,\n address owner\n ) external returns (address) {\n address synERC20Clone = Clones.clone(synapseERC20Address);\n ISynapseERC20(synERC20Clone).initialize(name, symbol, decimals, owner);\n\n emit SynapseERC20Created(synERC20Clone);\n\n return synERC20Clone;\n }\n}\n" + }, + "contracts/bridge/interfaces/ISynapseERC20.sol": { + "content": "// SPDX-License-Identifier: MIT\n\n\npragma solidity 0.6.12;\n\ninterface ISynapseERC20 { \n function initialize(\n string memory _name, string memory _symbol, uint8 _decimals, address owner) external;\n\n function mint(address to, uint256 amount) external;\n}\n\n" + }, + "contracts/bridge/wrappers/AvaxJewelMigration.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.6.12;\n\nimport '@openzeppelin/contracts/token/ERC20/ERC20.sol';\nimport \"@openzeppelin/contracts/token/ERC20/SafeERC20.sol\";\nimport \"@openzeppelin/contracts/access/Ownable.sol\";\n\nimport '../interfaces/ISynapseBridge.sol';\n\ninterface IERC20Mintable is IERC20 {\n function mint(address to, uint256 amount) external;\n}\n\ncontract AvaxJewelMigration is Ownable {\n using SafeERC20 for IERC20;\n using SafeERC20 for IERC20Mintable;\n\n\n ISynapseBridge constant synapseBridge = ISynapseBridge(0xC05e61d0E7a63D27546389B7aD62FdFf5A91aACE);\n // MULTICHAIN JEWEL \n IERC20 constant legacyToken = IERC20(0x4f60a160D8C2DDdaAfe16FCC57566dB84D674BD6);\n // SYNAPSE JEWEL\n IERC20 constant newToken = IERC20(0x997Ddaa07d716995DE90577C123Db411584E5E46);\n uint256 constant MAX_UINT256 = 2**256 - 1;\n\n constructor() public {\n newToken.safeApprove(address(synapseBridge), MAX_UINT256);\n }\n\n function migrate(uint256 amount) public {\n legacyToken.safeTransferFrom(msg.sender, address(this), amount);\n IERC20Mintable(address(newToken)).mint(msg.sender, amount);\n }\n\n function migrateAndBridge(uint256 amount, address to, uint256 chainId) external {\n migrate(amount);\n synapseBridge.redeem(to, chainId, newToken, amount);\n }\n\n function redeemLegacy() external onlyOwner {\n uint256 legacyBalance = legacyToken.balanceOf(address(this));\n legacyToken.safeTransfer(owner(), legacyBalance);\n }\n} " + }, + "contracts/bridge/interfaces/ISynapseBridge.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.6.12;\n\nimport '@openzeppelin/contracts/token/ERC20/SafeERC20.sol';\nimport '@openzeppelin/contracts/token/ERC20/ERC20Burnable.sol';\n\ninterface ISynapseBridge {\n using SafeERC20 for IERC20;\n\n function deposit(\n address to,\n uint256 chainId,\n IERC20 token,\n uint256 amount\n ) external;\n\n function depositAndSwap(\n address to,\n uint256 chainId,\n IERC20 token,\n uint256 amount,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 minDy,\n uint256 deadline\n ) external;\n\n function redeem(\n address to,\n uint256 chainId,\n IERC20 token,\n uint256 amount\n ) external;\n\n\n function redeemv2(\n bytes32 to,\n uint256 chainId,\n IERC20 token,\n uint256 amount\n ) external;\n\n\n function redeemAndSwap(\n address to,\n uint256 chainId,\n IERC20 token,\n uint256 amount,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 minDy,\n uint256 deadline\n ) external;\n\n function redeemAndRemove(\n address to,\n uint256 chainId,\n IERC20 token,\n uint256 amount,\n uint8 liqTokenIndex,\n uint256 liqMinAmount,\n uint256 liqDeadline\n ) external;\n}\n" + }, + "@openzeppelin/contracts/token/ERC20/ERC20Burnable.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <0.8.0;\n\nimport \"../../utils/Context.sol\";\nimport \"./ERC20.sol\";\n\n/**\n * @dev Extension of {ERC20} that allows token holders to destroy both their own\n * tokens and those that they have an allowance for, in a way that can be\n * recognized off-chain (via event analysis).\n */\nabstract contract ERC20Burnable is Context, ERC20 {\n using SafeMath for uint256;\n\n /**\n * @dev Destroys `amount` tokens from the caller.\n *\n * See {ERC20-_burn}.\n */\n function burn(uint256 amount) public virtual {\n _burn(_msgSender(), amount);\n }\n\n /**\n * @dev Destroys `amount` tokens from `account`, deducting from the caller's\n * allowance.\n *\n * See {ERC20-_burn} and {ERC20-allowance}.\n *\n * Requirements:\n *\n * - the caller must have allowance for ``accounts``'s tokens of at least\n * `amount`.\n */\n function burnFrom(address account, uint256 amount) public virtual {\n uint256 decreasedAllowance = allowance(account, _msgSender()).sub(amount, \"ERC20: burn amount exceeds allowance\");\n\n _approve(account, _msgSender(), decreasedAllowance);\n _burn(account, amount);\n }\n}\n" + }, + "contracts/bridge/wrappers/MoonriverBridgeZap.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.6.12;\n\nimport \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/SafeERC20.sol\";\nimport \"../interfaces/ISwap.sol\";\nimport \"../interfaces/ISynapseBridge.sol\";\nimport \"../interfaces/IWETH9.sol\";\n\ninterface IFrax {\n function exchangeCanonicalForOld(address bridge_token_address, uint256 token_amount) external returns (uint256);\n}\n\ncontract MoonriverBridgeZap {\n using SafeERC20 for IERC20;\n\n ISynapseBridge synapseBridge;\n address payable public immutable WETH_ADDRESS;\n IFrax private constant CANOLICAL_FRAX = IFrax(0x1A93B23281CC1CDE4C4741353F3064709A16197d);\n IERC20 private constant SYN_FRAX = IERC20(0xE96AC70907ffF3Efee79f502C985A7A21Bce407d);\n\n mapping(address => address) public swapMap;\n mapping(address => IERC20[]) public swapTokensMap;\n\n uint256 constant MAX_UINT256 = 2**256 - 1;\n\n constructor(\n address payable _wethAddress,\n address _swapOne,\n address tokenOne,\n address _swapTwo,\n address tokenTwo,\n ISynapseBridge _synapseBridge\n ) public {\n WETH_ADDRESS = _wethAddress;\n synapseBridge = _synapseBridge;\n swapMap[tokenOne] = _swapOne;\n swapMap[tokenTwo] = _swapTwo;\n IERC20(_wethAddress).safeIncreaseAllowance(address(_synapseBridge), MAX_UINT256);\n if (address(_swapOne) != address(0)) {\n {\n uint8 i;\n for (; i < 32; i++) {\n try ISwap(_swapOne).getToken(i) returns (\n IERC20 token\n ) {\n swapTokensMap[_swapOne].push(token);\n token.safeApprove(address(_swapOne), MAX_UINT256);\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n } catch {\n break;\n }\n }\n require(i > 1, \"swap must have at least 2 tokens\");\n }\n }\n if (address(_swapTwo) != address(0)) {\n {\n uint8 i;\n for (; i < 32; i++) {\n try ISwap(_swapTwo).getToken(i) returns (\n IERC20 token\n ) {\n swapTokensMap[_swapTwo].push(token);\n token.safeApprove(address(_swapTwo), MAX_UINT256);\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n } catch {\n break;\n }\n }\n require(i > 1, \"swap must have at least 2 tokens\");\n }\n }\n }\n\n /**\n * @notice Calculate amount of tokens you receive on swap\n * @param tokenIndexFrom the token the user wants to sell\n * @param tokenIndexTo the token the user wants to buy\n * @param dx the amount of tokens the user wants to sell. If the token charges\n * a fee on transfers, use the amount that gets transferred after the fee.\n * @return amount of tokens the user will receive\n */\n function calculateSwap(\n IERC20 token,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx\n ) external view virtual returns (uint256) {\n ISwap swap = ISwap(\n swapMap[address(token)]\n );\n return swap.calculateSwap(tokenIndexFrom, tokenIndexTo, dx);\n }\n\n function swapAndRedeem(\n address to,\n uint256 chainId,\n IERC20 token,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx,\n uint256 minDy,\n uint256 deadline\n ) external {\n ISwap swap = ISwap(swapMap[address(token)]);\n require(address(swap) != address(0), \"Swap is 0x00\");\n IERC20[] memory tokens = swapTokensMap[address(swap)];\n tokens[tokenIndexFrom].safeTransferFrom(\n msg.sender,\n address(this),\n dx\n );\n // swap\n\n uint256 swappedAmount = swap.swap(\n tokenIndexFrom,\n tokenIndexTo,\n dx,\n minDy,\n deadline\n );\n // deposit into bridge, gets nUSD\n if (\n token.allowance(address(this), address(synapseBridge)) <\n swappedAmount\n ) {\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n }\n synapseBridge.redeem(to, chainId, token, swappedAmount);\n }\n\n function swapAndRedeemAndSwap(\n address to,\n uint256 chainId,\n IERC20 token,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx,\n uint256 minDy,\n uint256 deadline,\n uint8 swapTokenIndexFrom,\n uint8 swapTokenIndexTo,\n uint256 swapMinDy,\n uint256 swapDeadline\n ) external {\n require(\n address(swapMap[address(token)]) != address(0),\n \"Swap is 0x00\"\n );\n IERC20[] memory tokens = swapTokensMap[\n swapMap[address(token)]\n ];\n tokens[tokenIndexFrom].safeTransferFrom(\n msg.sender,\n address(this),\n dx\n );\n // swap\n\n uint256 swappedAmount = ISwap(swapMap[address(token)]).swap(tokenIndexFrom, tokenIndexTo, dx, minDy, deadline);\n // deposit into bridge, gets nUSD\n if (\n token.allowance(address(this), address(synapseBridge)) <\n swappedAmount\n ) {\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n }\n synapseBridge.redeemAndSwap(\n to,\n chainId,\n token,\n swappedAmount,\n swapTokenIndexFrom,\n swapTokenIndexTo,\n swapMinDy,\n swapDeadline\n );\n }\n\n function swapAndRedeemAndRemove(\n address to,\n uint256 chainId,\n IERC20 token,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx,\n uint256 minDy,\n uint256 deadline,\n uint8 liqTokenIndex,\n uint256 liqMinAmount,\n uint256 liqDeadline\n ) external {\n ISwap swap = ISwap(swapMap[address(token)]);\n require(address(swap) != address(0), \"Swap is 0x00\");\n IERC20[] memory tokens = swapTokensMap[address(swap)];\n tokens[tokenIndexFrom].safeTransferFrom(\n msg.sender,\n address(this),\n dx\n );\n // swap\n\n uint256 swappedAmount = swap.swap(\n tokenIndexFrom,\n tokenIndexTo,\n dx,\n minDy,\n deadline\n );\n // deposit into bridge, gets nUSD\n if (\n token.allowance(address(this), address(synapseBridge)) <\n swappedAmount\n ) {\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n }\n synapseBridge.redeemAndRemove(\n to,\n chainId,\n token,\n swappedAmount,\n liqTokenIndex,\n liqMinAmount,\n liqDeadline\n );\n }\n\n /**\n * @notice wraps SynapseBridge redeem()\n * @param to address on other chain to redeem underlying assets to\n * @param chainId which underlying chain to bridge assets onto\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n **/\n function redeem(\n address to,\n uint256 chainId,\n IERC20 token,\n uint256 amount\n ) external {\n token.safeTransferFrom(msg.sender, address(this), amount);\n if (address(token) == address(CANOLICAL_FRAX)) {\n uint256 swappedAmount = CANOLICAL_FRAX.exchangeCanonicalForOld(address(SYN_FRAX), amount);\n if (SYN_FRAX.allowance(address(this), address(synapseBridge)) < amount) {\n SYN_FRAX.safeApprove(address(synapseBridge), MAX_UINT256);\n }\n synapseBridge.redeem(to, chainId, SYN_FRAX, swappedAmount);\n } else {\n if (token.allowance(address(this), address(synapseBridge)) < amount) {\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n }\n synapseBridge.redeem(to, chainId, token, amount);\n }\n }\n\n /**\n * @notice Wraps SynapseBridge redeemv2() function\n * @param to address on other chain to bridge assets to\n * @param chainId which chain to bridge assets onto\n * @param token ERC20 compatible token to redeem into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n **/\n function redeemv2(\n bytes32 to,\n uint256 chainId,\n IERC20 token,\n uint256 amount\n ) external {\n token.safeTransferFrom(msg.sender, address(this), amount);\n\n if (token.allowance(address(this), address(synapseBridge)) < amount) {\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n }\n synapseBridge.redeemv2(to, chainId, token, amount);\n }\n\n /**\n * @notice wraps SynapseBridge redeem()\n * @param to address on other chain to redeem underlying assets to\n * @param chainId which underlying chain to bridge assets onto\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n **/\n function deposit(\n address to,\n uint256 chainId,\n IERC20 token,\n uint256 amount\n ) external {\n token.safeTransferFrom(msg.sender, address(this), amount);\n if (token.allowance(address(this), address(synapseBridge)) < amount) {\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n }\n synapseBridge.deposit(to, chainId, token, amount);\n }\n\n /**\n * @notice Wraps SynapseBridge deposit() function to make it compatible w/ ETH -> WETH conversions\n * @param to address on other chain to bridge assets to\n * @param chainId which chain to bridge assets onto\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n **/\n function depositETH(\n address to,\n uint256 chainId,\n uint256 amount\n ) external payable {\n require(msg.value > 0 && msg.value == amount, 'INCORRECT MSG VALUE');\n IWETH9(WETH_ADDRESS).deposit{value: msg.value}();\n synapseBridge.deposit(to, chainId, IERC20(WETH_ADDRESS), amount);\n }\n\n\n\n function swapETHAndRedeem(\n address to,\n uint256 chainId,\n IERC20 token,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx,\n uint256 minDy,\n uint256 deadline\n ) external payable {\n require(WETH_ADDRESS != address(0), \"WETH 0\");\n require(msg.value > 0 && msg.value == dx, \"INCORRECT MSG VALUE\");\n ISwap swap = ISwap(swapMap[address(token)]);\n require(address(swap) != address(0), \"Swap is 0x00\");\n IWETH9(WETH_ADDRESS).deposit{value: msg.value}();\n\n // swap\n uint256 swappedAmount = swap.swap(\n tokenIndexFrom,\n tokenIndexTo,\n dx,\n minDy,\n deadline\n );\n synapseBridge.redeem(to, chainId, token, swappedAmount);\n }\n\n /**\n * @notice Wraps redeemAndSwap on SynapseBridge.sol\n * Relays to nodes that (typically) a wrapped synAsset ERC20 token has been burned and the underlying needs to be redeeemed on the native chain. This function indicates to the nodes that they should attempt to redeem the LP token for the underlying assets (E.g \"swap\" out of the LP token)\n * @param to address on other chain to redeem underlying assets to\n * @param chainId which underlying chain to bridge assets onto\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n * @param tokenIndexFrom the token the user wants to swap from\n * @param tokenIndexTo the token the user wants to swap to\n * @param minDy the min amount the user would like to receive, or revert to only minting the SynERC20 token crosschain.\n * @param deadline latest timestamp to accept this transaction\n **/\n function redeemAndSwap(\n address to,\n uint256 chainId,\n IERC20 token,\n uint256 amount,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 minDy,\n uint256 deadline\n ) external {\n token.safeTransferFrom(msg.sender, address(this), amount);\n if (token.allowance(address(this), address(synapseBridge)) < amount) {\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n }\n synapseBridge.redeemAndSwap(\n to,\n chainId,\n token,\n amount,\n tokenIndexFrom,\n tokenIndexTo,\n minDy,\n deadline\n );\n }\n\n /**\n * @notice Wraps redeemAndRemove on SynapseBridge\n * Relays to nodes that (typically) a wrapped synAsset ERC20 token has been burned and the underlying needs to be redeeemed on the native chain. This function indicates to the nodes that they should attempt to redeem the LP token for the underlying assets (E.g \"swap\" out of the LP token)\n * @param to address on other chain to redeem underlying assets to\n * @param chainId which underlying chain to bridge assets onto\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount of (typically) LP token to pass to the nodes to attempt to removeLiquidity() with to redeem for the underlying assets of the LP token\n * @param liqTokenIndex Specifies which of the underlying LP assets the nodes should attempt to redeem for\n * @param liqMinAmount Specifies the minimum amount of the underlying asset needed for the nodes to execute the redeem/swap\n * @param liqDeadline Specificies the deadline that the nodes are allowed to try to redeem/swap the LP token\n **/\n function redeemAndRemove(\n address to,\n uint256 chainId,\n IERC20 token,\n uint256 amount,\n uint8 liqTokenIndex,\n uint256 liqMinAmount,\n uint256 liqDeadline\n ) external {\n token.safeTransferFrom(msg.sender, address(this), amount);\n if (token.allowance(address(this), address(synapseBridge)) < amount) {\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n }\n synapseBridge.redeemAndRemove(\n to,\n chainId,\n token,\n amount,\n liqTokenIndex,\n liqMinAmount,\n liqDeadline\n );\n }\n}\n" + }, + "contracts/bridge/interfaces/ISwap.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.6.12;\n\nimport '@openzeppelin/contracts/token/ERC20/ERC20.sol';\n\ninterface ISwap {\n // pool data view functions\n function getA() external view returns (uint256);\n\n function getToken(uint8 index) external view returns (IERC20);\n\n function getTokenIndex(address tokenAddress) external view returns (uint8);\n\n function getTokenBalance(uint8 index) external view returns (uint256);\n\n function getVirtualPrice() external view returns (uint256);\n\n // min return calculation functions\n function calculateSwap(\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx\n ) external view returns (uint256);\n\n function calculateTokenAmount(uint256[] calldata amounts, bool deposit)\n external\n view\n returns (uint256);\n\n function calculateRemoveLiquidity(uint256 amount)\n external\n view\n returns (uint256[] memory);\n\n function calculateRemoveLiquidityOneToken(\n uint256 tokenAmount,\n uint8 tokenIndex\n ) external view returns (uint256 availableTokenAmount);\n\n // state modifying functions\n function initialize(\n IERC20[] memory pooledTokens,\n uint8[] memory decimals,\n string memory lpTokenName,\n string memory lpTokenSymbol,\n uint256 a,\n uint256 fee,\n uint256 adminFee,\n address lpTokenTargetAddress\n ) external;\n\n function swap(\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx,\n uint256 minDy,\n uint256 deadline\n ) external returns (uint256);\n\n function addLiquidity(\n uint256[] calldata amounts,\n uint256 minToMint,\n uint256 deadline\n ) external returns (uint256);\n\n function removeLiquidity(\n uint256 amount,\n uint256[] calldata minAmounts,\n uint256 deadline\n ) external returns (uint256[] memory);\n\n function removeLiquidityOneToken(\n uint256 tokenAmount,\n uint8 tokenIndex,\n uint256 minAmount,\n uint256 deadline\n ) external returns (uint256);\n\n function removeLiquidityImbalance(\n uint256[] calldata amounts,\n uint256 maxBurnAmount,\n uint256 deadline\n ) external returns (uint256);\n}\n" + }, + "contracts/bridge/interfaces/IWETH9.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.4.0;\n\ninterface IWETH9 {\n function name() external view returns (string memory);\n\n function symbol() external view returns (string memory);\n\n function decimals() external view returns (uint8);\n\n function balanceOf(address) external view returns (uint256);\n\n function allowance(address, address) external view returns (uint256);\n\n receive() external payable;\n\n function deposit() external payable;\n\n function withdraw(uint256 wad) external;\n\n function totalSupply() external view returns (uint256);\n\n function approve(address guy, uint256 wad) external returns (bool);\n\n function transfer(address dst, uint256 wad) external returns (bool);\n\n function transferFrom(\n address src,\n address dst,\n uint256 wad\n ) external returns (bool);\n}" + }, + "contracts/bridge/wrappers/L2BridgeZap.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.6.12;\n\nimport \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/SafeERC20.sol\";\nimport \"../interfaces/ISwap.sol\";\nimport \"../interfaces/ISynapseBridge.sol\";\nimport \"../interfaces/IWETH9.sol\";\n\ncontract L2BridgeZap {\n using SafeERC20 for IERC20;\n\n ISynapseBridge synapseBridge;\n address payable public immutable WETH_ADDRESS;\n\n mapping(address => address) public swapMap;\n mapping(address => IERC20[]) public swapTokensMap;\n\n uint256 constant MAX_UINT256 = 2**256 - 1;\n\n constructor(\n address payable _wethAddress,\n address _swapOne,\n address tokenOne,\n address _swapTwo,\n address tokenTwo,\n ISynapseBridge _synapseBridge\n ) public {\n WETH_ADDRESS = _wethAddress;\n synapseBridge = _synapseBridge;\n swapMap[tokenOne] = _swapOne;\n swapMap[tokenTwo] = _swapTwo;\n if (_wethAddress != address(0)) {\n IERC20(_wethAddress).safeIncreaseAllowance(address(_synapseBridge), MAX_UINT256);\n }\n if (address(_swapOne) != address(0)) {\n {\n uint8 i;\n for (; i < 32; i++) {\n try ISwap(_swapOne).getToken(i) returns (\n IERC20 token\n ) {\n swapTokensMap[_swapOne].push(token);\n token.safeApprove(address(_swapOne), MAX_UINT256);\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n } catch {\n break;\n }\n }\n require(i > 1, \"swap must have at least 2 tokens\");\n }\n }\n if (address(_swapTwo) != address(0)) {\n {\n uint8 i;\n for (; i < 32; i++) {\n try ISwap(_swapTwo).getToken(i) returns (\n IERC20 token\n ) {\n swapTokensMap[_swapTwo].push(token);\n token.safeApprove(address(_swapTwo), MAX_UINT256);\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n } catch {\n break;\n }\n }\n require(i > 1, \"swap must have at least 2 tokens\");\n }\n }\n }\n\n /**\n * @notice Calculate amount of tokens you receive on swap\n * @param tokenIndexFrom the token the user wants to sell\n * @param tokenIndexTo the token the user wants to buy\n * @param dx the amount of tokens the user wants to sell. If the token charges\n * a fee on transfers, use the amount that gets transferred after the fee.\n * @return amount of tokens the user will receive\n */\n function calculateSwap(\n IERC20 token,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx\n ) external view virtual returns (uint256) {\n ISwap swap = ISwap(\n swapMap[address(token)]\n );\n return swap.calculateSwap(tokenIndexFrom, tokenIndexTo, dx);\n }\n\n function swapAndRedeem(\n address to,\n uint256 chainId,\n IERC20 token,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx,\n uint256 minDy,\n uint256 deadline\n ) external {\n ISwap swap = ISwap(swapMap[address(token)]);\n require(address(swap) != address(0), \"Swap is 0x00\");\n IERC20[] memory tokens = swapTokensMap[address(swap)];\n tokens[tokenIndexFrom].safeTransferFrom(\n msg.sender,\n address(this),\n dx\n );\n // swap\n\n uint256 swappedAmount = swap.swap(\n tokenIndexFrom,\n tokenIndexTo,\n dx,\n minDy,\n deadline\n );\n // deposit into bridge, gets nUSD\n if (\n token.allowance(address(this), address(synapseBridge)) <\n swappedAmount\n ) {\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n }\n synapseBridge.redeem(to, chainId, token, swappedAmount);\n }\n\n function swapAndRedeemAndSwap(\n address to,\n uint256 chainId,\n IERC20 token,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx,\n uint256 minDy,\n uint256 deadline,\n uint8 swapTokenIndexFrom,\n uint8 swapTokenIndexTo,\n uint256 swapMinDy,\n uint256 swapDeadline\n ) external {\n require(\n address(swapMap[address(token)]) != address(0),\n \"Swap is 0x00\"\n );\n IERC20[] memory tokens = swapTokensMap[\n swapMap[address(token)]\n ];\n tokens[tokenIndexFrom].safeTransferFrom(\n msg.sender,\n address(this),\n dx\n );\n // swap\n\n uint256 swappedAmount = ISwap(swapMap[address(token)]).swap(tokenIndexFrom, tokenIndexTo, dx, minDy, deadline);\n // deposit into bridge, gets nUSD\n if (\n token.allowance(address(this), address(synapseBridge)) <\n swappedAmount\n ) {\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n }\n synapseBridge.redeemAndSwap(\n to,\n chainId,\n token,\n swappedAmount,\n swapTokenIndexFrom,\n swapTokenIndexTo,\n swapMinDy,\n swapDeadline\n );\n }\n\n function swapAndRedeemAndRemove(\n address to,\n uint256 chainId,\n IERC20 token,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx,\n uint256 minDy,\n uint256 deadline,\n uint8 liqTokenIndex,\n uint256 liqMinAmount,\n uint256 liqDeadline\n ) external {\n ISwap swap = ISwap(swapMap[address(token)]);\n require(address(swap) != address(0), \"Swap is 0x00\");\n IERC20[] memory tokens = swapTokensMap[address(swap)];\n tokens[tokenIndexFrom].safeTransferFrom(\n msg.sender,\n address(this),\n dx\n );\n // swap\n\n uint256 swappedAmount = swap.swap(\n tokenIndexFrom,\n tokenIndexTo,\n dx,\n minDy,\n deadline\n );\n // deposit into bridge, gets nUSD\n if (\n token.allowance(address(this), address(synapseBridge)) <\n swappedAmount\n ) {\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n }\n synapseBridge.redeemAndRemove(\n to,\n chainId,\n token,\n swappedAmount,\n liqTokenIndex,\n liqMinAmount,\n liqDeadline\n );\n }\n\n /**\n * @notice wraps SynapseBridge redeem()\n * @param to address on other chain to redeem underlying assets to\n * @param chainId which underlying chain to bridge assets onto\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n **/\n function redeem(\n address to,\n uint256 chainId,\n IERC20 token,\n uint256 amount\n ) external {\n token.safeTransferFrom(msg.sender, address(this), amount);\n if (token.allowance(address(this), address(synapseBridge)) < amount) {\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n }\n synapseBridge.redeem(to, chainId, token, amount);\n }\n\n /**\n * @notice wraps SynapseBridge redeem()\n * @param to address on other chain to redeem underlying assets to\n * @param chainId which underlying chain to bridge assets onto\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n **/\n function deposit(\n address to,\n uint256 chainId,\n IERC20 token,\n uint256 amount\n ) external {\n token.safeTransferFrom(msg.sender, address(this), amount);\n if (token.allowance(address(this), address(synapseBridge)) < amount) {\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n }\n synapseBridge.deposit(to, chainId, token, amount);\n }\n\n /**\n * @notice Wraps SynapseBridge deposit() function to make it compatible w/ ETH -> WETH conversions\n * @param to address on other chain to bridge assets to\n * @param chainId which chain to bridge assets onto\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n **/\n function depositETH(\n address to,\n uint256 chainId,\n uint256 amount\n ) external payable {\n require(msg.value > 0 && msg.value == amount, 'INCORRECT MSG VALUE');\n IWETH9(WETH_ADDRESS).deposit{value: msg.value}();\n synapseBridge.deposit(to, chainId, IERC20(WETH_ADDRESS), amount);\n }\n\n\n function swapETHAndRedeem(\n address to,\n uint256 chainId,\n IERC20 token,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx,\n uint256 minDy,\n uint256 deadline\n ) external payable {\n require(WETH_ADDRESS != address(0), \"WETH 0\");\n require(msg.value > 0 && msg.value == dx, \"INCORRECT MSG VALUE\");\n ISwap swap = ISwap(swapMap[address(token)]);\n require(address(swap) != address(0), \"Swap is 0x00\");\n IWETH9(WETH_ADDRESS).deposit{value: msg.value}();\n\n // swap\n uint256 swappedAmount = swap.swap(\n tokenIndexFrom,\n tokenIndexTo,\n dx,\n minDy,\n deadline\n );\n synapseBridge.redeem(to, chainId, token, swappedAmount);\n }\n\n\n function swapETHAndRedeemAndSwap(\n address to,\n uint256 chainId,\n IERC20 token,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx,\n uint256 minDy,\n uint256 deadline,\n uint8 swapTokenIndexFrom,\n uint8 swapTokenIndexTo,\n uint256 swapMinDy,\n uint256 swapDeadline\n ) external payable {\n require(WETH_ADDRESS != address(0), \"WETH 0\");\n require(msg.value > 0 && msg.value == dx, \"INCORRECT MSG VALUE\");\n ISwap swap = ISwap(swapMap[address(token)]);\n require(address(swap) != address(0), \"Swap is 0x00\");\n IWETH9(WETH_ADDRESS).deposit{value: msg.value}();\n\n // swap\n uint256 swappedAmount = swap.swap(\n tokenIndexFrom,\n tokenIndexTo,\n dx,\n minDy,\n deadline\n );\n synapseBridge.redeemAndSwap(to, chainId, token, swappedAmount,swapTokenIndexFrom,\n swapTokenIndexTo,\n swapMinDy,\n swapDeadline);\n }\n\n\n /**\n * @notice Wraps redeemAndSwap on SynapseBridge.sol\n * Relays to nodes that (typically) a wrapped synAsset ERC20 token has been burned and the underlying needs to be redeeemed on the native chain. This function indicates to the nodes that they should attempt to redeem the LP token for the underlying assets (E.g \"swap\" out of the LP token)\n * @param to address on other chain to redeem underlying assets to\n * @param chainId which underlying chain to bridge assets onto\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n * @param tokenIndexFrom the token the user wants to swap from\n * @param tokenIndexTo the token the user wants to swap to\n * @param minDy the min amount the user would like to receive, or revert to only minting the SynERC20 token crosschain.\n * @param deadline latest timestamp to accept this transaction\n **/\n function redeemAndSwap(\n address to,\n uint256 chainId,\n IERC20 token,\n uint256 amount,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 minDy,\n uint256 deadline\n ) external {\n token.safeTransferFrom(msg.sender, address(this), amount);\n if (token.allowance(address(this), address(synapseBridge)) < amount) {\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n }\n synapseBridge.redeemAndSwap(\n to,\n chainId,\n token,\n amount,\n tokenIndexFrom,\n tokenIndexTo,\n minDy,\n deadline\n );\n }\n\n /**\n * @notice Wraps redeemAndRemove on SynapseBridge\n * Relays to nodes that (typically) a wrapped synAsset ERC20 token has been burned and the underlying needs to be redeeemed on the native chain. This function indicates to the nodes that they should attempt to redeem the LP token for the underlying assets (E.g \"swap\" out of the LP token)\n * @param to address on other chain to redeem underlying assets to\n * @param chainId which underlying chain to bridge assets onto\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount of (typically) LP token to pass to the nodes to attempt to removeLiquidity() with to redeem for the underlying assets of the LP token\n * @param liqTokenIndex Specifies which of the underlying LP assets the nodes should attempt to redeem for\n * @param liqMinAmount Specifies the minimum amount of the underlying asset needed for the nodes to execute the redeem/swap\n * @param liqDeadline Specificies the deadline that the nodes are allowed to try to redeem/swap the LP token\n **/\n function redeemAndRemove(\n address to,\n uint256 chainId,\n IERC20 token,\n uint256 amount,\n uint8 liqTokenIndex,\n uint256 liqMinAmount,\n uint256 liqDeadline\n ) external {\n token.safeTransferFrom(msg.sender, address(this), amount);\n if (token.allowance(address(this), address(synapseBridge)) < amount) {\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n }\n synapseBridge.redeemAndRemove(\n to,\n chainId,\n token,\n amount,\n liqTokenIndex,\n liqMinAmount,\n liqDeadline\n );\n }\n\n /**\n * @notice Wraps SynapseBridge redeemv2() function\n * @param to address on other chain to bridge assets to\n * @param chainId which chain to bridge assets onto\n * @param token ERC20 compatible token to redeem into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n **/\n function redeemv2(\n bytes32 to,\n uint256 chainId,\n IERC20 token,\n uint256 amount\n ) external {\n token.safeTransferFrom(msg.sender, address(this), amount);\n\n if (token.allowance(address(this), address(synapseBridge)) < amount) {\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n }\n synapseBridge.redeemv2(to, chainId, token, amount);\n }\n}\n" + }, + "contracts/bridge/wrappers/L1BridgeZap.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.6.12;\n\nimport '@openzeppelin/contracts/token/ERC20/IERC20.sol';\nimport '@openzeppelin/contracts/token/ERC20/SafeERC20.sol';\nimport '../interfaces/ISwap.sol';\nimport '../interfaces/ISynapseBridge.sol';\nimport \"../interfaces/IWETH9.sol\";\n\n\n/**\n * @title L1BridgeZap\n * @notice This contract is responsible for handling user Zaps into the SynapseBridge contract, through the Synapse Swap contracts. It does so\n * It does so by combining the action of addLiquidity() to the base swap pool, and then calling either deposit() or depositAndSwap() on the bridge.\n * This is done in hopes of automating portions of the bridge user experience to users, while keeping the SynapseBridge contract logic small.\n *\n * @dev This contract should be deployed with a base Swap.sol address and a SynapseBridge.sol address, otherwise, it will not function.\n */\ncontract L1BridgeZap {\n using SafeERC20 for IERC20;\n\n uint256 constant MAX_UINT256 = 2**256 - 1;\n \n ISwap baseSwap;\n ISynapseBridge synapseBridge;\n IERC20[] public baseTokens;\n address payable public immutable WETH_ADDRESS;\n \n\n /**\n * @notice Constructs the contract, approves each token inside of baseSwap to be used by baseSwap (needed for addLiquidity())\n */\n constructor(address payable _wethAddress, ISwap _baseSwap, ISynapseBridge _synapseBridge) public {\n WETH_ADDRESS = _wethAddress;\n baseSwap = _baseSwap;\n synapseBridge = _synapseBridge;\n IERC20(_wethAddress).safeIncreaseAllowance(address(_synapseBridge), MAX_UINT256);\n if (address(_baseSwap) != address(0)) {\n {\n uint8 i;\n for (; i < 32; i++) {\n try _baseSwap.getToken(i) returns (IERC20 token) {\n baseTokens.push(token);\n token.safeIncreaseAllowance(address(_baseSwap), MAX_UINT256);\n } catch {\n break;\n }\n }\n require(i > 1, 'baseSwap must have at least 2 tokens');\n }\n }\n }\n \n /**\n * @notice Wraps SynapseBridge deposit() function to make it compatible w/ ETH -> WETH conversions\n * @param to address on other chain to bridge assets to\n * @param chainId which chain to bridge assets onto\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n **/\n function depositETH(\n address to,\n uint256 chainId,\n uint256 amount\n ) external payable {\n require(msg.value > 0 && msg.value == amount, 'INCORRECT MSG VALUE');\n IWETH9(WETH_ADDRESS).deposit{value: msg.value}();\n synapseBridge.deposit(to, chainId, IERC20(WETH_ADDRESS), amount);\n }\n\n /**\n * @notice Wraps SynapseBridge depositAndSwap() function to make it compatible w/ ETH -> WETH conversions\n * @param to address on other chain to bridge assets to\n * @param chainId which chain to bridge assets onto\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n * @param tokenIndexFrom the token the user wants to swap from\n * @param tokenIndexTo the token the user wants to swap to\n * @param minDy the min amount the user would like to receive, or revert to only minting the SynERC20 token crosschain.\n * @param deadline latest timestamp to accept this transaction\n **/\n function depositETHAndSwap(\n address to,\n uint256 chainId,\n uint256 amount,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 minDy,\n uint256 deadline\n ) external payable {\n require(msg.value > 0 && msg.value == amount, 'INCORRECT MSG VALUE');\n IWETH9(WETH_ADDRESS).deposit{value: msg.value}();\n synapseBridge.depositAndSwap(to, chainId, IERC20(WETH_ADDRESS), amount, tokenIndexFrom, tokenIndexTo, minDy, deadline);\n }\n\n\n /**\n * @notice A simple method to calculate prices from deposits or\n * withdrawals, excluding fees but including slippage. This is\n * helpful as an input into the various \"min\" parameters on calls\n * to fight front-running\n *\n * @dev This shouldn't be used outside frontends for user estimates.\n *\n * @param amounts an array of token amounts to deposit or withdrawal,\n * corresponding to pooledTokens. The amount should be in each\n * pooled token's native precision.\n * @param deposit whether this is a deposit or a withdrawal\n * @return token amount the user will receive\n */\n function calculateTokenAmount(uint256[] calldata amounts, bool deposit)\n external\n view\n virtual\n returns (uint256)\n {\n return baseSwap.calculateTokenAmount(amounts, deposit);\n }\n\n /**\n * @notice Calculate the amount of underlying token available to withdraw\n * when withdrawing via only single token\n * @param tokenAmount the amount of LP token to burn\n * @param tokenIndex index of which token will be withdrawn\n * @return availableTokenAmount calculated amount of underlying token\n * available to withdraw\n */\n function calculateRemoveLiquidityOneToken(\n uint256 tokenAmount,\n uint8 tokenIndex\n ) external view virtual returns (uint256 availableTokenAmount) {\n return baseSwap.calculateRemoveLiquidityOneToken(tokenAmount, tokenIndex);\n }\n\n\n /**\n * @notice Combines adding liquidity to the given Swap, and calls deposit() on the bridge using that LP token\n * @param to address on other chain to bridge assets to\n * @param chainId which chain to bridge assets onto\n * @param token ERC20 compatible token to deposit into the bridge\n * @param liquidityAmounts the amounts of each token to add, in their native precision\n * @param minToMint the minimum LP tokens adding this amount of liquidity\n * should mint, otherwise revert. Handy for front-running mitigation\n * @param deadline latest timestamp to accept this transaction\n **/\n function zapAndDeposit(\n address to,\n uint256 chainId,\n IERC20 token,\n uint256[] calldata liquidityAmounts,\n uint256 minToMint,\n uint256 deadline\n ) external {\n // add liquidity\n for (uint256 i = 0; i < baseTokens.length; i++) {\n if (liquidityAmounts[i] != 0) {\n baseTokens[i].safeTransferFrom(\n msg.sender,\n address(this),\n liquidityAmounts[i]\n );\n }\n }\n\n uint256 liqAdded = baseSwap.addLiquidity(\n liquidityAmounts,\n minToMint,\n deadline\n );\n // deposit into bridge, gets nUSD\n if (token.allowance(address(this), address(synapseBridge)) < liqAdded) {\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n }\n synapseBridge.deposit(to, chainId, token, liqAdded);\n }\n\n /**\n * @notice Combines adding liquidity to the given Swap, and calls depositAndSwap() on the bridge using that LP token\n * @param to address on other chain to bridge assets to\n * @param chainId which chain to bridge assets onto\n * @param token ERC20 compatible token to deposit into the bridge\n * @param liquidityAmounts the amounts of each token to add, in their native precision\n * @param minToMint the minimum LP tokens adding this amount of liquidity\n * should mint, otherwise revert. Handy for front-running mitigation\n * @param liqDeadline latest timestamp to accept this transaction\n * @param tokenIndexFrom the token the user wants to swap from\n * @param tokenIndexTo the token the user wants to swap to\n * @param minDy the min amount the user would like to receive, or revert to only minting the SynERC20 token crosschain.\n * @param swapDeadline latest timestamp to accept this transaction\n **/\n function zapAndDepositAndSwap(\n address to,\n uint256 chainId,\n IERC20 token,\n uint256[] calldata liquidityAmounts,\n uint256 minToMint,\n uint256 liqDeadline,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 minDy,\n uint256 swapDeadline\n ) external {\n // add liquidity\n for (uint256 i = 0; i < baseTokens.length; i++) {\n if (liquidityAmounts[i] != 0) {\n baseTokens[i].safeTransferFrom(\n msg.sender,\n address(this),\n liquidityAmounts[i]\n );\n }\n }\n\n uint256 liqAdded = baseSwap.addLiquidity(\n liquidityAmounts,\n minToMint,\n liqDeadline\n );\n // deposit into bridge, bridge attemps to swap into desired asset\n if (token.allowance(address(this), address(synapseBridge)) < liqAdded) {\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n }\n synapseBridge.depositAndSwap(\n to,\n chainId,\n token,\n liqAdded,\n tokenIndexFrom,\n tokenIndexTo,\n minDy,\n swapDeadline\n );\n }\n\n /**\n * @notice Wraps SynapseBridge deposit() function\n * @param to address on other chain to bridge assets to\n * @param chainId which chain to bridge assets onto\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n **/\n function deposit(\n address to,\n uint256 chainId,\n IERC20 token,\n uint256 amount\n ) external {\n token.safeTransferFrom(msg.sender, address(this), amount);\n\n if (token.allowance(address(this), address(synapseBridge)) < amount) {\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n }\n synapseBridge.deposit(to, chainId, token, amount);\n }\n \n /**\n * @notice Wraps SynapseBridge depositAndSwap() function\n * @param to address on other chain to bridge assets to\n * @param chainId which chain to bridge assets onto\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n * @param tokenIndexFrom the token the user wants to swap from\n * @param tokenIndexTo the token the user wants to swap to\n * @param minDy the min amount the user would like to receive, or revert to only minting the SynERC20 token crosschain.\n * @param deadline latest timestamp to accept this transaction\n **/\n function depositAndSwap(\n address to,\n uint256 chainId,\n IERC20 token,\n uint256 amount,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 minDy,\n uint256 deadline\n ) external {\n token.safeTransferFrom(msg.sender, address(this), amount);\n \n if (token.allowance(address(this), address(synapseBridge)) < amount) {\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n }\n synapseBridge.depositAndSwap(to, chainId, token, amount, tokenIndexFrom, tokenIndexTo, minDy, deadline);\n }\n\n\n /**\n * @notice Wraps SynapseBridge redeem() function\n * @param to address on other chain to bridge assets to\n * @param chainId which chain to bridge assets onto\n * @param token ERC20 compatible token to redeem into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n **/\n function redeem(\n address to,\n uint256 chainId,\n IERC20 token,\n uint256 amount\n ) external {\n token.safeTransferFrom(msg.sender, address(this), amount);\n\n if (token.allowance(address(this), address(synapseBridge)) < amount) {\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n }\n synapseBridge.redeem(to, chainId, token, amount);\n }\n\n /**\n * @notice Wraps SynapseBridge redeemv2() function\n * @param to address on other chain to bridge assets to\n * @param chainId which chain to bridge assets onto\n * @param token ERC20 compatible token to redeem into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n **/\n function redeemv2(\n bytes32 to,\n uint256 chainId,\n IERC20 token,\n uint256 amount\n ) external {\n token.safeTransferFrom(msg.sender, address(this), amount);\n\n if (token.allowance(address(this), address(synapseBridge)) < amount) {\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n }\n synapseBridge.redeemv2(to, chainId, token, amount);\n }\n\n}\n" + }, + "contracts/bridge/wrappers/MigratorBridgeZap.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.6.12;\n\nimport '@openzeppelin/contracts/token/ERC20/IERC20.sol';\nimport '@openzeppelin/contracts/token/ERC20/SafeERC20.sol';\nimport '@openzeppelin/contracts/math/SafeMath.sol';\n\nimport '../interfaces/ISynapseBridge.sol';\nimport '../interfaces/IERC20Migrator.sol';\n\ncontract MigratorBridgeZap {\n using SafeERC20 for IERC20;\n using SafeMath for uint256;\n \n ISynapseBridge constant synapseBridge = ISynapseBridge(0xd123f70AE324d34A9E76b67a27bf77593bA8749f);\n IERC20Migrator constant erc20Migrator = IERC20Migrator(0xf0284FB86adA5E4D82555C529677eEA3B2C3E022); \n IERC20 constant legacyToken = IERC20(0x42F6f551ae042cBe50C739158b4f0CAC0Edb9096);\n IERC20 constant newToken = IERC20(0xa4080f1778e69467E905B8d6F72f6e441f9e9484);\n uint256 constant MAX_UINT256 = 2**256 - 1;\n\n constructor() public {\n legacyToken.safeApprove(address(erc20Migrator), MAX_UINT256);\n newToken.safeApprove(address(synapseBridge), MAX_UINT256);\n }\n\n function migrate(uint256 amount) external {\n legacyToken.safeTransferFrom(msg.sender, address(this), amount);\n erc20Migrator.migrate(amount);\n newToken.safeTransfer(msg.sender, amount.mul(5).div(2));\n }\n\n function migrateAndBridge(uint256 amount, address to, uint256 chainId) external {\n legacyToken.safeTransferFrom(msg.sender, address(this), amount);\n erc20Migrator.migrate(amount);\n synapseBridge.redeem(to, chainId, newToken, amount.mul(5).div(2));\n }\n}" + }, + "contracts/bridge/interfaces/IERC20Migrator.sol": { + "content": "// SPDX-License-Identifier: MIT\n\n\npragma solidity 0.6.12;\n\ninterface IERC20Migrator { \n function migrate(uint256 amount) external;\n}\n\n" + }, + "contracts/bridge/wrappers/JewelBridgeSwap.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.6.12;\n\nimport '@openzeppelin/contracts/token/ERC20/ERC20.sol';\nimport \"@openzeppelin/contracts/token/ERC20/SafeERC20.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/ERC20Burnable.sol\";\nimport \"@openzeppelin/contracts/math/SafeMath.sol\";\n\ninterface IERC20Mintable is IERC20 {\n function mint(address to, uint256 amount) external;\n}\n\ncontract JewelBridgeSwap {\n using SafeERC20 for IERC20;\n using SafeERC20 for IERC20Mintable;\n using SafeMath for uint256;\n\n // Maps token address to an index in the pool. Used to prevent duplicate tokens in the pool.\n // getTokenIndex function also relies on this mapping to retrieve token index.\n mapping(address => uint8) private tokenIndexes;\n IERC20[2] pooledTokens;\n \n constructor(IERC20 tokenA, IERC20 mintableTokenB) public {\n pooledTokens[0] = tokenA;\n pooledTokens[1] = mintableTokenB;\n tokenIndexes[address(tokenA)] = 0;\n tokenIndexes[address(mintableTokenB)] = 1;\n }\n\n /**\n * @notice Return address of the pooled token at given index. Reverts if tokenIndex is out of range.\n * @param index the index of the token\n * @return address of the token at given index\n */\n function getToken(uint8 index) public view returns (IERC20) {\n require(index < pooledTokens.length, \"Out of range\");\n return pooledTokens[index];\n }\n\n /**\n * @notice Return the index of the given token address. Reverts if no matching\n * token is found.\n * @param tokenAddress address of the token\n * @return the index of the given token address\n */\n function getTokenIndex(address tokenAddress)\n public\n view\n returns (uint8)\n {\n uint8 index = tokenIndexes[tokenAddress];\n require(\n address(getToken(index)) == tokenAddress,\n \"Token does not exist\"\n );\n return index;\n }\n\n /**\n * @notice Calculate amount of tokens you receive on swap\n * @param tokenIndexFrom the token the user wants to sell\n * @param tokenIndexTo the token the user wants to buy\n * @param dx the amount of tokens the user wants to swap. \n * @return amount of tokens the user will receive\n */\n function calculateSwap(\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx\n ) external view returns (uint256) {\n return dx;\n }\n\n /**\n * @notice Swap two tokens using this pool\n * @param tokenIndexFrom the token the user wants to swap from\n * @param tokenIndexTo the token the user wants to swap to\n * @param dx the amount of tokens the user wants to swap from\n * @param minDy the min amount the user would like to receive, or revert.\n * @param deadline latest timestamp to accept this transaction\n */\n function swap(\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx,\n uint256 minDy,\n uint256 deadline\n )\n external\n returns (uint256)\n {\n {\n IERC20 tokenFrom = pooledTokens[tokenIndexFrom];\n require(\n dx <= tokenFrom.balanceOf(msg.sender),\n \"Cannot swap more than you own\"\n );\n // Transfer tokens first to see if a fee was charged on transfer\n uint256 beforeBalance = tokenFrom.balanceOf(address(this));\n tokenFrom.safeTransferFrom(msg.sender, address(this), dx);\n\n // Use the actual transferred amount for AMM math\n dx = tokenFrom.balanceOf(address(this)).sub(beforeBalance);\n }\n\n // redeem JEWEL for synJEWEL\n if (tokenIndexFrom == 0 && tokenIndexTo == 1) {\n IERC20Mintable(address(pooledTokens[tokenIndexTo])).mint(msg.sender, dx);\n return dx;\n // redeem synJEWEL for JEWEL\n } else if (tokenIndexFrom == 1 && tokenIndexTo == 0) {\n ERC20Burnable(address(pooledTokens[tokenIndexFrom])).burn(dx);\n pooledTokens[tokenIndexTo].safeTransfer(msg.sender, dx);\n return dx;\n } else {\n revert(\"Unsupported indexes\");\n }\n }\n}" + }, + "contracts/bridge/testing/SynapseToken.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity >=0.6.0 <0.8.0;\n\n\nimport \"@openzeppelin/contracts/token/ERC20/ERC20.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/ERC20Burnable.sol\";\nimport \"@openzeppelin/contracts/access/AccessControl.sol\";\nimport \"@openzeppelin/contracts/drafts/ERC20Permit.sol\";\n\ncontract Synapse is ERC20, ERC20Burnable, AccessControl, ERC20Permit {\n bytes32 public constant MINTER_ROLE = keccak256(\"MINTER_ROLE\");\n\n constructor() public ERC20(\"Synapse\", \"SYN\") ERC20Permit(\"Synapse\") {\n _setupRole(DEFAULT_ADMIN_ROLE, msg.sender);\n _setupRole(MINTER_ROLE, msg.sender);\n }\n\n function mint(address to, uint256 amount) external {\n require(hasRole(MINTER_ROLE, msg.sender));\n _mint(to, amount);\n }\n}" + }, + "@openzeppelin/contracts/access/AccessControl.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <0.8.0;\n\nimport \"../utils/EnumerableSet.sol\";\nimport \"../utils/Address.sol\";\nimport \"../utils/Context.sol\";\n\n/**\n * @dev Contract module that allows children to implement role-based access\n * control mechanisms.\n *\n * Roles are referred to by their `bytes32` identifier. These should be exposed\n * in the external API and be unique. The best way to achieve this is by\n * using `public constant` hash digests:\n *\n * ```\n * bytes32 public constant MY_ROLE = keccak256(\"MY_ROLE\");\n * ```\n *\n * Roles can be used to represent a set of permissions. To restrict access to a\n * function call, use {hasRole}:\n *\n * ```\n * function foo() public {\n * require(hasRole(MY_ROLE, msg.sender));\n * ...\n * }\n * ```\n *\n * Roles can be granted and revoked dynamically via the {grantRole} and\n * {revokeRole} functions. Each role has an associated admin role, and only\n * accounts that have a role's admin role can call {grantRole} and {revokeRole}.\n *\n * By default, the admin role for all roles is `DEFAULT_ADMIN_ROLE`, which means\n * that only accounts with this role will be able to grant or revoke other\n * roles. More complex role relationships can be created by using\n * {_setRoleAdmin}.\n *\n * WARNING: The `DEFAULT_ADMIN_ROLE` is also its own admin: it has permission to\n * grant and revoke this role. Extra precautions should be taken to secure\n * accounts that have been granted it.\n */\nabstract contract AccessControl is Context {\n using EnumerableSet for EnumerableSet.AddressSet;\n using Address for address;\n\n struct RoleData {\n EnumerableSet.AddressSet members;\n bytes32 adminRole;\n }\n\n mapping (bytes32 => RoleData) private _roles;\n\n bytes32 public constant DEFAULT_ADMIN_ROLE = 0x00;\n\n /**\n * @dev Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole`\n *\n * `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite\n * {RoleAdminChanged} not being emitted signaling this.\n *\n * _Available since v3.1._\n */\n event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole);\n\n /**\n * @dev Emitted when `account` is granted `role`.\n *\n * `sender` is the account that originated the contract call, an admin role\n * bearer except when using {_setupRole}.\n */\n event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender);\n\n /**\n * @dev Emitted when `account` is revoked `role`.\n *\n * `sender` is the account that originated the contract call:\n * - if using `revokeRole`, it is the admin role bearer\n * - if using `renounceRole`, it is the role bearer (i.e. `account`)\n */\n event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender);\n\n /**\n * @dev Returns `true` if `account` has been granted `role`.\n */\n function hasRole(bytes32 role, address account) public view returns (bool) {\n return _roles[role].members.contains(account);\n }\n\n /**\n * @dev Returns the number of accounts that have `role`. Can be used\n * together with {getRoleMember} to enumerate all bearers of a role.\n */\n function getRoleMemberCount(bytes32 role) public view returns (uint256) {\n return _roles[role].members.length();\n }\n\n /**\n * @dev Returns one of the accounts that have `role`. `index` must be a\n * value between 0 and {getRoleMemberCount}, non-inclusive.\n *\n * Role bearers are not sorted in any particular way, and their ordering may\n * change at any point.\n *\n * WARNING: When using {getRoleMember} and {getRoleMemberCount}, make sure\n * you perform all queries on the same block. See the following\n * https://forum.openzeppelin.com/t/iterating-over-elements-on-enumerableset-in-openzeppelin-contracts/2296[forum post]\n * for more information.\n */\n function getRoleMember(bytes32 role, uint256 index) public view returns (address) {\n return _roles[role].members.at(index);\n }\n\n /**\n * @dev Returns the admin role that controls `role`. See {grantRole} and\n * {revokeRole}.\n *\n * To change a role's admin, use {_setRoleAdmin}.\n */\n function getRoleAdmin(bytes32 role) public view returns (bytes32) {\n return _roles[role].adminRole;\n }\n\n /**\n * @dev Grants `role` to `account`.\n *\n * If `account` had not been already granted `role`, emits a {RoleGranted}\n * event.\n *\n * Requirements:\n *\n * - the caller must have ``role``'s admin role.\n */\n function grantRole(bytes32 role, address account) public virtual {\n require(hasRole(_roles[role].adminRole, _msgSender()), \"AccessControl: sender must be an admin to grant\");\n\n _grantRole(role, account);\n }\n\n /**\n * @dev Revokes `role` from `account`.\n *\n * If `account` had been granted `role`, emits a {RoleRevoked} event.\n *\n * Requirements:\n *\n * - the caller must have ``role``'s admin role.\n */\n function revokeRole(bytes32 role, address account) public virtual {\n require(hasRole(_roles[role].adminRole, _msgSender()), \"AccessControl: sender must be an admin to revoke\");\n\n _revokeRole(role, account);\n }\n\n /**\n * @dev Revokes `role` from the calling account.\n *\n * Roles are often managed via {grantRole} and {revokeRole}: this function's\n * purpose is to provide a mechanism for accounts to lose their privileges\n * if they are compromised (such as when a trusted device is misplaced).\n *\n * If the calling account had been granted `role`, emits a {RoleRevoked}\n * event.\n *\n * Requirements:\n *\n * - the caller must be `account`.\n */\n function renounceRole(bytes32 role, address account) public virtual {\n require(account == _msgSender(), \"AccessControl: can only renounce roles for self\");\n\n _revokeRole(role, account);\n }\n\n /**\n * @dev Grants `role` to `account`.\n *\n * If `account` had not been already granted `role`, emits a {RoleGranted}\n * event. Note that unlike {grantRole}, this function doesn't perform any\n * checks on the calling account.\n *\n * [WARNING]\n * ====\n * This function should only be called from the constructor when setting\n * up the initial roles for the system.\n *\n * Using this function in any other way is effectively circumventing the admin\n * system imposed by {AccessControl}.\n * ====\n */\n function _setupRole(bytes32 role, address account) internal virtual {\n _grantRole(role, account);\n }\n\n /**\n * @dev Sets `adminRole` as ``role``'s admin role.\n *\n * Emits a {RoleAdminChanged} event.\n */\n function _setRoleAdmin(bytes32 role, bytes32 adminRole) internal virtual {\n emit RoleAdminChanged(role, _roles[role].adminRole, adminRole);\n _roles[role].adminRole = adminRole;\n }\n\n function _grantRole(bytes32 role, address account) private {\n if (_roles[role].members.add(account)) {\n emit RoleGranted(role, account, _msgSender());\n }\n }\n\n function _revokeRole(bytes32 role, address account) private {\n if (_roles[role].members.remove(account)) {\n emit RoleRevoked(role, account, _msgSender());\n }\n }\n}\n" + }, + "@openzeppelin/contracts/drafts/ERC20Permit.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.5 <0.8.0;\n\nimport \"../token/ERC20/ERC20.sol\";\nimport \"./IERC20Permit.sol\";\nimport \"../cryptography/ECDSA.sol\";\nimport \"../utils/Counters.sol\";\nimport \"./EIP712.sol\";\n\n/**\n * @dev Implementation of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in\n * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612].\n *\n * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by\n * presenting a message signed by the account. By not relying on `{IERC20-approve}`, the token holder account doesn't\n * need to send a transaction, and thus is not required to hold Ether at all.\n *\n * _Available since v3.4._\n */\nabstract contract ERC20Permit is ERC20, IERC20Permit, EIP712 {\n using Counters for Counters.Counter;\n\n mapping (address => Counters.Counter) private _nonces;\n\n // solhint-disable-next-line var-name-mixedcase\n bytes32 private immutable _PERMIT_TYPEHASH = keccak256(\"Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)\");\n\n /**\n * @dev Initializes the {EIP712} domain separator using the `name` parameter, and setting `version` to `\"1\"`.\n *\n * It's a good idea to use the same `name` that is defined as the ERC20 token name.\n */\n constructor(string memory name) internal EIP712(name, \"1\") {\n }\n\n /**\n * @dev See {IERC20Permit-permit}.\n */\n function permit(address owner, address spender, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s) public virtual override {\n // solhint-disable-next-line not-rely-on-time\n require(block.timestamp <= deadline, \"ERC20Permit: expired deadline\");\n\n bytes32 structHash = keccak256(\n abi.encode(\n _PERMIT_TYPEHASH,\n owner,\n spender,\n value,\n _nonces[owner].current(),\n deadline\n )\n );\n\n bytes32 hash = _hashTypedDataV4(structHash);\n\n address signer = ECDSA.recover(hash, v, r, s);\n require(signer == owner, \"ERC20Permit: invalid signature\");\n\n _nonces[owner].increment();\n _approve(owner, spender, value);\n }\n\n /**\n * @dev See {IERC20Permit-nonces}.\n */\n function nonces(address owner) public view override returns (uint256) {\n return _nonces[owner].current();\n }\n\n /**\n * @dev See {IERC20Permit-DOMAIN_SEPARATOR}.\n */\n // solhint-disable-next-line func-name-mixedcase\n function DOMAIN_SEPARATOR() external view override returns (bytes32) {\n return _domainSeparatorV4();\n }\n}\n" + }, + "@openzeppelin/contracts/utils/EnumerableSet.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <0.8.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" + }, + "@openzeppelin/contracts/drafts/IERC20Permit.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <0.8.0;\n\n/**\n * @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in\n * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612].\n *\n * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by\n * presenting a message signed by the account. By not relying on `{IERC20-approve}`, the token holder account doesn't\n * need to send a transaction, and thus is not required to hold Ether at all.\n */\ninterface IERC20Permit {\n /**\n * @dev Sets `value` as the allowance of `spender` over `owner`'s tokens,\n * given `owner`'s signed approval.\n *\n * IMPORTANT: The same issues {IERC20-approve} has related to transaction\n * ordering also apply here.\n *\n * Emits an {Approval} event.\n *\n * Requirements:\n *\n * - `spender` cannot be the zero address.\n * - `deadline` must be a timestamp in the future.\n * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner`\n * over the EIP712-formatted function arguments.\n * - the signature must use ``owner``'s current nonce (see {nonces}).\n *\n * For more information on the signature format, see the\n * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP\n * section].\n */\n function permit(address owner, address spender, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s) external;\n\n /**\n * @dev Returns the current nonce for `owner`. This value must be\n * included whenever a signature is generated for {permit}.\n *\n * Every successful call to {permit} increases ``owner``'s nonce by one. This\n * prevents a signature from being used multiple times.\n */\n function nonces(address owner) external view returns (uint256);\n\n /**\n * @dev Returns the domain separator used in the encoding of the signature for `permit`, as defined by {EIP712}.\n */\n // solhint-disable-next-line func-name-mixedcase\n function DOMAIN_SEPARATOR() external view returns (bytes32);\n}\n" + }, + "@openzeppelin/contracts/cryptography/ECDSA.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <0.8.0;\n\n/**\n * @dev Elliptic Curve Digital Signature Algorithm (ECDSA) operations.\n *\n * These functions can be used to verify that a message was signed by the holder\n * of the private keys of a given address.\n */\nlibrary ECDSA {\n /**\n * @dev Returns the address that signed a hashed message (`hash`) with\n * `signature`. This address can then be used for verification purposes.\n *\n * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:\n * this function rejects them by requiring the `s` value to be in the lower\n * half order, and the `v` value to be either 27 or 28.\n *\n * IMPORTANT: `hash` _must_ be the result of a hash operation for the\n * verification to be secure: it is possible to craft signatures that\n * recover to arbitrary addresses for non-hashed data. A safe way to ensure\n * this is by receiving a hash of the original message (which may otherwise\n * be too long), and then calling {toEthSignedMessageHash} on it.\n */\n function recover(bytes32 hash, bytes memory signature) internal pure returns (address) {\n // Check the signature length\n if (signature.length != 65) {\n revert(\"ECDSA: invalid signature length\");\n }\n\n // Divide the signature in r, s and v variables\n bytes32 r;\n bytes32 s;\n uint8 v;\n\n // ecrecover takes the signature parameters, and the only way to get them\n // currently is to use assembly.\n // solhint-disable-next-line no-inline-assembly\n assembly {\n r := mload(add(signature, 0x20))\n s := mload(add(signature, 0x40))\n v := byte(0, mload(add(signature, 0x60)))\n }\n\n return recover(hash, v, r, s);\n }\n\n /**\n * @dev Overload of {ECDSA-recover-bytes32-bytes-} that receives the `v`,\n * `r` and `s` signature fields separately.\n */\n function recover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) internal pure returns (address) {\n // EIP-2 still allows signature malleability for ecrecover(). Remove this possibility and make the signature\n // unique. Appendix F in the Ethereum Yellow paper (https://ethereum.github.io/yellowpaper/paper.pdf), defines\n // the valid range for s in (281): 0 < s < secp256k1n ÷ 2 + 1, and for v in (282): v ∈ {27, 28}. Most\n // signatures from current libraries generate a unique signature with an s-value in the lower half order.\n //\n // If your library generates malleable signatures, such as s-values in the upper range, calculate a new s-value\n // with 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 - s1 and flip v from 27 to 28 or\n // vice versa. If your library also generates signatures with 0/1 for v instead 27/28, add 27 to v to accept\n // these malleable signatures as well.\n require(uint256(s) <= 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0, \"ECDSA: invalid signature 's' value\");\n require(v == 27 || v == 28, \"ECDSA: invalid signature 'v' value\");\n\n // If the signature is valid (and not malleable), return the signer address\n address signer = ecrecover(hash, v, r, s);\n require(signer != address(0), \"ECDSA: invalid signature\");\n\n return signer;\n }\n\n /**\n * @dev Returns an Ethereum Signed Message, created from a `hash`. This\n * replicates the behavior of the\n * https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_sign[`eth_sign`]\n * JSON-RPC method.\n *\n * See {recover}.\n */\n function toEthSignedMessageHash(bytes32 hash) internal pure returns (bytes32) {\n // 32 is the length in bytes of hash,\n // enforced by the type signature above\n return keccak256(abi.encodePacked(\"\\x19Ethereum Signed Message:\\n32\", hash));\n }\n}\n" + }, + "@openzeppelin/contracts/utils/Counters.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <0.8.0;\n\nimport \"../math/SafeMath.sol\";\n\n/**\n * @title Counters\n * @author Matt Condon (@shrugs)\n * @dev Provides counters that can only be incremented or decremented by one. This can be used e.g. to track the number\n * of elements in a mapping, issuing ERC721 ids, or counting request ids.\n *\n * Include with `using Counters for Counters.Counter;`\n * Since it is not possible to overflow a 256 bit integer with increments of one, `increment` can skip the {SafeMath}\n * overflow check, thereby saving gas. This does assume however correct usage, in that the underlying `_value` is never\n * directly accessed.\n */\nlibrary Counters {\n using SafeMath for uint256;\n\n struct Counter {\n // This variable should never be directly accessed by users of the library: interactions must be restricted to\n // the library's function. As of Solidity v0.5.2, this cannot be enforced, though there is a proposal to add\n // this feature: see https://github.com/ethereum/solidity/issues/4637\n uint256 _value; // default: 0\n }\n\n function current(Counter storage counter) internal view returns (uint256) {\n return counter._value;\n }\n\n function increment(Counter storage counter) internal {\n // The {SafeMath} overflow check can be skipped here, see the comment at the top\n counter._value += 1;\n }\n\n function decrement(Counter storage counter) internal {\n counter._value = counter._value.sub(1);\n }\n}\n" + }, + "@openzeppelin/contracts/drafts/EIP712.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <0.8.0;\n\n/**\n * @dev https://eips.ethereum.org/EIPS/eip-712[EIP 712] is a standard for hashing and signing of typed structured data.\n *\n * The encoding specified in the EIP is very generic, and such a generic implementation in Solidity is not feasible,\n * thus this contract does not implement the encoding itself. Protocols need to implement the type-specific encoding\n * they need in their contracts using a combination of `abi.encode` and `keccak256`.\n *\n * This contract implements the EIP 712 domain separator ({_domainSeparatorV4}) that is used as part of the encoding\n * scheme, and the final step of the encoding to obtain the message digest that is then signed via ECDSA\n * ({_hashTypedDataV4}).\n *\n * The implementation of the domain separator was designed to be as efficient as possible while still properly updating\n * the chain id to protect against replay attacks on an eventual fork of the chain.\n *\n * NOTE: This contract implements the version of the encoding known as \"v4\", as implemented by the JSON RPC method\n * https://docs.metamask.io/guide/signing-data.html[`eth_signTypedDataV4` in MetaMask].\n *\n * _Available since v3.4._\n */\nabstract contract EIP712 {\n /* solhint-disable var-name-mixedcase */\n // Cache the domain separator as an immutable value, but also store the chain id that it corresponds to, in order to\n // invalidate the cached domain separator if the chain id changes.\n bytes32 private immutable _CACHED_DOMAIN_SEPARATOR;\n uint256 private immutable _CACHED_CHAIN_ID;\n\n bytes32 private immutable _HASHED_NAME;\n bytes32 private immutable _HASHED_VERSION;\n bytes32 private immutable _TYPE_HASH;\n /* solhint-enable var-name-mixedcase */\n\n /**\n * @dev Initializes the domain separator and parameter caches.\n *\n * The meaning of `name` and `version` is specified in\n * https://eips.ethereum.org/EIPS/eip-712#definition-of-domainseparator[EIP 712]:\n *\n * - `name`: the user readable name of the signing domain, i.e. the name of the DApp or the protocol.\n * - `version`: the current major version of the signing domain.\n *\n * NOTE: These parameters cannot be changed except through a xref:learn::upgrading-smart-contracts.adoc[smart\n * contract upgrade].\n */\n constructor(string memory name, string memory version) internal {\n bytes32 hashedName = keccak256(bytes(name));\n bytes32 hashedVersion = keccak256(bytes(version));\n bytes32 typeHash = keccak256(\"EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)\");\n _HASHED_NAME = hashedName;\n _HASHED_VERSION = hashedVersion;\n _CACHED_CHAIN_ID = _getChainId();\n _CACHED_DOMAIN_SEPARATOR = _buildDomainSeparator(typeHash, hashedName, hashedVersion);\n _TYPE_HASH = typeHash;\n }\n\n /**\n * @dev Returns the domain separator for the current chain.\n */\n function _domainSeparatorV4() internal view virtual returns (bytes32) {\n if (_getChainId() == _CACHED_CHAIN_ID) {\n return _CACHED_DOMAIN_SEPARATOR;\n } else {\n return _buildDomainSeparator(_TYPE_HASH, _HASHED_NAME, _HASHED_VERSION);\n }\n }\n\n function _buildDomainSeparator(bytes32 typeHash, bytes32 name, bytes32 version) private view returns (bytes32) {\n return keccak256(\n abi.encode(\n typeHash,\n name,\n version,\n _getChainId(),\n address(this)\n )\n );\n }\n\n /**\n * @dev Given an already https://eips.ethereum.org/EIPS/eip-712#definition-of-hashstruct[hashed struct], this\n * function returns the hash of the fully encoded EIP712 message for this domain.\n *\n * This hash can be used together with {ECDSA-recover} to obtain the signer of a message. For example:\n *\n * ```solidity\n * bytes32 digest = _hashTypedDataV4(keccak256(abi.encode(\n * keccak256(\"Mail(address to,string contents)\"),\n * mailTo,\n * keccak256(bytes(mailContents))\n * )));\n * address signer = ECDSA.recover(digest, signature);\n * ```\n */\n function _hashTypedDataV4(bytes32 structHash) internal view virtual returns (bytes32) {\n return keccak256(abi.encodePacked(\"\\x19\\x01\", _domainSeparatorV4(), structHash));\n }\n\n function _getChainId() private view returns (uint256 chainId) {\n this; // silence state mutability warning without generating bytecode - see https://github.com/ethereum/solidity/issues/2691\n // solhint-disable-next-line no-inline-assembly\n assembly {\n chainId := chainid()\n }\n }\n}\n" + }, + "contracts/bridge/mocks/ERC20Mock.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.6.12;\n\nimport \"@openzeppelin/contracts/token/ERC20/ERC20.sol\";\n\ncontract ERC20Mock is ERC20 {\n constructor(\n string memory name,\n string memory symbol,\n uint256 supply\n ) public ERC20(name, symbol) {\n _mint(msg.sender, supply);\n }\n\n function mint(address to, uint256 amount) external {\n _mint(to, amount);\n }\n}" + }, + "contracts/bridge/interfaces/IMetaSwapDeposit.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.6.12;\nimport '@openzeppelin/contracts/token/ERC20/ERC20.sol';\n\n/**\n * @title IMetaSwapDeposit interface\n * @notice Interface for the meta swap contract.\n * @dev implement this interface to develop a a factory-patterned ECDSA node management contract\n **/\ninterface IMetaSwapDeposit {\n // min return calculation functions\n function calculateSwap(\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx\n ) external view returns (uint256);\n\n function swap(\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx,\n uint256 minDy,\n uint256 deadline\n ) external returns (uint256);\n\n function getToken(uint256 index) external view returns (IERC20);\n}\n" + }, + "contracts/amm/interfaces/IMetaSwapDeposit.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.6.12;\n\nimport \"@openzeppelin/contracts/token/ERC20/ERC20.sol\";\nimport \"./ISwap.sol\";\nimport \"./IMetaSwap.sol\";\n\ninterface IMetaSwapDeposit {\n function initialize(\n ISwap baseSwap_,\n IMetaSwap metaSwap_,\n IERC20 metaLPToken_\n ) external;\n}\n" + }, + "contracts/amm/interfaces/IMetaSwap.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.6.12;\n\nimport \"@openzeppelin/contracts/token/ERC20/ERC20.sol\";\n\ninterface IMetaSwap {\n // pool data view functions\n function getA() external view returns (uint256);\n\n function getToken(uint8 index) external view returns (IERC20);\n\n function getTokenIndex(address tokenAddress) external view returns (uint8);\n\n function getTokenBalance(uint8 index) external view returns (uint256);\n\n function getVirtualPrice() external view returns (uint256);\n\n function isGuarded() external view returns (bool);\n\n // min return calculation functions\n function calculateSwap(\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx\n ) external view returns (uint256);\n\n function calculateSwapUnderlying(\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx\n ) external view returns (uint256);\n\n function calculateTokenAmount(uint256[] calldata amounts, bool deposit)\n external\n view\n returns (uint256);\n\n function calculateRemoveLiquidity(uint256 amount)\n external\n view\n returns (uint256[] memory);\n\n function calculateRemoveLiquidityOneToken(\n uint256 tokenAmount,\n uint8 tokenIndex\n ) external view returns (uint256 availableTokenAmount);\n\n // state modifying functions\n function initializeMetaSwap(\n IERC20[] memory pooledTokens,\n uint8[] memory decimals,\n string memory lpTokenName,\n string memory lpTokenSymbol,\n uint256 a,\n uint256 fee,\n uint256 adminFee,\n address lpTokenTargetAddress,\n address baseSwap\n ) external;\n\n function swap(\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx,\n uint256 minDy,\n uint256 deadline\n ) external returns (uint256);\n\n function swapUnderlying(\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx,\n uint256 minDy,\n uint256 deadline\n ) external returns (uint256);\n\n function addLiquidity(\n uint256[] calldata amounts,\n uint256 minToMint,\n uint256 deadline\n ) external returns (uint256);\n\n function removeLiquidity(\n uint256 amount,\n uint256[] calldata minAmounts,\n uint256 deadline\n ) external returns (uint256[] memory);\n\n function removeLiquidityOneToken(\n uint256 tokenAmount,\n uint8 tokenIndex,\n uint256 minAmount,\n uint256 deadline\n ) external returns (uint256);\n\n function removeLiquidityImbalance(\n uint256[] calldata amounts,\n uint256 maxBurnAmount,\n uint256 deadline\n ) external returns (uint256);\n\n function swapStorage()\n external\n view\n returns (\n uint256 initialA,\n uint256 futureA,\n uint256 initialATime,\n uint256 futureATime,\n uint256 swapFee,\n uint256 adminFee,\n address lpToken\n );\n}\n" + }, + "contracts/amm/helper/GenericERC20.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.6.12;\n\nimport \"@openzeppelin/contracts/token/ERC20/ERC20.sol\";\nimport \"@openzeppelin/contracts/access/Ownable.sol\";\n\n/**\n * @title Generic ERC20 token\n * @notice This contract simulates a generic ERC20 token that is mintable and burnable.\n */\ncontract GenericERC20 is ERC20, Ownable {\n /**\n * @notice Deploy this contract with given name, symbol, and decimals\n * @dev the caller of this constructor will become the owner of this contract\n * @param name_ name of this token\n * @param symbol_ symbol of this token\n * @param decimals_ number of decimals this token will be based on\n */\n constructor(\n string memory name_,\n string memory symbol_,\n uint8 decimals_\n ) public ERC20(name_, symbol_) {\n _setupDecimals(decimals_);\n }\n\n /**\n * @notice Mints given amount of tokens to recipient\n * @dev only owner can call this mint function\n * @param recipient address of account to receive the tokens\n * @param amount amount of tokens to mint\n */\n function mint(address recipient, uint256 amount) external onlyOwner {\n require(amount != 0, \"amount == 0\");\n _mint(recipient, amount);\n }\n}\n" + }, + "contracts/bridge/wrappers/HarmonyBridgeZap.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.6.12;\n\nimport \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/SafeERC20.sol\";\nimport \"../interfaces/ISwap.sol\";\nimport \"../interfaces/ISynapseBridge.sol\";\nimport \"../interfaces/IWETH9.sol\";\n\ninterface IFrax {\n function exchangeCanonicalForOld(address bridge_token_address, uint256 token_amount) external returns (uint256);\n}\n\ncontract HarmonyBridgeZap {\n using SafeERC20 for IERC20;\n\n ISynapseBridge synapseBridge;\n address payable public immutable WETH_ADDRESS;\n IFrax private constant CANOLICAL_FRAX = IFrax(0xFa7191D292d5633f702B0bd7E3E3BcCC0e633200);\n IERC20 private constant SYN_FRAX = IERC20(0x1852F70512298d56e9c8FDd905e02581E04ddb2a);\n\n mapping(address => address) public swapMap;\n mapping(address => IERC20[]) public swapTokensMap;\n\n uint256 constant MAX_UINT256 = 2**256 - 1;\n\n constructor(\n address payable _wethAddress,\n address _swapOne,\n address tokenOne,\n address _swapTwo,\n address tokenTwo,\n address _swapThree,\n address tokenThree,\n address _swapFour,\n address tokenFour,\n ISynapseBridge _synapseBridge\n ) public {\n WETH_ADDRESS = _wethAddress;\n synapseBridge = _synapseBridge;\n swapMap[tokenOne] = _swapOne;\n swapMap[tokenTwo] = _swapTwo;\n swapMap[tokenThree] = _swapThree;\n swapMap[tokenFour] = _swapFour;\n\n if (address(_swapOne) != address(0)) {\n {\n uint8 i;\n for (; i < 32; i++) {\n try ISwap(_swapOne).getToken(i) returns (\n IERC20 token\n ) {\n swapTokensMap[_swapOne].push(token);\n token.safeApprove(address(_swapOne), MAX_UINT256);\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n } catch {\n break;\n }\n }\n require(i > 1, \"swap must have at least 2 tokens\");\n }\n }\n if (address(_swapTwo) != address(0)) {\n {\n uint8 i;\n for (; i < 32; i++) {\n try ISwap(_swapTwo).getToken(i) returns (\n IERC20 token\n ) {\n swapTokensMap[_swapTwo].push(token);\n token.safeApprove(address(_swapTwo), MAX_UINT256);\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n } catch {\n break;\n }\n }\n require(i > 1, \"swap must have at least 2 tokens\");\n }\n }\n\n if (address(_swapThree) != address(0)) {\n {\n uint8 i;\n for (; i < 32; i++) {\n try ISwap(_swapThree).getToken(i) returns (\n IERC20 token\n ) {\n swapTokensMap[_swapThree].push(token);\n token.safeApprove(address(_swapThree), MAX_UINT256);\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n } catch {\n break;\n }\n }\n require(i > 1, \"swap must have at least 2 tokens\");\n }\n }\n\n if (address(_swapFour) != address(0)) {\n {\n uint8 i;\n for (; i < 32; i++) {\n try ISwap(_swapFour).getToken(i) returns (\n IERC20 token\n ) {\n swapTokensMap[_swapFour].push(token);\n token.safeApprove(address(_swapFour), MAX_UINT256);\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n } catch {\n break;\n }\n }\n require(i > 1, \"swap must have at least 2 tokens\");\n }\n }\n }\n\n /**\n * @notice Calculate amount of tokens you receive on swap\n * @param tokenIndexFrom the token the user wants to sell\n * @param tokenIndexTo the token the user wants to buy\n * @param dx the amount of tokens the user wants to sell. If the token charges\n * a fee on transfers, use the amount that gets transferred after the fee.\n * @return amount of tokens the user will receive\n */\n function calculateSwap(\n IERC20 token,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx\n ) external view virtual returns (uint256) {\n ISwap swap = ISwap(\n swapMap[address(token)]\n );\n return swap.calculateSwap(tokenIndexFrom, tokenIndexTo, dx);\n }\n\n function swapAndRedeem(\n address to,\n uint256 chainId,\n IERC20 token,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx,\n uint256 minDy,\n uint256 deadline\n ) external {\n ISwap swap = ISwap(swapMap[address(token)]);\n require(address(swap) != address(0), \"Swap is 0x00\");\n IERC20[] memory tokens = swapTokensMap[address(swap)];\n tokens[tokenIndexFrom].safeTransferFrom(\n msg.sender,\n address(this),\n dx\n );\n // swap\n\n uint256 swappedAmount = swap.swap(\n tokenIndexFrom,\n tokenIndexTo,\n dx,\n minDy,\n deadline\n );\n // deposit into bridge, gets nUSD\n if (\n token.allowance(address(this), address(synapseBridge)) <\n swappedAmount\n ) {\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n }\n synapseBridge.redeem(to, chainId, token, swappedAmount);\n }\n\n function swapAndRedeemAndSwap(\n address to,\n uint256 chainId,\n IERC20 token,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx,\n uint256 minDy,\n uint256 deadline,\n uint8 swapTokenIndexFrom,\n uint8 swapTokenIndexTo,\n uint256 swapMinDy,\n uint256 swapDeadline\n ) external {\n require(\n address(swapMap[address(token)]) != address(0),\n \"Swap is 0x00\"\n );\n IERC20[] memory tokens = swapTokensMap[\n swapMap[address(token)]\n ];\n tokens[tokenIndexFrom].safeTransferFrom(\n msg.sender,\n address(this),\n dx\n );\n // swap\n\n uint256 swappedAmount = ISwap(swapMap[address(token)]).swap(tokenIndexFrom, tokenIndexTo, dx, minDy, deadline);\n // deposit into bridge, gets nUSD\n if (\n token.allowance(address(this), address(synapseBridge)) <\n swappedAmount\n ) {\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n }\n synapseBridge.redeemAndSwap(\n to,\n chainId,\n token,\n swappedAmount,\n swapTokenIndexFrom,\n swapTokenIndexTo,\n swapMinDy,\n swapDeadline\n );\n }\n\n function swapAndRedeemAndRemove(\n address to,\n uint256 chainId,\n IERC20 token,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx,\n uint256 minDy,\n uint256 deadline,\n uint8 liqTokenIndex,\n uint256 liqMinAmount,\n uint256 liqDeadline\n ) external {\n ISwap swap = ISwap(swapMap[address(token)]);\n require(address(swap) != address(0), \"Swap is 0x00\");\n IERC20[] memory tokens = swapTokensMap[address(swap)];\n tokens[tokenIndexFrom].safeTransferFrom(\n msg.sender,\n address(this),\n dx\n );\n // swap\n\n uint256 swappedAmount = swap.swap(\n tokenIndexFrom,\n tokenIndexTo,\n dx,\n minDy,\n deadline\n );\n // deposit into bridge, gets nUSD\n if (\n token.allowance(address(this), address(synapseBridge)) <\n swappedAmount\n ) {\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n }\n synapseBridge.redeemAndRemove(\n to,\n chainId,\n token,\n swappedAmount,\n liqTokenIndex,\n liqMinAmount,\n liqDeadline\n );\n }\n\n /**\n * @notice wraps SynapseBridge redeem()\n * @param to address on other chain to redeem underlying assets to\n * @param chainId which underlying chain to bridge assets onto\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n **/\n function redeem(\n address to,\n uint256 chainId,\n IERC20 token,\n uint256 amount\n ) external {\n token.safeTransferFrom(msg.sender, address(this), amount);\n if (address(token) == address(CANOLICAL_FRAX)) {\n uint256 swappedAmount = CANOLICAL_FRAX.exchangeCanonicalForOld(address(SYN_FRAX), amount);\n if (SYN_FRAX.allowance(address(this), address(synapseBridge)) < amount) {\n SYN_FRAX.safeApprove(address(synapseBridge), MAX_UINT256);\n }\n synapseBridge.redeem(to, chainId, SYN_FRAX, swappedAmount);\n } else {\n if (token.allowance(address(this), address(synapseBridge)) < amount) {\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n }\n synapseBridge.redeem(to, chainId, token, amount);\n }\n \n }\n\n /**\n * @notice Wraps SynapseBridge redeemv2() function\n * @param to address on other chain to bridge assets to\n * @param chainId which chain to bridge assets onto\n * @param token ERC20 compatible token to redeem into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n **/\n function redeemv2(\n bytes32 to,\n uint256 chainId,\n IERC20 token,\n uint256 amount\n ) external {\n token.safeTransferFrom(msg.sender, address(this), amount);\n\n if (token.allowance(address(this), address(synapseBridge)) < amount) {\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n }\n synapseBridge.redeemv2(to, chainId, token, amount);\n }\n\n /**\n * @notice wraps SynapseBridge redeem()\n * @param to address on other chain to redeem underlying assets to\n * @param chainId which underlying chain to bridge assets onto\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n **/\n function deposit(\n address to,\n uint256 chainId,\n IERC20 token,\n uint256 amount\n ) external {\n token.safeTransferFrom(msg.sender, address(this), amount);\n if (token.allowance(address(this), address(synapseBridge)) < amount) {\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n }\n synapseBridge.deposit(to, chainId, token, amount);\n }\n\n function swapETHAndRedeem(\n address to,\n uint256 chainId,\n IERC20 token,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx,\n uint256 minDy,\n uint256 deadline\n ) external payable {\n require(WETH_ADDRESS != address(0), \"WETH 0\");\n require(msg.value > 0 && msg.value == dx, \"INCORRECT MSG VALUE\");\n ISwap swap = ISwap(swapMap[address(token)]);\n require(address(swap) != address(0), \"Swap is 0x00\");\n IWETH9(WETH_ADDRESS).deposit{value: msg.value}();\n\n // swap\n uint256 swappedAmount = swap.swap(\n tokenIndexFrom,\n tokenIndexTo,\n dx,\n minDy,\n deadline\n );\n synapseBridge.redeem(to, chainId, token, swappedAmount);\n }\n\n /**\n * @notice Wraps redeemAndSwap on SynapseBridge.sol\n * Relays to nodes that (typically) a wrapped synAsset ERC20 token has been burned and the underlying needs to be redeeemed on the native chain. This function indicates to the nodes that they should attempt to redeem the LP token for the underlying assets (E.g \"swap\" out of the LP token)\n * @param to address on other chain to redeem underlying assets to\n * @param chainId which underlying chain to bridge assets onto\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n * @param tokenIndexFrom the token the user wants to swap from\n * @param tokenIndexTo the token the user wants to swap to\n * @param minDy the min amount the user would like to receive, or revert to only minting the SynERC20 token crosschain.\n * @param deadline latest timestamp to accept this transaction\n **/\n function redeemAndSwap(\n address to,\n uint256 chainId,\n IERC20 token,\n uint256 amount,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 minDy,\n uint256 deadline\n ) external {\n token.safeTransferFrom(msg.sender, address(this), amount);\n if (token.allowance(address(this), address(synapseBridge)) < amount) {\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n }\n synapseBridge.redeemAndSwap(\n to,\n chainId,\n token,\n amount,\n tokenIndexFrom,\n tokenIndexTo,\n minDy,\n deadline\n );\n }\n\n /**\n * @notice Wraps redeemAndRemove on SynapseBridge\n * Relays to nodes that (typically) a wrapped synAsset ERC20 token has been burned and the underlying needs to be redeeemed on the native chain. This function indicates to the nodes that they should attempt to redeem the LP token for the underlying assets (E.g \"swap\" out of the LP token)\n * @param to address on other chain to redeem underlying assets to\n * @param chainId which underlying chain to bridge assets onto\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount of (typically) LP token to pass to the nodes to attempt to removeLiquidity() with to redeem for the underlying assets of the LP token\n * @param liqTokenIndex Specifies which of the underlying LP assets the nodes should attempt to redeem for\n * @param liqMinAmount Specifies the minimum amount of the underlying asset needed for the nodes to execute the redeem/swap\n * @param liqDeadline Specificies the deadline that the nodes are allowed to try to redeem/swap the LP token\n **/\n function redeemAndRemove(\n address to,\n uint256 chainId,\n IERC20 token,\n uint256 amount,\n uint8 liqTokenIndex,\n uint256 liqMinAmount,\n uint256 liqDeadline\n ) external {\n token.safeTransferFrom(msg.sender, address(this), amount);\n if (token.allowance(address(this), address(synapseBridge)) < amount) {\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n }\n synapseBridge.redeemAndRemove(\n to,\n chainId,\n token,\n amount,\n liqTokenIndex,\n liqMinAmount,\n liqDeadline\n );\n }\n}\n" + }, + "contracts/bridge/wrappers/AvalancheBridgeZap.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.6.12;\n\nimport \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/SafeERC20.sol\";\nimport \"../interfaces/ISwap.sol\";\nimport \"../interfaces/ISynapseBridge.sol\";\nimport \"../interfaces/IWETH9.sol\";\n\ncontract AvalancheBridgeZap {\n using SafeERC20 for IERC20;\n\n ISynapseBridge synapseBridge;\n address payable public immutable WETH_ADDRESS;\n\n mapping(address => address) public swapMap;\n mapping(address => IERC20[]) public swapTokensMap;\n\n uint256 constant MAX_UINT256 = 2**256 - 1;\n\n constructor(\n address payable _wethAddress,\n address _swapOne,\n address tokenOne,\n address _swapTwo,\n address tokenTwo,\n ISynapseBridge _synapseBridge\n ) public {\n WETH_ADDRESS = _wethAddress;\n synapseBridge = _synapseBridge;\n swapMap[tokenOne] = _swapOne;\n swapMap[tokenTwo] = _swapTwo;\n if (_wethAddress != address(0)) {\n IERC20(_wethAddress).safeIncreaseAllowance(address(_synapseBridge), MAX_UINT256);\n }\n if (address(_swapOne) != address(0)) {\n {\n uint8 i;\n for (; i < 32; i++) {\n try ISwap(_swapOne).getToken(i) returns (\n IERC20 token\n ) {\n swapTokensMap[_swapOne].push(token);\n token.safeApprove(address(_swapOne), MAX_UINT256);\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n } catch {\n break;\n }\n }\n require(i > 1, \"swap must have at least 2 tokens\");\n }\n }\n if (address(_swapTwo) != address(0)) {\n {\n uint8 i;\n for (; i < 32; i++) {\n try ISwap(_swapTwo).getToken(i) returns (\n IERC20 token\n ) {\n swapTokensMap[_swapTwo].push(token);\n token.safeApprove(address(_swapTwo), MAX_UINT256);\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n } catch {\n break;\n }\n }\n require(i > 1, \"swap must have at least 2 tokens\");\n }\n }\n }\n\n /**\n * @notice Calculate amount of tokens you receive on swap\n * @param tokenIndexFrom the token the user wants to sell\n * @param tokenIndexTo the token the user wants to buy\n * @param dx the amount of tokens the user wants to sell. If the token charges\n * a fee on transfers, use the amount that gets transferred after the fee.\n * @return amount of tokens the user will receive\n */\n function calculateSwap(\n IERC20 token,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx\n ) external view virtual returns (uint256) {\n ISwap swap = ISwap(\n swapMap[address(token)]\n );\n return swap.calculateSwap(tokenIndexFrom, tokenIndexTo, dx);\n }\n\n function swapAndRedeem(\n address to,\n uint256 chainId,\n IERC20 token,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx,\n uint256 minDy,\n uint256 deadline\n ) external {\n ISwap swap = ISwap(swapMap[address(token)]);\n require(address(swap) != address(0), \"Swap is 0x00\");\n IERC20[] memory tokens = swapTokensMap[address(swap)];\n tokens[tokenIndexFrom].safeTransferFrom(\n msg.sender,\n address(this),\n dx\n );\n // swap\n\n uint256 swappedAmount = swap.swap(\n tokenIndexFrom,\n tokenIndexTo,\n dx,\n minDy,\n deadline\n );\n // deposit into bridge, gets nUSD\n if (\n token.allowance(address(this), address(synapseBridge)) <\n swappedAmount\n ) {\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n }\n synapseBridge.redeem(to, chainId, token, swappedAmount);\n }\n\n function swapAndRedeemAndSwap(\n address to,\n uint256 chainId,\n IERC20 token,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx,\n uint256 minDy,\n uint256 deadline,\n uint8 swapTokenIndexFrom,\n uint8 swapTokenIndexTo,\n uint256 swapMinDy,\n uint256 swapDeadline\n ) external {\n require(\n address(swapMap[address(token)]) != address(0),\n \"Swap is 0x00\"\n );\n IERC20[] memory tokens = swapTokensMap[\n swapMap[address(token)]\n ];\n tokens[tokenIndexFrom].safeTransferFrom(\n msg.sender,\n address(this),\n dx\n );\n // swap\n\n uint256 swappedAmount = ISwap(swapMap[address(token)]).swap(tokenIndexFrom, tokenIndexTo, dx, minDy, deadline);\n // deposit into bridge, gets nUSD\n if (\n token.allowance(address(this), address(synapseBridge)) <\n swappedAmount\n ) {\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n }\n synapseBridge.redeemAndSwap(\n to,\n chainId,\n token,\n swappedAmount,\n swapTokenIndexFrom,\n swapTokenIndexTo,\n swapMinDy,\n swapDeadline\n );\n }\n\n function swapAndRedeemAndRemove(\n address to,\n uint256 chainId,\n IERC20 token,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx,\n uint256 minDy,\n uint256 deadline,\n uint8 liqTokenIndex,\n uint256 liqMinAmount,\n uint256 liqDeadline\n ) external {\n ISwap swap = ISwap(swapMap[address(token)]);\n require(address(swap) != address(0), \"Swap is 0x00\");\n IERC20[] memory tokens = swapTokensMap[address(swap)];\n tokens[tokenIndexFrom].safeTransferFrom(\n msg.sender,\n address(this),\n dx\n );\n // swap\n\n uint256 swappedAmount = swap.swap(\n tokenIndexFrom,\n tokenIndexTo,\n dx,\n minDy,\n deadline\n );\n // deposit into bridge, gets nUSD\n if (\n token.allowance(address(this), address(synapseBridge)) <\n swappedAmount\n ) {\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n }\n synapseBridge.redeemAndRemove(\n to,\n chainId,\n token,\n swappedAmount,\n liqTokenIndex,\n liqMinAmount,\n liqDeadline\n );\n }\n\n /**\n * @notice wraps SynapseBridge redeem()\n * @param to address on other chain to redeem underlying assets to\n * @param chainId which underlying chain to bridge assets onto\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n **/\n function redeem(\n address to,\n uint256 chainId,\n IERC20 token,\n uint256 amount\n ) external {\n token.safeTransferFrom(msg.sender, address(this), amount);\n if (token.allowance(address(this), address(synapseBridge)) < amount) {\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n }\n synapseBridge.redeem(to, chainId, token, amount);\n }\n\n /**\n * @notice wraps SynapseBridge redeem()\n * @param to address on other chain to redeem underlying assets to\n * @param chainId which underlying chain to bridge assets onto\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n **/\n function deposit(\n address to,\n uint256 chainId,\n IERC20 token,\n uint256 amount\n ) external {\n token.safeTransferFrom(msg.sender, address(this), amount);\n if (token.allowance(address(this), address(synapseBridge)) < amount) {\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n }\n synapseBridge.deposit(to, chainId, token, amount);\n }\n\n /**\n * @notice Wraps SynapseBridge deposit() function to make it compatible w/ ETH -> WETH conversions\n * @param to address on other chain to bridge assets to\n * @param chainId which chain to bridge assets onto\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n **/\n function depositETH(\n address to,\n uint256 chainId,\n uint256 amount\n ) external payable {\n require(msg.value > 0 && msg.value == amount, 'INCORRECT MSG VALUE');\n IWETH9(WETH_ADDRESS).deposit{value: msg.value}();\n synapseBridge.deposit(to, chainId, IERC20(WETH_ADDRESS), amount);\n }\n\n\n function swapETHAndRedeem(\n address to,\n uint256 chainId,\n IERC20 token,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx,\n uint256 minDy,\n uint256 deadline\n ) external payable {\n require(WETH_ADDRESS != address(0), \"WETH 0\");\n require(msg.value > 0 && msg.value == dx, \"INCORRECT MSG VALUE\");\n ISwap swap = ISwap(swapMap[address(token)]);\n require(address(swap) != address(0), \"Swap is 0x00\");\n IWETH9(WETH_ADDRESS).deposit{value: msg.value}();\n\n // swap\n uint256 swappedAmount = swap.swap(\n tokenIndexFrom,\n tokenIndexTo,\n dx,\n minDy,\n deadline\n );\n synapseBridge.redeem(to, chainId, token, swappedAmount);\n }\n\n\n function swapETHAndRedeemAndSwap(\n address to,\n uint256 chainId,\n IERC20 token,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx,\n uint256 minDy,\n uint256 deadline,\n uint8 swapTokenIndexFrom,\n uint8 swapTokenIndexTo,\n uint256 swapMinDy,\n uint256 swapDeadline\n ) external payable {\n require(WETH_ADDRESS != address(0), \"WETH 0\");\n require(msg.value > 0 && msg.value == dx, \"INCORRECT MSG VALUE\");\n ISwap swap = ISwap(swapMap[address(token)]);\n require(address(swap) != address(0), \"Swap is 0x00\");\n IWETH9(WETH_ADDRESS).deposit{value: msg.value}();\n\n // swap\n uint256 swappedAmount = swap.swap(\n tokenIndexFrom,\n tokenIndexTo,\n dx,\n minDy,\n deadline\n );\n synapseBridge.redeemAndSwap(to, chainId, token, swappedAmount,swapTokenIndexFrom,\n swapTokenIndexTo,\n swapMinDy,\n swapDeadline);\n }\n\n\n /**\n * @notice Wraps redeemAndSwap on SynapseBridge.sol\n * Relays to nodes that (typically) a wrapped synAsset ERC20 token has been burned and the underlying needs to be redeeemed on the native chain. This function indicates to the nodes that they should attempt to redeem the LP token for the underlying assets (E.g \"swap\" out of the LP token)\n * @param to address on other chain to redeem underlying assets to\n * @param chainId which underlying chain to bridge assets onto\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n * @param tokenIndexFrom the token the user wants to swap from\n * @param tokenIndexTo the token the user wants to swap to\n * @param minDy the min amount the user would like to receive, or revert to only minting the SynERC20 token crosschain.\n * @param deadline latest timestamp to accept this transaction\n **/\n function redeemAndSwap(\n address to,\n uint256 chainId,\n IERC20 token,\n uint256 amount,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 minDy,\n uint256 deadline\n ) external {\n token.safeTransferFrom(msg.sender, address(this), amount);\n if (token.allowance(address(this), address(synapseBridge)) < amount) {\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n }\n synapseBridge.redeemAndSwap(\n to,\n chainId,\n token,\n amount,\n tokenIndexFrom,\n tokenIndexTo,\n minDy,\n deadline\n );\n }\n\n /**\n * @notice Wraps redeemAndRemove on SynapseBridge\n * Relays to nodes that (typically) a wrapped synAsset ERC20 token has been burned and the underlying needs to be redeeemed on the native chain. This function indicates to the nodes that they should attempt to redeem the LP token for the underlying assets (E.g \"swap\" out of the LP token)\n * @param to address on other chain to redeem underlying assets to\n * @param chainId which underlying chain to bridge assets onto\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount of (typically) LP token to pass to the nodes to attempt to removeLiquidity() with to redeem for the underlying assets of the LP token\n * @param liqTokenIndex Specifies which of the underlying LP assets the nodes should attempt to redeem for\n * @param liqMinAmount Specifies the minimum amount of the underlying asset needed for the nodes to execute the redeem/swap\n * @param liqDeadline Specificies the deadline that the nodes are allowed to try to redeem/swap the LP token\n **/\n function redeemAndRemove(\n address to,\n uint256 chainId,\n IERC20 token,\n uint256 amount,\n uint8 liqTokenIndex,\n uint256 liqMinAmount,\n uint256 liqDeadline\n ) external {\n token.safeTransferFrom(msg.sender, address(this), amount);\n if (token.allowance(address(this), address(synapseBridge)) < amount) {\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n }\n synapseBridge.redeemAndRemove(\n to,\n chainId,\n token,\n amount,\n liqTokenIndex,\n liqMinAmount,\n liqDeadline\n );\n }\n\n /**\n * @notice Wraps SynapseBridge redeemv2() function\n * @param to address on other chain to bridge assets to\n * @param chainId which chain to bridge assets onto\n * @param token ERC20 compatible token to redeem into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n **/\n function redeemv2(\n bytes32 to,\n uint256 chainId,\n IERC20 token,\n uint256 amount\n ) external {\n token.safeTransferFrom(msg.sender, address(this), amount);\n\n if (token.allowance(address(this), address(synapseBridge)) < amount) {\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n }\n synapseBridge.redeemv2(to, chainId, token, amount);\n }\n}\n" + }, + "contracts/bridge/SynapseBridge.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.6.12;\n\nimport \"@openzeppelin/contracts-upgradeable/proxy/Initializable.sol\";\nimport \"@openzeppelin/contracts-upgradeable/access/AccessControlUpgradeable.sol\";\nimport \"@openzeppelin/contracts-upgradeable/utils/ReentrancyGuardUpgradeable.sol\";\nimport \"@openzeppelin/contracts-upgradeable/utils/PausableUpgradeable.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/SafeERC20.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/ERC20Burnable.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport \"@openzeppelin/contracts/math/SafeMath.sol\";\n\nimport \"./interfaces/ISwap.sol\";\nimport \"./interfaces/IWETH9.sol\";\n\ninterface IERC20Mintable is IERC20 {\n function mint(address to, uint256 amount) external;\n}\n\ncontract SynapseBridge is\n Initializable,\n AccessControlUpgradeable,\n ReentrancyGuardUpgradeable,\n PausableUpgradeable\n{\n using SafeERC20 for IERC20;\n using SafeERC20 for IERC20Mintable;\n using SafeMath for uint256;\n\n bytes32 public constant NODEGROUP_ROLE = keccak256(\"NODEGROUP_ROLE\");\n bytes32 public constant GOVERNANCE_ROLE = keccak256(\"GOVERNANCE_ROLE\");\n\n mapping(address => uint256) private fees;\n\n uint256 public startBlockNumber;\n uint256 public constant bridgeVersion = 6;\n uint256 public chainGasAmount;\n address payable public WETH_ADDRESS;\n\n mapping(bytes32 => bool) private kappaMap;\n\n receive() external payable {}\n\n function initialize() external initializer {\n startBlockNumber = block.number;\n _setupRole(DEFAULT_ADMIN_ROLE, msg.sender);\n __AccessControl_init();\n }\n\n function setChainGasAmount(uint256 amount) external {\n require(hasRole(GOVERNANCE_ROLE, msg.sender), \"Not governance\");\n chainGasAmount = amount;\n }\n\n function setWethAddress(address payable _wethAddress) external {\n require(hasRole(DEFAULT_ADMIN_ROLE, msg.sender), \"Not admin\");\n WETH_ADDRESS = _wethAddress;\n }\n\n function addKappas(bytes32[] calldata kappas) external {\n require(hasRole(GOVERNANCE_ROLE, msg.sender), \"Not governance\");\n for (uint256 i = 0; i < kappas.length; ++i) {\n kappaMap[kappas[i]] = true;\n }\n }\n\n event TokenDeposit(\n address indexed to,\n uint256 chainId,\n IERC20 token,\n uint256 amount\n );\n event TokenRedeem(\n address indexed to,\n uint256 chainId,\n IERC20 token,\n uint256 amount\n );\n event TokenWithdraw(\n address indexed to,\n IERC20 token,\n uint256 amount,\n uint256 fee,\n bytes32 indexed kappa\n );\n event TokenMint(\n address indexed to,\n IERC20Mintable token,\n uint256 amount,\n uint256 fee,\n bytes32 indexed kappa\n );\n event TokenDepositAndSwap(\n address indexed to,\n uint256 chainId,\n IERC20 token,\n uint256 amount,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 minDy,\n uint256 deadline\n );\n event TokenMintAndSwap(\n address indexed to,\n IERC20Mintable token,\n uint256 amount,\n uint256 fee,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 minDy,\n uint256 deadline,\n bool swapSuccess,\n bytes32 indexed kappa\n );\n event TokenRedeemAndSwap(\n address indexed to,\n uint256 chainId,\n IERC20 token,\n uint256 amount,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 minDy,\n uint256 deadline\n );\n event TokenRedeemAndRemove(\n address indexed to,\n uint256 chainId,\n IERC20 token,\n uint256 amount,\n uint8 swapTokenIndex,\n uint256 swapMinAmount,\n uint256 swapDeadline\n );\n event TokenWithdrawAndRemove(\n address indexed to,\n IERC20 token,\n uint256 amount,\n uint256 fee,\n uint8 swapTokenIndex,\n uint256 swapMinAmount,\n uint256 swapDeadline,\n bool swapSuccess,\n bytes32 indexed kappa\n );\n\n // v2 events\n event TokenRedeemV2(\n bytes32 indexed to,\n uint256 chainId,\n IERC20 token,\n uint256 amount\n );\n\n // VIEW FUNCTIONS ***/\n function getFeeBalance(address tokenAddress)\n external\n view\n returns (uint256)\n {\n return fees[tokenAddress];\n }\n\n function kappaExists(bytes32 kappa) external view returns (bool) {\n return kappaMap[kappa];\n }\n\n // FEE FUNCTIONS ***/\n /**\n * * @notice withdraw specified ERC20 token fees to a given address\n * * @param token ERC20 token in which fees acccumulated to transfer\n * * @param to Address to send the fees to\n */\n function withdrawFees(IERC20 token, address to) external whenNotPaused {\n require(hasRole(GOVERNANCE_ROLE, msg.sender), \"Not governance\");\n require(to != address(0), \"Address is 0x000\");\n if (fees[address(token)] != 0) {\n token.safeTransfer(to, fees[address(token)]);\n fees[address(token)] = 0;\n }\n }\n\n // PAUSABLE FUNCTIONS ***/\n function pause() external {\n require(hasRole(GOVERNANCE_ROLE, msg.sender), \"Not governance\");\n _pause();\n }\n\n function unpause() external {\n require(hasRole(GOVERNANCE_ROLE, msg.sender), \"Not governance\");\n _unpause();\n }\n\n /**\n * @notice Relays to nodes to transfers an ERC20 token cross-chain\n * @param to address on other chain to bridge assets to\n * @param chainId which chain to bridge assets onto\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n **/\n function deposit(\n address to,\n uint256 chainId,\n IERC20 token,\n uint256 amount\n ) external nonReentrant whenNotPaused {\n emit TokenDeposit(to, chainId, token, amount);\n token.safeTransferFrom(msg.sender, address(this), amount);\n }\n\n /**\n * @notice Relays to nodes that (typically) a wrapped synAsset ERC20 token has been burned and the underlying needs to be redeeemed on the native chain\n * @param to address on other chain to redeem underlying assets to\n * @param chainId which underlying chain to bridge assets onto\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n **/\n function redeem(\n address to,\n uint256 chainId,\n ERC20Burnable token,\n uint256 amount\n ) external nonReentrant whenNotPaused {\n emit TokenRedeem(to, chainId, token, amount);\n token.burnFrom(msg.sender, amount);\n }\n\n /**\n * @notice Function to be called by the node group to withdraw the underlying assets from the contract\n * @param to address on chain to send underlying assets to\n * @param token ERC20 compatible token to withdraw from the bridge\n * @param amount Amount in native token decimals to withdraw\n * @param fee Amount in native token decimals to save to the contract as fees\n * @param kappa kappa\n **/\n function withdraw(\n address to,\n IERC20 token,\n uint256 amount,\n uint256 fee,\n bytes32 kappa\n ) external nonReentrant whenNotPaused {\n require(\n hasRole(NODEGROUP_ROLE, msg.sender),\n \"Caller is not a node group\"\n );\n require(amount > fee, \"Amount must be greater than fee\");\n require(!kappaMap[kappa], \"Kappa is already present\");\n kappaMap[kappa] = true;\n fees[address(token)] = fees[address(token)].add(fee);\n if (address(token) == WETH_ADDRESS && WETH_ADDRESS != address(0)) {\n IWETH9(WETH_ADDRESS).withdraw(amount.sub(fee));\n (bool success, ) = to.call{value: amount.sub(fee)}(\"\");\n require(success, \"ETH_TRANSFER_FAILED\");\n emit TokenWithdraw(to, token, amount, fee, kappa);\n } else {\n emit TokenWithdraw(to, token, amount, fee, kappa);\n token.safeTransfer(to, amount.sub(fee));\n }\n }\n\n /**\n * @notice Nodes call this function to mint a SynERC20 (or any asset that the bridge is given minter access to). This is called by the nodes after a TokenDeposit event is emitted.\n * @dev This means the SynapseBridge.sol contract must have minter access to the token attempting to be minted\n * @param to address on other chain to redeem underlying assets to\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain post-fees\n * @param fee Amount in native token decimals to save to the contract as fees\n * @param kappa kappa\n **/\n function mint(\n address payable to,\n IERC20Mintable token,\n uint256 amount,\n uint256 fee,\n bytes32 kappa\n ) external nonReentrant whenNotPaused {\n require(\n hasRole(NODEGROUP_ROLE, msg.sender),\n \"Caller is not a node group\"\n );\n require(amount > fee, \"Amount must be greater than fee\");\n require(!kappaMap[kappa], \"Kappa is already present\");\n kappaMap[kappa] = true;\n fees[address(token)] = fees[address(token)].add(fee);\n emit TokenMint(to, token, amount.sub(fee), fee, kappa);\n token.mint(address(this), amount);\n IERC20(token).safeTransfer(to, amount.sub(fee));\n if (chainGasAmount != 0 && address(this).balance > chainGasAmount) {\n to.call.value(chainGasAmount)(\"\");\n }\n }\n\n /**\n * @notice Relays to nodes to both transfer an ERC20 token cross-chain, and then have the nodes execute a swap through a liquidity pool on behalf of the user.\n * @param to address on other chain to bridge assets to\n * @param chainId which chain to bridge assets onto\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n * @param tokenIndexFrom the token the user wants to swap from\n * @param tokenIndexTo the token the user wants to swap to\n * @param minDy the min amount the user would like to receive, or revert to only minting the SynERC20 token crosschain.\n * @param deadline latest timestamp to accept this transaction\n **/\n function depositAndSwap(\n address to,\n uint256 chainId,\n IERC20 token,\n uint256 amount,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 minDy,\n uint256 deadline\n ) external nonReentrant whenNotPaused {\n emit TokenDepositAndSwap(\n to,\n chainId,\n token,\n amount,\n tokenIndexFrom,\n tokenIndexTo,\n minDy,\n deadline\n );\n token.safeTransferFrom(msg.sender, address(this), amount);\n }\n\n /**\n * @notice Relays to nodes that (typically) a wrapped synAsset ERC20 token has been burned and the underlying needs to be redeeemed on the native chain. This function indicates to the nodes that they should attempt to redeem the LP token for the underlying assets (E.g \"swap\" out of the LP token)\n * @param to address on other chain to redeem underlying assets to\n * @param chainId which underlying chain to bridge assets onto\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n * @param tokenIndexFrom the token the user wants to swap from\n * @param tokenIndexTo the token the user wants to swap to\n * @param minDy the min amount the user would like to receive, or revert to only minting the SynERC20 token crosschain.\n * @param deadline latest timestamp to accept this transaction\n **/\n function redeemAndSwap(\n address to,\n uint256 chainId,\n ERC20Burnable token,\n uint256 amount,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 minDy,\n uint256 deadline\n ) external nonReentrant whenNotPaused {\n emit TokenRedeemAndSwap(\n to,\n chainId,\n token,\n amount,\n tokenIndexFrom,\n tokenIndexTo,\n minDy,\n deadline\n );\n token.burnFrom(msg.sender, amount);\n }\n\n /**\n * @notice Relays to nodes that (typically) a wrapped synAsset ERC20 token has been burned and the underlying needs to be redeeemed on the native chain. This function indicates to the nodes that they should attempt to redeem the LP token for the underlying assets (E.g \"swap\" out of the LP token)\n * @param to address on other chain to redeem underlying assets to\n * @param chainId which underlying chain to bridge assets onto\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n * @param swapTokenIndex Specifies which of the underlying LP assets the nodes should attempt to redeem for\n * @param swapMinAmount Specifies the minimum amount of the underlying asset needed for the nodes to execute the redeem/swap\n * @param swapDeadline Specificies the deadline that the nodes are allowed to try to redeem/swap the LP token\n **/\n function redeemAndRemove(\n address to,\n uint256 chainId,\n ERC20Burnable token,\n uint256 amount,\n uint8 swapTokenIndex,\n uint256 swapMinAmount,\n uint256 swapDeadline\n ) external nonReentrant whenNotPaused {\n emit TokenRedeemAndRemove(\n to,\n chainId,\n token,\n amount,\n swapTokenIndex,\n swapMinAmount,\n swapDeadline\n );\n token.burnFrom(msg.sender, amount);\n }\n\n /**\n * @notice Nodes call this function to mint a SynERC20 (or any asset that the bridge is given minter access to), and then attempt to swap the SynERC20 into the desired destination asset. This is called by the nodes after a TokenDepositAndSwap event is emitted.\n * @dev This means the BridgeDeposit.sol contract must have minter access to the token attempting to be minted\n * @param to address on other chain to redeem underlying assets to\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain post-fees\n * @param fee Amount in native token decimals to save to the contract as fees\n * @param pool Destination chain's pool to use to swap SynERC20 -> Asset. The nodes determine this by using PoolConfig.sol.\n * @param tokenIndexFrom Index of the SynERC20 asset in the pool\n * @param tokenIndexTo Index of the desired final asset\n * @param minDy Minumum amount (in final asset decimals) that must be swapped for, otherwise the user will receive the SynERC20.\n * @param deadline Epoch time of the deadline that the swap is allowed to be executed.\n * @param kappa kappa\n **/\n function mintAndSwap(\n address payable to,\n IERC20Mintable token,\n uint256 amount,\n uint256 fee,\n ISwap pool,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 minDy,\n uint256 deadline,\n bytes32 kappa\n ) external nonReentrant whenNotPaused {\n require(\n hasRole(NODEGROUP_ROLE, msg.sender),\n \"Caller is not a node group\"\n );\n require(amount > fee, \"Amount must be greater than fee\");\n require(!kappaMap[kappa], \"Kappa is already present\");\n kappaMap[kappa] = true;\n fees[address(token)] = fees[address(token)].add(fee);\n // Transfer gas airdrop\n if (chainGasAmount != 0 && address(this).balance > chainGasAmount) {\n to.call.value(chainGasAmount)(\"\");\n }\n // first check to make sure more will be given than min amount required\n uint256 expectedOutput = ISwap(pool).calculateSwap(\n tokenIndexFrom,\n tokenIndexTo,\n amount.sub(fee)\n );\n\n if (expectedOutput >= minDy) {\n // proceed with swap\n token.mint(address(this), amount);\n token.safeIncreaseAllowance(address(pool), amount);\n try\n ISwap(pool).swap(\n tokenIndexFrom,\n tokenIndexTo,\n amount.sub(fee),\n minDy,\n deadline\n )\n returns (uint256 finalSwappedAmount) {\n // Swap succeeded, transfer swapped asset\n IERC20 swappedTokenTo = ISwap(pool).getToken(tokenIndexTo);\n if (\n address(swappedTokenTo) == WETH_ADDRESS &&\n WETH_ADDRESS != address(0)\n ) {\n IWETH9(WETH_ADDRESS).withdraw(finalSwappedAmount);\n (bool success, ) = to.call{value: finalSwappedAmount}(\"\");\n require(success, \"ETH_TRANSFER_FAILED\");\n emit TokenMintAndSwap(\n to,\n token,\n finalSwappedAmount,\n fee,\n tokenIndexFrom,\n tokenIndexTo,\n minDy,\n deadline,\n true,\n kappa\n );\n } else {\n swappedTokenTo.safeTransfer(to, finalSwappedAmount);\n emit TokenMintAndSwap(\n to,\n token,\n finalSwappedAmount,\n fee,\n tokenIndexFrom,\n tokenIndexTo,\n minDy,\n deadline,\n true,\n kappa\n );\n }\n } catch {\n IERC20(token).safeTransfer(to, amount.sub(fee));\n emit TokenMintAndSwap(\n to,\n token,\n amount.sub(fee),\n fee,\n tokenIndexFrom,\n tokenIndexTo,\n minDy,\n deadline,\n false,\n kappa\n );\n }\n } else {\n token.mint(address(this), amount);\n IERC20(token).safeTransfer(to, amount.sub(fee));\n emit TokenMintAndSwap(\n to,\n token,\n amount.sub(fee),\n fee,\n tokenIndexFrom,\n tokenIndexTo,\n minDy,\n deadline,\n false,\n kappa\n );\n }\n }\n\n /**\n * @notice Function to be called by the node group to withdraw the underlying assets from the contract\n * @param to address on chain to send underlying assets to\n * @param token ERC20 compatible token to withdraw from the bridge\n * @param amount Amount in native token decimals to withdraw\n * @param fee Amount in native token decimals to save to the contract as fees\n * @param pool Destination chain's pool to use to swap SynERC20 -> Asset. The nodes determine this by using PoolConfig.sol.\n * @param swapTokenIndex Specifies which of the underlying LP assets the nodes should attempt to redeem for\n * @param swapMinAmount Specifies the minimum amount of the underlying asset needed for the nodes to execute the redeem/swap\n * @param swapDeadline Specificies the deadline that the nodes are allowed to try to redeem/swap the LP token\n * @param kappa kappa\n **/\n function withdrawAndRemove(\n address to,\n IERC20 token,\n uint256 amount,\n uint256 fee,\n ISwap pool,\n uint8 swapTokenIndex,\n uint256 swapMinAmount,\n uint256 swapDeadline,\n bytes32 kappa\n ) external nonReentrant whenNotPaused {\n require(\n hasRole(NODEGROUP_ROLE, msg.sender),\n \"Caller is not a node group\"\n );\n require(amount > fee, \"Amount must be greater than fee\");\n require(!kappaMap[kappa], \"Kappa is already present\");\n kappaMap[kappa] = true;\n fees[address(token)] = fees[address(token)].add(fee);\n // first check to make sure more will be given than min amount required\n uint256 expectedOutput = ISwap(pool).calculateRemoveLiquidityOneToken(\n amount.sub(fee),\n swapTokenIndex\n );\n\n if (expectedOutput >= swapMinAmount) {\n token.safeIncreaseAllowance(address(pool), amount.sub(fee));\n try\n ISwap(pool).removeLiquidityOneToken(\n amount.sub(fee),\n swapTokenIndex,\n swapMinAmount,\n swapDeadline\n )\n returns (uint256 finalSwappedAmount) {\n // Swap succeeded, transfer swapped asset\n IERC20 swappedTokenTo = ISwap(pool).getToken(swapTokenIndex);\n swappedTokenTo.safeTransfer(to, finalSwappedAmount);\n emit TokenWithdrawAndRemove(\n to,\n token,\n finalSwappedAmount,\n fee,\n swapTokenIndex,\n swapMinAmount,\n swapDeadline,\n true,\n kappa\n );\n } catch {\n IERC20(token).safeTransfer(to, amount.sub(fee));\n emit TokenWithdrawAndRemove(\n to,\n token,\n amount.sub(fee),\n fee,\n swapTokenIndex,\n swapMinAmount,\n swapDeadline,\n false,\n kappa\n );\n }\n } else {\n token.safeTransfer(to, amount.sub(fee));\n emit TokenWithdrawAndRemove(\n to,\n token,\n amount.sub(fee),\n fee,\n swapTokenIndex,\n swapMinAmount,\n swapDeadline,\n false,\n kappa\n );\n }\n }\n\n // BRIDGE FUNCTIONS TO HANDLE DIFF ADDRESSES\n /**\n * @notice Relays to nodes that (typically) a wrapped synAsset ERC20 token has been burned and the underlying needs to be redeeemed on the native chain\n * @param to address on other chain to redeem underlying assets to\n * @param chainId which underlying chain to bridge assets onto\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n **/\n function redeemV2(\n bytes32 to,\n uint256 chainId,\n ERC20Burnable token,\n uint256 amount\n ) external nonReentrant whenNotPaused {\n emit TokenRedeemV2(to, chainId, token, amount);\n token.burnFrom(msg.sender, amount);\n }\n}\n" + }, + "@openzeppelin/contracts-upgradeable/access/AccessControlUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <0.8.0;\n\nimport \"../utils/EnumerableSetUpgradeable.sol\";\nimport \"../utils/AddressUpgradeable.sol\";\nimport \"../utils/ContextUpgradeable.sol\";\nimport \"../proxy/Initializable.sol\";\n\n/**\n * @dev Contract module that allows children to implement role-based access\n * control mechanisms.\n *\n * Roles are referred to by their `bytes32` identifier. These should be exposed\n * in the external API and be unique. The best way to achieve this is by\n * using `public constant` hash digests:\n *\n * ```\n * bytes32 public constant MY_ROLE = keccak256(\"MY_ROLE\");\n * ```\n *\n * Roles can be used to represent a set of permissions. To restrict access to a\n * function call, use {hasRole}:\n *\n * ```\n * function foo() public {\n * require(hasRole(MY_ROLE, msg.sender));\n * ...\n * }\n * ```\n *\n * Roles can be granted and revoked dynamically via the {grantRole} and\n * {revokeRole} functions. Each role has an associated admin role, and only\n * accounts that have a role's admin role can call {grantRole} and {revokeRole}.\n *\n * By default, the admin role for all roles is `DEFAULT_ADMIN_ROLE`, which means\n * that only accounts with this role will be able to grant or revoke other\n * roles. More complex role relationships can be created by using\n * {_setRoleAdmin}.\n *\n * WARNING: The `DEFAULT_ADMIN_ROLE` is also its own admin: it has permission to\n * grant and revoke this role. Extra precautions should be taken to secure\n * accounts that have been granted it.\n */\nabstract contract AccessControlUpgradeable is Initializable, ContextUpgradeable {\n function __AccessControl_init() internal initializer {\n __Context_init_unchained();\n __AccessControl_init_unchained();\n }\n\n function __AccessControl_init_unchained() internal initializer {\n }\n using EnumerableSetUpgradeable for EnumerableSetUpgradeable.AddressSet;\n using AddressUpgradeable for address;\n\n struct RoleData {\n EnumerableSetUpgradeable.AddressSet members;\n bytes32 adminRole;\n }\n\n mapping (bytes32 => RoleData) private _roles;\n\n bytes32 public constant DEFAULT_ADMIN_ROLE = 0x00;\n\n /**\n * @dev Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole`\n *\n * `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite\n * {RoleAdminChanged} not being emitted signaling this.\n *\n * _Available since v3.1._\n */\n event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole);\n\n /**\n * @dev Emitted when `account` is granted `role`.\n *\n * `sender` is the account that originated the contract call, an admin role\n * bearer except when using {_setupRole}.\n */\n event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender);\n\n /**\n * @dev Emitted when `account` is revoked `role`.\n *\n * `sender` is the account that originated the contract call:\n * - if using `revokeRole`, it is the admin role bearer\n * - if using `renounceRole`, it is the role bearer (i.e. `account`)\n */\n event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender);\n\n /**\n * @dev Returns `true` if `account` has been granted `role`.\n */\n function hasRole(bytes32 role, address account) public view returns (bool) {\n return _roles[role].members.contains(account);\n }\n\n /**\n * @dev Returns the number of accounts that have `role`. Can be used\n * together with {getRoleMember} to enumerate all bearers of a role.\n */\n function getRoleMemberCount(bytes32 role) public view returns (uint256) {\n return _roles[role].members.length();\n }\n\n /**\n * @dev Returns one of the accounts that have `role`. `index` must be a\n * value between 0 and {getRoleMemberCount}, non-inclusive.\n *\n * Role bearers are not sorted in any particular way, and their ordering may\n * change at any point.\n *\n * WARNING: When using {getRoleMember} and {getRoleMemberCount}, make sure\n * you perform all queries on the same block. See the following\n * https://forum.openzeppelin.com/t/iterating-over-elements-on-enumerableset-in-openzeppelin-contracts/2296[forum post]\n * for more information.\n */\n function getRoleMember(bytes32 role, uint256 index) public view returns (address) {\n return _roles[role].members.at(index);\n }\n\n /**\n * @dev Returns the admin role that controls `role`. See {grantRole} and\n * {revokeRole}.\n *\n * To change a role's admin, use {_setRoleAdmin}.\n */\n function getRoleAdmin(bytes32 role) public view returns (bytes32) {\n return _roles[role].adminRole;\n }\n\n /**\n * @dev Grants `role` to `account`.\n *\n * If `account` had not been already granted `role`, emits a {RoleGranted}\n * event.\n *\n * Requirements:\n *\n * - the caller must have ``role``'s admin role.\n */\n function grantRole(bytes32 role, address account) public virtual {\n require(hasRole(_roles[role].adminRole, _msgSender()), \"AccessControl: sender must be an admin to grant\");\n\n _grantRole(role, account);\n }\n\n /**\n * @dev Revokes `role` from `account`.\n *\n * If `account` had been granted `role`, emits a {RoleRevoked} event.\n *\n * Requirements:\n *\n * - the caller must have ``role``'s admin role.\n */\n function revokeRole(bytes32 role, address account) public virtual {\n require(hasRole(_roles[role].adminRole, _msgSender()), \"AccessControl: sender must be an admin to revoke\");\n\n _revokeRole(role, account);\n }\n\n /**\n * @dev Revokes `role` from the calling account.\n *\n * Roles are often managed via {grantRole} and {revokeRole}: this function's\n * purpose is to provide a mechanism for accounts to lose their privileges\n * if they are compromised (such as when a trusted device is misplaced).\n *\n * If the calling account had been granted `role`, emits a {RoleRevoked}\n * event.\n *\n * Requirements:\n *\n * - the caller must be `account`.\n */\n function renounceRole(bytes32 role, address account) public virtual {\n require(account == _msgSender(), \"AccessControl: can only renounce roles for self\");\n\n _revokeRole(role, account);\n }\n\n /**\n * @dev Grants `role` to `account`.\n *\n * If `account` had not been already granted `role`, emits a {RoleGranted}\n * event. Note that unlike {grantRole}, this function doesn't perform any\n * checks on the calling account.\n *\n * [WARNING]\n * ====\n * This function should only be called from the constructor when setting\n * up the initial roles for the system.\n *\n * Using this function in any other way is effectively circumventing the admin\n * system imposed by {AccessControl}.\n * ====\n */\n function _setupRole(bytes32 role, address account) internal virtual {\n _grantRole(role, account);\n }\n\n /**\n * @dev Sets `adminRole` as ``role``'s admin role.\n *\n * Emits a {RoleAdminChanged} event.\n */\n function _setRoleAdmin(bytes32 role, bytes32 adminRole) internal virtual {\n emit RoleAdminChanged(role, _roles[role].adminRole, adminRole);\n _roles[role].adminRole = adminRole;\n }\n\n function _grantRole(bytes32 role, address account) private {\n if (_roles[role].members.add(account)) {\n emit RoleGranted(role, account, _msgSender());\n }\n }\n\n function _revokeRole(bytes32 role, address account) private {\n if (_roles[role].members.remove(account)) {\n emit RoleRevoked(role, account, _msgSender());\n }\n }\n uint256[49] private __gap;\n}\n" + }, + "@openzeppelin/contracts-upgradeable/utils/EnumerableSetUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <0.8.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 EnumerableSetUpgradeable {\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" + }, + "contracts/bridge/MoonriverSynapseBridge.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.6.12;\n\nimport \"@openzeppelin/contracts-upgradeable/proxy/Initializable.sol\";\nimport \"@openzeppelin/contracts-upgradeable/access/AccessControlUpgradeable.sol\";\nimport \"@openzeppelin/contracts-upgradeable/utils/ReentrancyGuardUpgradeable.sol\";\nimport \"@openzeppelin/contracts-upgradeable/utils/PausableUpgradeable.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/SafeERC20.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/ERC20Burnable.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport \"@openzeppelin/contracts/math/SafeMath.sol\";\n\nimport \"./interfaces/ISwap.sol\";\nimport \"./interfaces/IWETH9.sol\";\n\ninterface IERC20Mintable is IERC20 {\n function mint(address to, uint256 amount) external;\n}\n\ninterface IFrax {\n function exchangeOldForCanonical(\n address bridge_token_address,\n uint256 token_amount\n ) external returns (uint256);\n}\n\ncontract MRSynapseBridge is\n Initializable,\n AccessControlUpgradeable,\n ReentrancyGuardUpgradeable,\n PausableUpgradeable\n{\n using SafeERC20 for IERC20;\n using SafeERC20 for IERC20Mintable;\n using SafeMath for uint256;\n\n bytes32 public constant NODEGROUP_ROLE = keccak256(\"NODEGROUP_ROLE\");\n bytes32 public constant GOVERNANCE_ROLE = keccak256(\"GOVERNANCE_ROLE\");\n\n mapping(address => uint256) private fees;\n\n uint256 public startBlockNumber;\n uint256 public constant bridgeVersion = 6;\n uint256 public chainGasAmount;\n address payable public WETH_ADDRESS;\n\n mapping(bytes32 => bool) private kappaMap;\n\n receive() external payable {}\n\n function initialize() external initializer {\n startBlockNumber = block.number;\n _setupRole(DEFAULT_ADMIN_ROLE, msg.sender);\n __AccessControl_init();\n }\n\n function setChainGasAmount(uint256 amount) external {\n require(hasRole(GOVERNANCE_ROLE, msg.sender), \"Not governance\");\n chainGasAmount = amount;\n }\n\n function setWethAddress(address payable _wethAddress) external {\n require(hasRole(DEFAULT_ADMIN_ROLE, msg.sender), \"Not admin\");\n WETH_ADDRESS = _wethAddress;\n }\n\n function addKappas(bytes32[] calldata kappas) external {\n require(hasRole(GOVERNANCE_ROLE, msg.sender), \"Not governance\");\n for (uint256 i = 0; i < kappas.length; ++i) {\n kappaMap[kappas[i]] = true;\n }\n }\n\n event TokenDeposit(\n address indexed to,\n uint256 chainId,\n IERC20 token,\n uint256 amount\n );\n event TokenRedeem(\n address indexed to,\n uint256 chainId,\n IERC20 token,\n uint256 amount\n );\n event TokenWithdraw(\n address indexed to,\n IERC20 token,\n uint256 amount,\n uint256 fee,\n bytes32 indexed kappa\n );\n event TokenMint(\n address indexed to,\n IERC20Mintable token,\n uint256 amount,\n uint256 fee,\n bytes32 indexed kappa\n );\n event TokenDepositAndSwap(\n address indexed to,\n uint256 chainId,\n IERC20 token,\n uint256 amount,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 minDy,\n uint256 deadline\n );\n event TokenMintAndSwap(\n address indexed to,\n IERC20Mintable token,\n uint256 amount,\n uint256 fee,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 minDy,\n uint256 deadline,\n bool swapSuccess,\n bytes32 indexed kappa\n );\n event TokenRedeemAndSwap(\n address indexed to,\n uint256 chainId,\n IERC20 token,\n uint256 amount,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 minDy,\n uint256 deadline\n );\n event TokenRedeemAndRemove(\n address indexed to,\n uint256 chainId,\n IERC20 token,\n uint256 amount,\n uint8 swapTokenIndex,\n uint256 swapMinAmount,\n uint256 swapDeadline\n );\n event TokenWithdrawAndRemove(\n address indexed to,\n IERC20 token,\n uint256 amount,\n uint256 fee,\n uint8 swapTokenIndex,\n uint256 swapMinAmount,\n uint256 swapDeadline,\n bool swapSuccess,\n bytes32 indexed kappa\n );\n\n // v2 events\n event TokenRedeemV2(\n bytes32 indexed to,\n uint256 chainId,\n IERC20 token,\n uint256 amount\n );\n\n // VIEW FUNCTIONS ***/\n function getFeeBalance(address tokenAddress)\n external\n view\n returns (uint256)\n {\n return fees[tokenAddress];\n }\n\n function kappaExists(bytes32 kappa) external view returns (bool) {\n return kappaMap[kappa];\n }\n\n // FEE FUNCTIONS ***/\n /**\n * * @notice withdraw specified ERC20 token fees to a given address\n * * @param token ERC20 token in which fees acccumulated to transfer\n * * @param to Address to send the fees to\n */\n function withdrawFees(IERC20 token, address to) external whenNotPaused {\n require(hasRole(GOVERNANCE_ROLE, msg.sender), \"Not governance\");\n require(to != address(0), \"Address is 0x000\");\n if (fees[address(token)] != 0) {\n token.safeTransfer(to, fees[address(token)]);\n fees[address(token)] = 0;\n }\n }\n\n // PAUSABLE FUNCTIONS ***/\n function pause() external {\n require(hasRole(GOVERNANCE_ROLE, msg.sender), \"Not governance\");\n _pause();\n }\n\n function unpause() external {\n require(hasRole(GOVERNANCE_ROLE, msg.sender), \"Not governance\");\n _unpause();\n }\n\n /**\n * @notice Relays to nodes to transfers an ERC20 token cross-chain\n * @param to address on other chain to bridge assets to\n * @param chainId which chain to bridge assets onto\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n **/\n function deposit(\n address to,\n uint256 chainId,\n IERC20 token,\n uint256 amount\n ) external nonReentrant whenNotPaused {\n emit TokenDeposit(to, chainId, token, amount);\n token.safeTransferFrom(msg.sender, address(this), amount);\n }\n\n /**\n * @notice Relays to nodes that (typically) a wrapped synAsset ERC20 token has been burned and the underlying needs to be redeeemed on the native chain\n * @param to address on other chain to redeem underlying assets to\n * @param chainId which underlying chain to bridge assets onto\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n **/\n function redeem(\n address to,\n uint256 chainId,\n ERC20Burnable token,\n uint256 amount\n ) external nonReentrant whenNotPaused {\n emit TokenRedeem(to, chainId, token, amount);\n token.burnFrom(msg.sender, amount);\n }\n\n /**\n * @notice Function to be called by the node group to withdraw the underlying assets from the contract\n * @param to address on chain to send underlying assets to\n * @param token ERC20 compatible token to withdraw from the bridge\n * @param amount Amount in native token decimals to withdraw\n * @param fee Amount in native token decimals to save to the contract as fees\n * @param kappa kappa\n **/\n function withdraw(\n address to,\n IERC20 token,\n uint256 amount,\n uint256 fee,\n bytes32 kappa\n ) external nonReentrant whenNotPaused {\n require(\n hasRole(NODEGROUP_ROLE, msg.sender),\n \"Caller is not a node group\"\n );\n require(amount > fee, \"Amount must be greater than fee\");\n require(!kappaMap[kappa], \"Kappa is already present\");\n kappaMap[kappa] = true;\n fees[address(token)] = fees[address(token)].add(fee);\n if (address(token) == WETH_ADDRESS && WETH_ADDRESS != address(0)) {\n IWETH9(WETH_ADDRESS).withdraw(amount.sub(fee));\n (bool success, ) = to.call{value: amount.sub(fee)}(\"\");\n require(success, \"ETH_TRANSFER_FAILED\");\n emit TokenWithdraw(to, token, amount, fee, kappa);\n } else {\n emit TokenWithdraw(to, token, amount, fee, kappa);\n token.safeTransfer(to, amount.sub(fee));\n }\n }\n\n /**\n * @notice Nodes call this function to mint a SynERC20 (or any asset that the bridge is given minter access to). This is called by the nodes after a TokenDeposit event is emitted.\n * @dev This means the SynapseBridge.sol contract must have minter access to the token attempting to be minted\n * @param to address on other chain to redeem underlying assets to\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain post-fees\n * @param fee Amount in native token decimals to save to the contract as fees\n * @param kappa kappa\n **/\n function mint(\n address payable to,\n IERC20Mintable token,\n uint256 amount,\n uint256 fee,\n bytes32 kappa\n ) external nonReentrant whenNotPaused {\n require(\n hasRole(NODEGROUP_ROLE, msg.sender),\n \"Caller is not a node group\"\n );\n require(amount > fee, \"Amount must be greater than fee\");\n require(!kappaMap[kappa], \"Kappa is already present\");\n kappaMap[kappa] = true;\n fees[address(token)] = fees[address(token)].add(fee);\n emit TokenMint(to, token, amount.sub(fee), fee, kappa);\n token.mint(address(this), amount);\n // checks if synFRAX\n if (address(token) == 0xE96AC70907ffF3Efee79f502C985A7A21Bce407d) {\n token.safeIncreaseAllowance(\n 0x1A93B23281CC1CDE4C4741353F3064709A16197d,\n amount.sub(fee)\n );\n try\n IFrax(0x1A93B23281CC1CDE4C4741353F3064709A16197d)\n .exchangeOldForCanonical(address(token), amount.sub(fee))\n returns (uint256 canolical_tokens_out) {\n IERC20(0x1A93B23281CC1CDE4C4741353F3064709A16197d).safeTransfer(\n to,\n canolical_tokens_out\n );\n } catch {\n IERC20(token).safeTransfer(to, amount.sub(fee));\n }\n } else {\n IERC20(token).safeTransfer(to, amount.sub(fee));\n }\n if (chainGasAmount != 0 && address(this).balance > chainGasAmount) {\n to.call.value(chainGasAmount)(\"\");\n }\n }\n\n /**\n * @notice Relays to nodes to both transfer an ERC20 token cross-chain, and then have the nodes execute a swap through a liquidity pool on behalf of the user.\n * @param to address on other chain to bridge assets to\n * @param chainId which chain to bridge assets onto\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n * @param tokenIndexFrom the token the user wants to swap from\n * @param tokenIndexTo the token the user wants to swap to\n * @param minDy the min amount the user would like to receive, or revert to only minting the SynERC20 token crosschain.\n * @param deadline latest timestamp to accept this transaction\n **/\n function depositAndSwap(\n address to,\n uint256 chainId,\n IERC20 token,\n uint256 amount,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 minDy,\n uint256 deadline\n ) external nonReentrant whenNotPaused {\n emit TokenDepositAndSwap(\n to,\n chainId,\n token,\n amount,\n tokenIndexFrom,\n tokenIndexTo,\n minDy,\n deadline\n );\n token.safeTransferFrom(msg.sender, address(this), amount);\n }\n\n /**\n * @notice Relays to nodes that (typically) a wrapped synAsset ERC20 token has been burned and the underlying needs to be redeeemed on the native chain. This function indicates to the nodes that they should attempt to redeem the LP token for the underlying assets (E.g \"swap\" out of the LP token)\n * @param to address on other chain to redeem underlying assets to\n * @param chainId which underlying chain to bridge assets onto\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n * @param tokenIndexFrom the token the user wants to swap from\n * @param tokenIndexTo the token the user wants to swap to\n * @param minDy the min amount the user would like to receive, or revert to only minting the SynERC20 token crosschain.\n * @param deadline latest timestamp to accept this transaction\n **/\n function redeemAndSwap(\n address to,\n uint256 chainId,\n ERC20Burnable token,\n uint256 amount,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 minDy,\n uint256 deadline\n ) external nonReentrant whenNotPaused {\n emit TokenRedeemAndSwap(\n to,\n chainId,\n token,\n amount,\n tokenIndexFrom,\n tokenIndexTo,\n minDy,\n deadline\n );\n token.burnFrom(msg.sender, amount);\n }\n\n /**\n * @notice Relays to nodes that (typically) a wrapped synAsset ERC20 token has been burned and the underlying needs to be redeeemed on the native chain. This function indicates to the nodes that they should attempt to redeem the LP token for the underlying assets (E.g \"swap\" out of the LP token)\n * @param to address on other chain to redeem underlying assets to\n * @param chainId which underlying chain to bridge assets onto\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n * @param swapTokenIndex Specifies which of the underlying LP assets the nodes should attempt to redeem for\n * @param swapMinAmount Specifies the minimum amount of the underlying asset needed for the nodes to execute the redeem/swap\n * @param swapDeadline Specificies the deadline that the nodes are allowed to try to redeem/swap the LP token\n **/\n function redeemAndRemove(\n address to,\n uint256 chainId,\n ERC20Burnable token,\n uint256 amount,\n uint8 swapTokenIndex,\n uint256 swapMinAmount,\n uint256 swapDeadline\n ) external nonReentrant whenNotPaused {\n emit TokenRedeemAndRemove(\n to,\n chainId,\n token,\n amount,\n swapTokenIndex,\n swapMinAmount,\n swapDeadline\n );\n token.burnFrom(msg.sender, amount);\n }\n\n /**\n * @notice Nodes call this function to mint a SynERC20 (or any asset that the bridge is given minter access to), and then attempt to swap the SynERC20 into the desired destination asset. This is called by the nodes after a TokenDepositAndSwap event is emitted.\n * @dev This means the BridgeDeposit.sol contract must have minter access to the token attempting to be minted\n * @param to address on other chain to redeem underlying assets to\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain post-fees\n * @param fee Amount in native token decimals to save to the contract as fees\n * @param pool Destination chain's pool to use to swap SynERC20 -> Asset. The nodes determine this by using PoolConfig.sol.\n * @param tokenIndexFrom Index of the SynERC20 asset in the pool\n * @param tokenIndexTo Index of the desired final asset\n * @param minDy Minumum amount (in final asset decimals) that must be swapped for, otherwise the user will receive the SynERC20.\n * @param deadline Epoch time of the deadline that the swap is allowed to be executed.\n * @param kappa kappa\n **/\n function mintAndSwap(\n address payable to,\n IERC20Mintable token,\n uint256 amount,\n uint256 fee,\n ISwap pool,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 minDy,\n uint256 deadline,\n bytes32 kappa\n ) external nonReentrant whenNotPaused {\n require(\n hasRole(NODEGROUP_ROLE, msg.sender),\n \"Caller is not a node group\"\n );\n require(amount > fee, \"Amount must be greater than fee\");\n require(!kappaMap[kappa], \"Kappa is already present\");\n kappaMap[kappa] = true;\n fees[address(token)] = fees[address(token)].add(fee);\n // Transfer gas airdrop\n if (chainGasAmount != 0 && address(this).balance > chainGasAmount) {\n to.call.value(chainGasAmount)(\"\");\n }\n // first check to make sure more will be given than min amount required\n uint256 expectedOutput = ISwap(pool).calculateSwap(\n tokenIndexFrom,\n tokenIndexTo,\n amount.sub(fee)\n );\n\n if (expectedOutput >= minDy) {\n // proceed with swap\n token.mint(address(this), amount);\n token.safeIncreaseAllowance(address(pool), amount);\n try\n ISwap(pool).swap(\n tokenIndexFrom,\n tokenIndexTo,\n amount.sub(fee),\n minDy,\n deadline\n )\n returns (uint256 finalSwappedAmount) {\n // Swap succeeded, transfer swapped asset\n IERC20 swappedTokenTo = ISwap(pool).getToken(tokenIndexTo);\n if (\n address(swappedTokenTo) == WETH_ADDRESS &&\n WETH_ADDRESS != address(0)\n ) {\n IWETH9(WETH_ADDRESS).withdraw(finalSwappedAmount);\n (bool success, ) = to.call{value: finalSwappedAmount}(\"\");\n require(success, \"ETH_TRANSFER_FAILED\");\n emit TokenMintAndSwap(\n to,\n token,\n finalSwappedAmount,\n fee,\n tokenIndexFrom,\n tokenIndexTo,\n minDy,\n deadline,\n true,\n kappa\n );\n } else {\n swappedTokenTo.safeTransfer(to, finalSwappedAmount);\n emit TokenMintAndSwap(\n to,\n token,\n finalSwappedAmount,\n fee,\n tokenIndexFrom,\n tokenIndexTo,\n minDy,\n deadline,\n true,\n kappa\n );\n }\n } catch {\n IERC20(token).safeTransfer(to, amount.sub(fee));\n emit TokenMintAndSwap(\n to,\n token,\n amount.sub(fee),\n fee,\n tokenIndexFrom,\n tokenIndexTo,\n minDy,\n deadline,\n false,\n kappa\n );\n }\n } else {\n token.mint(address(this), amount);\n IERC20(token).safeTransfer(to, amount.sub(fee));\n emit TokenMintAndSwap(\n to,\n token,\n amount.sub(fee),\n fee,\n tokenIndexFrom,\n tokenIndexTo,\n minDy,\n deadline,\n false,\n kappa\n );\n }\n }\n\n /**\n * @notice Function to be called by the node group to withdraw the underlying assets from the contract\n * @param to address on chain to send underlying assets to\n * @param token ERC20 compatible token to withdraw from the bridge\n * @param amount Amount in native token decimals to withdraw\n * @param fee Amount in native token decimals to save to the contract as fees\n * @param pool Destination chain's pool to use to swap SynERC20 -> Asset. The nodes determine this by using PoolConfig.sol.\n * @param swapTokenIndex Specifies which of the underlying LP assets the nodes should attempt to redeem for\n * @param swapMinAmount Specifies the minimum amount of the underlying asset needed for the nodes to execute the redeem/swap\n * @param swapDeadline Specificies the deadline that the nodes are allowed to try to redeem/swap the LP token\n * @param kappa kappa\n **/\n function withdrawAndRemove(\n address to,\n IERC20 token,\n uint256 amount,\n uint256 fee,\n ISwap pool,\n uint8 swapTokenIndex,\n uint256 swapMinAmount,\n uint256 swapDeadline,\n bytes32 kappa\n ) external nonReentrant whenNotPaused {\n require(\n hasRole(NODEGROUP_ROLE, msg.sender),\n \"Caller is not a node group\"\n );\n require(amount > fee, \"Amount must be greater than fee\");\n require(!kappaMap[kappa], \"Kappa is already present\");\n kappaMap[kappa] = true;\n fees[address(token)] = fees[address(token)].add(fee);\n // first check to make sure more will be given than min amount required\n uint256 expectedOutput = ISwap(pool).calculateRemoveLiquidityOneToken(\n amount.sub(fee),\n swapTokenIndex\n );\n\n if (expectedOutput >= swapMinAmount) {\n token.safeIncreaseAllowance(address(pool), amount.sub(fee));\n try\n ISwap(pool).removeLiquidityOneToken(\n amount.sub(fee),\n swapTokenIndex,\n swapMinAmount,\n swapDeadline\n )\n returns (uint256 finalSwappedAmount) {\n // Swap succeeded, transfer swapped asset\n IERC20 swappedTokenTo = ISwap(pool).getToken(swapTokenIndex);\n swappedTokenTo.safeTransfer(to, finalSwappedAmount);\n emit TokenWithdrawAndRemove(\n to,\n token,\n finalSwappedAmount,\n fee,\n swapTokenIndex,\n swapMinAmount,\n swapDeadline,\n true,\n kappa\n );\n } catch {\n IERC20(token).safeTransfer(to, amount.sub(fee));\n emit TokenWithdrawAndRemove(\n to,\n token,\n amount.sub(fee),\n fee,\n swapTokenIndex,\n swapMinAmount,\n swapDeadline,\n false,\n kappa\n );\n }\n } else {\n token.safeTransfer(to, amount.sub(fee));\n emit TokenWithdrawAndRemove(\n to,\n token,\n amount.sub(fee),\n fee,\n swapTokenIndex,\n swapMinAmount,\n swapDeadline,\n false,\n kappa\n );\n }\n }\n\n // BRIDGE FUNCTIONS TO HANDLE DIFF ADDRESSES\n /**\n * @notice Relays to nodes that (typically) a wrapped synAsset ERC20 token has been burned and the underlying needs to be redeeemed on the native chain\n * @param to address on other chain to redeem underlying assets to\n * @param chainId which underlying chain to bridge assets onto\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n **/\n function redeemV2(\n bytes32 to,\n uint256 chainId,\n ERC20Burnable token,\n uint256 amount\n ) external nonReentrant whenNotPaused {\n emit TokenRedeemV2(to, chainId, token, amount);\n token.burnFrom(msg.sender, amount);\n }\n}\n" + }, + "contracts/bridge/HarmonySynapseBridge.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.6.12;\n\nimport \"@openzeppelin/contracts-upgradeable/proxy/Initializable.sol\";\nimport \"@openzeppelin/contracts-upgradeable/access/AccessControlUpgradeable.sol\";\nimport \"@openzeppelin/contracts-upgradeable/utils/ReentrancyGuardUpgradeable.sol\";\nimport \"@openzeppelin/contracts-upgradeable/utils/PausableUpgradeable.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/SafeERC20.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/ERC20Burnable.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport \"@openzeppelin/contracts/math/SafeMath.sol\";\n\nimport \"./interfaces/ISwap.sol\";\nimport \"./interfaces/IWETH9.sol\";\n\ninterface IERC20Mintable is IERC20 {\n function mint(address to, uint256 amount) external;\n}\n\ninterface IFrax {\n function exchangeOldForCanonical(\n address bridge_token_address,\n uint256 token_amount\n ) external returns (uint256);\n}\n\ncontract HarmonySynapseBridge is\n Initializable,\n AccessControlUpgradeable,\n ReentrancyGuardUpgradeable,\n PausableUpgradeable\n{\n using SafeERC20 for IERC20;\n using SafeERC20 for IERC20Mintable;\n using SafeMath for uint256;\n\n bytes32 public constant NODEGROUP_ROLE = keccak256(\"NODEGROUP_ROLE\");\n bytes32 public constant GOVERNANCE_ROLE = keccak256(\"GOVERNANCE_ROLE\");\n\n mapping(address => uint256) private fees;\n\n uint256 public startBlockNumber;\n uint256 public constant bridgeVersion = 6;\n uint256 public chainGasAmount;\n address payable public WETH_ADDRESS;\n\n mapping(bytes32 => bool) private kappaMap;\n\n receive() external payable {}\n\n function initialize() external initializer {\n startBlockNumber = block.number;\n _setupRole(DEFAULT_ADMIN_ROLE, msg.sender);\n __AccessControl_init();\n }\n\n function setChainGasAmount(uint256 amount) external {\n require(hasRole(GOVERNANCE_ROLE, msg.sender), \"Not governance\");\n chainGasAmount = amount;\n }\n\n function setWethAddress(address payable _wethAddress) external {\n require(hasRole(DEFAULT_ADMIN_ROLE, msg.sender), \"Not admin\");\n WETH_ADDRESS = _wethAddress;\n }\n\n function addKappas(bytes32[] calldata kappas) external {\n require(hasRole(GOVERNANCE_ROLE, msg.sender), \"Not governance\");\n for (uint256 i = 0; i < kappas.length; ++i) {\n kappaMap[kappas[i]] = true;\n }\n }\n\n event TokenDeposit(\n address indexed to,\n uint256 chainId,\n IERC20 token,\n uint256 amount\n );\n event TokenRedeem(\n address indexed to,\n uint256 chainId,\n IERC20 token,\n uint256 amount\n );\n event TokenWithdraw(\n address indexed to,\n IERC20 token,\n uint256 amount,\n uint256 fee,\n bytes32 indexed kappa\n );\n event TokenMint(\n address indexed to,\n IERC20Mintable token,\n uint256 amount,\n uint256 fee,\n bytes32 indexed kappa\n );\n event TokenDepositAndSwap(\n address indexed to,\n uint256 chainId,\n IERC20 token,\n uint256 amount,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 minDy,\n uint256 deadline\n );\n event TokenMintAndSwap(\n address indexed to,\n IERC20Mintable token,\n uint256 amount,\n uint256 fee,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 minDy,\n uint256 deadline,\n bool swapSuccess,\n bytes32 indexed kappa\n );\n event TokenRedeemAndSwap(\n address indexed to,\n uint256 chainId,\n IERC20 token,\n uint256 amount,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 minDy,\n uint256 deadline\n );\n event TokenRedeemAndRemove(\n address indexed to,\n uint256 chainId,\n IERC20 token,\n uint256 amount,\n uint8 swapTokenIndex,\n uint256 swapMinAmount,\n uint256 swapDeadline\n );\n event TokenWithdrawAndRemove(\n address indexed to,\n IERC20 token,\n uint256 amount,\n uint256 fee,\n uint8 swapTokenIndex,\n uint256 swapMinAmount,\n uint256 swapDeadline,\n bool swapSuccess,\n bytes32 indexed kappa\n );\n\n // v2 events\n event TokenRedeemV2(\n bytes32 indexed to,\n uint256 chainId,\n IERC20 token,\n uint256 amount\n );\n\n // VIEW FUNCTIONS ***/\n function getFeeBalance(address tokenAddress)\n external\n view\n returns (uint256)\n {\n return fees[tokenAddress];\n }\n\n function kappaExists(bytes32 kappa) external view returns (bool) {\n return kappaMap[kappa];\n }\n\n // FEE FUNCTIONS ***/\n /**\n * * @notice withdraw specified ERC20 token fees to a given address\n * * @param token ERC20 token in which fees acccumulated to transfer\n * * @param to Address to send the fees to\n */\n function withdrawFees(IERC20 token, address to) external whenNotPaused {\n require(hasRole(GOVERNANCE_ROLE, msg.sender), \"Not governance\");\n require(to != address(0), \"Address is 0x000\");\n if (fees[address(token)] != 0) {\n token.safeTransfer(to, fees[address(token)]);\n fees[address(token)] = 0;\n }\n }\n\n // PAUSABLE FUNCTIONS ***/\n function pause() external {\n require(hasRole(GOVERNANCE_ROLE, msg.sender), \"Not governance\");\n _pause();\n }\n\n function unpause() external {\n require(hasRole(GOVERNANCE_ROLE, msg.sender), \"Not governance\");\n _unpause();\n }\n\n /**\n * @notice Relays to nodes to transfers an ERC20 token cross-chain\n * @param to address on other chain to bridge assets to\n * @param chainId which chain to bridge assets onto\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n **/\n function deposit(\n address to,\n uint256 chainId,\n IERC20 token,\n uint256 amount\n ) external nonReentrant whenNotPaused {\n emit TokenDeposit(to, chainId, token, amount);\n token.safeTransferFrom(msg.sender, address(this), amount);\n }\n\n /**\n * @notice Relays to nodes that (typically) a wrapped synAsset ERC20 token has been burned and the underlying needs to be redeeemed on the native chain\n * @param to address on other chain to redeem underlying assets to\n * @param chainId which underlying chain to bridge assets onto\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n **/\n function redeem(\n address to,\n uint256 chainId,\n ERC20Burnable token,\n uint256 amount\n ) external nonReentrant whenNotPaused {\n emit TokenRedeem(to, chainId, token, amount);\n token.burnFrom(msg.sender, amount);\n }\n\n /**\n * @notice Function to be called by the node group to withdraw the underlying assets from the contract\n * @param to address on chain to send underlying assets to\n * @param token ERC20 compatible token to withdraw from the bridge\n * @param amount Amount in native token decimals to withdraw\n * @param fee Amount in native token decimals to save to the contract as fees\n * @param kappa kappa\n **/\n function withdraw(\n address to,\n IERC20 token,\n uint256 amount,\n uint256 fee,\n bytes32 kappa\n ) external nonReentrant whenNotPaused {\n require(\n hasRole(NODEGROUP_ROLE, msg.sender),\n \"Caller is not a node group\"\n );\n require(amount > fee, \"Amount must be greater than fee\");\n require(!kappaMap[kappa], \"Kappa is already present\");\n kappaMap[kappa] = true;\n fees[address(token)] = fees[address(token)].add(fee);\n if (address(token) == WETH_ADDRESS && WETH_ADDRESS != address(0)) {\n IWETH9(WETH_ADDRESS).withdraw(amount.sub(fee));\n (bool success, ) = to.call{value: amount.sub(fee)}(\"\");\n require(success, \"ETH_TRANSFER_FAILED\");\n emit TokenWithdraw(to, token, amount, fee, kappa);\n } else {\n emit TokenWithdraw(to, token, amount, fee, kappa);\n token.safeTransfer(to, amount.sub(fee));\n }\n }\n\n /**\n * @notice Nodes call this function to mint a SynERC20 (or any asset that the bridge is given minter access to). This is called by the nodes after a TokenDeposit event is emitted.\n * @dev This means the SynapseBridge.sol contract must have minter access to the token attempting to be minted\n * @param to address on other chain to redeem underlying assets to\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain post-fees\n * @param fee Amount in native token decimals to save to the contract as fees\n * @param kappa kappa\n **/\n function mint(\n address payable to,\n IERC20Mintable token,\n uint256 amount,\n uint256 fee,\n bytes32 kappa\n ) external nonReentrant whenNotPaused {\n require(\n hasRole(NODEGROUP_ROLE, msg.sender),\n \"Caller is not a node group\"\n );\n require(amount > fee, \"Amount must be greater than fee\");\n require(!kappaMap[kappa], \"Kappa is already present\");\n kappaMap[kappa] = true;\n fees[address(token)] = fees[address(token)].add(fee);\n emit TokenMint(to, token, amount.sub(fee), fee, kappa);\n token.mint(address(this), amount);\n // checks if synFRAX\n if (address(token) == 0x1852F70512298d56e9c8FDd905e02581E04ddb2a) {\n if (\n token.allowance(\n address(this),\n 0xFa7191D292d5633f702B0bd7E3E3BcCC0e633200\n ) < amount.sub(fee)\n ) {\n token.safeApprove(\n address(0xFa7191D292d5633f702B0bd7E3E3BcCC0e633200),\n 0\n );\n token.safeApprove(\n address(0xFa7191D292d5633f702B0bd7E3E3BcCC0e633200),\n type(uint256).max\n );\n }\n try\n IFrax(0xFa7191D292d5633f702B0bd7E3E3BcCC0e633200)\n .exchangeOldForCanonical(address(token), amount.sub(fee))\n returns (uint256 canolical_tokens_out) {\n IERC20(0xFa7191D292d5633f702B0bd7E3E3BcCC0e633200).safeTransfer(\n to,\n canolical_tokens_out\n );\n } catch {\n IERC20(token).safeTransfer(to, amount.sub(fee));\n }\n } else {\n IERC20(token).safeTransfer(to, amount.sub(fee));\n }\n if (chainGasAmount != 0 && address(this).balance > chainGasAmount) {\n to.call.value(chainGasAmount)(\"\");\n }\n }\n\n /**\n * @notice Relays to nodes to both transfer an ERC20 token cross-chain, and then have the nodes execute a swap through a liquidity pool on behalf of the user.\n * @param to address on other chain to bridge assets to\n * @param chainId which chain to bridge assets onto\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n * @param tokenIndexFrom the token the user wants to swap from\n * @param tokenIndexTo the token the user wants to swap to\n * @param minDy the min amount the user would like to receive, or revert to only minting the SynERC20 token crosschain.\n * @param deadline latest timestamp to accept this transaction\n **/\n function depositAndSwap(\n address to,\n uint256 chainId,\n IERC20 token,\n uint256 amount,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 minDy,\n uint256 deadline\n ) external nonReentrant whenNotPaused {\n emit TokenDepositAndSwap(\n to,\n chainId,\n token,\n amount,\n tokenIndexFrom,\n tokenIndexTo,\n minDy,\n deadline\n );\n token.safeTransferFrom(msg.sender, address(this), amount);\n }\n\n /**\n * @notice Relays to nodes that (typically) a wrapped synAsset ERC20 token has been burned and the underlying needs to be redeeemed on the native chain. This function indicates to the nodes that they should attempt to redeem the LP token for the underlying assets (E.g \"swap\" out of the LP token)\n * @param to address on other chain to redeem underlying assets to\n * @param chainId which underlying chain to bridge assets onto\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n * @param tokenIndexFrom the token the user wants to swap from\n * @param tokenIndexTo the token the user wants to swap to\n * @param minDy the min amount the user would like to receive, or revert to only minting the SynERC20 token crosschain.\n * @param deadline latest timestamp to accept this transaction\n **/\n function redeemAndSwap(\n address to,\n uint256 chainId,\n ERC20Burnable token,\n uint256 amount,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 minDy,\n uint256 deadline\n ) external nonReentrant whenNotPaused {\n emit TokenRedeemAndSwap(\n to,\n chainId,\n token,\n amount,\n tokenIndexFrom,\n tokenIndexTo,\n minDy,\n deadline\n );\n token.burnFrom(msg.sender, amount);\n }\n\n /**\n * @notice Relays to nodes that (typically) a wrapped synAsset ERC20 token has been burned and the underlying needs to be redeeemed on the native chain. This function indicates to the nodes that they should attempt to redeem the LP token for the underlying assets (E.g \"swap\" out of the LP token)\n * @param to address on other chain to redeem underlying assets to\n * @param chainId which underlying chain to bridge assets onto\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n * @param swapTokenIndex Specifies which of the underlying LP assets the nodes should attempt to redeem for\n * @param swapMinAmount Specifies the minimum amount of the underlying asset needed for the nodes to execute the redeem/swap\n * @param swapDeadline Specificies the deadline that the nodes are allowed to try to redeem/swap the LP token\n **/\n function redeemAndRemove(\n address to,\n uint256 chainId,\n ERC20Burnable token,\n uint256 amount,\n uint8 swapTokenIndex,\n uint256 swapMinAmount,\n uint256 swapDeadline\n ) external nonReentrant whenNotPaused {\n emit TokenRedeemAndRemove(\n to,\n chainId,\n token,\n amount,\n swapTokenIndex,\n swapMinAmount,\n swapDeadline\n );\n token.burnFrom(msg.sender, amount);\n }\n\n /**\n * @notice Nodes call this function to mint a SynERC20 (or any asset that the bridge is given minter access to), and then attempt to swap the SynERC20 into the desired destination asset. This is called by the nodes after a TokenDepositAndSwap event is emitted.\n * @dev This means the BridgeDeposit.sol contract must have minter access to the token attempting to be minted\n * @param to address on other chain to redeem underlying assets to\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain post-fees\n * @param fee Amount in native token decimals to save to the contract as fees\n * @param pool Destination chain's pool to use to swap SynERC20 -> Asset. The nodes determine this by using PoolConfig.sol.\n * @param tokenIndexFrom Index of the SynERC20 asset in the pool\n * @param tokenIndexTo Index of the desired final asset\n * @param minDy Minumum amount (in final asset decimals) that must be swapped for, otherwise the user will receive the SynERC20.\n * @param deadline Epoch time of the deadline that the swap is allowed to be executed.\n * @param kappa kappa\n **/\n function mintAndSwap(\n address payable to,\n IERC20Mintable token,\n uint256 amount,\n uint256 fee,\n ISwap pool,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 minDy,\n uint256 deadline,\n bytes32 kappa\n ) external nonReentrant whenNotPaused {\n require(\n hasRole(NODEGROUP_ROLE, msg.sender),\n \"Caller is not a node group\"\n );\n require(amount > fee, \"Amount must be greater than fee\");\n require(!kappaMap[kappa], \"Kappa is already present\");\n kappaMap[kappa] = true;\n fees[address(token)] = fees[address(token)].add(fee);\n // Transfer gas airdrop\n if (chainGasAmount != 0 && address(this).balance > chainGasAmount) {\n to.call.value(chainGasAmount)(\"\");\n }\n // first check to make sure more will be given than min amount required\n uint256 expectedOutput = ISwap(pool).calculateSwap(\n tokenIndexFrom,\n tokenIndexTo,\n amount.sub(fee)\n );\n\n if (expectedOutput >= minDy) {\n // proceed with swap\n token.mint(address(this), amount);\n token.safeIncreaseAllowance(address(pool), amount);\n try\n ISwap(pool).swap(\n tokenIndexFrom,\n tokenIndexTo,\n amount.sub(fee),\n minDy,\n deadline\n )\n returns (uint256 finalSwappedAmount) {\n // Swap succeeded, transfer swapped asset\n IERC20 swappedTokenTo = ISwap(pool).getToken(tokenIndexTo);\n if (\n address(swappedTokenTo) == WETH_ADDRESS &&\n WETH_ADDRESS != address(0)\n ) {\n IWETH9(WETH_ADDRESS).withdraw(finalSwappedAmount);\n (bool success, ) = to.call{value: finalSwappedAmount}(\"\");\n require(success, \"ETH_TRANSFER_FAILED\");\n emit TokenMintAndSwap(\n to,\n token,\n finalSwappedAmount,\n fee,\n tokenIndexFrom,\n tokenIndexTo,\n minDy,\n deadline,\n true,\n kappa\n );\n } else {\n swappedTokenTo.safeTransfer(to, finalSwappedAmount);\n emit TokenMintAndSwap(\n to,\n token,\n finalSwappedAmount,\n fee,\n tokenIndexFrom,\n tokenIndexTo,\n minDy,\n deadline,\n true,\n kappa\n );\n }\n } catch {\n IERC20(token).safeTransfer(to, amount.sub(fee));\n emit TokenMintAndSwap(\n to,\n token,\n amount.sub(fee),\n fee,\n tokenIndexFrom,\n tokenIndexTo,\n minDy,\n deadline,\n false,\n kappa\n );\n }\n } else {\n token.mint(address(this), amount);\n IERC20(token).safeTransfer(to, amount.sub(fee));\n emit TokenMintAndSwap(\n to,\n token,\n amount.sub(fee),\n fee,\n tokenIndexFrom,\n tokenIndexTo,\n minDy,\n deadline,\n false,\n kappa\n );\n }\n }\n\n /**\n * @notice Function to be called by the node group to withdraw the underlying assets from the contract\n * @param to address on chain to send underlying assets to\n * @param token ERC20 compatible token to withdraw from the bridge\n * @param amount Amount in native token decimals to withdraw\n * @param fee Amount in native token decimals to save to the contract as fees\n * @param pool Destination chain's pool to use to swap SynERC20 -> Asset. The nodes determine this by using PoolConfig.sol.\n * @param swapTokenIndex Specifies which of the underlying LP assets the nodes should attempt to redeem for\n * @param swapMinAmount Specifies the minimum amount of the underlying asset needed for the nodes to execute the redeem/swap\n * @param swapDeadline Specificies the deadline that the nodes are allowed to try to redeem/swap the LP token\n * @param kappa kappa\n **/\n function withdrawAndRemove(\n address to,\n IERC20 token,\n uint256 amount,\n uint256 fee,\n ISwap pool,\n uint8 swapTokenIndex,\n uint256 swapMinAmount,\n uint256 swapDeadline,\n bytes32 kappa\n ) external nonReentrant whenNotPaused {\n require(\n hasRole(NODEGROUP_ROLE, msg.sender),\n \"Caller is not a node group\"\n );\n require(amount > fee, \"Amount must be greater than fee\");\n require(!kappaMap[kappa], \"Kappa is already present\");\n kappaMap[kappa] = true;\n fees[address(token)] = fees[address(token)].add(fee);\n // first check to make sure more will be given than min amount required\n uint256 expectedOutput = ISwap(pool).calculateRemoveLiquidityOneToken(\n amount.sub(fee),\n swapTokenIndex\n );\n\n if (expectedOutput >= swapMinAmount) {\n token.safeIncreaseAllowance(address(pool), amount.sub(fee));\n try\n ISwap(pool).removeLiquidityOneToken(\n amount.sub(fee),\n swapTokenIndex,\n swapMinAmount,\n swapDeadline\n )\n returns (uint256 finalSwappedAmount) {\n // Swap succeeded, transfer swapped asset\n IERC20 swappedTokenTo = ISwap(pool).getToken(swapTokenIndex);\n swappedTokenTo.safeTransfer(to, finalSwappedAmount);\n emit TokenWithdrawAndRemove(\n to,\n token,\n finalSwappedAmount,\n fee,\n swapTokenIndex,\n swapMinAmount,\n swapDeadline,\n true,\n kappa\n );\n } catch {\n IERC20(token).safeTransfer(to, amount.sub(fee));\n emit TokenWithdrawAndRemove(\n to,\n token,\n amount.sub(fee),\n fee,\n swapTokenIndex,\n swapMinAmount,\n swapDeadline,\n false,\n kappa\n );\n }\n } else {\n token.safeTransfer(to, amount.sub(fee));\n emit TokenWithdrawAndRemove(\n to,\n token,\n amount.sub(fee),\n fee,\n swapTokenIndex,\n swapMinAmount,\n swapDeadline,\n false,\n kappa\n );\n }\n }\n\n // BRIDGE FUNCTIONS TO HANDLE DIFF ADDRESSES\n /**\n * @notice Relays to nodes that (typically) a wrapped synAsset ERC20 token has been burned and the underlying needs to be redeeemed on the native chain\n * @param to address on other chain to redeem underlying assets to\n * @param chainId which underlying chain to bridge assets onto\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n **/\n function redeemV2(\n bytes32 to,\n uint256 chainId,\n ERC20Burnable token,\n uint256 amount\n ) external nonReentrant whenNotPaused {\n emit TokenRedeemV2(to, chainId, token, amount);\n token.burnFrom(msg.sender, amount);\n }\n}\n" + }, + "contracts/bridge/SynapseERC20.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.6.12;\n\nimport \"@openzeppelin/contracts-upgradeable/token/ERC20/ERC20Upgradeable.sol\";\nimport \"@openzeppelin/contracts-upgradeable/token/ERC20/ERC20BurnableUpgradeable.sol\";\nimport \"@openzeppelin/contracts-upgradeable/drafts/ERC20PermitUpgradeable.sol\";\nimport \"@openzeppelin/contracts-upgradeable/access/AccessControlUpgradeable.sol\";\nimport \"@openzeppelin/contracts-upgradeable/proxy/Initializable.sol\";\n\ncontract SynapseERC20 is\n Initializable,\n ContextUpgradeable,\n AccessControlUpgradeable,\n ERC20BurnableUpgradeable,\n ERC20PermitUpgradeable\n{\n bytes32 public constant MINTER_ROLE = keccak256(\"MINTER_ROLE\");\n\n /**\n * @notice Initializes this ERC20 contract with the given parameters.\n * @param name Token name\n * @param symbol Token symbol\n * @param decimals Token name\n * @param owner admin address to be initialized with\n */\n function initialize(\n string memory name,\n string memory symbol,\n uint8 decimals,\n address owner\n ) external initializer {\n __Context_init_unchained();\n __AccessControl_init_unchained();\n __ERC20_init_unchained(name, symbol);\n __ERC20Burnable_init_unchained();\n _setupDecimals(decimals);\n __ERC20Permit_init(name);\n _setupRole(DEFAULT_ADMIN_ROLE, owner);\n }\n\n function mint(address to, uint256 amount) external {\n require(hasRole(MINTER_ROLE, msg.sender), \"Not a minter\");\n _mint(to, amount);\n }\n}\n" + }, + "@openzeppelin/contracts-upgradeable/drafts/ERC20PermitUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.5 <0.8.0;\n\nimport \"../token/ERC20/ERC20Upgradeable.sol\";\nimport \"./IERC20PermitUpgradeable.sol\";\nimport \"../cryptography/ECDSAUpgradeable.sol\";\nimport \"../utils/CountersUpgradeable.sol\";\nimport \"./EIP712Upgradeable.sol\";\nimport \"../proxy/Initializable.sol\";\n\n/**\n * @dev Implementation of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in\n * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612].\n *\n * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by\n * presenting a message signed by the account. By not relying on `{IERC20-approve}`, the token holder account doesn't\n * need to send a transaction, and thus is not required to hold Ether at all.\n *\n * _Available since v3.4._\n */\nabstract contract ERC20PermitUpgradeable is Initializable, ERC20Upgradeable, IERC20PermitUpgradeable, EIP712Upgradeable {\n using CountersUpgradeable for CountersUpgradeable.Counter;\n\n mapping (address => CountersUpgradeable.Counter) private _nonces;\n\n // solhint-disable-next-line var-name-mixedcase\n bytes32 private _PERMIT_TYPEHASH;\n\n /**\n * @dev Initializes the {EIP712} domain separator using the `name` parameter, and setting `version` to `\"1\"`.\n *\n * It's a good idea to use the same `name` that is defined as the ERC20 token name.\n */\n function __ERC20Permit_init(string memory name) internal initializer {\n __Context_init_unchained();\n __EIP712_init_unchained(name, \"1\");\n __ERC20Permit_init_unchained(name);\n }\n\n function __ERC20Permit_init_unchained(string memory name) internal initializer {\n _PERMIT_TYPEHASH = keccak256(\"Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)\");\n }\n\n /**\n * @dev See {IERC20Permit-permit}.\n */\n function permit(address owner, address spender, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s) public virtual override {\n // solhint-disable-next-line not-rely-on-time\n require(block.timestamp <= deadline, \"ERC20Permit: expired deadline\");\n\n bytes32 structHash = keccak256(\n abi.encode(\n _PERMIT_TYPEHASH,\n owner,\n spender,\n value,\n _nonces[owner].current(),\n deadline\n )\n );\n\n bytes32 hash = _hashTypedDataV4(structHash);\n\n address signer = ECDSAUpgradeable.recover(hash, v, r, s);\n require(signer == owner, \"ERC20Permit: invalid signature\");\n\n _nonces[owner].increment();\n _approve(owner, spender, value);\n }\n\n /**\n * @dev See {IERC20Permit-nonces}.\n */\n function nonces(address owner) public view override returns (uint256) {\n return _nonces[owner].current();\n }\n\n /**\n * @dev See {IERC20Permit-DOMAIN_SEPARATOR}.\n */\n // solhint-disable-next-line func-name-mixedcase\n function DOMAIN_SEPARATOR() external view override returns (bytes32) {\n return _domainSeparatorV4();\n }\n uint256[49] private __gap;\n}\n" + }, + "@openzeppelin/contracts-upgradeable/drafts/IERC20PermitUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <0.8.0;\n\n/**\n * @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in\n * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612].\n *\n * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by\n * presenting a message signed by the account. By not relying on `{IERC20-approve}`, the token holder account doesn't\n * need to send a transaction, and thus is not required to hold Ether at all.\n */\ninterface IERC20PermitUpgradeable {\n /**\n * @dev Sets `value` as the allowance of `spender` over `owner`'s tokens,\n * given `owner`'s signed approval.\n *\n * IMPORTANT: The same issues {IERC20-approve} has related to transaction\n * ordering also apply here.\n *\n * Emits an {Approval} event.\n *\n * Requirements:\n *\n * - `spender` cannot be the zero address.\n * - `deadline` must be a timestamp in the future.\n * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner`\n * over the EIP712-formatted function arguments.\n * - the signature must use ``owner``'s current nonce (see {nonces}).\n *\n * For more information on the signature format, see the\n * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP\n * section].\n */\n function permit(address owner, address spender, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s) external;\n\n /**\n * @dev Returns the current nonce for `owner`. This value must be\n * included whenever a signature is generated for {permit}.\n *\n * Every successful call to {permit} increases ``owner``'s nonce by one. This\n * prevents a signature from being used multiple times.\n */\n function nonces(address owner) external view returns (uint256);\n\n /**\n * @dev Returns the domain separator used in the encoding of the signature for `permit`, as defined by {EIP712}.\n */\n // solhint-disable-next-line func-name-mixedcase\n function DOMAIN_SEPARATOR() external view returns (bytes32);\n}\n" + }, + "@openzeppelin/contracts-upgradeable/cryptography/ECDSAUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <0.8.0;\n\n/**\n * @dev Elliptic Curve Digital Signature Algorithm (ECDSA) operations.\n *\n * These functions can be used to verify that a message was signed by the holder\n * of the private keys of a given address.\n */\nlibrary ECDSAUpgradeable {\n /**\n * @dev Returns the address that signed a hashed message (`hash`) with\n * `signature`. This address can then be used for verification purposes.\n *\n * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:\n * this function rejects them by requiring the `s` value to be in the lower\n * half order, and the `v` value to be either 27 or 28.\n *\n * IMPORTANT: `hash` _must_ be the result of a hash operation for the\n * verification to be secure: it is possible to craft signatures that\n * recover to arbitrary addresses for non-hashed data. A safe way to ensure\n * this is by receiving a hash of the original message (which may otherwise\n * be too long), and then calling {toEthSignedMessageHash} on it.\n */\n function recover(bytes32 hash, bytes memory signature) internal pure returns (address) {\n // Check the signature length\n if (signature.length != 65) {\n revert(\"ECDSA: invalid signature length\");\n }\n\n // Divide the signature in r, s and v variables\n bytes32 r;\n bytes32 s;\n uint8 v;\n\n // ecrecover takes the signature parameters, and the only way to get them\n // currently is to use assembly.\n // solhint-disable-next-line no-inline-assembly\n assembly {\n r := mload(add(signature, 0x20))\n s := mload(add(signature, 0x40))\n v := byte(0, mload(add(signature, 0x60)))\n }\n\n return recover(hash, v, r, s);\n }\n\n /**\n * @dev Overload of {ECDSA-recover-bytes32-bytes-} that receives the `v`,\n * `r` and `s` signature fields separately.\n */\n function recover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) internal pure returns (address) {\n // EIP-2 still allows signature malleability for ecrecover(). Remove this possibility and make the signature\n // unique. Appendix F in the Ethereum Yellow paper (https://ethereum.github.io/yellowpaper/paper.pdf), defines\n // the valid range for s in (281): 0 < s < secp256k1n ÷ 2 + 1, and for v in (282): v ∈ {27, 28}. Most\n // signatures from current libraries generate a unique signature with an s-value in the lower half order.\n //\n // If your library generates malleable signatures, such as s-values in the upper range, calculate a new s-value\n // with 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 - s1 and flip v from 27 to 28 or\n // vice versa. If your library also generates signatures with 0/1 for v instead 27/28, add 27 to v to accept\n // these malleable signatures as well.\n require(uint256(s) <= 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0, \"ECDSA: invalid signature 's' value\");\n require(v == 27 || v == 28, \"ECDSA: invalid signature 'v' value\");\n\n // If the signature is valid (and not malleable), return the signer address\n address signer = ecrecover(hash, v, r, s);\n require(signer != address(0), \"ECDSA: invalid signature\");\n\n return signer;\n }\n\n /**\n * @dev Returns an Ethereum Signed Message, created from a `hash`. This\n * replicates the behavior of the\n * https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_sign[`eth_sign`]\n * JSON-RPC method.\n *\n * See {recover}.\n */\n function toEthSignedMessageHash(bytes32 hash) internal pure returns (bytes32) {\n // 32 is the length in bytes of hash,\n // enforced by the type signature above\n return keccak256(abi.encodePacked(\"\\x19Ethereum Signed Message:\\n32\", hash));\n }\n}\n" + }, + "@openzeppelin/contracts-upgradeable/utils/CountersUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <0.8.0;\n\nimport \"../math/SafeMathUpgradeable.sol\";\n\n/**\n * @title Counters\n * @author Matt Condon (@shrugs)\n * @dev Provides counters that can only be incremented or decremented by one. This can be used e.g. to track the number\n * of elements in a mapping, issuing ERC721 ids, or counting request ids.\n *\n * Include with `using Counters for Counters.Counter;`\n * Since it is not possible to overflow a 256 bit integer with increments of one, `increment` can skip the {SafeMath}\n * overflow check, thereby saving gas. This does assume however correct usage, in that the underlying `_value` is never\n * directly accessed.\n */\nlibrary CountersUpgradeable {\n using SafeMathUpgradeable for uint256;\n\n struct Counter {\n // This variable should never be directly accessed by users of the library: interactions must be restricted to\n // the library's function. As of Solidity v0.5.2, this cannot be enforced, though there is a proposal to add\n // this feature: see https://github.com/ethereum/solidity/issues/4637\n uint256 _value; // default: 0\n }\n\n function current(Counter storage counter) internal view returns (uint256) {\n return counter._value;\n }\n\n function increment(Counter storage counter) internal {\n // The {SafeMath} overflow check can be skipped here, see the comment at the top\n counter._value += 1;\n }\n\n function decrement(Counter storage counter) internal {\n counter._value = counter._value.sub(1);\n }\n}\n" + }, + "@openzeppelin/contracts-upgradeable/drafts/EIP712Upgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <0.8.0;\nimport \"../proxy/Initializable.sol\";\n\n/**\n * @dev https://eips.ethereum.org/EIPS/eip-712[EIP 712] is a standard for hashing and signing of typed structured data.\n *\n * The encoding specified in the EIP is very generic, and such a generic implementation in Solidity is not feasible,\n * thus this contract does not implement the encoding itself. Protocols need to implement the type-specific encoding\n * they need in their contracts using a combination of `abi.encode` and `keccak256`.\n *\n * This contract implements the EIP 712 domain separator ({_domainSeparatorV4}) that is used as part of the encoding\n * scheme, and the final step of the encoding to obtain the message digest that is then signed via ECDSA\n * ({_hashTypedDataV4}).\n *\n * The implementation of the domain separator was designed to be as efficient as possible while still properly updating\n * the chain id to protect against replay attacks on an eventual fork of the chain.\n *\n * NOTE: This contract implements the version of the encoding known as \"v4\", as implemented by the JSON RPC method\n * https://docs.metamask.io/guide/signing-data.html[`eth_signTypedDataV4` in MetaMask].\n *\n * _Available since v3.4._\n */\nabstract contract EIP712Upgradeable is Initializable {\n /* solhint-disable var-name-mixedcase */\n bytes32 private _HASHED_NAME;\n bytes32 private _HASHED_VERSION;\n bytes32 private constant _TYPE_HASH = keccak256(\"EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)\");\n /* solhint-enable var-name-mixedcase */\n\n /**\n * @dev Initializes the domain separator and parameter caches.\n *\n * The meaning of `name` and `version` is specified in\n * https://eips.ethereum.org/EIPS/eip-712#definition-of-domainseparator[EIP 712]:\n *\n * - `name`: the user readable name of the signing domain, i.e. the name of the DApp or the protocol.\n * - `version`: the current major version of the signing domain.\n *\n * NOTE: These parameters cannot be changed except through a xref:learn::upgrading-smart-contracts.adoc[smart\n * contract upgrade].\n */\n function __EIP712_init(string memory name, string memory version) internal initializer {\n __EIP712_init_unchained(name, version);\n }\n\n function __EIP712_init_unchained(string memory name, string memory version) internal initializer {\n bytes32 hashedName = keccak256(bytes(name));\n bytes32 hashedVersion = keccak256(bytes(version));\n _HASHED_NAME = hashedName;\n _HASHED_VERSION = hashedVersion;\n }\n\n /**\n * @dev Returns the domain separator for the current chain.\n */\n function _domainSeparatorV4() internal view returns (bytes32) {\n return _buildDomainSeparator(_TYPE_HASH, _EIP712NameHash(), _EIP712VersionHash());\n }\n\n function _buildDomainSeparator(bytes32 typeHash, bytes32 name, bytes32 version) private view returns (bytes32) {\n return keccak256(\n abi.encode(\n typeHash,\n name,\n version,\n _getChainId(),\n address(this)\n )\n );\n }\n\n /**\n * @dev Given an already https://eips.ethereum.org/EIPS/eip-712#definition-of-hashstruct[hashed struct], this\n * function returns the hash of the fully encoded EIP712 message for this domain.\n *\n * This hash can be used together with {ECDSA-recover} to obtain the signer of a message. For example:\n *\n * ```solidity\n * bytes32 digest = _hashTypedDataV4(keccak256(abi.encode(\n * keccak256(\"Mail(address to,string contents)\"),\n * mailTo,\n * keccak256(bytes(mailContents))\n * )));\n * address signer = ECDSA.recover(digest, signature);\n * ```\n */\n function _hashTypedDataV4(bytes32 structHash) internal view virtual returns (bytes32) {\n return keccak256(abi.encodePacked(\"\\x19\\x01\", _domainSeparatorV4(), structHash));\n }\n\n function _getChainId() private view returns (uint256 chainId) {\n this; // silence state mutability warning without generating bytecode - see https://github.com/ethereum/solidity/issues/2691\n // solhint-disable-next-line no-inline-assembly\n assembly {\n chainId := chainid()\n }\n }\n\n /**\n * @dev The hash of the name parameter for the EIP712 domain.\n *\n * NOTE: This function reads from storage by default, but can be redefined to return a constant value if gas costs\n * are a concern.\n */\n function _EIP712NameHash() internal virtual view returns (bytes32) {\n return _HASHED_NAME;\n }\n\n /**\n * @dev The hash of the version parameter for the EIP712 domain.\n *\n * NOTE: This function reads from storage by default, but can be redefined to return a constant value if gas costs\n * are a concern.\n */\n function _EIP712VersionHash() internal virtual view returns (bytes32) {\n return _HASHED_VERSION;\n }\n uint256[50] private __gap;\n}\n" + }, + "contracts/auxiliary/DummyWethProxy.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.6.12;\nimport \"@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol\";\nimport \"@openzeppelin/contracts-upgradeable/proxy/Initializable.sol\";\n\ninterface IWETH9 {\n function name() external view returns (string memory);\n\n function symbol() external view returns (string memory);\n\n function decimals() external view returns (uint8);\n\n function balanceOf(address) external view returns (uint256);\n\n function allowance(address, address) external view returns (uint256);\n\n receive() external payable;\n\n function deposit() external payable;\n\n function withdraw(uint256 wad) external;\n\n function totalSupply() external view returns (uint256);\n\n function approve(address guy, uint256 wad) external returns (bool);\n\n function transfer(address dst, uint256 wad) external returns (bool);\n\n function transferFrom(\n address src,\n address dst,\n uint256 wad\n ) external returns (bool);\n}\n\ncontract DummyWethProxy is Initializable, OwnableUpgradeable {\n function initialize() external initializer {\n __Ownable_init();\n }\n\n IWETH9 public WETH;\n\n function setWETHAddress(address payable _weth) external onlyOwner {\n WETH = IWETH9(_weth);\n }\n\n function withdrawToSelf(uint256 amount) external {\n WETH.withdraw(amount);\n }\n\n function rescue(uint256 amount) external onlyOwner {\n WETH.transfer(owner(), amount);\n }\n\n receive() external payable {}\n\n fallback() external payable {}\n}\n" + }, + "contracts/amm/helper/test/TestMathUtils.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.6.12;\n\nimport \"../../MathUtils.sol\";\n\ncontract TestMathUtils {\n using MathUtils for uint256;\n\n function difference(uint256 a, uint256 b) public pure returns (uint256) {\n return a.difference(b);\n }\n\n function within1(uint256 a, uint256 b) public pure returns (bool) {\n return a.within1(b);\n }\n}\n" + }, + "contracts/bridge/ERC20Migrator.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.6.12;\n\nimport \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/SafeERC20.sol\";\nimport \"@openzeppelin/contracts/math/SafeMath.sol\";\n\n/**\n * @title ERC20Migrator\n * @dev This contract can be used to migrate an ERC20 token from one\n * contract to another, where each token holder has to opt-in to the migration.\n * To opt-in, users must approve for this contract the number of tokens they\n * want to migrate. Once the allowance is set up, anyone can trigger the\n * migration to the new token contract. In this way, token holders \"turn in\"\n * their old balance and will be minted an equal amount in the new token.\n * The new token contract must be mintable.\n * ```\n */\n\ninterface IERC20Mintable is IERC20 {\n function mint(address to, uint256 amount) external;\n}\n\ncontract ERC20Migrator {\n using SafeERC20 for IERC20;\n using SafeMath for uint256;\n\n // Address of the old token contract\n IERC20 private _legacyToken;\n\n // Address of the new token contract\n IERC20Mintable private _newToken;\n\n /**\n * @param legacyToken address of the old token contract\n */\n constructor(IERC20 legacyToken, IERC20Mintable newToken) public {\n _legacyToken = legacyToken;\n _newToken = newToken;\n }\n\n /**\n * @dev Returns the legacy token that is being migrated.\n */\n function legacyToken() external view returns (IERC20) {\n return _legacyToken;\n }\n\n /**\n * @dev Returns the new token to which we are migrating.\n */\n function newToken() external view returns (IERC20) {\n return _newToken;\n }\n\n /**\n * @dev Transfers part of an account's balance in the old token to this\n * contract, and mints the same amount of new tokens for that account.\n * @param amount amount of tokens to be migrated\n */\n function migrate(uint256 amount) external {\n _legacyToken.safeTransferFrom(msg.sender, address(this), amount);\n uint256 amountToMint = amount.mul(5).div(2);\n _newToken.mint(msg.sender, amountToMint);\n }\n}\n" + }, + "contracts/bridge/ECDSANodeManagement.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.6.12;\n\nimport \"./utils/AddressArrayUtils.sol\";\nimport \"@openzeppelin/contracts/math/SafeMath.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/SafeERC20.sol\";\n\ncontract ECDSANodeManagement {\n using AddressArrayUtils for address[];\n using SafeMath for uint256;\n using SafeERC20 for IERC20;\n\n // Status of the keep.\n // Active means the keep is active.\n // Closed means the keep was closed happily.\n // Terminated means the keep was closed due to misbehavior.\n enum Status {\n Active,\n Closed,\n Terminated\n }\n\n // Address of the keep's owner.\n address public owner;\n\n // List of keep members' addresses.\n address[] public members;\n\n // Minimum number of honest keep members required to produce a signature.\n uint256 public honestThreshold;\n\n // Keep's ECDSA public key serialized to 64-bytes, where X and Y coordinates\n // are padded with zeros to 32-byte each.\n bytes public publicKey;\n\n // The timestamp at which keep has been created and key generation process\n // started.\n uint256 internal keyGenerationStartTimestamp;\n\n // Map stores public key by member addresses. All members should submit the\n // same public key.\n mapping(address => bytes) internal submittedPublicKeys;\n\n // The current status of the keep.\n // If the keep is Active members monitor it and support requests from the\n // keep owner.\n // If the owner decides to close the keep the flag is set to Closed.\n // If the owner seizes member bonds the flag is set to Terminated.\n Status internal status;\n\n // Flags execution of contract initialization.\n bool internal isInitialized;\n\n // Notification that the submitted public key does not match a key submitted\n // by other member. The event contains address of the member who tried to\n // submit a public key and a conflicting public key submitted already by other\n // member.\n event ConflictingPublicKeySubmitted(\n address indexed submittingMember,\n bytes conflictingPublicKey\n );\n\n // Notification that keep's ECDSA public key has been successfully established.\n event PublicKeyPublished(bytes publicKey);\n\n // Notification that the keep was closed by the owner.\n // Members no longer need to support this keep.\n event KeepClosed();\n\n // Notification that the keep has been terminated by the owner.\n // Members no longer need to support this keep.\n event KeepTerminated();\n\n /// @notice Returns keep's ECDSA public key.\n /// @return Keep's ECDSA public key.\n function getPublicKey() external view returns (bytes memory) {\n return publicKey;\n }\n\n /// @notice Submits a public key to the keep.\n /// @dev Public key is published successfully if all members submit the same\n /// value. In case of conflicts with others members submissions it will emit\n /// `ConflictingPublicKeySubmitted` event. When all submitted keys match\n /// it will store the key as keep's public key and emit a `PublicKeyPublished`\n /// event.\n /// @param _publicKey Signer's public key.\n function submitPublicKey(bytes calldata _publicKey) external onlyMember {\n require(\n !hasMemberSubmittedPublicKey(msg.sender),\n \"Member already submitted a public key\"\n );\n\n require(_publicKey.length == 64, \"Public key must be 64 bytes long\");\n\n submittedPublicKeys[msg.sender] = _publicKey;\n\n // Check if public keys submitted by all keep members are the same as\n // the currently submitted one.\n uint256 matchingPublicKeysCount = 0;\n for (uint256 i = 0; i < members.length; i++) {\n if (\n keccak256(submittedPublicKeys[members[i]]) !=\n keccak256(_publicKey)\n ) {\n // Emit an event only if compared member already submitted a value.\n if (hasMemberSubmittedPublicKey(members[i])) {\n emit ConflictingPublicKeySubmitted(\n msg.sender,\n submittedPublicKeys[members[i]]\n );\n }\n } else {\n matchingPublicKeysCount++;\n }\n }\n\n if (matchingPublicKeysCount != members.length) {\n return;\n }\n\n // All submitted signatures match.\n publicKey = _publicKey;\n emit PublicKeyPublished(_publicKey);\n }\n\n /// @notice Gets the owner of the keep.\n /// @return Address of the keep owner.\n function getOwner() external view returns (address) {\n return owner;\n }\n\n /// @notice Gets the timestamp the keep was opened at.\n /// @return Timestamp the keep was opened at.\n function getOpenedTimestamp() external view returns (uint256) {\n return keyGenerationStartTimestamp;\n }\n\n /// @notice Closes keep when owner decides that they no longer need it.\n /// Releases bonds to the keep members.\n /// @dev The function can be called only by the owner of the keep and only\n /// if the keep has not been already closed.\n function closeKeep() public onlyOwner onlyWhenActive {\n markAsClosed();\n }\n\n /// @notice Returns true if the keep is active.\n /// @return true if the keep is active, false otherwise.\n function isActive() public view returns (bool) {\n return status == Status.Active;\n }\n\n /// @notice Returns true if the keep is closed and members no longer support\n /// this keep.\n /// @return true if the keep is closed, false otherwise.\n function isClosed() public view returns (bool) {\n return status == Status.Closed;\n }\n\n /// @notice Returns true if the keep has been terminated.\n /// Keep is terminated when bonds are seized and members no longer support\n /// this keep.\n /// @return true if the keep has been terminated, false otherwise.\n function isTerminated() public view returns (bool) {\n return status == Status.Terminated;\n }\n\n /// @notice Returns members of the keep.\n /// @return List of the keep members' addresses.\n function getMembers() public view returns (address[] memory) {\n return members;\n }\n\n /// @notice Initialization function.\n /// @dev We use clone factory to create new keep. That is why this contract\n /// doesn't have a constructor. We provide keep parameters for each instance\n /// function after cloning instances from the master contract.\n /// Initialization must happen in the same transaction in which the clone is\n /// created.\n /// @param _owner Address of the keep owner.\n /// @param _members Addresses of the keep members.\n /// @param _honestThreshold Minimum number of honest keep members.\n function initialize(\n address _owner,\n address[] memory _members,\n uint256 _honestThreshold\n ) public {\n require(!isInitialized, \"Contract already initialized\");\n require(_owner != address(0));\n owner = _owner;\n members = _members;\n honestThreshold = _honestThreshold;\n\n status = Status.Active;\n isInitialized = true;\n\n /* solium-disable-next-line security/no-block-members*/\n keyGenerationStartTimestamp = block.timestamp;\n }\n\n /// @notice Checks if the member already submitted a public key.\n /// @param _member Address of the member.\n /// @return True if member already submitted a public key, else false.\n function hasMemberSubmittedPublicKey(address _member)\n internal\n view\n returns (bool)\n {\n return submittedPublicKeys[_member].length != 0;\n }\n\n /// @notice Marks the keep as closed.\n /// Keep can be marked as closed only when there is no signing in progress\n /// or the requested signing process has timed out.\n function markAsClosed() internal {\n status = Status.Closed;\n emit KeepClosed();\n }\n\n /// @notice Marks the keep as terminated.\n /// Keep can be marked as terminated only when there is no signing in progress\n /// or the requested signing process has timed out.\n function markAsTerminated() internal {\n status = Status.Terminated;\n emit KeepTerminated();\n }\n\n /// @notice Coverts a public key to an ethereum address.\n /// @param _publicKey Public key provided as 64-bytes concatenation of\n /// X and Y coordinates (32-bytes each).\n /// @return Ethereum address.\n function publicKeyToAddress(bytes memory _publicKey)\n internal\n pure\n returns (address)\n {\n // We hash the public key and then truncate last 20 bytes of the digest\n // which is the ethereum address.\n return address(uint160(uint256(keccak256(_publicKey))));\n }\n\n /// @notice Terminates the keep.\n function terminateKeep() internal {\n markAsTerminated();\n }\n\n /// @notice Checks if the caller is the keep's owner.\n /// @dev Throws an error if called by any account other than owner.\n modifier onlyOwner() {\n require(owner == msg.sender, \"Caller is not the keep owner\");\n _;\n }\n\n /// @notice Checks if the caller is a keep member.\n /// @dev Throws an error if called by any account other than one of the members.\n modifier onlyMember() {\n require(members.contains(msg.sender), \"Caller is not the keep member\");\n _;\n }\n\n /// @notice Checks if the keep is currently active.\n /// @dev Throws an error if called when the keep has been already closed.\n modifier onlyWhenActive() {\n require(isActive(), \"Keep is not active\");\n _;\n }\n}\n" + }, + "contracts/bridge/utils/AddressArrayUtils.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.6.12;\n\nlibrary AddressArrayUtils {\n function contains(address[] memory self, address _address)\n internal\n pure\n returns (bool)\n {\n for (uint256 i = 0; i < self.length; i++) {\n if (_address == self[i]) {\n return true;\n }\n }\n return false;\n }\n}" + }, + "contracts/bridge/testing/NodeEnv.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.6.12;\npragma experimental ABIEncoderV2;\n\nimport '@openzeppelin/contracts/access/AccessControl.sol';\nimport \"../utils/EnumerableStringMap.sol\";\n\n/**\n * @title NodeEnv contract\n * @author Synapse Authors\n * @notice This contract implements a key-value store for storing variables on which synapse nodes must coordinate\n * methods are purposely arbitrary to allow these fields to be defined in synapse improvement proposals.\n * @notice This token is used for configuring different tokens on the bridge and mapping them across chains.\n**/\ncontract NodeEnv is AccessControl {\n using EnumerableStringMap for EnumerableStringMap.StringToStringMap;\n // BRIDGEMANAGER_ROLE owns the bridge. They are the only user that can call setters on this contract\n bytes32 public constant BRIDGEMANAGER_ROLE = keccak256('BRIDGEMANAGER_ROLE');\n // _config stores the config\n EnumerableStringMap.StringToStringMap private _config; // key is tokenAddress,chainID\n\n // ConfigUpdate is emitted when the config is updated by the user\n event ConfigUpdate(\n string key\n );\n\n constructor() public {\n _setupRole(DEFAULT_ADMIN_ROLE, msg.sender);\n _setupRole(BRIDGEMANAGER_ROLE, msg.sender);\n }\n\n /**\n * @notice get the length of the config\n *\n * @dev this is useful for enumerating through all keys in the env\n */\n function keyCount()\n external\n view\n returns (uint256){\n return _config.length();\n }\n\n /**\n * @notice gets the key/value pair by it's index\n *\n * Requirements:\n *\n * - `index` must be strictly less than {length}.\n */\n function keyValueByIndex(uint256 index) external view returns(string memory, string memory){\n return _config.at(index);\n }\n\n /**\n * @notice gets the value associated with the key\n */\n function get(string calldata _key) external view returns(string memory){\n string memory key = _key;\n return _config.get(key);\n }\n\n /**\n * @notice sets the key\n *\n * @dev caller must have bridge manager role\n */\n function set(string calldata _key, string calldata _value) external returns(bool) {\n require(\n hasRole(BRIDGEMANAGER_ROLE, msg.sender),\n 'Caller is not Bridge Manager'\n );\n string memory key = _key;\n string memory value = _value;\n\n return _config.set(key, value);\n }\n}" + }, + "contracts/bridge/utils/EnumerableStringMap.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.6.12;\n\nimport \"@openzeppelin/contracts/utils/EnumerableSet.sol\";\n\n/**\n * @title EnumerableStringMap\n * @dev Library for managing an enumerable variant of Solidity's\n * https://solidity.readthedocs.io/en/latest/types.html#mapping-types[`mapping`]\n * type.\n *\n * Maps have the following properties:\n *\n * - Entries are added, removed, and checked for existence in constant time\n * (O(1)).\n * - Entries are enumerated in O(n). No guarantees are made on the ordering.\n *\n * this isn't a terribly gas efficient implementation because it emphasizes usability over gas efficiency\n * by allowing arbitrary length string memorys. If Gettetrs/Setters are going to be used frequently in contracts\n * consider using the OpenZeppeling Bytes32 implementation\n *\n * this also differs from the OpenZeppelin implementation by keccac256 hashing the string memorys\n * so we can use enumerable bytes32 set\n */\nlibrary EnumerableStringMap {\n using EnumerableSet for EnumerableSet.Bytes32Set;\n\n // To implement this library for multiple types with as little code\n // repetition as possible, we write it in terms of a generic Map type with\n // bytes32 keys and values.\n // The Map implementation uses private functions, and user-facing\n // implementations (such as Uint256ToAddressMap) are just wrappers around\n // the underlying Map.\n // This means that we can only create new EnumerableMaps for types that fit\n // in bytes32.\n\n struct Map {\n // Storage of keys as a set\n EnumerableSet.Bytes32Set _keys;\n // Mapping of keys to resulting values to allow key lookup in the set\n mapping(bytes32 => string) _hashKeyMap;\n // values\n mapping(bytes32 => string) _values;\n }\n\n /**\n * @dev Adds a key-value pair to a map, or updates the value for an existing\n * key. O(1).\n *\n * Returns true if the key was added to the map, that is if it was not\n * already present.\n */\n function _set(\n Map storage map,\n string memory key,\n string memory value\n ) private returns (bool) {\n bytes32 keyHash = keccak256(abi.encodePacked(key));\n map._values[keyHash] = value;\n map._hashKeyMap[keyHash] = key;\n return map._keys.add(keyHash);\n }\n\n /**\n * @dev Removes a key-value pair from a map. O(1).\n *\n * Returns true if the key was removed from the map, that is if it was present.\n */\n function _remove(Map storage map, bytes32 keyHash) private returns (bool) {\n delete map._values[keyHash];\n delete map._hashKeyMap[keyHash];\n return map._keys.remove(keyHash);\n }\n\n /**\n * @dev Returns true if the key is in the map. O(1).\n */\n function _contains(Map storage map, bytes32 keyHash) private view returns (bool) {\n return map._keys.contains(keyHash);\n }\n\n /**\n * @dev Returns the number of key-value pairs in the map. O(1).\n */\n function _length(Map storage map) private view returns (uint256) {\n return map._keys.length();\n }\n\n /**\n * @dev Returns the key-value pair stored at position `index` in the map. O(1).\n *\n * Note that there are no guarantees on the ordering of entries inside the\n * array, and it may change when more entries are added or removed.\n *\n * Requirements:\n *\n * - `index` must be strictly less than {length}.\n */\n function _at(Map storage map, uint256 index) private view returns (string memory, string memory) {\n bytes32 keyHash = map._keys.at(index);\n return (map._hashKeyMap[keyHash], map._values[keyHash]);\n }\n\n /**\n * @dev Tries to returns the value associated with `key`. O(1).\n * Does not revert if `key` is not in the map.\n */\n function _tryGet(Map storage map, bytes32 keyHash) private view returns (bool, string memory) {\n string memory value = map._values[keyHash];\n if (keccak256(bytes(value)) == keccak256(bytes(\"\"))) {\n return (_contains(map, keyHash), \"\");\n } else {\n return (true, value);\n }\n }\n\n /**\n * @dev Returns the value associated with `key`. O(1).\n *\n * Requirements:\n *\n * - `key` must be in the map.\n */\n function _get(Map storage map, bytes32 keyHash) private view returns (string memory) {\n string memory value = map._values[keyHash];\n require(_contains(map, keyHash), \"EnumerableMap: nonexistent key\");\n return value;\n }\n\n // StringToStringMap\n struct StringToStringMap {\n Map _inner;\n }\n\n /**\n * @dev Adds a key-value pair to a map, or updates the value for an existing\n * key. O(1).\n *\n * Returns true if the key was added to the map, that is if it was not\n * already present.\n */\n function set(\n StringToStringMap storage map,\n string memory key,\n string memory value\n ) internal returns (bool) {\n return _set(map._inner, key, value);\n }\n\n /**\n * @dev Removes a value from a set. O(1).\n *\n * Returns true if the key was removed from the map, that is if it was present.\n */\n function remove(StringToStringMap storage map, string memory key) internal returns (bool) {\n return _remove(map._inner, keccak256(abi.encodePacked(key)));\n }\n\n /**\n * @dev Returns true if the key is in the map. O(1).\n */\n function contains(StringToStringMap storage map, string memory key) internal view returns (bool) {\n return _contains(map._inner, keccak256(abi.encodePacked(key)));\n }\n\n /**\n * @dev Returns the number of elements in the map. O(1).\n */\n function length(StringToStringMap storage map) internal view returns (uint256) {\n return _length(map._inner);\n }\n\n /**\n * @dev Returns the element stored at position `index` in the set. O(1).\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(StringToStringMap storage map, uint256 index) internal view returns (string memory, string memory) {\n return _at(map._inner, index);\n }\n\n /**\n * @dev Tries to returns the value associated with `key`. O(1).\n * Does not revert if `key` is not in the map.\n *\n * _Available since v3.4._\n */\n function tryGet(StringToStringMap storage map, uint256 key) internal view returns (bool, string memory) {\n (bool success, string memory value) = _tryGet(map._inner, bytes32(key));\n return (success, value);\n }\n\n /**\n * @dev Returns the value associated with `key`. O(1).\n *\n * Requirements:\n *\n * - `key` must be in the map.\n */\n function get(StringToStringMap storage map, string memory key) internal view returns (string memory) {\n return _get(map._inner, keccak256(abi.encodePacked(key)));\n }\n}" + }, + "contracts/bridge/PoolConfig.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.6.12;\npragma experimental ABIEncoderV2;\n\nimport \"@openzeppelin/contracts/access/AccessControl.sol\";\n\ncontract PoolConfig is AccessControl {\n bytes32 public constant BRIDGEMANAGER_ROLE =\n keccak256(\"BRIDGEMANAGER_ROLE\");\n mapping(address => mapping(uint256 => Pool)) private _pool; // key is tokenAddress,chainID\n\n struct Pool {\n address tokenAddress;\n uint256 chainId;\n address poolAddress;\n bool metaswap;\n }\n\n constructor() public {\n _setupRole(DEFAULT_ADMIN_ROLE, msg.sender);\n _setupRole(BRIDGEMANAGER_ROLE, msg.sender);\n }\n\n function getPoolConfig(address tokenAddress, uint256 chainID)\n external\n view\n returns (Pool memory)\n {\n return _pool[tokenAddress][chainID];\n }\n\n function setPoolConfig(\n address tokenAddress,\n uint256 chainID,\n address poolAddress,\n bool metaswap\n ) external returns (Pool memory) {\n require(\n hasRole(BRIDGEMANAGER_ROLE, msg.sender),\n \"Caller is not Bridge Manager\"\n );\n Pool memory newPool = Pool(\n tokenAddress,\n chainID,\n poolAddress,\n metaswap\n );\n _pool[tokenAddress][chainID] = newPool;\n return newPool;\n }\n}\n" + }, + "contracts/bridge/BridgeConfigV3.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.6.12;\npragma experimental ABIEncoderV2;\n\nimport \"@openzeppelin/contracts/access/AccessControl.sol\";\nimport \"@openzeppelin/contracts/math/SafeMath.sol\";\n\n/**\n * @title BridgeConfig contract\n * @notice This token is used for configuring different tokens on the bridge and mapping them across chains.\n **/\n\ncontract BridgeConfigV3 is AccessControl {\n using SafeMath for uint256;\n bytes32 public constant BRIDGEMANAGER_ROLE =\n keccak256(\"BRIDGEMANAGER_ROLE\");\n bytes32[] private _allTokenIDs;\n mapping(bytes32 => Token[]) private _allTokens; // key is tokenID\n mapping(uint256 => mapping(string => bytes32)) private _tokenIDMap; // key is chainID,tokenAddress\n mapping(bytes32 => mapping(uint256 => Token)) private _tokens; // key is tokenID,chainID\n mapping(address => mapping(uint256 => Pool)) private _pool; // key is tokenAddress,chainID\n mapping(uint256 => uint256) private _maxGasPrice; // key is tokenID,chainID\n uint256 public constant bridgeConfigVersion = 3;\n\n // the denominator used to calculate fees. For example, an\n // LP fee might be something like tradeAmount.mul(fee).div(FEE_DENOMINATOR)\n uint256 private constant FEE_DENOMINATOR = 10**10;\n\n // this struct must be initialized using setTokenConfig for each token that directly interacts with the bridge\n struct Token {\n uint256 chainId;\n string tokenAddress;\n uint8 tokenDecimals;\n uint256 maxSwap;\n uint256 minSwap;\n uint256 swapFee;\n uint256 maxSwapFee;\n uint256 minSwapFee;\n bool hasUnderlying;\n bool isUnderlying;\n }\n\n struct Pool {\n address tokenAddress;\n uint256 chainId;\n address poolAddress;\n bool metaswap;\n }\n\n constructor() public {\n _setupRole(DEFAULT_ADMIN_ROLE, msg.sender);\n }\n\n /**\n * @notice Returns a list of all existing token IDs converted to strings\n */\n function getAllTokenIDs() public view returns (string[] memory result) {\n uint256 length = _allTokenIDs.length;\n result = new string[](length);\n for (uint256 i = 0; i < length; ++i) {\n result[i] = toString(_allTokenIDs[i]);\n }\n }\n\n function _getTokenID(string memory tokenAddress, uint256 chainID)\n internal\n view\n returns (string memory)\n {\n return toString(_tokenIDMap[chainID][tokenAddress]);\n }\n\n function getTokenID(string memory tokenAddress, uint256 chainID)\n public\n view\n returns (string memory)\n {\n return _getTokenID(_toLower(tokenAddress), chainID);\n }\n\n /**\n * @notice Returns the token ID (string) of the cross-chain token inputted\n * @param tokenAddress address of token to get ID for\n * @param chainID chainID of which to get token ID for\n */\n function getTokenID(address tokenAddress, uint256 chainID)\n public\n view\n returns (string memory)\n {\n return _getTokenID(_toLower(toString(tokenAddress)), chainID);\n }\n\n /**\n * @notice Returns the full token config struct\n * @param tokenID String input of the token ID for the token\n * @param chainID Chain ID of which token address + config to get\n */\n function getToken(string memory tokenID, uint256 chainID)\n public\n view\n returns (Token memory token)\n {\n return _tokens[toBytes32(tokenID)][chainID];\n }\n\n /**\n * @notice Returns the full token config struct\n * @param tokenID String input of the token ID for the token\n * @param chainID Chain ID of which token address + config to get\n */\n function getTokenByID(string memory tokenID, uint256 chainID)\n public\n view\n returns (Token memory token)\n {\n return _tokens[toBytes32(tokenID)][chainID];\n }\n\n /**\n * @notice Returns token config struct, given an address and chainID\n * @param tokenAddress Matches the token ID by using a combo of address + chain ID\n * @param chainID Chain ID of which token to get config for\n */\n function getTokenByAddress(string memory tokenAddress, uint256 chainID)\n public\n view\n returns (Token memory token)\n {\n return _tokens[_tokenIDMap[chainID][_toLower(tokenAddress)]][chainID];\n }\n\n function getTokenByEVMAddress(address tokenAddress, uint256 chainID)\n public\n view\n returns (Token memory token)\n {\n return\n _tokens[_tokenIDMap[chainID][_toLower(toString(tokenAddress))]][\n chainID\n ];\n }\n\n /**\n * @notice Returns true if the token has an underlying token -- meaning the token is deposited into the bridge\n * @param tokenID String to check if it is a withdraw/underlying token\n */\n function hasUnderlyingToken(string memory tokenID)\n public\n view\n returns (bool)\n {\n bytes32 bytesTokenID = toBytes32(tokenID);\n Token[] memory _mcTokens = _allTokens[bytesTokenID];\n for (uint256 i = 0; i < _mcTokens.length; ++i) {\n if (_mcTokens[i].hasUnderlying) {\n return true;\n }\n }\n return false;\n }\n\n /**\n * @notice Returns which token is the underlying token to withdraw\n * @param tokenID string token ID\n */\n function getUnderlyingToken(string memory tokenID)\n public\n view\n returns (Token memory token)\n {\n bytes32 bytesTokenID = toBytes32(tokenID);\n Token[] memory _mcTokens = _allTokens[bytesTokenID];\n for (uint256 i = 0; i < _mcTokens.length; ++i) {\n if (_mcTokens[i].isUnderlying) {\n return _mcTokens[i];\n }\n }\n }\n\n /**\n @notice Public function returning if token ID exists given a string\n */\n function isTokenIDExist(string memory tokenID) public view returns (bool) {\n return _isTokenIDExist(toBytes32(tokenID));\n }\n\n /**\n @notice Internal function returning if token ID exists given bytes32 version of the ID\n */\n function _isTokenIDExist(bytes32 tokenID) internal view returns (bool) {\n for (uint256 i = 0; i < _allTokenIDs.length; ++i) {\n if (_allTokenIDs[i] == tokenID) {\n return true;\n }\n }\n return false;\n }\n\n /**\n * @notice Internal function which handles logic of setting token ID and dealing with mappings\n * @param tokenID bytes32 version of ID\n * @param chainID which chain to set the token config for\n * @param tokenToAdd Token object to set the mapping to\n */\n function _setTokenConfig(\n bytes32 tokenID,\n uint256 chainID,\n Token memory tokenToAdd\n ) internal returns (bool) {\n _tokens[tokenID][chainID] = tokenToAdd;\n if (!_isTokenIDExist(tokenID)) {\n _allTokenIDs.push(tokenID);\n }\n\n Token[] storage _mcTokens = _allTokens[tokenID];\n for (uint256 i = 0; i < _mcTokens.length; ++i) {\n if (_mcTokens[i].chainId == chainID) {\n string memory oldToken = _mcTokens[i].tokenAddress;\n if (!compareStrings(tokenToAdd.tokenAddress, oldToken)) {\n _mcTokens[i].tokenAddress = tokenToAdd.tokenAddress;\n _tokenIDMap[chainID][oldToken] = keccak256(\"\");\n _tokenIDMap[chainID][tokenToAdd.tokenAddress] = tokenID;\n }\n }\n }\n _mcTokens.push(tokenToAdd);\n _tokenIDMap[chainID][tokenToAdd.tokenAddress] = tokenID;\n return true;\n }\n\n /**\n * @notice Main write function of this contract - Handles creating the struct and passing it to the internal logic function\n * @param tokenID string ID to set the token config object form\n * @param chainID chain ID to use for the token config object\n * @param tokenAddress token address of the token on the given chain\n * @param tokenDecimals decimals of token\n * @param maxSwap maximum amount of token allowed to be transferred at once - in native token decimals\n * @param minSwap minimum amount of token needed to be transferred at once - in native token decimals\n * @param swapFee percent based swap fee -- 10e6 == 10bps\n * @param maxSwapFee max swap fee to be charged - in native token decimals\n * @param minSwapFee min swap fee to be charged - in native token decimals - especially useful for mainnet ETH\n * @param hasUnderlying bool which represents whether this is a global mint token or one to withdraw()\n * @param isUnderlying bool which represents if this token is the one to withdraw on the given chain\n */\n function setTokenConfig(\n string calldata tokenID,\n uint256 chainID,\n address tokenAddress,\n uint8 tokenDecimals,\n uint256 maxSwap,\n uint256 minSwap,\n uint256 swapFee,\n uint256 maxSwapFee,\n uint256 minSwapFee,\n bool hasUnderlying,\n bool isUnderlying\n ) public returns (bool) {\n require(hasRole(BRIDGEMANAGER_ROLE, msg.sender));\n return\n setTokenConfig(\n tokenID,\n chainID,\n toString(tokenAddress),\n tokenDecimals,\n maxSwap,\n minSwap,\n swapFee,\n maxSwapFee,\n minSwapFee,\n hasUnderlying,\n isUnderlying\n );\n }\n\n /**\n * @notice Main write function of this contract - Handles creating the struct and passing it to the internal logic function\n * @param tokenID string ID to set the token config object form\n * @param chainID chain ID to use for the token config object\n * @param tokenAddress token address of the token on the given chain\n * @param tokenDecimals decimals of token\n * @param maxSwap maximum amount of token allowed to be transferred at once - in native token decimals\n * @param minSwap minimum amount of token needed to be transferred at once - in native token decimals\n * @param swapFee percent based swap fee -- 10e6 == 10bps\n * @param maxSwapFee max swap fee to be charged - in native token decimals\n * @param minSwapFee min swap fee to be charged - in native token decimals - especially useful for mainnet ETH\n * @param hasUnderlying bool which represents whether this is a global mint token or one to withdraw()\n * @param isUnderlying bool which represents if this token is the one to withdraw on the given chain\n */\n function setTokenConfig(\n string calldata tokenID,\n uint256 chainID,\n string memory tokenAddress,\n uint8 tokenDecimals,\n uint256 maxSwap,\n uint256 minSwap,\n uint256 swapFee,\n uint256 maxSwapFee,\n uint256 minSwapFee,\n bool hasUnderlying,\n bool isUnderlying\n ) public returns (bool) {\n require(hasRole(BRIDGEMANAGER_ROLE, msg.sender));\n Token memory tokenToAdd;\n tokenToAdd.tokenAddress = _toLower(tokenAddress);\n tokenToAdd.tokenDecimals = tokenDecimals;\n tokenToAdd.maxSwap = maxSwap;\n tokenToAdd.minSwap = minSwap;\n tokenToAdd.swapFee = swapFee;\n tokenToAdd.maxSwapFee = maxSwapFee;\n tokenToAdd.minSwapFee = minSwapFee;\n tokenToAdd.hasUnderlying = hasUnderlying;\n tokenToAdd.isUnderlying = isUnderlying;\n tokenToAdd.chainId = chainID;\n\n return _setTokenConfig(toBytes32(tokenID), chainID, tokenToAdd);\n }\n\n function _calculateSwapFee(\n string memory tokenAddress,\n uint256 chainID,\n uint256 amount\n ) internal view returns (uint256) {\n Token memory token = _tokens[_tokenIDMap[chainID][tokenAddress]][\n chainID\n ];\n uint256 calculatedSwapFee = amount.mul(token.swapFee).div(\n FEE_DENOMINATOR\n );\n if (\n calculatedSwapFee > token.minSwapFee &&\n calculatedSwapFee < token.maxSwapFee\n ) {\n return calculatedSwapFee;\n } else if (calculatedSwapFee > token.maxSwapFee) {\n return token.maxSwapFee;\n } else {\n return token.minSwapFee;\n }\n }\n\n /**\n * @notice Calculates bridge swap fee based on the destination chain's token transfer.\n * @dev This means the fee should be calculated based on the chain that the nodes emit a tx on\n * @param tokenAddress address of the destination token to query token config for\n * @param chainID destination chain ID to query the token config for\n * @param amount in native token decimals\n * @return Fee calculated in token decimals\n */\n function calculateSwapFee(\n string memory tokenAddress,\n uint256 chainID,\n uint256 amount\n ) external view returns (uint256) {\n return _calculateSwapFee(_toLower(tokenAddress), chainID, amount);\n }\n\n /**\n * @notice Calculates bridge swap fee based on the destination chain's token transfer.\n * @dev This means the fee should be calculated based on the chain that the nodes emit a tx on\n * @param tokenAddress address of the destination token to query token config for\n * @param chainID destination chain ID to query the token config for\n * @param amount in native token decimals\n * @return Fee calculated in token decimals\n */\n function calculateSwapFee(\n address tokenAddress,\n uint256 chainID,\n uint256 amount\n ) external view returns (uint256) {\n return\n _calculateSwapFee(\n _toLower(toString(tokenAddress)),\n chainID,\n amount\n );\n }\n\n // GAS PRICING\n\n /**\n * @notice sets the max gas price for a chain\n */\n function setMaxGasPrice(uint256 chainID, uint256 maxPrice) public {\n require(hasRole(BRIDGEMANAGER_ROLE, msg.sender));\n _maxGasPrice[chainID] = maxPrice;\n }\n\n /**\n * @notice gets the max gas price for a chain\n */\n function getMaxGasPrice(uint256 chainID) public view returns (uint256) {\n return _maxGasPrice[chainID];\n }\n\n // POOL CONFIG\n\n function getPoolConfig(address tokenAddress, uint256 chainID)\n external\n view\n returns (Pool memory)\n {\n return _pool[tokenAddress][chainID];\n }\n\n function setPoolConfig(\n address tokenAddress,\n uint256 chainID,\n address poolAddress,\n bool metaswap\n ) external returns (Pool memory) {\n require(\n hasRole(BRIDGEMANAGER_ROLE, msg.sender),\n \"Caller is not Bridge Manager\"\n );\n Pool memory newPool = Pool(\n tokenAddress,\n chainID,\n poolAddress,\n metaswap\n );\n _pool[tokenAddress][chainID] = newPool;\n return newPool;\n }\n\n // UTILITY FUNCTIONS\n\n function toString(bytes32 data) internal pure returns (string memory) {\n uint8 i = 0;\n while (i < 32 && data[i] != 0) {\n ++i;\n }\n bytes memory bs = new bytes(i);\n for (uint8 j = 0; j < i; ++j) {\n bs[j] = data[j];\n }\n return string(bs);\n }\n\n // toBytes32 converts a string to a bytes 32\n function toBytes32(string memory str)\n internal\n pure\n returns (bytes32 result)\n {\n require(bytes(str).length <= 32);\n assembly {\n result := mload(add(str, 32))\n }\n }\n\n function toString(address x) internal pure returns (string memory) {\n bytes memory s = new bytes(40);\n for (uint256 i = 0; i < 20; i++) {\n bytes1 b = bytes1(uint8(uint256(uint160(x)) / (2**(8 * (19 - i)))));\n bytes1 hi = bytes1(uint8(b) / 16);\n bytes1 lo = bytes1(uint8(b) - 16 * uint8(hi));\n s[2 * i] = char(hi);\n s[2 * i + 1] = char(lo);\n }\n\n string memory addrPrefix = \"0x\";\n\n return concat(addrPrefix, string(s));\n }\n\n function concat(string memory _x, string memory _y)\n internal\n pure\n returns (string memory)\n {\n bytes memory _xBytes = bytes(_x);\n bytes memory _yBytes = bytes(_y);\n\n string memory _tmpValue = new string(_xBytes.length + _yBytes.length);\n bytes memory _newValue = bytes(_tmpValue);\n\n uint256 i;\n uint256 j;\n\n for (i = 0; i < _xBytes.length; i++) {\n _newValue[j++] = _xBytes[i];\n }\n\n for (i = 0; i < _yBytes.length; i++) {\n _newValue[j++] = _yBytes[i];\n }\n\n return string(_newValue);\n }\n\n function char(bytes1 b) internal pure returns (bytes1 c) {\n if (uint8(b) < 10) {\n c = bytes1(uint8(b) + 0x30);\n } else {\n c = bytes1(uint8(b) + 0x57);\n }\n }\n\n function compareStrings(string memory a, string memory b)\n internal\n pure\n returns (bool)\n {\n return (keccak256(abi.encodePacked((a))) ==\n keccak256(abi.encodePacked((b))));\n }\n\n function _toLower(string memory str) internal pure returns (string memory) {\n bytes memory bStr = bytes(str);\n bytes memory bLower = new bytes(bStr.length);\n for (uint256 i = 0; i < bStr.length; i++) {\n // Uppercase character...\n if ((uint8(bStr[i]) >= 65) && (uint8(bStr[i]) <= 90)) {\n // So we add 32 to make it lowercase\n bLower[i] = bytes1(uint8(bStr[i]) + 32);\n } else {\n bLower[i] = bStr[i];\n }\n }\n return string(bLower);\n }\n}\n" + }, + "contracts/bridge/wrappers/GMXWrapper.sol": { + "content": "// SPDX-License-Identifier: MIT\n\nimport '@openzeppelin/contracts/math/SafeMath.sol';\n\npragma solidity 0.6.12;\n\ninterface IGMX {\n function burn(address _account, uint256 _amount) external;\n function balanceOf(address account) external view returns (uint256);\n function mint(address _account, uint256 _amount) external;\n}\n\ncontract GMXWrapper {\n using SafeMath for uint256;\n\n address constant public gmx = 0x62edc0692BD897D2295872a9FFCac5425011c661;\n address constant public bridge = 0xC05e61d0E7a63D27546389B7aD62FdFf5A91aACE;\n\n function transfer(address _recipient, uint256 _amount) external returns (bool) {\n require(msg.sender == bridge);\n _transfer(msg.sender, _recipient, _amount);\n return true;\n }\n\n function _transfer(address _sender, address _recipient, uint256 _amount) private {\n require(_sender != address(0), \"BaseToken: transfer from the zero address\");\n require(_recipient != address(0), \"BaseToken: transfer to the zero address\");\n IGMX(gmx).burn(_sender, _amount);\n IGMX(gmx).mint(_recipient, _amount);\n }\n\n function mint(address _addr, uint256 _amount) external {\n require(msg.sender == bridge);\n uint256 preMint = IGMX(gmx).balanceOf(_addr);\n IGMX(gmx).mint(_addr, _amount);\n uint256 postMint = IGMX(gmx).balanceOf(_addr);\n require(preMint.add(_amount) == postMint, \"Mint incomplete\");\n }\n\n function burnFrom(address _addr, uint256 _amount) external {\n require(msg.sender == bridge);\n uint256 preBurn = IGMX(gmx).balanceOf(_addr);\n IGMX(gmx).burn(_addr, _amount);\n uint256 postBurn = IGMX(gmx).balanceOf(_addr);\n require(postBurn.add(_amount) == preBurn, \"Burn incomplete\");\n }\n}" + }, + "contracts/amm/SwapEthWrapper.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.6.12;\n\nimport \"@openzeppelin/contracts/math/SafeMath.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/SafeERC20.sol\";\nimport \"./Swap.sol\";\nimport \"./interfaces/IWETH9.sol\";\n\n/**\n * @title SwapEthWrapper\n * @notice A wrapper contract for Swap contracts that have WETH as one of the pooled tokens.\n * @author Jongseung Lim (@weeb_mcgee)\n */\ncontract SwapEthWrapper {\n using SafeERC20 for IERC20;\n using SafeMath for uint256;\n\n // constants\n uint8 private constant MAX_UINT8 = 2**8 - 1;\n uint256 private constant MAX_UINT256 = 2**256 - 1;\n\n // immutables\n Swap public immutable SWAP;\n LPToken public immutable LP_TOKEN;\n address payable public immutable WETH_ADDRESS;\n address public immutable OWNER;\n uint8 public immutable WETH_INDEX;\n\n IERC20[] public pooledTokens;\n\n /**\n * @notice Deploys this contract with given WETH9 address and Swap address. It will attempt to\n * fetch information about the given Swap pool. If the Swap pool does not contain WETH9,\n * this call will be reverted. Owner address must be given so that `rescue()` function\n * can be limited.\n * @param wethAddress address to the WETH9 contract\n * @param swap address to the Swap contract that has WETH9 as one of the tokens\n * @param owner address that will be allowed to call `rescue()`\n */\n constructor(\n address payable wethAddress,\n Swap swap,\n address owner\n ) public {\n (, , , , , , LPToken lpToken) = swap.swapStorage();\n uint8 wethIndex = MAX_UINT8;\n\n for (uint8 i = 0; i < MAX_UINT8; i++) {\n try swap.getToken(i) returns (IERC20 token) {\n pooledTokens.push(token);\n if (address(token) == wethAddress) {\n wethIndex = i;\n }\n // Approve pooled tokens to be used by Swap\n token.approve(address(swap), MAX_UINT256);\n } catch {\n break;\n }\n }\n require(wethIndex != MAX_UINT8, \"WETH was not found in the swap pool\");\n\n // Set immutable variables\n WETH_INDEX = wethIndex;\n WETH_ADDRESS = wethAddress;\n SWAP = swap;\n LP_TOKEN = lpToken;\n OWNER = owner;\n\n // Approve LPToken to be used by Swap\n lpToken.approve(address(swap), MAX_UINT256);\n }\n\n /**\n * @notice Add liquidity to the pool with the given amounts of tokens.\n * @dev The msg.value of this call should match the value in amounts array\n * in position of WETH9.\n * @param amounts the amounts of each token to add, in their native precision\n * @param minToMint the minimum LP tokens adding this amount of liquidity\n * should mint, otherwise revert. Handy for front-running mitigation\n * @param deadline latest timestamp to accept this transaction\n * @return amount of LP token user minted and received\n */\n function addLiquidity(\n uint256[] memory amounts,\n uint256 minToMint,\n uint256 deadline\n ) external payable returns (uint256) {\n // If using ETH, deposit them to WETH.\n require(msg.value == amounts[WETH_INDEX], \"INCORRECT_MSG_VALUE\");\n if (msg.value > 0) {\n IWETH9(WETH_ADDRESS).deposit{value: msg.value}();\n }\n // Go through amounts array and transfer respective tokens to this contract.\n for (uint256 i = 0; i < amounts.length; i++) {\n uint256 amount = amounts[i];\n if (i != WETH_INDEX && amount > 0) {\n pooledTokens[i].safeTransferFrom(\n msg.sender,\n address(this),\n amount\n );\n }\n }\n // Add the assets to the pool\n uint256 lpTokenAmount = SWAP.addLiquidity(amounts, minToMint, deadline);\n // Send the LPToken to msg.sender\n IERC20(address(LP_TOKEN)).safeTransfer(msg.sender, lpTokenAmount);\n return lpTokenAmount;\n }\n\n /**\n * @notice Burn LP tokens to remove liquidity from the pool.\n * @dev Liquidity can always be removed, even when the pool is paused. Caller\n * will receive ETH instead of WETH9.\n * @param amount the amount of LP tokens to burn\n * @param minAmounts the minimum amounts of each token in the pool\n * acceptable for this burn. Useful as a front-running mitigation\n * @param deadline latest timestamp to accept this transaction\n * @return amounts of tokens user received\n */\n function removeLiquidity(\n uint256 amount,\n uint256[] calldata minAmounts,\n uint256 deadline\n ) external returns (uint256[] memory) {\n // Transfer LPToken from msg.sender to this contract.\n IERC20(address(LP_TOKEN)).safeTransferFrom(\n msg.sender,\n address(this),\n amount\n );\n // Remove liquidity\n uint256[] memory amounts = SWAP.removeLiquidity(\n amount,\n minAmounts,\n deadline\n );\n // Send the tokens back to the user\n for (uint256 i = 0; i < amounts.length; i++) {\n if (i != WETH_INDEX) {\n pooledTokens[i].safeTransfer(msg.sender, amounts[i]);\n } else {\n IWETH9(WETH_ADDRESS).withdraw(amounts[i]);\n // slither-disable-next-line arbitrary-send\n (bool success, ) = msg.sender.call{value: amounts[i]}(\"\");\n require(success, \"ETH_TRANSFER_FAILED\");\n }\n }\n return amounts;\n }\n\n /**\n * @notice Remove liquidity from the pool all in one token.\n * @dev Caller will receive ETH instead of WETH9.\n * @param tokenAmount the amount of the token you want to receive\n * @param tokenIndex the index of the token you want to receive\n * @param minAmount the minimum amount to withdraw, otherwise revert\n * @param deadline latest timestamp to accept this transaction\n * @return amount of chosen token user received\n */\n function removeLiquidityOneToken(\n uint256 tokenAmount,\n uint8 tokenIndex,\n uint256 minAmount,\n uint256 deadline\n ) external returns (uint256) {\n // Transfer LPToken from msg.sender to this contract.\n IERC20(address(LP_TOKEN)).safeTransferFrom(\n msg.sender,\n address(this),\n tokenAmount\n );\n // Withdraw via single token\n uint256 amount = SWAP.removeLiquidityOneToken(\n tokenAmount,\n tokenIndex,\n minAmount,\n deadline\n );\n // Transfer the token to msg.sender accordingly\n if (tokenIndex != WETH_INDEX) {\n pooledTokens[tokenIndex].safeTransfer(msg.sender, amount);\n } else {\n IWETH9(WETH_ADDRESS).withdraw(amount);\n // slither-disable-next-line arbitrary-send\n (bool success, ) = msg.sender.call{value: amount}(\"\");\n require(success, \"ETH_TRANSFER_FAILED\");\n }\n return amount;\n }\n\n /**\n * @notice Remove liquidity from the pool, weighted differently than the\n * pool's current balances.\n * @dev Caller will receive ETH instead of WETH9.\n * @param amounts how much of each token to withdraw\n * @param maxBurnAmount the max LP token provider is willing to pay to\n * remove liquidity. Useful as a front-running mitigation.\n * @param deadline latest timestamp to accept this transaction\n * @return amount of LP tokens burned\n */\n function removeLiquidityImbalance(\n uint256[] calldata amounts,\n uint256 maxBurnAmount,\n uint256 deadline\n ) external returns (uint256) {\n // Transfer LPToken from msg.sender to this contract.\n IERC20(address(LP_TOKEN)).safeTransferFrom(\n msg.sender,\n address(this),\n maxBurnAmount\n );\n // Withdraw in imbalanced ratio\n uint256 burnedLpTokenAmount = SWAP.removeLiquidityImbalance(\n amounts,\n maxBurnAmount,\n deadline\n );\n // Send the tokens back to the user\n for (uint256 i = 0; i < amounts.length; i++) {\n if (i != WETH_INDEX) {\n pooledTokens[i].safeTransfer(msg.sender, amounts[i]);\n } else {\n IWETH9(WETH_ADDRESS).withdraw(amounts[i]);\n // slither-disable-next-line arbitrary-send\n (bool success, ) = msg.sender.call{value: amounts[i]}(\"\");\n require(success, \"ETH_TRANSFER_FAILED\");\n }\n }\n // Send any extra LP tokens back as well\n uint256 extraLpTokenAmount = maxBurnAmount.sub(burnedLpTokenAmount);\n if (extraLpTokenAmount > 0) {\n IERC20(address(LP_TOKEN)).safeTransfer(\n msg.sender,\n extraLpTokenAmount\n );\n }\n return burnedLpTokenAmount;\n }\n\n /**\n * @notice Swap two tokens using the underlying pool. If tokenIndexFrom\n * represents WETH9 in the pool, the caller must set msg.value equal to dx.\n * If the user is swapping to WETH9 in the pool, the user will receive ETH instead.\n * @param tokenIndexFrom the token the user wants to swap from\n * @param tokenIndexTo the token the user wants to swap to\n * @param dx the amount of tokens the user wants to swap from\n * @param minDy the min amount the user would like to receive, or revert.\n * @param deadline latest timestamp to accept this transaction\n */\n function swap(\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx,\n uint256 minDy,\n uint256 deadline\n ) external payable returns (uint256) {\n // Transfer tokens from msg.sender to this contract\n if (tokenIndexFrom != WETH_INDEX) {\n IERC20(pooledTokens[tokenIndexFrom]).safeTransferFrom(\n msg.sender,\n address(this),\n dx\n );\n } else {\n require(msg.value == dx, \"INCORRECT_MSG_VALUE\");\n IWETH9(WETH_ADDRESS).deposit{value: msg.value}();\n }\n // Execute swap\n uint256 dy = SWAP.swap(\n tokenIndexFrom,\n tokenIndexTo,\n dx,\n minDy,\n deadline\n );\n // Transfer the swapped tokens to msg.sender\n if (tokenIndexTo != WETH_INDEX) {\n IERC20(pooledTokens[tokenIndexTo]).safeTransfer(msg.sender, dy);\n } else {\n IWETH9(WETH_ADDRESS).withdraw(dy);\n // slither-disable-next-line arbitrary-send\n (bool success, ) = msg.sender.call{value: dy}(\"\");\n require(success, \"ETH_TRANSFER_FAILED\");\n }\n return dy;\n }\n\n /**\n * @notice Rescues any of the ETH, the pooled tokens, or the LPToken that may be stuck\n * in this contract. Only the OWNER can call this function.\n */\n function rescue() external {\n require(msg.sender == OWNER, \"CALLED_BY_NON_OWNER\");\n IERC20[] memory tokens = pooledTokens;\n for (uint256 i = 0; i < tokens.length; i++) {\n tokens[i].safeTransfer(\n msg.sender,\n tokens[i].balanceOf(address(this))\n );\n }\n IERC20 lpToken_ = IERC20(address(LP_TOKEN));\n lpToken_.safeTransfer(msg.sender, lpToken_.balanceOf(address(this)));\n // slither-disable-next-line arbitrary-send\n (bool success, ) = msg.sender.call{value: address(this).balance}(\"\");\n require(success, \"ETH_TRANSFER_FAILED\");\n }\n\n receive() external payable {}\n\n // VIEW FUNCTIONS\n\n /**\n * @notice A simple method to calculate prices from deposits or\n * withdrawals, excluding fees but including slippage. This is\n * helpful as an input into the various \"min\" parameters on calls\n * to fight front-running\n *\n * @dev This shouldn't be used outside frontends for user estimates.\n *\n * @param amounts an array of token amounts to deposit or withdrawal,\n * corresponding to pooledTokens. The amount should be in each\n * pooled token's native precision. If a token charges a fee on transfers,\n * use the amount that gets transferred after the fee.\n * @param deposit whether this is a deposit or a withdrawal\n * @return token amount the user will receive\n */\n function calculateTokenAmount(uint256[] calldata amounts, bool deposit)\n external\n view\n returns (uint256)\n {\n return SWAP.calculateTokenAmount(amounts, deposit);\n }\n\n /**\n * @notice A simple method to calculate amount of each underlying\n * tokens that is returned upon burning given amount of LP tokens\n * @param amount the amount of LP tokens that would be burned on withdrawal\n * @return array of token balances that the user will receive\n */\n function calculateRemoveLiquidity(uint256 amount)\n external\n view\n returns (uint256[] memory)\n {\n return SWAP.calculateRemoveLiquidity(amount);\n }\n\n /**\n * @notice Calculate the amount of underlying token available to withdraw\n * when withdrawing via only single token\n * @param tokenAmount the amount of LP token to burn\n * @param tokenIndex index of which token will be withdrawn\n * @return availableTokenAmount calculated amount of underlying token\n * available to withdraw\n */\n function calculateRemoveLiquidityOneToken(\n uint256 tokenAmount,\n uint8 tokenIndex\n ) external view returns (uint256 availableTokenAmount) {\n return SWAP.calculateRemoveLiquidityOneToken(tokenAmount, tokenIndex);\n }\n}\n" + }, + "contracts/amm/interfaces/IWETH9.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.4.0;\n\ninterface IWETH9 {\n function name() external view returns (string memory);\n\n function symbol() external view returns (string memory);\n\n function decimals() external view returns (uint8);\n\n function balanceOf(address) external view returns (uint256);\n\n function allowance(address, address) external view returns (uint256);\n\n receive() external payable;\n\n function deposit() external payable;\n\n function withdraw(uint256 wad) external;\n\n function totalSupply() external view returns (uint256);\n\n function approve(address guy, uint256 wad) external returns (bool);\n\n function transfer(address dst, uint256 wad) external returns (bool);\n\n function transferFrom(\n address src,\n address dst,\n uint256 wad\n ) external returns (bool);\n}\n" + }, + "contracts/amm/helper/BaseSwapDeposit.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.6.12;\n\nimport \"@openzeppelin/contracts/math/SafeMath.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/SafeERC20.sol\";\nimport \"../interfaces/ISwap.sol\";\nimport \"@openzeppelin/contracts/utils/ReentrancyGuard.sol\";\n\ncontract BaseSwapDeposit is ReentrancyGuard {\n using SafeERC20 for IERC20;\n using SafeMath for uint256;\n\n ISwap public baseSwap;\n IERC20[] public baseTokens;\n\n uint256 constant MAX_UINT256 = 2**256 - 1;\n\n constructor(ISwap _baseSwap) public {\n baseSwap = _baseSwap;\n // Check and approve base level tokens to be deposited to the base Swap contract\n {\n uint8 i;\n for (; i < 32; i++) {\n try _baseSwap.getToken(i) returns (IERC20 token) {\n baseTokens.push(token);\n token.safeApprove(address(_baseSwap), MAX_UINT256);\n } catch {\n break;\n }\n }\n require(i > 1, \"baseSwap must have at least 2 tokens\");\n }\n }\n\n // Mutative functions\n\n /**\n * @notice Swap two underlying tokens using the meta pool and the base pool\n * @param tokenIndexFrom the token the user wants to swap from\n * @param tokenIndexTo the token the user wants to swap to\n * @param dx the amount of tokens the user wants to swap from\n * @param minDy the min amount the user would like to receive, or revert.\n * @param deadline latest timestamp to accept this transaction\n */\n function swap(\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx,\n uint256 minDy,\n uint256 deadline\n ) external nonReentrant returns (uint256) {\n baseTokens[tokenIndexFrom].safeTransferFrom(msg.sender, address(this), dx);\n uint256 tokenToAmount =\n baseSwap.swap(\n tokenIndexFrom,\n tokenIndexTo,\n dx,\n minDy,\n deadline\n );\n baseTokens[tokenIndexTo].safeTransfer(msg.sender, tokenToAmount);\n return tokenToAmount;\n }\n\n /**\n * @notice Calculate amount of tokens you receive on swap\n * @param tokenIndexFrom the token the user wants to sell\n * @param tokenIndexTo the token the user wants to buy\n * @param dx the amount of tokens the user wants to sell. If the token charges\n * a fee on transfers, use the amount that gets transferred after the fee.\n * @return amount of tokens the user will receive\n */\n function calculateSwap(\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx\n ) external view returns (uint256) {\n return\n baseSwap.calculateSwap(tokenIndexFrom, tokenIndexTo, dx);\n }\n\n /**\n * @notice Returns the address of the pooled token at given index. Reverts if tokenIndex is out of range.\n * @param index the index of the token\n * @return address of the token at given index\n */\n function getToken(uint256 index) external view returns (IERC20) {\n require(index < baseTokens.length, \"index out of range\");\n return baseTokens[index];\n }\n\n}" + }, + "@openzeppelin/contracts/utils/ReentrancyGuard.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <0.8.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 () internal {\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" + }, + "contracts/amm/AaveSwapWrapper.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.6.12;\n\nimport \"@openzeppelin/contracts/math/SafeMath.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/SafeERC20.sol\";\nimport \"./Swap.sol\";\n\ninterface ILendingPool {\n /**\n * @dev Deposits an `amount` of underlying asset into the reserve, receiving in return overlying aTokens.\n * - E.g. User deposits 100 USDC and gets in return 100 aUSDC\n * @param asset The address of the underlying asset to deposit\n * @param amount The amount to be deposited\n * @param onBehalfOf The address that will receive the aTokens, same as msg.sender if the user\n * wants to receive them on his own wallet, or a different address if the beneficiary of aTokens\n * is a different wallet\n * @param referralCode Code used to register the integrator originating the operation, for potential rewards.\n * 0 if the action is executed directly by the user, without any middle-man\n **/\n function deposit(\n address asset,\n uint256 amount,\n address onBehalfOf,\n uint16 referralCode\n ) external;\n\n /**\n * @dev Withdraws an `amount` of underlying asset from the reserve, burning the equivalent aTokens owned\n * E.g. User has 100 aUSDC, calls withdraw() and receives 100 USDC, burning the 100 aUSDC\n * @param asset The address of the underlying asset to withdraw\n * @param amount The underlying amount to be withdrawn\n * - Send the value type(uint256).max in order to withdraw the whole aToken balance\n * @param to Address that will receive the underlying, same as msg.sender if the user\n * wants to receive it on his own wallet, or a different address if the beneficiary is a\n * different wallet\n * @return The final amount withdrawn\n **/\n function withdraw(\n address asset,\n uint256 amount,\n address to\n ) external returns (uint256);\n}\n\n/**\n * @title AaveSwapWrapper\n * @notice A wrapper contract for interacting with aTokens\n */\ncontract AaveSwapWrapper {\n using SafeERC20 for IERC20;\n using SafeMath for uint256;\n mapping(uint8 => bool) private isUnderlyingIndex;\n\n // constants\n uint8 private constant MAX_UINT8 = 2**8 - 1;\n uint256 private constant MAX_UINT256 = 2**256 - 1;\n\n // immutables\n Swap public immutable SWAP;\n LPToken public immutable LP_TOKEN;\n address public immutable OWNER;\n IERC20[] public POOLED_TOKENS;\n IERC20[] public UNDERLYING_TOKENS;\n ILendingPool public LENDING_POOL;\n\n constructor(\n Swap swap,\n IERC20[] memory underlyingTokens,\n address lendingPool,\n address owner\n ) public {\n (, , , , , , LPToken lpToken) = swap.swapStorage();\n for (uint8 i = 0; i < MAX_UINT8; i++) {\n try swap.getToken(i) returns (IERC20 token) {\n POOLED_TOKENS.push(token);\n // Approve pooled tokens to be used by Swap\n token.approve(address(swap), MAX_UINT256);\n } catch {\n break;\n }\n }\n\n for (uint8 i = 0; i < POOLED_TOKENS.length; i++) {\n if (POOLED_TOKENS[i] == underlyingTokens[i]) {\n isUnderlyingIndex[i] = true;\n } else {\n isUnderlyingIndex[i] = false;\n underlyingTokens[i].approve(lendingPool, MAX_UINT256);\n }\n }\n\n // Set immutable variables\n SWAP = swap;\n LP_TOKEN = lpToken;\n OWNER = owner;\n UNDERLYING_TOKENS = underlyingTokens;\n LENDING_POOL = ILendingPool(lendingPool);\n\n // Approve LPToken to be used by Swap\n lpToken.approve(address(swap), MAX_UINT256);\n }\n\n /**\n * @notice Add liquidity to the pool with the given amounts of tokens.\n * @param amounts the amounts of each token to add, in their native precision\n * @param minToMint the minimum LP tokens adding this amount of liquidity\n * should mint, otherwise revert. Handy for front-running mitigation\n * @param deadline latest timestamp to accept this transaction\n * @return amount of LP token user minted and received\n */\n function addLiquidity(\n uint256[] memory amounts,\n uint256 minToMint,\n uint256 deadline\n ) external returns (uint256) {\n // Go through amounts array and transfer respective tokens to this contract.\n for (uint8 i = 0; i < amounts.length; i++) {\n uint256 amount = amounts[i];\n if (amount > 0) {\n UNDERLYING_TOKENS[i].safeTransferFrom(\n msg.sender,\n address(this),\n amount\n );\n if (isUnderlyingIndex[i] == false) {\n LENDING_POOL.deposit(\n address(UNDERLYING_TOKENS[i]),\n amount,\n address(this),\n 0\n );\n }\n }\n }\n\n // Add the assets to the pool\n uint256 lpTokenAmount = SWAP.addLiquidity(amounts, minToMint, deadline);\n // Send the LPToken to msg.sender\n IERC20(address(LP_TOKEN)).safeTransfer(msg.sender, lpTokenAmount);\n return lpTokenAmount;\n }\n\n /**\n * @notice Burn LP tokens to remove liquidity from the pool.\n * @dev Liquidity can always be removed, even when the pool is paused. Caller\n * will receive ETH instead of WETH9.\n * @param amount the amount of LP tokens to burn\n * @param minAmounts the minimum amounts of each token in the pool\n * acceptable for this burn. Useful as a front-running mitigation\n * @param deadline latest timestamp to accept this transaction\n * @return amounts of tokens user received\n */\n function removeLiquidity(\n uint256 amount,\n uint256[] calldata minAmounts,\n uint256 deadline\n ) external returns (uint256[] memory) {\n // Transfer LPToken from msg.sender to this contract.\n IERC20(address(LP_TOKEN)).safeTransferFrom(\n msg.sender,\n address(this),\n amount\n );\n // Remove liquidity\n uint256[] memory amounts = SWAP.removeLiquidity(\n amount,\n minAmounts,\n deadline\n );\n // Send the tokens back to the user\n for (uint8 i = 0; i < amounts.length; i++) {\n if (isUnderlyingIndex[i] == true) {\n UNDERLYING_TOKENS[i].safeTransfer(msg.sender, amounts[i]);\n } else {\n LENDING_POOL.withdraw(\n address(UNDERLYING_TOKENS[i]),\n amounts[i],\n msg.sender\n );\n // underlyingTokens[i].safeTransfer(msg.sender, amounts[i]);\n }\n }\n return amounts;\n }\n\n /**\n * @notice Remove liquidity from the pool all in one token.\n * @dev Caller will receive ETH instead of WETH9.\n * @param tokenAmount the amount of the token you want to receive\n * @param tokenIndex the index of the token you want to receive\n * @param minAmount the minimum amount to withdraw, otherwise revert\n * @param deadline latest timestamp to accept this transaction\n * @return amount of chosen token user received\n */\n function removeLiquidityOneToken(\n uint256 tokenAmount,\n uint8 tokenIndex,\n uint256 minAmount,\n uint256 deadline\n ) external returns (uint256) {\n // Transfer LPToken from msg.sender to this contract.\n IERC20(address(LP_TOKEN)).safeTransferFrom(\n msg.sender,\n address(this),\n tokenAmount\n );\n // Withdraw via single token\n uint256 amount = SWAP.removeLiquidityOneToken(\n tokenAmount,\n tokenIndex,\n minAmount,\n deadline\n );\n // Transfer the token to msg.sender accordingly\n if (isUnderlyingIndex[tokenIndex] == true) {\n UNDERLYING_TOKENS[tokenIndex].safeTransfer(msg.sender, amount);\n } else {\n LENDING_POOL.withdraw(\n address(UNDERLYING_TOKENS[tokenIndex]),\n amount,\n msg.sender\n );\n }\n return amount;\n }\n\n /**\n * @notice Swap two tokens using the underlying pool. If tokenIndexFrom\n * represents WETH9 in the pool, the caller must set msg.value equal to dx.\n * If the user is swapping to WETH9 in the pool, the user will receive ETH instead.\n * @param tokenIndexFrom the token the user wants to swap from\n * @param tokenIndexTo the token the user wants to swap to\n * @param dx the amount of tokens the user wants to swap from\n * @param minDy the min amount the user would like to receive, or revert.\n * @param deadline latest timestamp to accept this transaction\n */\n function swap(\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx,\n uint256 minDy,\n uint256 deadline\n ) external returns (uint256) {\n // Transfer tokens from msg.sender to this contract\n UNDERLYING_TOKENS[tokenIndexFrom].safeTransferFrom(\n msg.sender,\n address(this),\n dx\n );\n if (isUnderlyingIndex[tokenIndexFrom] == false) {\n LENDING_POOL.deposit(\n address(UNDERLYING_TOKENS[tokenIndexFrom]),\n dx,\n address(this),\n 0\n );\n }\n // Execute swap\n uint256 dy = SWAP.swap(\n tokenIndexFrom,\n tokenIndexTo,\n dx,\n minDy,\n deadline\n );\n // Transfer the swapped tokens to msg.sender\n if (isUnderlyingIndex[tokenIndexTo] == false) {\n LENDING_POOL.withdraw(\n address(UNDERLYING_TOKENS[tokenIndexTo]),\n dy,\n msg.sender\n );\n } else {\n UNDERLYING_TOKENS[tokenIndexTo].safeTransfer(msg.sender, dy);\n }\n return dy;\n }\n\n /**\n * @notice Rescues any of the ETH, the pooled tokens, or the LPToken that may be stuck\n * in this contract. Only the OWNER can call this function.\n */\n function rescue() external {\n require(msg.sender == OWNER, \"CALLED_BY_NON_OWNER\");\n IERC20[] memory tokens = POOLED_TOKENS;\n for (uint256 i = 0; i < tokens.length; i++) {\n tokens[i].safeTransfer(\n msg.sender,\n tokens[i].balanceOf(address(this))\n );\n }\n\n for (uint256 i = 0; i < UNDERLYING_TOKENS.length; i++) {\n UNDERLYING_TOKENS[i].safeTransfer(\n msg.sender,\n UNDERLYING_TOKENS[i].balanceOf(address(this))\n );\n }\n\n IERC20 lpToken_ = IERC20(address(LP_TOKEN));\n lpToken_.safeTransfer(msg.sender, lpToken_.balanceOf(address(this)));\n }\n\n // VIEW FUNCTIONS\n\n /**\n * @notice Calculate amount of tokens you receive on swap\n * @param tokenIndexFrom the token the user wants to sell\n * @param tokenIndexTo the token the user wants to buy\n * @param dx the amount of tokens the user wants to sell. If the token charges\n * a fee on transfers, use the amount that gets transferred after the fee.\n * @return amount of tokens the user will receive\n */\n function calculateSwap(\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx\n ) external view virtual returns (uint256) {\n return SWAP.calculateSwap(tokenIndexFrom, tokenIndexTo, dx);\n }\n\n /**\n * @notice A simple method to calculate prices from deposits or\n * withdrawals, excluding fees but including slippage. This is\n * helpful as an input into the various \"min\" parameters on calls\n * to fight front-running\n *\n * @dev This shouldn't be used outside frontends for user estimates.\n *\n * @param amounts an array of token amounts to deposit or withdrawal,\n * corresponding to pooledTokens. The amount should be in each\n * pooled token's native precision. If a token charges a fee on transfers,\n * use the amount that gets transferred after the fee.\n * @param deposit whether this is a deposit or a withdrawal\n * @return token amount the user will receive\n */\n function calculateTokenAmount(uint256[] calldata amounts, bool deposit)\n external\n view\n returns (uint256)\n {\n return SWAP.calculateTokenAmount(amounts, deposit);\n }\n\n /**\n * @notice A simple method to calculate amount of each underlying\n * tokens that is returned upon burning given amount of LP tokens\n * @param amount the amount of LP tokens that would be burned on withdrawal\n * @return array of token balances that the user will receive\n */\n function calculateRemoveLiquidity(uint256 amount)\n external\n view\n returns (uint256[] memory)\n {\n return SWAP.calculateRemoveLiquidity(amount);\n }\n\n /**\n * @notice Calculate the amount of underlying token available to withdraw\n * when withdrawing via only single token\n * @param tokenAmount the amount of LP token to burn\n * @param tokenIndex index of which token will be withdrawn\n * @return availableTokenAmount calculated amount of underlying token\n * available to withdraw\n */\n function calculateRemoveLiquidityOneToken(\n uint256 tokenAmount,\n uint8 tokenIndex\n ) external view returns (uint256 availableTokenAmount) {\n return SWAP.calculateRemoveLiquidityOneToken(tokenAmount, tokenIndex);\n }\n\n /**\n * @notice Return address of the pooled token at given index. Reverts if tokenIndex is out of range.\n * @param index the index of the token\n * @return address of the token at given index\n */\n function getToken(uint8 index) public view virtual returns (IERC20) {\n if (index < UNDERLYING_TOKENS.length) {\n return UNDERLYING_TOKENS[index];\n } else {\n revert();\n }\n }\n}\n" + }, + "contracts/bridge/ECDSAFactory.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.6.12;\n\nimport \"@openzeppelin/contracts/access/Ownable.sol\";\nimport \"@openzeppelin/contracts/proxy/Clones.sol\";\nimport \"./interfaces/IECDSANodeManagement.sol\";\n\ncontract ECDSAFactory is Ownable {\n event ECDSANodeGroupCreated(\n address indexed keepAddress,\n address[] members,\n address indexed owner,\n uint256 honestThreshold\n );\n\n struct LatestNodeGroup {\n address keepAddress;\n address[] members;\n address owner;\n uint256 honestThreshold;\n }\n\n LatestNodeGroup public latestNodeGroup;\n\n constructor() public Ownable() {}\n\n /// @notice Returns members of the keep.\n /// @return List of the keep members' addresses.\n function getMembers() public view returns (address[] memory) {\n return latestNodeGroup.members;\n }\n\n /**\n @notice Deploys a new node \n @param nodeMgmtAddress address of the ECDSANodeManagement contract to initialize with\n @param owner Owner of the ECDSANodeManagement contract who can determine if the node group is closed or active\n @param members Array of node group members addresses\n @param honestThreshold Number of signers to process a transaction \n @return Address of the newest node management contract created\n **/\n function deploy(\n address nodeMgmtAddress,\n address owner,\n address[] memory members,\n uint256 honestThreshold\n ) external onlyOwner returns (address) {\n address nodeClone = Clones.clone(nodeMgmtAddress);\n IECDSANodeManagement(nodeClone).initialize(\n owner,\n members,\n honestThreshold\n );\n\n latestNodeGroup.keepAddress = nodeClone;\n latestNodeGroup.members = members;\n latestNodeGroup.owner = owner;\n latestNodeGroup.honestThreshold = honestThreshold;\n\n emit ECDSANodeGroupCreated(nodeClone, members, owner, honestThreshold);\n return nodeClone;\n }\n}\n" + }, + "contracts/bridge/interfaces/IECDSANodeManagement.sol": { + "content": "// SPDX-License-Identifier: MIT\n\n\npragma solidity 0.6.12;\n\n/**\n * @title IECDSANodeManagement interface\n * @notice Interface for the ECDSA node management interface.\n * @dev implement this interface to develop a a factory-patterned ECDSA node management contract\n **/\ninterface IECDSANodeManagement { \n function initialize(\n address _owner,\n address[] memory _members,\n uint256 _honestThreshold) external;\n}\n\n" + }, + "contracts/auxiliary/DummyWeth.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.6.12;\nimport \"@openzeppelin/contracts/access/Ownable.sol\";\n\ninterface IWETH9 {\n function name() external view returns (string memory);\n\n function symbol() external view returns (string memory);\n\n function decimals() external view returns (uint8);\n\n function balanceOf(address) external view returns (uint256);\n\n function allowance(address, address) external view returns (uint256);\n\n receive() external payable;\n\n function deposit() external payable;\n\n function withdraw(uint256 wad) external;\n\n function totalSupply() external view returns (uint256);\n\n function approve(address guy, uint256 wad) external returns (bool);\n\n function transfer(address dst, uint256 wad) external returns (bool);\n\n function transferFrom(\n address src,\n address dst,\n uint256 wad\n ) external returns (bool);\n}\n\ncontract DummyWeth is Ownable {\n IWETH9 public WETH;\n\n function setWETHAddress(address payable _weth) external onlyOwner {\n WETH = IWETH9(_weth);\n }\n\n function withdrawToSelf(uint256 amount) external {\n WETH.withdraw(amount);\n }\n\n function rescue(uint256 amount) external onlyOwner {\n WETH.transfer(owner(), amount);\n }\n\n receive() external payable {}\n\n fallback() external payable {}\n}\n" + } + }, + "settings": { + "optimizer": { + "enabled": true, + "runs": 10000 + }, + "outputSelection": { + "*": { + "*": [ + "abi", + "evm.bytecode", + "evm.deployedBytecode", + "evm.methodIdentifiers", + "metadata", + "devdoc", + "userdoc", + "storageLayout", + "evm.gasEstimates", + "devdoc", + "userdoc" + ], + "": [ + "ast" + ] + } + }, + "metadata": { + "useLiteralContent": true + } + } +} \ No newline at end of file diff --git a/deployments/harmony/synJEWEL.json b/deployments/harmony/synJEWEL.json new file mode 100644 index 000000000..8aa38ec08 --- /dev/null +++ b/deployments/harmony/synJEWEL.json @@ -0,0 +1,668 @@ +{ + "address": "0x28b42698Caf46B4B012CF38b6C75867E0762186D", + "abi": [ + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "Approval", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "bytes32", + "name": "previousAdminRole", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "bytes32", + "name": "newAdminRole", + "type": "bytes32" + } + ], + "name": "RoleAdminChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "sender", + "type": "address" + } + ], + "name": "RoleGranted", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "sender", + "type": "address" + } + ], + "name": "RoleRevoked", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "Transfer", + "type": "event" + }, + { + "inputs": [], + "name": "DEFAULT_ADMIN_ROLE", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "DOMAIN_SEPARATOR", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "MINTER_ROLE", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "address", + "name": "spender", + "type": "address" + } + ], + "name": "allowance", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "approve", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "balanceOf", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "burn", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "burnFrom", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "decimals", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "subtractedValue", + "type": "uint256" + } + ], + "name": "decreaseAllowance", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + } + ], + "name": "getRoleAdmin", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "internalType": "uint256", + "name": "index", + "type": "uint256" + } + ], + "name": "getRoleMember", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + } + ], + "name": "getRoleMemberCount", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "grantRole", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "hasRole", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "addedValue", + "type": "uint256" + } + ], + "name": "increaseAllowance", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "name", + "type": "string" + }, + { + "internalType": "string", + "name": "symbol", + "type": "string" + }, + { + "internalType": "uint8", + "name": "decimals", + "type": "uint8" + }, + { + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "initialize", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "mint", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "name", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "nonces", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" + }, + { + "internalType": "uint8", + "name": "v", + "type": "uint8" + }, + { + "internalType": "bytes32", + "name": "r", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "s", + "type": "bytes32" + } + ], + "name": "permit", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "renounceRole", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "revokeRole", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "symbol", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "totalSupply", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "recipient", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "transfer", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "internalType": "address", + "name": "recipient", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "transferFrom", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + } + ] +} \ No newline at end of file diff --git a/deployments/mainnet/VSTA.json b/deployments/mainnet/VSTA.json new file mode 100644 index 000000000..1430b7a4b --- /dev/null +++ b/deployments/mainnet/VSTA.json @@ -0,0 +1,668 @@ +{ + "address": "0xA8d7F5e7C78ed0Fa097Cc5Ec66C1DC3104c9bbeb", + "abi": [ + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "Approval", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "bytes32", + "name": "previousAdminRole", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "bytes32", + "name": "newAdminRole", + "type": "bytes32" + } + ], + "name": "RoleAdminChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "sender", + "type": "address" + } + ], + "name": "RoleGranted", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "sender", + "type": "address" + } + ], + "name": "RoleRevoked", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "Transfer", + "type": "event" + }, + { + "inputs": [], + "name": "DEFAULT_ADMIN_ROLE", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "DOMAIN_SEPARATOR", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "MINTER_ROLE", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "address", + "name": "spender", + "type": "address" + } + ], + "name": "allowance", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "approve", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "balanceOf", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "burn", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "burnFrom", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "decimals", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "subtractedValue", + "type": "uint256" + } + ], + "name": "decreaseAllowance", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + } + ], + "name": "getRoleAdmin", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "internalType": "uint256", + "name": "index", + "type": "uint256" + } + ], + "name": "getRoleMember", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + } + ], + "name": "getRoleMemberCount", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "grantRole", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "hasRole", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "addedValue", + "type": "uint256" + } + ], + "name": "increaseAllowance", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "_name", + "type": "string" + }, + { + "internalType": "string", + "name": "_symbol", + "type": "string" + }, + { + "internalType": "uint8", + "name": "_decimals", + "type": "uint8" + }, + { + "internalType": "address", + "name": "_owner", + "type": "address" + } + ], + "name": "initialize", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "mint", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "name", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "nonces", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" + }, + { + "internalType": "uint8", + "name": "v", + "type": "uint8" + }, + { + "internalType": "bytes32", + "name": "r", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "s", + "type": "bytes32" + } + ], + "name": "permit", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "renounceRole", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "revokeRole", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "symbol", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "totalSupply", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "recipient", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "transfer", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "internalType": "address", + "name": "recipient", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "transferFrom", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + } + ] +} \ No newline at end of file diff --git a/deployments/optimism/L2BridgeZap.json b/deployments/optimism/L2BridgeZap.json index 61ac1f0c9..8eaeb166e 100644 --- a/deployments/optimism/L2BridgeZap.json +++ b/deployments/optimism/L2BridgeZap.json @@ -1,5 +1,5 @@ { - "address": "0x9CD619c50562a38edBdC3451ade7B58CaA71Ab32", + "address": "0x470f9522ff620eE45DF86C58E54E6A645fE3b4A7", "abi": [ { "inputs": [ @@ -112,6 +112,72 @@ "stateMutability": "nonpayable", "type": "function" }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "chainId", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "depositETH", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "chainId", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "internalType": "uint8", + "name": "tokenIndexFrom", + "type": "uint8" + }, + { + "internalType": "uint8", + "name": "tokenIndexTo", + "type": "uint8" + }, + { + "internalType": "uint256", + "name": "minDy", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" + } + ], + "name": "depositETHAndSwap", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, { "inputs": [ { @@ -231,6 +297,34 @@ "stateMutability": "nonpayable", "type": "function" }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "to", + "type": "bytes32" + }, + { + "internalType": "uint256", + "name": "chainId", + "type": "uint256" + }, + { + "internalType": "contract IERC20", + "name": "token", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "redeemv2", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, { "inputs": [ { @@ -570,76 +664,132 @@ "type": "function" } ], - "transactionHash": "0x4089c4a73c397822a553ed65bdc878e182239ab9c62227bb364a4c4fafd5684b", + "transactionHash": "0x7ca7d6a5bcd2fdfa1b567001d579654b3e2309d063042434cf192e8f230ea655", "receipt": { "to": null, "from": "0x0AF91FA049A7e1894F480bFE5bBa20142C6c29a9", - "contractAddress": "0x9CD619c50562a38edBdC3451ade7B58CaA71Ab32", + "contractAddress": "0x470f9522ff620eE45DF86C58E54E6A645fE3b4A7", "transactionIndex": 0, - "gasUsed": "2232330", - "logsBloom": "0x00000000000200000000000000000000000000000000000000000000004000000000000000000000000000000000000000001000000080000000000000200000000000000000000000000000000000000000000080002000000000000000000000000000000000000000000000000040000000000008000000000000000000000000000000000000000000000000000000010000000000000000000000000000020000000000200000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000040000000000000000000010000008000000000000000008008000000000000000000000000000000000", - "blockHash": "0xc45b7d6af69d7dba507fe320c31e4e59cd06a606a1b8ab19820e77132e16aad9", - "transactionHash": "0x4089c4a73c397822a553ed65bdc878e182239ab9c62227bb364a4c4fafd5684b", + "gasUsed": "2686255", + "logsBloom": "0x00000000000200000000008000000000000000000000000000000000004000000000000000000000000000000000000000000040004080000000000000200000000000000000000000000000000000000000040000002000000000000000000000000000000000000000000000000040000000000008000000000000000000000000000000000000000000000080000000010000000000000000000000000000020001000000200000000000000000000002000000000000000000000000000000000004000000000000000000010000000000000000040000000000000000000010000008000000000000000008000100000000000000000000080001010000", + "blockHash": "0x5ec6738ef2b36fa17ef41e861a6c33dd8aeab36667582407179c163cc51e2a77", + "transactionHash": "0x7ca7d6a5bcd2fdfa1b567001d579654b3e2309d063042434cf192e8f230ea655", "logs": [ { "transactionIndex": 0, - "blockNumber": 207184, - "transactionHash": "0x4089c4a73c397822a553ed65bdc878e182239ab9c62227bb364a4c4fafd5684b", + "blockNumber": 6102224, + "transactionHash": "0x7ca7d6a5bcd2fdfa1b567001d579654b3e2309d063042434cf192e8f230ea655", "address": "0x809DC529f07651bD43A172e8dB6f4a7a0d771036", "topics": [ "0x8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925", - "0x0000000000000000000000009cd619c50562a38edbdc3451ade7b58caa71ab32", + "0x000000000000000000000000470f9522ff620ee45df86c58e54e6a645fe3b4a7", "0x000000000000000000000000e27bff97ce92c3e1ff7aa9f86781fdd6d48f5ee9" ], "data": "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", "logIndex": 0, - "blockHash": "0xc45b7d6af69d7dba507fe320c31e4e59cd06a606a1b8ab19820e77132e16aad9" + "blockHash": "0x5ec6738ef2b36fa17ef41e861a6c33dd8aeab36667582407179c163cc51e2a77" }, { "transactionIndex": 0, - "blockNumber": 207184, - "transactionHash": "0x4089c4a73c397822a553ed65bdc878e182239ab9c62227bb364a4c4fafd5684b", + "blockNumber": 6102224, + "transactionHash": "0x7ca7d6a5bcd2fdfa1b567001d579654b3e2309d063042434cf192e8f230ea655", "address": "0x809DC529f07651bD43A172e8dB6f4a7a0d771036", "topics": [ "0x8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925", - "0x0000000000000000000000009cd619c50562a38edbdc3451ade7b58caa71ab32", + "0x000000000000000000000000470f9522ff620ee45df86c58e54e6a645fe3b4a7", "0x000000000000000000000000af41a65f786339e7911f4acdad6bd49426f2dc6b" ], "data": "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", "logIndex": 1, - "blockHash": "0xc45b7d6af69d7dba507fe320c31e4e59cd06a606a1b8ab19820e77132e16aad9" + "blockHash": "0x5ec6738ef2b36fa17ef41e861a6c33dd8aeab36667582407179c163cc51e2a77" }, { "transactionIndex": 0, - "blockNumber": 207184, - "transactionHash": "0x4089c4a73c397822a553ed65bdc878e182239ab9c62227bb364a4c4fafd5684b", + "blockNumber": 6102224, + "transactionHash": "0x7ca7d6a5bcd2fdfa1b567001d579654b3e2309d063042434cf192e8f230ea655", "address": "0x121ab82b49B2BC4c7901CA46B8277962b4350204", "topics": [ "0x8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925", - "0x0000000000000000000000009cd619c50562a38edbdc3451ade7b58caa71ab32", + "0x000000000000000000000000470f9522ff620ee45df86c58e54e6a645fe3b4a7", "0x000000000000000000000000e27bff97ce92c3e1ff7aa9f86781fdd6d48f5ee9" ], "data": "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", "logIndex": 2, - "blockHash": "0xc45b7d6af69d7dba507fe320c31e4e59cd06a606a1b8ab19820e77132e16aad9" + "blockHash": "0x5ec6738ef2b36fa17ef41e861a6c33dd8aeab36667582407179c163cc51e2a77" }, { "transactionIndex": 0, - "blockNumber": 207184, - "transactionHash": "0x4089c4a73c397822a553ed65bdc878e182239ab9c62227bb364a4c4fafd5684b", + "blockNumber": 6102224, + "transactionHash": "0x7ca7d6a5bcd2fdfa1b567001d579654b3e2309d063042434cf192e8f230ea655", "address": "0x121ab82b49B2BC4c7901CA46B8277962b4350204", "topics": [ "0x8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925", - "0x0000000000000000000000009cd619c50562a38edbdc3451ade7b58caa71ab32", + "0x000000000000000000000000470f9522ff620ee45df86c58e54e6a645fe3b4a7", "0x000000000000000000000000af41a65f786339e7911f4acdad6bd49426f2dc6b" ], "data": "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", "logIndex": 3, - "blockHash": "0xc45b7d6af69d7dba507fe320c31e4e59cd06a606a1b8ab19820e77132e16aad9" + "blockHash": "0x5ec6738ef2b36fa17ef41e861a6c33dd8aeab36667582407179c163cc51e2a77" + }, + { + "transactionIndex": 0, + "blockNumber": 6102224, + "transactionHash": "0x7ca7d6a5bcd2fdfa1b567001d579654b3e2309d063042434cf192e8f230ea655", + "address": "0x67C10C397dD0Ba417329543c1a40eb48AAa7cd00", + "topics": [ + "0x8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925", + "0x000000000000000000000000470f9522ff620ee45df86c58e54e6a645fe3b4a7", + "0x000000000000000000000000f44938b0125a6662f9536281ad2cd6c499f22004" + ], + "data": "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + "logIndex": 4, + "blockHash": "0x5ec6738ef2b36fa17ef41e861a6c33dd8aeab36667582407179c163cc51e2a77" + }, + { + "transactionIndex": 0, + "blockNumber": 6102224, + "transactionHash": "0x7ca7d6a5bcd2fdfa1b567001d579654b3e2309d063042434cf192e8f230ea655", + "address": "0x67C10C397dD0Ba417329543c1a40eb48AAa7cd00", + "topics": [ + "0x8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925", + "0x000000000000000000000000470f9522ff620ee45df86c58e54e6a645fe3b4a7", + "0x000000000000000000000000af41a65f786339e7911f4acdad6bd49426f2dc6b" + ], + "data": "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + "logIndex": 5, + "blockHash": "0x5ec6738ef2b36fa17ef41e861a6c33dd8aeab36667582407179c163cc51e2a77" + }, + { + "transactionIndex": 0, + "blockNumber": 6102224, + "transactionHash": "0x7ca7d6a5bcd2fdfa1b567001d579654b3e2309d063042434cf192e8f230ea655", + "address": "0x7F5c764cBc14f9669B88837ca1490cCa17c31607", + "topics": [ + "0x8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925", + "0x000000000000000000000000470f9522ff620ee45df86c58e54e6a645fe3b4a7", + "0x000000000000000000000000f44938b0125a6662f9536281ad2cd6c499f22004" + ], + "data": "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + "logIndex": 6, + "blockHash": "0x5ec6738ef2b36fa17ef41e861a6c33dd8aeab36667582407179c163cc51e2a77" + }, + { + "transactionIndex": 0, + "blockNumber": 6102224, + "transactionHash": "0x7ca7d6a5bcd2fdfa1b567001d579654b3e2309d063042434cf192e8f230ea655", + "address": "0x7F5c764cBc14f9669B88837ca1490cCa17c31607", + "topics": [ + "0x8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925", + "0x000000000000000000000000470f9522ff620ee45df86c58e54e6a645fe3b4a7", + "0x000000000000000000000000af41a65f786339e7911f4acdad6bd49426f2dc6b" + ], + "data": "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + "logIndex": 7, + "blockHash": "0x5ec6738ef2b36fa17ef41e861a6c33dd8aeab36667582407179c163cc51e2a77" } ], - "blockNumber": 207184, - "cumulativeGasUsed": "2232330", + "blockNumber": 6102224, + "cumulativeGasUsed": "2686255", "status": 1, "byzantium": true }, @@ -647,14 +797,14 @@ "0x121ab82b49B2BC4c7901CA46B8277962b4350204", "0xE27BFf97CE92C3e1Ff7AA9f86781FDd6D48F5eE9", "0x809DC529f07651bD43A172e8dB6f4a7a0d771036", - "0x0000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000", + "0xF44938b0125A6662f9536281aD2CD6c499F22004", + "0x67C10C397dD0Ba417329543c1a40eb48AAa7cd00", "0xAf41a65F786339e7911F4acDAD6BD49426F2Dc6b" ], - "solcInputHash": "108b75f9b78ef8ef1e4f5166a1fea50e", - "metadata": "{\"compiler\":{\"version\":\"0.6.12+commit.27d51765\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address payable\",\"name\":\"_wethAddress\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_swapOne\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenOne\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_swapTwo\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenTwo\",\"type\":\"address\"},{\"internalType\":\"contract ISynapseBridge\",\"name\":\"_synapseBridge\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"WETH_ADDRESS\",\"outputs\":[{\"internalType\":\"address payable\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contract IERC20\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint8\",\"name\":\"tokenIndexFrom\",\"type\":\"uint8\"},{\"internalType\":\"uint8\",\"name\":\"tokenIndexTo\",\"type\":\"uint8\"},{\"internalType\":\"uint256\",\"name\":\"dx\",\"type\":\"uint256\"}],\"name\":\"calculateSwap\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"chainId\",\"type\":\"uint256\"},{\"internalType\":\"contract IERC20\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"deposit\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"chainId\",\"type\":\"uint256\"},{\"internalType\":\"contract IERC20\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"redeem\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"chainId\",\"type\":\"uint256\"},{\"internalType\":\"contract IERC20\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"uint8\",\"name\":\"liqTokenIndex\",\"type\":\"uint8\"},{\"internalType\":\"uint256\",\"name\":\"liqMinAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"liqDeadline\",\"type\":\"uint256\"}],\"name\":\"redeemAndRemove\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"chainId\",\"type\":\"uint256\"},{\"internalType\":\"contract IERC20\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"uint8\",\"name\":\"tokenIndexFrom\",\"type\":\"uint8\"},{\"internalType\":\"uint8\",\"name\":\"tokenIndexTo\",\"type\":\"uint8\"},{\"internalType\":\"uint256\",\"name\":\"minDy\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"deadline\",\"type\":\"uint256\"}],\"name\":\"redeemAndSwap\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"chainId\",\"type\":\"uint256\"},{\"internalType\":\"contract IERC20\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint8\",\"name\":\"tokenIndexFrom\",\"type\":\"uint8\"},{\"internalType\":\"uint8\",\"name\":\"tokenIndexTo\",\"type\":\"uint8\"},{\"internalType\":\"uint256\",\"name\":\"dx\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"minDy\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"deadline\",\"type\":\"uint256\"}],\"name\":\"swapAndRedeem\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"chainId\",\"type\":\"uint256\"},{\"internalType\":\"contract IERC20\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint8\",\"name\":\"tokenIndexFrom\",\"type\":\"uint8\"},{\"internalType\":\"uint8\",\"name\":\"tokenIndexTo\",\"type\":\"uint8\"},{\"internalType\":\"uint256\",\"name\":\"dx\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"minDy\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"deadline\",\"type\":\"uint256\"},{\"internalType\":\"uint8\",\"name\":\"liqTokenIndex\",\"type\":\"uint8\"},{\"internalType\":\"uint256\",\"name\":\"liqMinAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"liqDeadline\",\"type\":\"uint256\"}],\"name\":\"swapAndRedeemAndRemove\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"chainId\",\"type\":\"uint256\"},{\"internalType\":\"contract IERC20\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint8\",\"name\":\"tokenIndexFrom\",\"type\":\"uint8\"},{\"internalType\":\"uint8\",\"name\":\"tokenIndexTo\",\"type\":\"uint8\"},{\"internalType\":\"uint256\",\"name\":\"dx\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"minDy\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"deadline\",\"type\":\"uint256\"},{\"internalType\":\"uint8\",\"name\":\"swapTokenIndexFrom\",\"type\":\"uint8\"},{\"internalType\":\"uint8\",\"name\":\"swapTokenIndexTo\",\"type\":\"uint8\"},{\"internalType\":\"uint256\",\"name\":\"swapMinDy\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"swapDeadline\",\"type\":\"uint256\"}],\"name\":\"swapAndRedeemAndSwap\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"chainId\",\"type\":\"uint256\"},{\"internalType\":\"contract IERC20\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint8\",\"name\":\"tokenIndexFrom\",\"type\":\"uint8\"},{\"internalType\":\"uint8\",\"name\":\"tokenIndexTo\",\"type\":\"uint8\"},{\"internalType\":\"uint256\",\"name\":\"dx\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"minDy\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"deadline\",\"type\":\"uint256\"}],\"name\":\"swapETHAndRedeem\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"chainId\",\"type\":\"uint256\"},{\"internalType\":\"contract IERC20\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint8\",\"name\":\"tokenIndexFrom\",\"type\":\"uint8\"},{\"internalType\":\"uint8\",\"name\":\"tokenIndexTo\",\"type\":\"uint8\"},{\"internalType\":\"uint256\",\"name\":\"dx\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"minDy\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"deadline\",\"type\":\"uint256\"},{\"internalType\":\"uint8\",\"name\":\"swapTokenIndexFrom\",\"type\":\"uint8\"},{\"internalType\":\"uint8\",\"name\":\"swapTokenIndexTo\",\"type\":\"uint8\"},{\"internalType\":\"uint256\",\"name\":\"swapMinDy\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"swapDeadline\",\"type\":\"uint256\"}],\"name\":\"swapETHAndRedeemAndSwap\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"swapMap\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"swapTokensMap\",\"outputs\":[{\"internalType\":\"contract IERC20\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{\"calculateSwap(address,uint8,uint8,uint256)\":{\"params\":{\"dx\":\"the amount of tokens the user wants to sell. If the token charges a fee on transfers, use the amount that gets transferred after the fee.\",\"tokenIndexFrom\":\"the token the user wants to sell\",\"tokenIndexTo\":\"the token the user wants to buy\"},\"returns\":{\"_0\":\"amount of tokens the user will receive\"}},\"deposit(address,uint256,address,uint256)\":{\"params\":{\"amount\":\"Amount in native token decimals to transfer cross-chain pre-fees*\",\"chainId\":\"which underlying chain to bridge assets onto\",\"to\":\"address on other chain to redeem underlying assets to\",\"token\":\"ERC20 compatible token to deposit into the bridge\"}},\"redeem(address,uint256,address,uint256)\":{\"params\":{\"amount\":\"Amount in native token decimals to transfer cross-chain pre-fees*\",\"chainId\":\"which underlying chain to bridge assets onto\",\"to\":\"address on other chain to redeem underlying assets to\",\"token\":\"ERC20 compatible token to deposit into the bridge\"}},\"redeemAndRemove(address,uint256,address,uint256,uint8,uint256,uint256)\":{\"params\":{\"amount\":\"Amount of (typically) LP token to pass to the nodes to attempt to removeLiquidity() with to redeem for the underlying assets of the LP token\",\"chainId\":\"which underlying chain to bridge assets onto\",\"liqDeadline\":\"Specificies the deadline that the nodes are allowed to try to redeem/swap the LP token*\",\"liqMinAmount\":\"Specifies the minimum amount of the underlying asset needed for the nodes to execute the redeem/swap\",\"liqTokenIndex\":\"Specifies which of the underlying LP assets the nodes should attempt to redeem for\",\"to\":\"address on other chain to redeem underlying assets to\",\"token\":\"ERC20 compatible token to deposit into the bridge\"}},\"redeemAndSwap(address,uint256,address,uint256,uint8,uint8,uint256,uint256)\":{\"params\":{\"amount\":\"Amount in native token decimals to transfer cross-chain pre-fees\",\"chainId\":\"which underlying chain to bridge assets onto\",\"deadline\":\"latest timestamp to accept this transaction*\",\"minDy\":\"the min amount the user would like to receive, or revert to only minting the SynERC20 token crosschain.\",\"to\":\"address on other chain to redeem underlying assets to\",\"token\":\"ERC20 compatible token to deposit into the bridge\",\"tokenIndexFrom\":\"the token the user wants to swap from\",\"tokenIndexTo\":\"the token the user wants to swap to\"}}},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{\"calculateSwap(address,uint8,uint8,uint256)\":{\"notice\":\"Calculate amount of tokens you receive on swap\"},\"deposit(address,uint256,address,uint256)\":{\"notice\":\"wraps SynapseBridge redeem()\"},\"redeem(address,uint256,address,uint256)\":{\"notice\":\"wraps SynapseBridge redeem()\"},\"redeemAndRemove(address,uint256,address,uint256,uint8,uint256,uint256)\":{\"notice\":\"Wraps redeemAndRemove on SynapseBridge Relays to nodes that (typically) a wrapped synAsset ERC20 token has been burned and the underlying needs to be redeeemed on the native chain. This function indicates to the nodes that they should attempt to redeem the LP token for the underlying assets (E.g \\\"swap\\\" out of the LP token)\"},\"redeemAndSwap(address,uint256,address,uint256,uint8,uint8,uint256,uint256)\":{\"notice\":\"Wraps redeemAndSwap on SynapseBridge.sol Relays to nodes that (typically) a wrapped synAsset ERC20 token has been burned and the underlying needs to be redeeemed on the native chain. This function indicates to the nodes that they should attempt to redeem the LP token for the underlying assets (E.g \\\"swap\\\" out of the LP token)\"}},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/bridge/wrappers/L2BridgeZap.sol\":\"L2BridgeZap\"},\"evmVersion\":\"istanbul\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":10000},\"remappings\":[]},\"sources\":{\"@openzeppelin/contracts/math/SafeMath.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity >=0.6.0 <0.8.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\",\"keccak256\":\"0xcc78a17dd88fa5a2edc60c8489e2f405c0913b377216a5b26b35656b2d0dab52\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/ERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity >=0.6.0 <0.8.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_) public {\\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\",\"keccak256\":\"0xca0c2396dbeb3503b51abf4248ebf77a1461edad513c01529df51850a012bee3\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/ERC20Burnable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity >=0.6.0 <0.8.0;\\n\\nimport \\\"../../utils/Context.sol\\\";\\nimport \\\"./ERC20.sol\\\";\\n\\n/**\\n * @dev Extension of {ERC20} that allows token holders to destroy both their own\\n * tokens and those that they have an allowance for, in a way that can be\\n * recognized off-chain (via event analysis).\\n */\\nabstract contract ERC20Burnable is Context, ERC20 {\\n using SafeMath for uint256;\\n\\n /**\\n * @dev Destroys `amount` tokens from the caller.\\n *\\n * See {ERC20-_burn}.\\n */\\n function burn(uint256 amount) public virtual {\\n _burn(_msgSender(), amount);\\n }\\n\\n /**\\n * @dev Destroys `amount` tokens from `account`, deducting from the caller's\\n * allowance.\\n *\\n * See {ERC20-_burn} and {ERC20-allowance}.\\n *\\n * Requirements:\\n *\\n * - the caller must have allowance for ``accounts``'s tokens of at least\\n * `amount`.\\n */\\n function burnFrom(address account, uint256 amount) public virtual {\\n uint256 decreasedAllowance = allowance(account, _msgSender()).sub(amount, \\\"ERC20: burn amount exceeds allowance\\\");\\n\\n _approve(account, _msgSender(), decreasedAllowance);\\n _burn(account, amount);\\n }\\n}\\n\",\"keccak256\":\"0x9c0eb3b0e11d2480d49991dc384f1e5f9c9b9967cc81944d50916a9b9c6c4984\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/IERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity >=0.6.0 <0.8.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\",\"keccak256\":\"0x5f02220344881ce43204ae4a6281145a67bc52c2bb1290a791857df3d19d78f5\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/SafeERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity >=0.6.0 <0.8.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\",\"keccak256\":\"0xf12dfbe97e6276980b83d2830bb0eb75e0cf4f3e626c2471137f82158ae6a0fc\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/Address.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity >=0.6.2 <0.8.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\",\"keccak256\":\"0x28911e614500ae7c607a432a709d35da25f3bc5ddc8bd12b278b66358070c0ea\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/Context.sol\":{\"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\",\"keccak256\":\"0x8d3cb350f04ff49cfb10aef08d87f19dcbaecc8027b0bed12f3275cd12f38cf0\",\"license\":\"MIT\"},\"contracts/bridge/interfaces/ISwap.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity 0.6.12;\\n\\nimport '@openzeppelin/contracts/token/ERC20/ERC20.sol';\\n\\ninterface ISwap {\\n // pool data view functions\\n function getA() external view returns (uint256);\\n\\n function getToken(uint8 index) external view returns (IERC20);\\n\\n function getTokenIndex(address tokenAddress) external view returns (uint8);\\n\\n function getTokenBalance(uint8 index) external view returns (uint256);\\n\\n function getVirtualPrice() external view returns (uint256);\\n\\n // min return calculation functions\\n function calculateSwap(\\n uint8 tokenIndexFrom,\\n uint8 tokenIndexTo,\\n uint256 dx\\n ) external view returns (uint256);\\n\\n function calculateTokenAmount(uint256[] calldata amounts, bool deposit)\\n external\\n view\\n returns (uint256);\\n\\n function calculateRemoveLiquidity(uint256 amount)\\n external\\n view\\n returns (uint256[] memory);\\n\\n function calculateRemoveLiquidityOneToken(\\n uint256 tokenAmount,\\n uint8 tokenIndex\\n ) external view returns (uint256 availableTokenAmount);\\n\\n // state modifying functions\\n function initialize(\\n IERC20[] memory pooledTokens,\\n uint8[] memory decimals,\\n string memory lpTokenName,\\n string memory lpTokenSymbol,\\n uint256 a,\\n uint256 fee,\\n uint256 adminFee,\\n address lpTokenTargetAddress\\n ) external;\\n\\n function swap(\\n uint8 tokenIndexFrom,\\n uint8 tokenIndexTo,\\n uint256 dx,\\n uint256 minDy,\\n uint256 deadline\\n ) external returns (uint256);\\n\\n function addLiquidity(\\n uint256[] calldata amounts,\\n uint256 minToMint,\\n uint256 deadline\\n ) external returns (uint256);\\n\\n function removeLiquidity(\\n uint256 amount,\\n uint256[] calldata minAmounts,\\n uint256 deadline\\n ) external returns (uint256[] memory);\\n\\n function removeLiquidityOneToken(\\n uint256 tokenAmount,\\n uint8 tokenIndex,\\n uint256 minAmount,\\n uint256 deadline\\n ) external returns (uint256);\\n\\n function removeLiquidityImbalance(\\n uint256[] calldata amounts,\\n uint256 maxBurnAmount,\\n uint256 deadline\\n ) external returns (uint256);\\n}\\n\",\"keccak256\":\"0xb51eb389637b2b595a09cd95ea4167a6d945719be1bc127eafae07c06abd8ca8\",\"license\":\"MIT\"},\"contracts/bridge/interfaces/ISynapseBridge.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity 0.6.12;\\n\\nimport '@openzeppelin/contracts/token/ERC20/SafeERC20.sol';\\nimport '@openzeppelin/contracts/token/ERC20/ERC20Burnable.sol';\\n\\ninterface ISynapseBridge {\\n using SafeERC20 for IERC20;\\n\\n function deposit(\\n address to,\\n uint256 chainId,\\n IERC20 token,\\n uint256 amount\\n ) external;\\n\\n function depositAndSwap(\\n address to,\\n uint256 chainId,\\n IERC20 token,\\n uint256 amount,\\n uint8 tokenIndexFrom,\\n uint8 tokenIndexTo,\\n uint256 minDy,\\n uint256 deadline\\n ) external;\\n\\n function redeem(\\n address to,\\n uint256 chainId,\\n IERC20 token,\\n uint256 amount\\n ) external;\\n\\n function redeemAndSwap(\\n address to,\\n uint256 chainId,\\n IERC20 token,\\n uint256 amount,\\n uint8 tokenIndexFrom,\\n uint8 tokenIndexTo,\\n uint256 minDy,\\n uint256 deadline\\n ) external;\\n\\n function redeemAndRemove(\\n address to,\\n uint256 chainId,\\n IERC20 token,\\n uint256 amount,\\n uint8 liqTokenIndex,\\n uint256 liqMinAmount,\\n uint256 liqDeadline\\n ) external;\\n}\\n\",\"keccak256\":\"0x481ef0dfbfdf319518480c86f83fe6caea352ced4aa05f26389285af5c7e4c19\",\"license\":\"MIT\"},\"contracts/bridge/interfaces/IWETH9.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity >=0.4.0;\\n\\ninterface IWETH9 {\\n function name() external view returns (string memory);\\n\\n function symbol() external view returns (string memory);\\n\\n function decimals() external view returns (uint8);\\n\\n function balanceOf(address) external view returns (uint256);\\n\\n function allowance(address, address) external view returns (uint256);\\n\\n receive() external payable;\\n\\n function deposit() external payable;\\n\\n function withdraw(uint256 wad) external;\\n\\n function totalSupply() external view returns (uint256);\\n\\n function approve(address guy, uint256 wad) external returns (bool);\\n\\n function transfer(address dst, uint256 wad) external returns (bool);\\n\\n function transferFrom(\\n address src,\\n address dst,\\n uint256 wad\\n ) external returns (bool);\\n}\",\"keccak256\":\"0x081ebde11dad2210d382564d40336f914d3d621750645f23707ca1a92139dbe2\",\"license\":\"MIT\"},\"contracts/bridge/wrappers/L2BridgeZap.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.6.12;\\n\\nimport \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\nimport \\\"@openzeppelin/contracts/token/ERC20/SafeERC20.sol\\\";\\nimport \\\"../interfaces/ISwap.sol\\\";\\nimport \\\"../interfaces/ISynapseBridge.sol\\\";\\nimport \\\"../interfaces/IWETH9.sol\\\";\\n\\ncontract L2BridgeZap {\\n using SafeERC20 for IERC20;\\n\\n ISynapseBridge synapseBridge;\\n address payable public immutable WETH_ADDRESS;\\n\\n mapping(address => address) public swapMap;\\n mapping(address => IERC20[]) public swapTokensMap;\\n\\n uint256 constant MAX_UINT256 = 2**256 - 1;\\n\\n constructor(\\n address payable _wethAddress,\\n address _swapOne,\\n address tokenOne,\\n address _swapTwo,\\n address tokenTwo,\\n ISynapseBridge _synapseBridge\\n ) public {\\n WETH_ADDRESS = _wethAddress;\\n synapseBridge = _synapseBridge;\\n swapMap[tokenOne] = _swapOne;\\n swapMap[tokenTwo] = _swapTwo;\\n\\n if (address(_swapOne) != address(0)) {\\n {\\n uint8 i;\\n for (; i < 32; i++) {\\n try ISwap(_swapOne).getToken(i) returns (\\n IERC20 token\\n ) {\\n swapTokensMap[_swapOne].push(token);\\n token.safeApprove(address(_swapOne), MAX_UINT256);\\n token.safeApprove(address(synapseBridge), MAX_UINT256);\\n } catch {\\n break;\\n }\\n }\\n require(i > 1, \\\"swap must have at least 2 tokens\\\");\\n }\\n }\\n if (address(_swapTwo) != address(0)) {\\n {\\n uint8 i;\\n for (; i < 32; i++) {\\n try ISwap(_swapTwo).getToken(i) returns (\\n IERC20 token\\n ) {\\n swapTokensMap[_swapTwo].push(token);\\n token.safeApprove(address(_swapTwo), MAX_UINT256);\\n token.safeApprove(address(synapseBridge), MAX_UINT256);\\n } catch {\\n break;\\n }\\n }\\n require(i > 1, \\\"swap must have at least 2 tokens\\\");\\n }\\n }\\n }\\n\\n /**\\n * @notice Calculate amount of tokens you receive on swap\\n * @param tokenIndexFrom the token the user wants to sell\\n * @param tokenIndexTo the token the user wants to buy\\n * @param dx the amount of tokens the user wants to sell. If the token charges\\n * a fee on transfers, use the amount that gets transferred after the fee.\\n * @return amount of tokens the user will receive\\n */\\n function calculateSwap(\\n IERC20 token,\\n uint8 tokenIndexFrom,\\n uint8 tokenIndexTo,\\n uint256 dx\\n ) external view virtual returns (uint256) {\\n ISwap swap = ISwap(\\n swapMap[address(token)]\\n );\\n return swap.calculateSwap(tokenIndexFrom, tokenIndexTo, dx);\\n }\\n\\n function swapAndRedeem(\\n address to,\\n uint256 chainId,\\n IERC20 token,\\n uint8 tokenIndexFrom,\\n uint8 tokenIndexTo,\\n uint256 dx,\\n uint256 minDy,\\n uint256 deadline\\n ) external {\\n ISwap swap = ISwap(swapMap[address(token)]);\\n require(address(swap) != address(0), \\\"Swap is 0x00\\\");\\n IERC20[] memory tokens = swapTokensMap[address(swap)];\\n tokens[tokenIndexFrom].safeTransferFrom(\\n msg.sender,\\n address(this),\\n dx\\n );\\n // swap\\n\\n uint256 swappedAmount = swap.swap(\\n tokenIndexFrom,\\n tokenIndexTo,\\n dx,\\n minDy,\\n deadline\\n );\\n // deposit into bridge, gets nUSD\\n if (\\n token.allowance(address(this), address(synapseBridge)) <\\n swappedAmount\\n ) {\\n token.safeApprove(address(synapseBridge), MAX_UINT256);\\n }\\n synapseBridge.redeem(to, chainId, token, swappedAmount);\\n }\\n\\n function swapAndRedeemAndSwap(\\n address to,\\n uint256 chainId,\\n IERC20 token,\\n uint8 tokenIndexFrom,\\n uint8 tokenIndexTo,\\n uint256 dx,\\n uint256 minDy,\\n uint256 deadline,\\n uint8 swapTokenIndexFrom,\\n uint8 swapTokenIndexTo,\\n uint256 swapMinDy,\\n uint256 swapDeadline\\n ) external {\\n require(\\n address(swapMap[address(token)]) != address(0),\\n \\\"Swap is 0x00\\\"\\n );\\n IERC20[] memory tokens = swapTokensMap[\\n swapMap[address(token)]\\n ];\\n tokens[tokenIndexFrom].safeTransferFrom(\\n msg.sender,\\n address(this),\\n dx\\n );\\n // swap\\n\\n uint256 swappedAmount = ISwap(swapMap[address(token)]).swap(tokenIndexFrom, tokenIndexTo, dx, minDy, deadline);\\n // deposit into bridge, gets nUSD\\n if (\\n token.allowance(address(this), address(synapseBridge)) <\\n swappedAmount\\n ) {\\n token.safeApprove(address(synapseBridge), MAX_UINT256);\\n }\\n synapseBridge.redeemAndSwap(\\n to,\\n chainId,\\n token,\\n swappedAmount,\\n swapTokenIndexFrom,\\n swapTokenIndexTo,\\n swapMinDy,\\n swapDeadline\\n );\\n }\\n\\n function swapAndRedeemAndRemove(\\n address to,\\n uint256 chainId,\\n IERC20 token,\\n uint8 tokenIndexFrom,\\n uint8 tokenIndexTo,\\n uint256 dx,\\n uint256 minDy,\\n uint256 deadline,\\n uint8 liqTokenIndex,\\n uint256 liqMinAmount,\\n uint256 liqDeadline\\n ) external {\\n ISwap swap = ISwap(swapMap[address(token)]);\\n require(address(swap) != address(0), \\\"Swap is 0x00\\\");\\n IERC20[] memory tokens = swapTokensMap[address(swap)];\\n tokens[tokenIndexFrom].safeTransferFrom(\\n msg.sender,\\n address(this),\\n dx\\n );\\n // swap\\n\\n uint256 swappedAmount = swap.swap(\\n tokenIndexFrom,\\n tokenIndexTo,\\n dx,\\n minDy,\\n deadline\\n );\\n // deposit into bridge, gets nUSD\\n if (\\n token.allowance(address(this), address(synapseBridge)) <\\n swappedAmount\\n ) {\\n token.safeApprove(address(synapseBridge), MAX_UINT256);\\n }\\n synapseBridge.redeemAndRemove(\\n to,\\n chainId,\\n token,\\n swappedAmount,\\n liqTokenIndex,\\n liqMinAmount,\\n liqDeadline\\n );\\n }\\n\\n /**\\n * @notice wraps SynapseBridge redeem()\\n * @param to address on other chain to redeem underlying assets to\\n * @param chainId which underlying chain to bridge assets onto\\n * @param token ERC20 compatible token to deposit into the bridge\\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\\n **/\\n function redeem(\\n address to,\\n uint256 chainId,\\n IERC20 token,\\n uint256 amount\\n ) external {\\n token.safeTransferFrom(msg.sender, address(this), amount);\\n if (token.allowance(address(this), address(synapseBridge)) < amount) {\\n token.safeApprove(address(synapseBridge), MAX_UINT256);\\n }\\n synapseBridge.redeem(to, chainId, token, amount);\\n }\\n\\n /**\\n * @notice wraps SynapseBridge redeem()\\n * @param to address on other chain to redeem underlying assets to\\n * @param chainId which underlying chain to bridge assets onto\\n * @param token ERC20 compatible token to deposit into the bridge\\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\\n **/\\n function deposit(\\n address to,\\n uint256 chainId,\\n IERC20 token,\\n uint256 amount\\n ) external {\\n token.safeTransferFrom(msg.sender, address(this), amount);\\n if (token.allowance(address(this), address(synapseBridge)) < amount) {\\n token.safeApprove(address(synapseBridge), MAX_UINT256);\\n }\\n synapseBridge.deposit(to, chainId, token, amount);\\n }\\n\\n function swapETHAndRedeem(\\n address to,\\n uint256 chainId,\\n IERC20 token,\\n uint8 tokenIndexFrom,\\n uint8 tokenIndexTo,\\n uint256 dx,\\n uint256 minDy,\\n uint256 deadline\\n ) external payable {\\n require(WETH_ADDRESS != address(0), \\\"WETH 0\\\");\\n require(msg.value > 0 && msg.value == dx, \\\"INCORRECT MSG VALUE\\\");\\n ISwap swap = ISwap(swapMap[address(token)]);\\n require(address(swap) != address(0), \\\"Swap is 0x00\\\");\\n IWETH9(WETH_ADDRESS).deposit{value: msg.value}();\\n\\n // swap\\n uint256 swappedAmount = swap.swap(\\n tokenIndexFrom,\\n tokenIndexTo,\\n dx,\\n minDy,\\n deadline\\n );\\n synapseBridge.redeem(to, chainId, token, swappedAmount);\\n }\\n\\n\\n function swapETHAndRedeemAndSwap(\\n address to,\\n uint256 chainId,\\n IERC20 token,\\n uint8 tokenIndexFrom,\\n uint8 tokenIndexTo,\\n uint256 dx,\\n uint256 minDy,\\n uint256 deadline,\\n uint8 swapTokenIndexFrom,\\n uint8 swapTokenIndexTo,\\n uint256 swapMinDy,\\n uint256 swapDeadline\\n ) external payable {\\n require(WETH_ADDRESS != address(0), \\\"WETH 0\\\");\\n require(msg.value > 0 && msg.value == dx, \\\"INCORRECT MSG VALUE\\\");\\n ISwap swap = ISwap(swapMap[address(token)]);\\n require(address(swap) != address(0), \\\"Swap is 0x00\\\");\\n IWETH9(WETH_ADDRESS).deposit{value: msg.value}();\\n\\n // swap\\n uint256 swappedAmount = swap.swap(\\n tokenIndexFrom,\\n tokenIndexTo,\\n dx,\\n minDy,\\n deadline\\n );\\n synapseBridge.redeemAndSwap(to, chainId, token, swappedAmount,swapTokenIndexFrom,\\n swapTokenIndexTo,\\n swapMinDy,\\n swapDeadline);\\n }\\n\\n\\n /**\\n * @notice Wraps redeemAndSwap on SynapseBridge.sol\\n * Relays to nodes that (typically) a wrapped synAsset ERC20 token has been burned and the underlying needs to be redeeemed on the native chain. This function indicates to the nodes that they should attempt to redeem the LP token for the underlying assets (E.g \\\"swap\\\" out of the LP token)\\n * @param to address on other chain to redeem underlying assets to\\n * @param chainId which underlying chain to bridge assets onto\\n * @param token ERC20 compatible token to deposit into the bridge\\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\\n * @param tokenIndexFrom the token the user wants to swap from\\n * @param tokenIndexTo the token the user wants to swap to\\n * @param minDy the min amount the user would like to receive, or revert to only minting the SynERC20 token crosschain.\\n * @param deadline latest timestamp to accept this transaction\\n **/\\n function redeemAndSwap(\\n address to,\\n uint256 chainId,\\n IERC20 token,\\n uint256 amount,\\n uint8 tokenIndexFrom,\\n uint8 tokenIndexTo,\\n uint256 minDy,\\n uint256 deadline\\n ) external {\\n token.safeTransferFrom(msg.sender, address(this), amount);\\n if (token.allowance(address(this), address(synapseBridge)) < amount) {\\n token.safeApprove(address(synapseBridge), MAX_UINT256);\\n }\\n synapseBridge.redeemAndSwap(\\n to,\\n chainId,\\n token,\\n amount,\\n tokenIndexFrom,\\n tokenIndexTo,\\n minDy,\\n deadline\\n );\\n }\\n\\n /**\\n * @notice Wraps redeemAndRemove on SynapseBridge\\n * Relays to nodes that (typically) a wrapped synAsset ERC20 token has been burned and the underlying needs to be redeeemed on the native chain. This function indicates to the nodes that they should attempt to redeem the LP token for the underlying assets (E.g \\\"swap\\\" out of the LP token)\\n * @param to address on other chain to redeem underlying assets to\\n * @param chainId which underlying chain to bridge assets onto\\n * @param token ERC20 compatible token to deposit into the bridge\\n * @param amount Amount of (typically) LP token to pass to the nodes to attempt to removeLiquidity() with to redeem for the underlying assets of the LP token\\n * @param liqTokenIndex Specifies which of the underlying LP assets the nodes should attempt to redeem for\\n * @param liqMinAmount Specifies the minimum amount of the underlying asset needed for the nodes to execute the redeem/swap\\n * @param liqDeadline Specificies the deadline that the nodes are allowed to try to redeem/swap the LP token\\n **/\\n function redeemAndRemove(\\n address to,\\n uint256 chainId,\\n IERC20 token,\\n uint256 amount,\\n uint8 liqTokenIndex,\\n uint256 liqMinAmount,\\n uint256 liqDeadline\\n ) external {\\n token.safeTransferFrom(msg.sender, address(this), amount);\\n if (token.allowance(address(this), address(synapseBridge)) < amount) {\\n token.safeApprove(address(synapseBridge), MAX_UINT256);\\n }\\n synapseBridge.redeemAndRemove(\\n to,\\n chainId,\\n token,\\n amount,\\n liqTokenIndex,\\n liqMinAmount,\\n liqDeadline\\n );\\n }\\n}\\n\",\"keccak256\":\"0x043e92ba8b68f2c38096e8869ac7bf55e8ba0cfbe8b4dafbddcbe406e0cc9c8b\",\"license\":\"MIT\"}},\"version\":1}", - "bytecode": "0x60a06040523480156200001157600080fd5b5060405162002a1938038062002a19833981810160405260c08110156200003757600080fd5b50805160208083015160408085015160608087015160808089015160a0909901519288901b6001600160601b0319169052600080546001600160a01b03199081166001600160a01b038086169190911783558086168352600190985285822080548216898916908117909155888b168352959091208054909116968216969096179095559495929490939291156200022d5760005b60208160ff161015620001e357856001600160a01b03166382b86600826040518263ffffffff1660e01b8152600401808260ff16815260200191505060206040518083038186803b1580156200012157600080fd5b505afa9250505080156200014857506040513d60208110156200014357600080fd5b505160015b6200015357620001e3565b6001600160a01b038781166000908152600260209081526040822080546001810182559083529181902090910180546001600160a01b0319169284169283179055620001af9190899060001990620003ad811b62001bea17901c565b600054620001d9906001600160a01b038381169116600019620003ad602090811b62001bea17901c565b50600101620000cc565b60018160ff16116200022b576040805162461bcd60e51b8152602060048201819052602482015260008051602062002999833981519152604482015290519081900360640190fd5b505b6001600160a01b03831615620003a15760005b60208160ff1610156200035757836001600160a01b03166382b86600826040518263ffffffff1660e01b8152600401808260ff16815260200191505060206040518083038186803b1580156200029557600080fd5b505afa925050508015620002bc57506040513d6020811015620002b757600080fd5b505160015b620002c75762000357565b6001600160a01b038581166000908152600260209081526040822080546001810182559083529181902090910180546001600160a01b0319169284169283179055620003239190879060001990620003ad811b62001bea17901c565b6000546200034d906001600160a01b038381169116600019620003ad602090811b62001bea17901c565b5060010162000240565b60018160ff16116200039f576040805162461bcd60e51b8152602060048201819052602482015260008051602062002999833981519152604482015290519081900360640190fd5b505b505050505050620007c0565b80158062000437575060408051636eb1769f60e11b81523060048201526001600160a01b03848116602483015291519185169163dd62ed3e91604480820192602092909190829003018186803b1580156200040757600080fd5b505afa1580156200041c573d6000803e3d6000fd5b505050506040513d60208110156200043357600080fd5b5051155b620004745760405162461bcd60e51b8152600401808060200182810382526036815260200180620029e36036913960400191505060405180910390fd5b604080516001600160a01b038416602482015260448082018490528251808303909101815260649091019091526020810180516001600160e01b0390811663095ea7b360e01b17909152620004cc918591620004d116565b505050565b60606200052d826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b03166200058d60201b62001d49179092919060201c565b805190915015620004cc578080602001905160208110156200054e57600080fd5b5051620004cc5760405162461bcd60e51b815260040180806020018281038252602a815260200180620029b9602a913960400191505060405180910390fd5b60606200059e8484600085620005a8565b90505b9392505050565b606082471015620005eb5760405162461bcd60e51b8152600401808060200182810382526026815260200180620029736026913960400191505060405180910390fd5b620005f68562000710565b62000648576040805162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000604482015290519081900360640190fd5b60006060866001600160a01b031685876040518082805190602001908083835b60208310620006895780518252601f19909201916020918201910162000668565b6001836020036101000a03801982511681845116808217855250505050505090500191505060006040518083038185875af1925050503d8060008114620006ed576040519150601f19603f3d011682016040523d82523d6000602084013e620006f2565b606091505b5090925090506200070582828662000716565b979650505050505050565b3b151590565b6060831562000727575081620005a1565b825115620007385782518084602001fd5b8160405162461bcd60e51b81526004018080602001828103825283818151815260200191508051906020019080838360005b83811015620007845781810151838201526020016200076a565b50505050905090810190601f168015620007b25780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b60805160601c612181620007f2600039806105635280610a865280610bce528061109752806111df52506121816000f3fe6080604052600436106100d25760003560e01c806365749c9d1161007f57806385528f0b1161005957806385528f0b1461041b57806390d250741461044e5780639f33072714610495578063f3f094a11461051a576100d2565b806365749c9d146102fc578063798af72014610356578063839ed90a146103b4576100d2565b8063393494b8116100b0578063393494b8146101e45780633d5da1641461021d5780634a517a5514610295576100d2565b8063040141e5146100d7578063174dc9521461010857806336e712ed14610188575b600080fd5b3480156100e357600080fd5b506100ec610561565b604080516001600160a01b039092168252519081900360200190f35b34801561011457600080fd5b50610186600480360361016081101561012c57600080fd5b506001600160a01b0381358116916020810135916040820135169060ff6060820135811691608081013582169160a08201359160c08101359160e08201359161010081013590911690610120810135906101400135610585565b005b34801561019457600080fd5b50610186600480360360e08110156101ab57600080fd5b506001600160a01b0381358116916020810135916040820135169060608101359060ff6080820135169060a08101359060c001356108ce565b3480156101f057600080fd5b506100ec6004803603604081101561020757600080fd5b506001600160a01b038135169060200135610a4f565b610186600480360361018081101561023457600080fd5b506001600160a01b0381358116916020810135916040820135169060ff6060820135811691608081013582169160a08201359160c08101359160e0820135916101008101358216916101208201351690610140810135906101600135610a84565b3480156102a157600080fd5b5061018660048036036101008110156102b957600080fd5b506001600160a01b0381358116916020810135916040820135169060ff606082013581169160808101359091169060a08101359060c08101359060e00135610d94565b610186600480360361010081101561031357600080fd5b506001600160a01b0381358116916020810135916040820135169060ff606082013581169160808101359091169060a08101359060c08101359060e00135611095565b34801561036257600080fd5b506103a26004803603608081101561037957600080fd5b506001600160a01b038135169060ff6020820135811691604081013590911690606001356113a1565b60408051918252519081900360200190f35b3480156103c057600080fd5b5061018660048036036101008110156103d857600080fd5b506001600160a01b0381358116916020810135916040820135169060608101359060ff608082013581169160a08101359091169060c08101359060e0013561145a565b34801561042757600080fd5b506100ec6004803603602081101561043e57600080fd5b50356001600160a01b03166115e5565b34801561045a57600080fd5b506101866004803603608081101561047157600080fd5b506001600160a01b0381358116916020810135916040820135169060600135611600565b3480156104a157600080fd5b5061018660048036036101808110156104b957600080fd5b506001600160a01b0381358116916020810135916040820135169060ff6060820135811691608081013582169160a08201359160c08101359160e0820135916101008101358216916101208201351690610140810135906101600135611767565b34801561052657600080fd5b506101866004803603608081101561053d57600080fd5b506001600160a01b0381358116916020810135916040820135169060600135611aa1565b7f000000000000000000000000000000000000000000000000000000000000000081565b6001600160a01b03808a1660009081526001602052604090205416806105f2576040805162461bcd60e51b815260206004820152600c60248201527f5377617020697320307830300000000000000000000000000000000000000000604482015290519081900360640190fd5b6001600160a01b03811660009081526002602090815260409182902080548351818402810184019094528084526060939283018282801561065c57602002820191906000526020600020905b81546001600160a01b0316815260019091019060200180831161063e575b5050505050905061069933308a848e60ff168151811061067857fe5b60200260200101516001600160a01b0316611d62909392919063ffffffff16565b604080517f9169558600000000000000000000000000000000000000000000000000000000815260ff808d1660048301528b166024820152604481018a9052606481018990526084810188905290516000916001600160a01b0385169163916955869160a48082019260209290919082900301818787803b15801561071d57600080fd5b505af1158015610731573d6000803e3d6000fd5b505050506040513d602081101561074757600080fd5b5051600054604080517fdd62ed3e0000000000000000000000000000000000000000000000000000000081523060048201526001600160a01b03928316602482015290519293508392918f169163dd62ed3e91604480820192602092909190829003018186803b1580156107ba57600080fd5b505afa1580156107ce573d6000803e3d6000fd5b505050506040513d60208110156107e457600080fd5b5051101561080857600054610808906001600160a01b038e81169116600019611bea565b60008054906101000a90046001600160a01b03166001600160a01b03166336e712ed8f8f8f858b8b8b6040518863ffffffff1660e01b815260040180886001600160a01b03168152602001878152602001866001600160a01b031681526020018581526020018460ff168152602001838152602001828152602001975050505050505050600060405180830381600087803b1580156108a657600080fd5b505af11580156108ba573d6000803e3d6000fd5b505050505050505050505050505050505050565b6108e36001600160a01b038616333087611d62565b600054604080517fdd62ed3e0000000000000000000000000000000000000000000000000000000081523060048201526001600160a01b0392831660248201529051869288169163dd62ed3e916044808301926020929190829003018186803b15801561094f57600080fd5b505afa158015610963573d6000803e3d6000fd5b505050506040513d602081101561097957600080fd5b5051101561099d5760005461099d906001600160a01b038781169116600019611bea565b60008054604080517f36e712ed0000000000000000000000000000000000000000000000000000000081526001600160a01b038b81166004830152602482018b905289811660448301526064820189905260ff8816608483015260a4820187905260c48201869052915191909216926336e712ed9260e4808201939182900301818387803b158015610a2e57600080fd5b505af1158015610a42573d6000803e3d6000fd5b5050505050505050505050565b60026020528160005260406000208181548110610a6857fe5b6000918252602090912001546001600160a01b03169150829050565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316610aff576040805162461bcd60e51b815260206004820152600660248201527f5745544820300000000000000000000000000000000000000000000000000000604482015290519081900360640190fd5b600034118015610b0e57508634145b610b5f576040805162461bcd60e51b815260206004820152601360248201527f494e434f5252454354204d53472056414c554500000000000000000000000000604482015290519081900360640190fd5b6001600160a01b03808b166000908152600160205260409020541680610bcc576040805162461bcd60e51b815260206004820152600c60248201527f5377617020697320307830300000000000000000000000000000000000000000604482015290519081900360640190fd5b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663d0e30db0346040518263ffffffff1660e01b81526004016000604051808303818588803b158015610c2757600080fd5b505af1158015610c3b573d6000803e3d6000fd5b50505050506000816001600160a01b031663916955868c8c8c8c8c6040518663ffffffff1660e01b8152600401808660ff1681526020018560ff16815260200184815260200183815260200182815260200195505050505050602060405180830381600087803b158015610cae57600080fd5b505af1158015610cc2573d6000803e3d6000fd5b505050506040513d6020811015610cd857600080fd5b8101908080519060200190929190505050905060008054906101000a90046001600160a01b03166001600160a01b031663839ed90a8f8f8f858b8b8b8b6040518963ffffffff1660e01b815260040180896001600160a01b03168152602001888152602001876001600160a01b031681526020018681526020018560ff1681526020018460ff16815260200183815260200182815260200198505050505050505050600060405180830381600087803b1580156108a657600080fd5b6001600160a01b038087166000908152600160205260409020541680610e01576040805162461bcd60e51b815260206004820152600c60248201527f5377617020697320307830300000000000000000000000000000000000000000604482015290519081900360640190fd5b6001600160a01b038116600090815260026020908152604091829020805483518184028101840190945280845260609392830182828015610e6b57602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311610e4d575b50505050509050610e87333087848b60ff168151811061067857fe5b604080517f9169558600000000000000000000000000000000000000000000000000000000815260ff808a1660048301528816602482015260448101879052606481018690526084810185905290516000916001600160a01b0385169163916955869160a48082019260209290919082900301818787803b158015610f0b57600080fd5b505af1158015610f1f573d6000803e3d6000fd5b505050506040513d6020811015610f3557600080fd5b5051600054604080517fdd62ed3e0000000000000000000000000000000000000000000000000000000081523060048201526001600160a01b03928316602482015290519293508392918c169163dd62ed3e91604480820192602092909190829003018186803b158015610fa857600080fd5b505afa158015610fbc573d6000803e3d6000fd5b505050506040513d6020811015610fd257600080fd5b50511015610ff657600054610ff6906001600160a01b038b81169116600019611bea565b60008054604080517ff3f094a10000000000000000000000000000000000000000000000000000000081526001600160a01b038f81166004830152602482018f90528d81166044830152606482018690529151919092169263f3f094a1926084808201939182900301818387803b15801561107057600080fd5b505af1158015611084573d6000803e3d6000fd5b505050505050505050505050505050565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316611110576040805162461bcd60e51b815260206004820152600660248201527f5745544820300000000000000000000000000000000000000000000000000000604482015290519081900360640190fd5b60003411801561111f57508234145b611170576040805162461bcd60e51b815260206004820152601360248201527f494e434f5252454354204d53472056414c554500000000000000000000000000604482015290519081900360640190fd5b6001600160a01b0380871660009081526001602052604090205416806111dd576040805162461bcd60e51b815260206004820152600c60248201527f5377617020697320307830300000000000000000000000000000000000000000604482015290519081900360640190fd5b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663d0e30db0346040518263ffffffff1660e01b81526004016000604051808303818588803b15801561123857600080fd5b505af115801561124c573d6000803e3d6000fd5b5050604080517f9169558600000000000000000000000000000000000000000000000000000000815260ff808c1660048301528a1660248201526044810189905260648101889052608481018790529051600094506001600160a01b03861693506391695586925060a480830192602092919082900301818787803b1580156112d457600080fd5b505af11580156112e8573d6000803e3d6000fd5b505050506040513d60208110156112fe57600080fd5b505160008054604080517ff3f094a10000000000000000000000000000000000000000000000000000000081526001600160a01b038f81166004830152602482018f90528d8116604483015260648201869052915194955091169263f3f094a19260848084019391929182900301818387803b15801561137d57600080fd5b505af1158015611391573d6000803e3d6000fd5b5050505050505050505050505050565b6001600160a01b0380851660009081526001602090815260408083205481517fa95b089f00000000000000000000000000000000000000000000000000000000815260ff808a1660048301528816602482015260448101879052915193941692839263a95b089f9260648082019391829003018186803b15801561142457600080fd5b505afa158015611438573d6000803e3d6000fd5b505050506040513d602081101561144e57600080fd5b50519695505050505050565b61146f6001600160a01b038716333088611d62565b600054604080517fdd62ed3e0000000000000000000000000000000000000000000000000000000081523060048201526001600160a01b0392831660248201529051879289169163dd62ed3e916044808301926020929190829003018186803b1580156114db57600080fd5b505afa1580156114ef573d6000803e3d6000fd5b505050506040513d602081101561150557600080fd5b5051101561152957600054611529906001600160a01b038881169116600019611bea565b60008054604080517f839ed90a0000000000000000000000000000000000000000000000000000000081526001600160a01b038c81166004830152602482018c90528a81166044830152606482018a905260ff808a166084840152881660a483015260c4820187905260e482018690529151919092169263839ed90a92610104808201939182900301818387803b1580156115c357600080fd5b505af11580156115d7573d6000803e3d6000fd5b505050505050505050505050565b6001602052600090815260409020546001600160a01b031681565b6116156001600160a01b038316333084611d62565b600054604080517fdd62ed3e0000000000000000000000000000000000000000000000000000000081523060048201526001600160a01b0392831660248201529051839285169163dd62ed3e916044808301926020929190829003018186803b15801561168157600080fd5b505afa158015611695573d6000803e3d6000fd5b505050506040513d60208110156116ab57600080fd5b505110156116cf576000546116cf906001600160a01b038481169116600019611bea565b60008054604080517f90d250740000000000000000000000000000000000000000000000000000000081526001600160a01b03888116600483015260248201889052868116604483015260648201869052915191909216926390d25074926084808201939182900301818387803b15801561174957600080fd5b505af115801561175d573d6000803e3d6000fd5b5050505050505050565b6001600160a01b038a8116600090815260016020526040902054166117d3576040805162461bcd60e51b815260206004820152600c60248201527f5377617020697320307830300000000000000000000000000000000000000000604482015290519081900360640190fd5b6001600160a01b03808b166000908152600160209081526040808320549093168252600281529082902080548351818402810184019094528084526060939283018282801561184b57602002820191906000526020600020905b81546001600160a01b0316815260019091019060200180831161182d575b5050505050905061186733308a848e60ff168151811061067857fe5b6000600160008d6001600160a01b03166001600160a01b0316815260200190815260200160002060009054906101000a90046001600160a01b03166001600160a01b031663916955868c8c8c8c8c6040518663ffffffff1660e01b8152600401808660ff1681526020018560ff16815260200184815260200183815260200182815260200195505050505050602060405180830381600087803b15801561190d57600080fd5b505af1158015611921573d6000803e3d6000fd5b505050506040513d602081101561193757600080fd5b5051600054604080517fdd62ed3e0000000000000000000000000000000000000000000000000000000081523060048201526001600160a01b03928316602482015290519293508392918f169163dd62ed3e91604480820192602092909190829003018186803b1580156119aa57600080fd5b505afa1580156119be573d6000803e3d6000fd5b505050506040513d60208110156119d457600080fd5b505110156119f8576000546119f8906001600160a01b038e81169116600019611bea565b60008054906101000a90046001600160a01b03166001600160a01b031663839ed90a8f8f8f858b8b8b8b6040518963ffffffff1660e01b815260040180896001600160a01b03168152602001888152602001876001600160a01b031681526020018681526020018560ff1681526020018460ff16815260200183815260200182815260200198505050505050505050600060405180830381600087803b1580156108a657600080fd5b611ab66001600160a01b038316333084611d62565b600054604080517fdd62ed3e0000000000000000000000000000000000000000000000000000000081523060048201526001600160a01b0392831660248201529051839285169163dd62ed3e916044808301926020929190829003018186803b158015611b2257600080fd5b505afa158015611b36573d6000803e3d6000fd5b505050506040513d6020811015611b4c57600080fd5b50511015611b7057600054611b70906001600160a01b038481169116600019611bea565b60008054604080517ff3f094a10000000000000000000000000000000000000000000000000000000081526001600160a01b038881166004830152602482018890528681166044830152606482018690529151919092169263f3f094a1926084808201939182900301818387803b15801561174957600080fd5b801580611c895750604080517fdd62ed3e0000000000000000000000000000000000000000000000000000000081523060048201526001600160a01b03848116602483015291519185169163dd62ed3e91604480820192602092909190829003018186803b158015611c5b57600080fd5b505afa158015611c6f573d6000803e3d6000fd5b505050506040513d6020811015611c8557600080fd5b5051155b611cc45760405162461bcd60e51b81526004018080602001828103825260368152602001806121166036913960400191505060405180910390fd5b604080516001600160a01b038416602482015260448082018490528251808303909101815260649091019091526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f095ea7b300000000000000000000000000000000000000000000000000000000179052611d44908490611df0565b505050565b6060611d588484600085611ea1565b90505b9392505050565b604080516001600160a01b0380861660248301528416604482015260648082018490528251808303909101815260849091019091526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f23b872dd00000000000000000000000000000000000000000000000000000000179052611dea908590611df0565b50505050565b6060611e45826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b0316611d499092919063ffffffff16565b805190915015611d4457808060200190516020811015611e6457600080fd5b5051611d445760405162461bcd60e51b815260040180806020018281038252602a8152602001806120ec602a913960400191505060405180910390fd5b606082471015611ee25760405162461bcd60e51b81526004018080602001828103825260268152602001806120c66026913960400191505060405180910390fd5b611eeb8561201b565b611f3c576040805162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000604482015290519081900360640190fd5b60006060866001600160a01b031685876040518082805190602001908083835b60208310611f9957805182527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe09092019160209182019101611f5c565b6001836020036101000a03801982511681845116808217855250505050505090500191505060006040518083038185875af1925050503d8060008114611ffb576040519150601f19603f3d011682016040523d82523d6000602084013e612000565b606091505b5091509150612010828286612021565b979650505050505050565b3b151590565b60608315612030575081611d5b565b8251156120405782518084602001fd5b8160405162461bcd60e51b81526004018080602001828103825283818151815260200191508051906020019080838360005b8381101561208a578181015183820152602001612072565b50505050905090810190601f1680156120b75780820380516001836020036101000a031916815260200191505b509250505060405180910390fdfe416464726573733a20696e73756666696369656e742062616c616e636520666f722063616c6c5361666545524332303a204552433230206f7065726174696f6e20646964206e6f7420737563636565645361666545524332303a20617070726f76652066726f6d206e6f6e2d7a65726f20746f206e6f6e2d7a65726f20616c6c6f77616e6365a264697066735822122066588cb14596d85644754cda29c9287e7e73593ce3e2c72a10ec98f4c1a2eb4164736f6c634300060c0033416464726573733a20696e73756666696369656e742062616c616e636520666f722063616c6c73776170206d7573742068617665206174206c65617374203220746f6b656e735361666545524332303a204552433230206f7065726174696f6e20646964206e6f7420737563636565645361666545524332303a20617070726f76652066726f6d206e6f6e2d7a65726f20746f206e6f6e2d7a65726f20616c6c6f77616e6365", - "deployedBytecode": "0x6080604052600436106100d25760003560e01c806365749c9d1161007f57806385528f0b1161005957806385528f0b1461041b57806390d250741461044e5780639f33072714610495578063f3f094a11461051a576100d2565b806365749c9d146102fc578063798af72014610356578063839ed90a146103b4576100d2565b8063393494b8116100b0578063393494b8146101e45780633d5da1641461021d5780634a517a5514610295576100d2565b8063040141e5146100d7578063174dc9521461010857806336e712ed14610188575b600080fd5b3480156100e357600080fd5b506100ec610561565b604080516001600160a01b039092168252519081900360200190f35b34801561011457600080fd5b50610186600480360361016081101561012c57600080fd5b506001600160a01b0381358116916020810135916040820135169060ff6060820135811691608081013582169160a08201359160c08101359160e08201359161010081013590911690610120810135906101400135610585565b005b34801561019457600080fd5b50610186600480360360e08110156101ab57600080fd5b506001600160a01b0381358116916020810135916040820135169060608101359060ff6080820135169060a08101359060c001356108ce565b3480156101f057600080fd5b506100ec6004803603604081101561020757600080fd5b506001600160a01b038135169060200135610a4f565b610186600480360361018081101561023457600080fd5b506001600160a01b0381358116916020810135916040820135169060ff6060820135811691608081013582169160a08201359160c08101359160e0820135916101008101358216916101208201351690610140810135906101600135610a84565b3480156102a157600080fd5b5061018660048036036101008110156102b957600080fd5b506001600160a01b0381358116916020810135916040820135169060ff606082013581169160808101359091169060a08101359060c08101359060e00135610d94565b610186600480360361010081101561031357600080fd5b506001600160a01b0381358116916020810135916040820135169060ff606082013581169160808101359091169060a08101359060c08101359060e00135611095565b34801561036257600080fd5b506103a26004803603608081101561037957600080fd5b506001600160a01b038135169060ff6020820135811691604081013590911690606001356113a1565b60408051918252519081900360200190f35b3480156103c057600080fd5b5061018660048036036101008110156103d857600080fd5b506001600160a01b0381358116916020810135916040820135169060608101359060ff608082013581169160a08101359091169060c08101359060e0013561145a565b34801561042757600080fd5b506100ec6004803603602081101561043e57600080fd5b50356001600160a01b03166115e5565b34801561045a57600080fd5b506101866004803603608081101561047157600080fd5b506001600160a01b0381358116916020810135916040820135169060600135611600565b3480156104a157600080fd5b5061018660048036036101808110156104b957600080fd5b506001600160a01b0381358116916020810135916040820135169060ff6060820135811691608081013582169160a08201359160c08101359160e0820135916101008101358216916101208201351690610140810135906101600135611767565b34801561052657600080fd5b506101866004803603608081101561053d57600080fd5b506001600160a01b0381358116916020810135916040820135169060600135611aa1565b7f000000000000000000000000000000000000000000000000000000000000000081565b6001600160a01b03808a1660009081526001602052604090205416806105f2576040805162461bcd60e51b815260206004820152600c60248201527f5377617020697320307830300000000000000000000000000000000000000000604482015290519081900360640190fd5b6001600160a01b03811660009081526002602090815260409182902080548351818402810184019094528084526060939283018282801561065c57602002820191906000526020600020905b81546001600160a01b0316815260019091019060200180831161063e575b5050505050905061069933308a848e60ff168151811061067857fe5b60200260200101516001600160a01b0316611d62909392919063ffffffff16565b604080517f9169558600000000000000000000000000000000000000000000000000000000815260ff808d1660048301528b166024820152604481018a9052606481018990526084810188905290516000916001600160a01b0385169163916955869160a48082019260209290919082900301818787803b15801561071d57600080fd5b505af1158015610731573d6000803e3d6000fd5b505050506040513d602081101561074757600080fd5b5051600054604080517fdd62ed3e0000000000000000000000000000000000000000000000000000000081523060048201526001600160a01b03928316602482015290519293508392918f169163dd62ed3e91604480820192602092909190829003018186803b1580156107ba57600080fd5b505afa1580156107ce573d6000803e3d6000fd5b505050506040513d60208110156107e457600080fd5b5051101561080857600054610808906001600160a01b038e81169116600019611bea565b60008054906101000a90046001600160a01b03166001600160a01b03166336e712ed8f8f8f858b8b8b6040518863ffffffff1660e01b815260040180886001600160a01b03168152602001878152602001866001600160a01b031681526020018581526020018460ff168152602001838152602001828152602001975050505050505050600060405180830381600087803b1580156108a657600080fd5b505af11580156108ba573d6000803e3d6000fd5b505050505050505050505050505050505050565b6108e36001600160a01b038616333087611d62565b600054604080517fdd62ed3e0000000000000000000000000000000000000000000000000000000081523060048201526001600160a01b0392831660248201529051869288169163dd62ed3e916044808301926020929190829003018186803b15801561094f57600080fd5b505afa158015610963573d6000803e3d6000fd5b505050506040513d602081101561097957600080fd5b5051101561099d5760005461099d906001600160a01b038781169116600019611bea565b60008054604080517f36e712ed0000000000000000000000000000000000000000000000000000000081526001600160a01b038b81166004830152602482018b905289811660448301526064820189905260ff8816608483015260a4820187905260c48201869052915191909216926336e712ed9260e4808201939182900301818387803b158015610a2e57600080fd5b505af1158015610a42573d6000803e3d6000fd5b5050505050505050505050565b60026020528160005260406000208181548110610a6857fe5b6000918252602090912001546001600160a01b03169150829050565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316610aff576040805162461bcd60e51b815260206004820152600660248201527f5745544820300000000000000000000000000000000000000000000000000000604482015290519081900360640190fd5b600034118015610b0e57508634145b610b5f576040805162461bcd60e51b815260206004820152601360248201527f494e434f5252454354204d53472056414c554500000000000000000000000000604482015290519081900360640190fd5b6001600160a01b03808b166000908152600160205260409020541680610bcc576040805162461bcd60e51b815260206004820152600c60248201527f5377617020697320307830300000000000000000000000000000000000000000604482015290519081900360640190fd5b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663d0e30db0346040518263ffffffff1660e01b81526004016000604051808303818588803b158015610c2757600080fd5b505af1158015610c3b573d6000803e3d6000fd5b50505050506000816001600160a01b031663916955868c8c8c8c8c6040518663ffffffff1660e01b8152600401808660ff1681526020018560ff16815260200184815260200183815260200182815260200195505050505050602060405180830381600087803b158015610cae57600080fd5b505af1158015610cc2573d6000803e3d6000fd5b505050506040513d6020811015610cd857600080fd5b8101908080519060200190929190505050905060008054906101000a90046001600160a01b03166001600160a01b031663839ed90a8f8f8f858b8b8b8b6040518963ffffffff1660e01b815260040180896001600160a01b03168152602001888152602001876001600160a01b031681526020018681526020018560ff1681526020018460ff16815260200183815260200182815260200198505050505050505050600060405180830381600087803b1580156108a657600080fd5b6001600160a01b038087166000908152600160205260409020541680610e01576040805162461bcd60e51b815260206004820152600c60248201527f5377617020697320307830300000000000000000000000000000000000000000604482015290519081900360640190fd5b6001600160a01b038116600090815260026020908152604091829020805483518184028101840190945280845260609392830182828015610e6b57602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311610e4d575b50505050509050610e87333087848b60ff168151811061067857fe5b604080517f9169558600000000000000000000000000000000000000000000000000000000815260ff808a1660048301528816602482015260448101879052606481018690526084810185905290516000916001600160a01b0385169163916955869160a48082019260209290919082900301818787803b158015610f0b57600080fd5b505af1158015610f1f573d6000803e3d6000fd5b505050506040513d6020811015610f3557600080fd5b5051600054604080517fdd62ed3e0000000000000000000000000000000000000000000000000000000081523060048201526001600160a01b03928316602482015290519293508392918c169163dd62ed3e91604480820192602092909190829003018186803b158015610fa857600080fd5b505afa158015610fbc573d6000803e3d6000fd5b505050506040513d6020811015610fd257600080fd5b50511015610ff657600054610ff6906001600160a01b038b81169116600019611bea565b60008054604080517ff3f094a10000000000000000000000000000000000000000000000000000000081526001600160a01b038f81166004830152602482018f90528d81166044830152606482018690529151919092169263f3f094a1926084808201939182900301818387803b15801561107057600080fd5b505af1158015611084573d6000803e3d6000fd5b505050505050505050505050505050565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316611110576040805162461bcd60e51b815260206004820152600660248201527f5745544820300000000000000000000000000000000000000000000000000000604482015290519081900360640190fd5b60003411801561111f57508234145b611170576040805162461bcd60e51b815260206004820152601360248201527f494e434f5252454354204d53472056414c554500000000000000000000000000604482015290519081900360640190fd5b6001600160a01b0380871660009081526001602052604090205416806111dd576040805162461bcd60e51b815260206004820152600c60248201527f5377617020697320307830300000000000000000000000000000000000000000604482015290519081900360640190fd5b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663d0e30db0346040518263ffffffff1660e01b81526004016000604051808303818588803b15801561123857600080fd5b505af115801561124c573d6000803e3d6000fd5b5050604080517f9169558600000000000000000000000000000000000000000000000000000000815260ff808c1660048301528a1660248201526044810189905260648101889052608481018790529051600094506001600160a01b03861693506391695586925060a480830192602092919082900301818787803b1580156112d457600080fd5b505af11580156112e8573d6000803e3d6000fd5b505050506040513d60208110156112fe57600080fd5b505160008054604080517ff3f094a10000000000000000000000000000000000000000000000000000000081526001600160a01b038f81166004830152602482018f90528d8116604483015260648201869052915194955091169263f3f094a19260848084019391929182900301818387803b15801561137d57600080fd5b505af1158015611391573d6000803e3d6000fd5b5050505050505050505050505050565b6001600160a01b0380851660009081526001602090815260408083205481517fa95b089f00000000000000000000000000000000000000000000000000000000815260ff808a1660048301528816602482015260448101879052915193941692839263a95b089f9260648082019391829003018186803b15801561142457600080fd5b505afa158015611438573d6000803e3d6000fd5b505050506040513d602081101561144e57600080fd5b50519695505050505050565b61146f6001600160a01b038716333088611d62565b600054604080517fdd62ed3e0000000000000000000000000000000000000000000000000000000081523060048201526001600160a01b0392831660248201529051879289169163dd62ed3e916044808301926020929190829003018186803b1580156114db57600080fd5b505afa1580156114ef573d6000803e3d6000fd5b505050506040513d602081101561150557600080fd5b5051101561152957600054611529906001600160a01b038881169116600019611bea565b60008054604080517f839ed90a0000000000000000000000000000000000000000000000000000000081526001600160a01b038c81166004830152602482018c90528a81166044830152606482018a905260ff808a166084840152881660a483015260c4820187905260e482018690529151919092169263839ed90a92610104808201939182900301818387803b1580156115c357600080fd5b505af11580156115d7573d6000803e3d6000fd5b505050505050505050505050565b6001602052600090815260409020546001600160a01b031681565b6116156001600160a01b038316333084611d62565b600054604080517fdd62ed3e0000000000000000000000000000000000000000000000000000000081523060048201526001600160a01b0392831660248201529051839285169163dd62ed3e916044808301926020929190829003018186803b15801561168157600080fd5b505afa158015611695573d6000803e3d6000fd5b505050506040513d60208110156116ab57600080fd5b505110156116cf576000546116cf906001600160a01b038481169116600019611bea565b60008054604080517f90d250740000000000000000000000000000000000000000000000000000000081526001600160a01b03888116600483015260248201889052868116604483015260648201869052915191909216926390d25074926084808201939182900301818387803b15801561174957600080fd5b505af115801561175d573d6000803e3d6000fd5b5050505050505050565b6001600160a01b038a8116600090815260016020526040902054166117d3576040805162461bcd60e51b815260206004820152600c60248201527f5377617020697320307830300000000000000000000000000000000000000000604482015290519081900360640190fd5b6001600160a01b03808b166000908152600160209081526040808320549093168252600281529082902080548351818402810184019094528084526060939283018282801561184b57602002820191906000526020600020905b81546001600160a01b0316815260019091019060200180831161182d575b5050505050905061186733308a848e60ff168151811061067857fe5b6000600160008d6001600160a01b03166001600160a01b0316815260200190815260200160002060009054906101000a90046001600160a01b03166001600160a01b031663916955868c8c8c8c8c6040518663ffffffff1660e01b8152600401808660ff1681526020018560ff16815260200184815260200183815260200182815260200195505050505050602060405180830381600087803b15801561190d57600080fd5b505af1158015611921573d6000803e3d6000fd5b505050506040513d602081101561193757600080fd5b5051600054604080517fdd62ed3e0000000000000000000000000000000000000000000000000000000081523060048201526001600160a01b03928316602482015290519293508392918f169163dd62ed3e91604480820192602092909190829003018186803b1580156119aa57600080fd5b505afa1580156119be573d6000803e3d6000fd5b505050506040513d60208110156119d457600080fd5b505110156119f8576000546119f8906001600160a01b038e81169116600019611bea565b60008054906101000a90046001600160a01b03166001600160a01b031663839ed90a8f8f8f858b8b8b8b6040518963ffffffff1660e01b815260040180896001600160a01b03168152602001888152602001876001600160a01b031681526020018681526020018560ff1681526020018460ff16815260200183815260200182815260200198505050505050505050600060405180830381600087803b1580156108a657600080fd5b611ab66001600160a01b038316333084611d62565b600054604080517fdd62ed3e0000000000000000000000000000000000000000000000000000000081523060048201526001600160a01b0392831660248201529051839285169163dd62ed3e916044808301926020929190829003018186803b158015611b2257600080fd5b505afa158015611b36573d6000803e3d6000fd5b505050506040513d6020811015611b4c57600080fd5b50511015611b7057600054611b70906001600160a01b038481169116600019611bea565b60008054604080517ff3f094a10000000000000000000000000000000000000000000000000000000081526001600160a01b038881166004830152602482018890528681166044830152606482018690529151919092169263f3f094a1926084808201939182900301818387803b15801561174957600080fd5b801580611c895750604080517fdd62ed3e0000000000000000000000000000000000000000000000000000000081523060048201526001600160a01b03848116602483015291519185169163dd62ed3e91604480820192602092909190829003018186803b158015611c5b57600080fd5b505afa158015611c6f573d6000803e3d6000fd5b505050506040513d6020811015611c8557600080fd5b5051155b611cc45760405162461bcd60e51b81526004018080602001828103825260368152602001806121166036913960400191505060405180910390fd5b604080516001600160a01b038416602482015260448082018490528251808303909101815260649091019091526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f095ea7b300000000000000000000000000000000000000000000000000000000179052611d44908490611df0565b505050565b6060611d588484600085611ea1565b90505b9392505050565b604080516001600160a01b0380861660248301528416604482015260648082018490528251808303909101815260849091019091526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f23b872dd00000000000000000000000000000000000000000000000000000000179052611dea908590611df0565b50505050565b6060611e45826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b0316611d499092919063ffffffff16565b805190915015611d4457808060200190516020811015611e6457600080fd5b5051611d445760405162461bcd60e51b815260040180806020018281038252602a8152602001806120ec602a913960400191505060405180910390fd5b606082471015611ee25760405162461bcd60e51b81526004018080602001828103825260268152602001806120c66026913960400191505060405180910390fd5b611eeb8561201b565b611f3c576040805162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000604482015290519081900360640190fd5b60006060866001600160a01b031685876040518082805190602001908083835b60208310611f9957805182527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe09092019160209182019101611f5c565b6001836020036101000a03801982511681845116808217855250505050505090500191505060006040518083038185875af1925050503d8060008114611ffb576040519150601f19603f3d011682016040523d82523d6000602084013e612000565b606091505b5091509150612010828286612021565b979650505050505050565b3b151590565b60608315612030575081611d5b565b8251156120405782518084602001fd5b8160405162461bcd60e51b81526004018080602001828103825283818151815260200191508051906020019080838360005b8381101561208a578181015183820152602001612072565b50505050905090810190601f1680156120b75780820380516001836020036101000a031916815260200191505b509250505060405180910390fdfe416464726573733a20696e73756666696369656e742062616c616e636520666f722063616c6c5361666545524332303a204552433230206f7065726174696f6e20646964206e6f7420737563636565645361666545524332303a20617070726f76652066726f6d206e6f6e2d7a65726f20746f206e6f6e2d7a65726f20616c6c6f77616e6365a264697066735822122066588cb14596d85644754cda29c9287e7e73593ce3e2c72a10ec98f4c1a2eb4164736f6c634300060c0033", + "solcInputHash": "c16492a84c84927e5b757d9d97068ec0", + "metadata": "{\"compiler\":{\"version\":\"0.6.12+commit.27d51765\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address payable\",\"name\":\"_wethAddress\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_swapOne\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenOne\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_swapTwo\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenTwo\",\"type\":\"address\"},{\"internalType\":\"contract ISynapseBridge\",\"name\":\"_synapseBridge\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"WETH_ADDRESS\",\"outputs\":[{\"internalType\":\"address payable\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contract IERC20\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint8\",\"name\":\"tokenIndexFrom\",\"type\":\"uint8\"},{\"internalType\":\"uint8\",\"name\":\"tokenIndexTo\",\"type\":\"uint8\"},{\"internalType\":\"uint256\",\"name\":\"dx\",\"type\":\"uint256\"}],\"name\":\"calculateSwap\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"chainId\",\"type\":\"uint256\"},{\"internalType\":\"contract IERC20\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"deposit\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"chainId\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"depositETH\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"chainId\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"uint8\",\"name\":\"tokenIndexFrom\",\"type\":\"uint8\"},{\"internalType\":\"uint8\",\"name\":\"tokenIndexTo\",\"type\":\"uint8\"},{\"internalType\":\"uint256\",\"name\":\"minDy\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"deadline\",\"type\":\"uint256\"}],\"name\":\"depositETHAndSwap\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"chainId\",\"type\":\"uint256\"},{\"internalType\":\"contract IERC20\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"redeem\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"chainId\",\"type\":\"uint256\"},{\"internalType\":\"contract IERC20\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"uint8\",\"name\":\"liqTokenIndex\",\"type\":\"uint8\"},{\"internalType\":\"uint256\",\"name\":\"liqMinAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"liqDeadline\",\"type\":\"uint256\"}],\"name\":\"redeemAndRemove\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"chainId\",\"type\":\"uint256\"},{\"internalType\":\"contract IERC20\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"uint8\",\"name\":\"tokenIndexFrom\",\"type\":\"uint8\"},{\"internalType\":\"uint8\",\"name\":\"tokenIndexTo\",\"type\":\"uint8\"},{\"internalType\":\"uint256\",\"name\":\"minDy\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"deadline\",\"type\":\"uint256\"}],\"name\":\"redeemAndSwap\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"to\",\"type\":\"bytes32\"},{\"internalType\":\"uint256\",\"name\":\"chainId\",\"type\":\"uint256\"},{\"internalType\":\"contract IERC20\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"redeemv2\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"chainId\",\"type\":\"uint256\"},{\"internalType\":\"contract IERC20\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint8\",\"name\":\"tokenIndexFrom\",\"type\":\"uint8\"},{\"internalType\":\"uint8\",\"name\":\"tokenIndexTo\",\"type\":\"uint8\"},{\"internalType\":\"uint256\",\"name\":\"dx\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"minDy\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"deadline\",\"type\":\"uint256\"}],\"name\":\"swapAndRedeem\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"chainId\",\"type\":\"uint256\"},{\"internalType\":\"contract IERC20\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint8\",\"name\":\"tokenIndexFrom\",\"type\":\"uint8\"},{\"internalType\":\"uint8\",\"name\":\"tokenIndexTo\",\"type\":\"uint8\"},{\"internalType\":\"uint256\",\"name\":\"dx\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"minDy\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"deadline\",\"type\":\"uint256\"},{\"internalType\":\"uint8\",\"name\":\"liqTokenIndex\",\"type\":\"uint8\"},{\"internalType\":\"uint256\",\"name\":\"liqMinAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"liqDeadline\",\"type\":\"uint256\"}],\"name\":\"swapAndRedeemAndRemove\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"chainId\",\"type\":\"uint256\"},{\"internalType\":\"contract IERC20\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint8\",\"name\":\"tokenIndexFrom\",\"type\":\"uint8\"},{\"internalType\":\"uint8\",\"name\":\"tokenIndexTo\",\"type\":\"uint8\"},{\"internalType\":\"uint256\",\"name\":\"dx\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"minDy\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"deadline\",\"type\":\"uint256\"},{\"internalType\":\"uint8\",\"name\":\"swapTokenIndexFrom\",\"type\":\"uint8\"},{\"internalType\":\"uint8\",\"name\":\"swapTokenIndexTo\",\"type\":\"uint8\"},{\"internalType\":\"uint256\",\"name\":\"swapMinDy\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"swapDeadline\",\"type\":\"uint256\"}],\"name\":\"swapAndRedeemAndSwap\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"chainId\",\"type\":\"uint256\"},{\"internalType\":\"contract IERC20\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint8\",\"name\":\"tokenIndexFrom\",\"type\":\"uint8\"},{\"internalType\":\"uint8\",\"name\":\"tokenIndexTo\",\"type\":\"uint8\"},{\"internalType\":\"uint256\",\"name\":\"dx\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"minDy\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"deadline\",\"type\":\"uint256\"}],\"name\":\"swapETHAndRedeem\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"chainId\",\"type\":\"uint256\"},{\"internalType\":\"contract IERC20\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint8\",\"name\":\"tokenIndexFrom\",\"type\":\"uint8\"},{\"internalType\":\"uint8\",\"name\":\"tokenIndexTo\",\"type\":\"uint8\"},{\"internalType\":\"uint256\",\"name\":\"dx\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"minDy\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"deadline\",\"type\":\"uint256\"},{\"internalType\":\"uint8\",\"name\":\"swapTokenIndexFrom\",\"type\":\"uint8\"},{\"internalType\":\"uint8\",\"name\":\"swapTokenIndexTo\",\"type\":\"uint8\"},{\"internalType\":\"uint256\",\"name\":\"swapMinDy\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"swapDeadline\",\"type\":\"uint256\"}],\"name\":\"swapETHAndRedeemAndSwap\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"swapMap\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"swapTokensMap\",\"outputs\":[{\"internalType\":\"contract IERC20\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{\"calculateSwap(address,uint8,uint8,uint256)\":{\"params\":{\"dx\":\"the amount of tokens the user wants to sell. If the token charges a fee on transfers, use the amount that gets transferred after the fee.\",\"tokenIndexFrom\":\"the token the user wants to sell\",\"tokenIndexTo\":\"the token the user wants to buy\"},\"returns\":{\"_0\":\"amount of tokens the user will receive\"}},\"deposit(address,uint256,address,uint256)\":{\"params\":{\"amount\":\"Amount in native token decimals to transfer cross-chain pre-fees*\",\"chainId\":\"which underlying chain to bridge assets onto\",\"to\":\"address on other chain to redeem underlying assets to\",\"token\":\"ERC20 compatible token to deposit into the bridge\"}},\"depositETH(address,uint256,uint256)\":{\"params\":{\"amount\":\"Amount in native token decimals to transfer cross-chain pre-fees*\",\"chainId\":\"which chain to bridge assets onto\",\"to\":\"address on other chain to bridge assets to\"}},\"depositETHAndSwap(address,uint256,uint256,uint8,uint8,uint256,uint256)\":{\"params\":{\"amount\":\"Amount in native token decimals to transfer cross-chain pre-fees\",\"chainId\":\"which chain to bridge assets onto\",\"deadline\":\"latest timestamp to accept this transaction*\",\"minDy\":\"the min amount the user would like to receive, or revert to only minting the SynERC20 token crosschain.\",\"to\":\"address on other chain to bridge assets to\",\"tokenIndexFrom\":\"the token the user wants to swap from\",\"tokenIndexTo\":\"the token the user wants to swap to\"}},\"redeem(address,uint256,address,uint256)\":{\"params\":{\"amount\":\"Amount in native token decimals to transfer cross-chain pre-fees*\",\"chainId\":\"which underlying chain to bridge assets onto\",\"to\":\"address on other chain to redeem underlying assets to\",\"token\":\"ERC20 compatible token to deposit into the bridge\"}},\"redeemAndRemove(address,uint256,address,uint256,uint8,uint256,uint256)\":{\"params\":{\"amount\":\"Amount of (typically) LP token to pass to the nodes to attempt to removeLiquidity() with to redeem for the underlying assets of the LP token\",\"chainId\":\"which underlying chain to bridge assets onto\",\"liqDeadline\":\"Specificies the deadline that the nodes are allowed to try to redeem/swap the LP token*\",\"liqMinAmount\":\"Specifies the minimum amount of the underlying asset needed for the nodes to execute the redeem/swap\",\"liqTokenIndex\":\"Specifies which of the underlying LP assets the nodes should attempt to redeem for\",\"to\":\"address on other chain to redeem underlying assets to\",\"token\":\"ERC20 compatible token to deposit into the bridge\"}},\"redeemAndSwap(address,uint256,address,uint256,uint8,uint8,uint256,uint256)\":{\"params\":{\"amount\":\"Amount in native token decimals to transfer cross-chain pre-fees\",\"chainId\":\"which underlying chain to bridge assets onto\",\"deadline\":\"latest timestamp to accept this transaction*\",\"minDy\":\"the min amount the user would like to receive, or revert to only minting the SynERC20 token crosschain.\",\"to\":\"address on other chain to redeem underlying assets to\",\"token\":\"ERC20 compatible token to deposit into the bridge\",\"tokenIndexFrom\":\"the token the user wants to swap from\",\"tokenIndexTo\":\"the token the user wants to swap to\"}},\"redeemv2(bytes32,uint256,address,uint256)\":{\"params\":{\"amount\":\"Amount in native token decimals to transfer cross-chain pre-fees*\",\"chainId\":\"which chain to bridge assets onto\",\"to\":\"address on other chain to bridge assets to\",\"token\":\"ERC20 compatible token to redeem into the bridge\"}}},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{\"calculateSwap(address,uint8,uint8,uint256)\":{\"notice\":\"Calculate amount of tokens you receive on swap\"},\"deposit(address,uint256,address,uint256)\":{\"notice\":\"wraps SynapseBridge redeem()\"},\"depositETH(address,uint256,uint256)\":{\"notice\":\"Wraps SynapseBridge deposit() function to make it compatible w/ ETH -> WETH conversions\"},\"depositETHAndSwap(address,uint256,uint256,uint8,uint8,uint256,uint256)\":{\"notice\":\"Wraps SynapseBridge depositAndSwap() function to make it compatible w/ ETH -> WETH conversions\"},\"redeem(address,uint256,address,uint256)\":{\"notice\":\"wraps SynapseBridge redeem()\"},\"redeemAndRemove(address,uint256,address,uint256,uint8,uint256,uint256)\":{\"notice\":\"Wraps redeemAndRemove on SynapseBridge Relays to nodes that (typically) a wrapped synAsset ERC20 token has been burned and the underlying needs to be redeeemed on the native chain. This function indicates to the nodes that they should attempt to redeem the LP token for the underlying assets (E.g \\\"swap\\\" out of the LP token)\"},\"redeemAndSwap(address,uint256,address,uint256,uint8,uint8,uint256,uint256)\":{\"notice\":\"Wraps redeemAndSwap on SynapseBridge.sol Relays to nodes that (typically) a wrapped synAsset ERC20 token has been burned and the underlying needs to be redeeemed on the native chain. This function indicates to the nodes that they should attempt to redeem the LP token for the underlying assets (E.g \\\"swap\\\" out of the LP token)\"},\"redeemv2(bytes32,uint256,address,uint256)\":{\"notice\":\"Wraps SynapseBridge redeemv2() function\"}},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/bridge/wrappers/L2BridgeZap.sol\":\"L2BridgeZap\"},\"evmVersion\":\"istanbul\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":10000},\"remappings\":[]},\"sources\":{\"@openzeppelin/contracts/math/SafeMath.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity >=0.6.0 <0.8.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\",\"keccak256\":\"0xcc78a17dd88fa5a2edc60c8489e2f405c0913b377216a5b26b35656b2d0dab52\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/ERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity >=0.6.0 <0.8.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_) public {\\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\",\"keccak256\":\"0xca0c2396dbeb3503b51abf4248ebf77a1461edad513c01529df51850a012bee3\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/ERC20Burnable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity >=0.6.0 <0.8.0;\\n\\nimport \\\"../../utils/Context.sol\\\";\\nimport \\\"./ERC20.sol\\\";\\n\\n/**\\n * @dev Extension of {ERC20} that allows token holders to destroy both their own\\n * tokens and those that they have an allowance for, in a way that can be\\n * recognized off-chain (via event analysis).\\n */\\nabstract contract ERC20Burnable is Context, ERC20 {\\n using SafeMath for uint256;\\n\\n /**\\n * @dev Destroys `amount` tokens from the caller.\\n *\\n * See {ERC20-_burn}.\\n */\\n function burn(uint256 amount) public virtual {\\n _burn(_msgSender(), amount);\\n }\\n\\n /**\\n * @dev Destroys `amount` tokens from `account`, deducting from the caller's\\n * allowance.\\n *\\n * See {ERC20-_burn} and {ERC20-allowance}.\\n *\\n * Requirements:\\n *\\n * - the caller must have allowance for ``accounts``'s tokens of at least\\n * `amount`.\\n */\\n function burnFrom(address account, uint256 amount) public virtual {\\n uint256 decreasedAllowance = allowance(account, _msgSender()).sub(amount, \\\"ERC20: burn amount exceeds allowance\\\");\\n\\n _approve(account, _msgSender(), decreasedAllowance);\\n _burn(account, amount);\\n }\\n}\\n\",\"keccak256\":\"0x9c0eb3b0e11d2480d49991dc384f1e5f9c9b9967cc81944d50916a9b9c6c4984\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/IERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity >=0.6.0 <0.8.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\",\"keccak256\":\"0x5f02220344881ce43204ae4a6281145a67bc52c2bb1290a791857df3d19d78f5\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/SafeERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity >=0.6.0 <0.8.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\",\"keccak256\":\"0xf12dfbe97e6276980b83d2830bb0eb75e0cf4f3e626c2471137f82158ae6a0fc\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/Address.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity >=0.6.2 <0.8.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\",\"keccak256\":\"0x28911e614500ae7c607a432a709d35da25f3bc5ddc8bd12b278b66358070c0ea\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/Context.sol\":{\"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\",\"keccak256\":\"0x8d3cb350f04ff49cfb10aef08d87f19dcbaecc8027b0bed12f3275cd12f38cf0\",\"license\":\"MIT\"},\"contracts/bridge/interfaces/ISwap.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity 0.6.12;\\n\\nimport '@openzeppelin/contracts/token/ERC20/ERC20.sol';\\n\\ninterface ISwap {\\n // pool data view functions\\n function getA() external view returns (uint256);\\n\\n function getToken(uint8 index) external view returns (IERC20);\\n\\n function getTokenIndex(address tokenAddress) external view returns (uint8);\\n\\n function getTokenBalance(uint8 index) external view returns (uint256);\\n\\n function getVirtualPrice() external view returns (uint256);\\n\\n // min return calculation functions\\n function calculateSwap(\\n uint8 tokenIndexFrom,\\n uint8 tokenIndexTo,\\n uint256 dx\\n ) external view returns (uint256);\\n\\n function calculateTokenAmount(uint256[] calldata amounts, bool deposit)\\n external\\n view\\n returns (uint256);\\n\\n function calculateRemoveLiquidity(uint256 amount)\\n external\\n view\\n returns (uint256[] memory);\\n\\n function calculateRemoveLiquidityOneToken(\\n uint256 tokenAmount,\\n uint8 tokenIndex\\n ) external view returns (uint256 availableTokenAmount);\\n\\n // state modifying functions\\n function initialize(\\n IERC20[] memory pooledTokens,\\n uint8[] memory decimals,\\n string memory lpTokenName,\\n string memory lpTokenSymbol,\\n uint256 a,\\n uint256 fee,\\n uint256 adminFee,\\n address lpTokenTargetAddress\\n ) external;\\n\\n function swap(\\n uint8 tokenIndexFrom,\\n uint8 tokenIndexTo,\\n uint256 dx,\\n uint256 minDy,\\n uint256 deadline\\n ) external returns (uint256);\\n\\n function addLiquidity(\\n uint256[] calldata amounts,\\n uint256 minToMint,\\n uint256 deadline\\n ) external returns (uint256);\\n\\n function removeLiquidity(\\n uint256 amount,\\n uint256[] calldata minAmounts,\\n uint256 deadline\\n ) external returns (uint256[] memory);\\n\\n function removeLiquidityOneToken(\\n uint256 tokenAmount,\\n uint8 tokenIndex,\\n uint256 minAmount,\\n uint256 deadline\\n ) external returns (uint256);\\n\\n function removeLiquidityImbalance(\\n uint256[] calldata amounts,\\n uint256 maxBurnAmount,\\n uint256 deadline\\n ) external returns (uint256);\\n}\\n\",\"keccak256\":\"0xb51eb389637b2b595a09cd95ea4167a6d945719be1bc127eafae07c06abd8ca8\",\"license\":\"MIT\"},\"contracts/bridge/interfaces/ISynapseBridge.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity 0.6.12;\\n\\nimport '@openzeppelin/contracts/token/ERC20/SafeERC20.sol';\\nimport '@openzeppelin/contracts/token/ERC20/ERC20Burnable.sol';\\n\\ninterface ISynapseBridge {\\n using SafeERC20 for IERC20;\\n\\n function deposit(\\n address to,\\n uint256 chainId,\\n IERC20 token,\\n uint256 amount\\n ) external;\\n\\n function depositAndSwap(\\n address to,\\n uint256 chainId,\\n IERC20 token,\\n uint256 amount,\\n uint8 tokenIndexFrom,\\n uint8 tokenIndexTo,\\n uint256 minDy,\\n uint256 deadline\\n ) external;\\n\\n function redeem(\\n address to,\\n uint256 chainId,\\n IERC20 token,\\n uint256 amount\\n ) external;\\n\\n\\n function redeemv2(\\n bytes32 to,\\n uint256 chainId,\\n IERC20 token,\\n uint256 amount\\n ) external;\\n\\n\\n function redeemAndSwap(\\n address to,\\n uint256 chainId,\\n IERC20 token,\\n uint256 amount,\\n uint8 tokenIndexFrom,\\n uint8 tokenIndexTo,\\n uint256 minDy,\\n uint256 deadline\\n ) external;\\n\\n function redeemAndRemove(\\n address to,\\n uint256 chainId,\\n IERC20 token,\\n uint256 amount,\\n uint8 liqTokenIndex,\\n uint256 liqMinAmount,\\n uint256 liqDeadline\\n ) external;\\n}\\n\",\"keccak256\":\"0x9ae06bbed7d464faceb9c63e929171f422b5eaee1f6d653742ab97862bc6609a\",\"license\":\"MIT\"},\"contracts/bridge/interfaces/IWETH9.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity >=0.4.0;\\n\\ninterface IWETH9 {\\n function name() external view returns (string memory);\\n\\n function symbol() external view returns (string memory);\\n\\n function decimals() external view returns (uint8);\\n\\n function balanceOf(address) external view returns (uint256);\\n\\n function allowance(address, address) external view returns (uint256);\\n\\n receive() external payable;\\n\\n function deposit() external payable;\\n\\n function withdraw(uint256 wad) external;\\n\\n function totalSupply() external view returns (uint256);\\n\\n function approve(address guy, uint256 wad) external returns (bool);\\n\\n function transfer(address dst, uint256 wad) external returns (bool);\\n\\n function transferFrom(\\n address src,\\n address dst,\\n uint256 wad\\n ) external returns (bool);\\n}\",\"keccak256\":\"0x081ebde11dad2210d382564d40336f914d3d621750645f23707ca1a92139dbe2\",\"license\":\"MIT\"},\"contracts/bridge/wrappers/L2BridgeZap.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.6.12;\\n\\nimport \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\nimport \\\"@openzeppelin/contracts/token/ERC20/SafeERC20.sol\\\";\\nimport \\\"../interfaces/ISwap.sol\\\";\\nimport \\\"../interfaces/ISynapseBridge.sol\\\";\\nimport \\\"../interfaces/IWETH9.sol\\\";\\n\\ncontract L2BridgeZap {\\n using SafeERC20 for IERC20;\\n\\n ISynapseBridge synapseBridge;\\n address payable public immutable WETH_ADDRESS;\\n\\n mapping(address => address) public swapMap;\\n mapping(address => IERC20[]) public swapTokensMap;\\n\\n uint256 constant MAX_UINT256 = 2**256 - 1;\\n\\n constructor(\\n address payable _wethAddress,\\n address _swapOne,\\n address tokenOne,\\n address _swapTwo,\\n address tokenTwo,\\n ISynapseBridge _synapseBridge\\n ) public {\\n WETH_ADDRESS = _wethAddress;\\n synapseBridge = _synapseBridge;\\n swapMap[tokenOne] = _swapOne;\\n swapMap[tokenTwo] = _swapTwo;\\n // if (_wethAddress != address(0)) {\\n // IERC20(_wethAddress).safeIncreaseAllowance(address(_synapseBridge), MAX_UINT256);\\n // }\\n if (address(_swapOne) != address(0)) {\\n {\\n uint8 i;\\n for (; i < 32; i++) {\\n try ISwap(_swapOne).getToken(i) returns (\\n IERC20 token\\n ) {\\n swapTokensMap[_swapOne].push(token);\\n token.safeApprove(address(_swapOne), MAX_UINT256);\\n token.safeApprove(address(synapseBridge), MAX_UINT256);\\n } catch {\\n break;\\n }\\n }\\n require(i > 1, \\\"swap must have at least 2 tokens\\\");\\n }\\n }\\n if (address(_swapTwo) != address(0)) {\\n {\\n uint8 i;\\n for (; i < 32; i++) {\\n try ISwap(_swapTwo).getToken(i) returns (\\n IERC20 token\\n ) {\\n swapTokensMap[_swapTwo].push(token);\\n token.safeApprove(address(_swapTwo), MAX_UINT256);\\n token.safeApprove(address(synapseBridge), MAX_UINT256);\\n } catch {\\n break;\\n }\\n }\\n require(i > 1, \\\"swap must have at least 2 tokens\\\");\\n }\\n }\\n }\\n\\n /**\\n * @notice Calculate amount of tokens you receive on swap\\n * @param tokenIndexFrom the token the user wants to sell\\n * @param tokenIndexTo the token the user wants to buy\\n * @param dx the amount of tokens the user wants to sell. If the token charges\\n * a fee on transfers, use the amount that gets transferred after the fee.\\n * @return amount of tokens the user will receive\\n */\\n function calculateSwap(\\n IERC20 token,\\n uint8 tokenIndexFrom,\\n uint8 tokenIndexTo,\\n uint256 dx\\n ) external view virtual returns (uint256) {\\n ISwap swap = ISwap(\\n swapMap[address(token)]\\n );\\n return swap.calculateSwap(tokenIndexFrom, tokenIndexTo, dx);\\n }\\n\\n function swapAndRedeem(\\n address to,\\n uint256 chainId,\\n IERC20 token,\\n uint8 tokenIndexFrom,\\n uint8 tokenIndexTo,\\n uint256 dx,\\n uint256 minDy,\\n uint256 deadline\\n ) external {\\n ISwap swap = ISwap(swapMap[address(token)]);\\n require(address(swap) != address(0), \\\"Swap is 0x00\\\");\\n IERC20[] memory tokens = swapTokensMap[address(swap)];\\n tokens[tokenIndexFrom].safeTransferFrom(\\n msg.sender,\\n address(this),\\n dx\\n );\\n // swap\\n\\n uint256 swappedAmount = swap.swap(\\n tokenIndexFrom,\\n tokenIndexTo,\\n dx,\\n minDy,\\n deadline\\n );\\n // deposit into bridge, gets nUSD\\n if (\\n token.allowance(address(this), address(synapseBridge)) <\\n swappedAmount\\n ) {\\n token.safeApprove(address(synapseBridge), MAX_UINT256);\\n }\\n synapseBridge.redeem(to, chainId, token, swappedAmount);\\n }\\n\\n function swapAndRedeemAndSwap(\\n address to,\\n uint256 chainId,\\n IERC20 token,\\n uint8 tokenIndexFrom,\\n uint8 tokenIndexTo,\\n uint256 dx,\\n uint256 minDy,\\n uint256 deadline,\\n uint8 swapTokenIndexFrom,\\n uint8 swapTokenIndexTo,\\n uint256 swapMinDy,\\n uint256 swapDeadline\\n ) external {\\n require(\\n address(swapMap[address(token)]) != address(0),\\n \\\"Swap is 0x00\\\"\\n );\\n IERC20[] memory tokens = swapTokensMap[\\n swapMap[address(token)]\\n ];\\n tokens[tokenIndexFrom].safeTransferFrom(\\n msg.sender,\\n address(this),\\n dx\\n );\\n // swap\\n\\n uint256 swappedAmount = ISwap(swapMap[address(token)]).swap(tokenIndexFrom, tokenIndexTo, dx, minDy, deadline);\\n // deposit into bridge, gets nUSD\\n if (\\n token.allowance(address(this), address(synapseBridge)) <\\n swappedAmount\\n ) {\\n token.safeApprove(address(synapseBridge), MAX_UINT256);\\n }\\n synapseBridge.redeemAndSwap(\\n to,\\n chainId,\\n token,\\n swappedAmount,\\n swapTokenIndexFrom,\\n swapTokenIndexTo,\\n swapMinDy,\\n swapDeadline\\n );\\n }\\n\\n function swapAndRedeemAndRemove(\\n address to,\\n uint256 chainId,\\n IERC20 token,\\n uint8 tokenIndexFrom,\\n uint8 tokenIndexTo,\\n uint256 dx,\\n uint256 minDy,\\n uint256 deadline,\\n uint8 liqTokenIndex,\\n uint256 liqMinAmount,\\n uint256 liqDeadline\\n ) external {\\n ISwap swap = ISwap(swapMap[address(token)]);\\n require(address(swap) != address(0), \\\"Swap is 0x00\\\");\\n IERC20[] memory tokens = swapTokensMap[address(swap)];\\n tokens[tokenIndexFrom].safeTransferFrom(\\n msg.sender,\\n address(this),\\n dx\\n );\\n // swap\\n\\n uint256 swappedAmount = swap.swap(\\n tokenIndexFrom,\\n tokenIndexTo,\\n dx,\\n minDy,\\n deadline\\n );\\n // deposit into bridge, gets nUSD\\n if (\\n token.allowance(address(this), address(synapseBridge)) <\\n swappedAmount\\n ) {\\n token.safeApprove(address(synapseBridge), MAX_UINT256);\\n }\\n synapseBridge.redeemAndRemove(\\n to,\\n chainId,\\n token,\\n swappedAmount,\\n liqTokenIndex,\\n liqMinAmount,\\n liqDeadline\\n );\\n }\\n\\n /**\\n * @notice wraps SynapseBridge redeem()\\n * @param to address on other chain to redeem underlying assets to\\n * @param chainId which underlying chain to bridge assets onto\\n * @param token ERC20 compatible token to deposit into the bridge\\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\\n **/\\n function redeem(\\n address to,\\n uint256 chainId,\\n IERC20 token,\\n uint256 amount\\n ) external {\\n token.safeTransferFrom(msg.sender, address(this), amount);\\n if (token.allowance(address(this), address(synapseBridge)) < amount) {\\n token.safeApprove(address(synapseBridge), MAX_UINT256);\\n }\\n synapseBridge.redeem(to, chainId, token, amount);\\n }\\n\\n /**\\n * @notice wraps SynapseBridge redeem()\\n * @param to address on other chain to redeem underlying assets to\\n * @param chainId which underlying chain to bridge assets onto\\n * @param token ERC20 compatible token to deposit into the bridge\\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\\n **/\\n function deposit(\\n address to,\\n uint256 chainId,\\n IERC20 token,\\n uint256 amount\\n ) external {\\n token.safeTransferFrom(msg.sender, address(this), amount);\\n if (token.allowance(address(this), address(synapseBridge)) < amount) {\\n token.safeApprove(address(synapseBridge), MAX_UINT256);\\n }\\n synapseBridge.deposit(to, chainId, token, amount);\\n }\\n\\n /**\\n * @notice Wraps SynapseBridge deposit() function to make it compatible w/ ETH -> WETH conversions\\n * @param to address on other chain to bridge assets to\\n * @param chainId which chain to bridge assets onto\\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\\n **/\\n function depositETH(\\n address to,\\n uint256 chainId,\\n uint256 amount\\n ) external payable {\\n require(msg.value > 0 && msg.value == amount, 'INCORRECT MSG VALUE');\\n IWETH9(WETH_ADDRESS).deposit{value: msg.value}();\\n synapseBridge.deposit(to, chainId, IERC20(WETH_ADDRESS), amount);\\n }\\n\\n\\n /**\\n * @notice Wraps SynapseBridge depositAndSwap() function to make it compatible w/ ETH -> WETH conversions\\n * @param to address on other chain to bridge assets to\\n * @param chainId which chain to bridge assets onto\\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\\n * @param tokenIndexFrom the token the user wants to swap from\\n * @param tokenIndexTo the token the user wants to swap to\\n * @param minDy the min amount the user would like to receive, or revert to only minting the SynERC20 token crosschain.\\n * @param deadline latest timestamp to accept this transaction\\n **/\\n function depositETHAndSwap(\\n address to,\\n uint256 chainId,\\n uint256 amount,\\n uint8 tokenIndexFrom,\\n uint8 tokenIndexTo,\\n uint256 minDy,\\n uint256 deadline\\n ) external payable {\\n require(msg.value > 0 && msg.value == amount, 'INCORRECT MSG VALUE');\\n IWETH9(WETH_ADDRESS).deposit{value: msg.value}();\\n synapseBridge.depositAndSwap(to, chainId, IERC20(WETH_ADDRESS), amount, tokenIndexFrom, tokenIndexTo, minDy, deadline);\\n }\\n\\n\\n function swapETHAndRedeem(\\n address to,\\n uint256 chainId,\\n IERC20 token,\\n uint8 tokenIndexFrom,\\n uint8 tokenIndexTo,\\n uint256 dx,\\n uint256 minDy,\\n uint256 deadline\\n ) external payable {\\n require(WETH_ADDRESS != address(0), \\\"WETH 0\\\");\\n require(msg.value > 0 && msg.value == dx, \\\"INCORRECT MSG VALUE\\\");\\n ISwap swap = ISwap(swapMap[address(token)]);\\n require(address(swap) != address(0), \\\"Swap is 0x00\\\");\\n IWETH9(WETH_ADDRESS).deposit{value: msg.value}();\\n\\n // swap\\n uint256 swappedAmount = swap.swap(\\n tokenIndexFrom,\\n tokenIndexTo,\\n dx,\\n minDy,\\n deadline\\n );\\n synapseBridge.redeem(to, chainId, token, swappedAmount);\\n }\\n\\n\\n function swapETHAndRedeemAndSwap(\\n address to,\\n uint256 chainId,\\n IERC20 token,\\n uint8 tokenIndexFrom,\\n uint8 tokenIndexTo,\\n uint256 dx,\\n uint256 minDy,\\n uint256 deadline,\\n uint8 swapTokenIndexFrom,\\n uint8 swapTokenIndexTo,\\n uint256 swapMinDy,\\n uint256 swapDeadline\\n ) external payable {\\n require(WETH_ADDRESS != address(0), \\\"WETH 0\\\");\\n require(msg.value > 0 && msg.value == dx, \\\"INCORRECT MSG VALUE\\\");\\n ISwap swap = ISwap(swapMap[address(token)]);\\n require(address(swap) != address(0), \\\"Swap is 0x00\\\");\\n IWETH9(WETH_ADDRESS).deposit{value: msg.value}();\\n\\n // swap\\n uint256 swappedAmount = swap.swap(\\n tokenIndexFrom,\\n tokenIndexTo,\\n dx,\\n minDy,\\n deadline\\n );\\n synapseBridge.redeemAndSwap(to, chainId, token, swappedAmount,swapTokenIndexFrom,\\n swapTokenIndexTo,\\n swapMinDy,\\n swapDeadline);\\n }\\n\\n\\n /**\\n * @notice Wraps redeemAndSwap on SynapseBridge.sol\\n * Relays to nodes that (typically) a wrapped synAsset ERC20 token has been burned and the underlying needs to be redeeemed on the native chain. This function indicates to the nodes that they should attempt to redeem the LP token for the underlying assets (E.g \\\"swap\\\" out of the LP token)\\n * @param to address on other chain to redeem underlying assets to\\n * @param chainId which underlying chain to bridge assets onto\\n * @param token ERC20 compatible token to deposit into the bridge\\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\\n * @param tokenIndexFrom the token the user wants to swap from\\n * @param tokenIndexTo the token the user wants to swap to\\n * @param minDy the min amount the user would like to receive, or revert to only minting the SynERC20 token crosschain.\\n * @param deadline latest timestamp to accept this transaction\\n **/\\n function redeemAndSwap(\\n address to,\\n uint256 chainId,\\n IERC20 token,\\n uint256 amount,\\n uint8 tokenIndexFrom,\\n uint8 tokenIndexTo,\\n uint256 minDy,\\n uint256 deadline\\n ) external {\\n token.safeTransferFrom(msg.sender, address(this), amount);\\n if (token.allowance(address(this), address(synapseBridge)) < amount) {\\n token.safeApprove(address(synapseBridge), MAX_UINT256);\\n }\\n synapseBridge.redeemAndSwap(\\n to,\\n chainId,\\n token,\\n amount,\\n tokenIndexFrom,\\n tokenIndexTo,\\n minDy,\\n deadline\\n );\\n }\\n\\n /**\\n * @notice Wraps redeemAndRemove on SynapseBridge\\n * Relays to nodes that (typically) a wrapped synAsset ERC20 token has been burned and the underlying needs to be redeeemed on the native chain. This function indicates to the nodes that they should attempt to redeem the LP token for the underlying assets (E.g \\\"swap\\\" out of the LP token)\\n * @param to address on other chain to redeem underlying assets to\\n * @param chainId which underlying chain to bridge assets onto\\n * @param token ERC20 compatible token to deposit into the bridge\\n * @param amount Amount of (typically) LP token to pass to the nodes to attempt to removeLiquidity() with to redeem for the underlying assets of the LP token\\n * @param liqTokenIndex Specifies which of the underlying LP assets the nodes should attempt to redeem for\\n * @param liqMinAmount Specifies the minimum amount of the underlying asset needed for the nodes to execute the redeem/swap\\n * @param liqDeadline Specificies the deadline that the nodes are allowed to try to redeem/swap the LP token\\n **/\\n function redeemAndRemove(\\n address to,\\n uint256 chainId,\\n IERC20 token,\\n uint256 amount,\\n uint8 liqTokenIndex,\\n uint256 liqMinAmount,\\n uint256 liqDeadline\\n ) external {\\n token.safeTransferFrom(msg.sender, address(this), amount);\\n if (token.allowance(address(this), address(synapseBridge)) < amount) {\\n token.safeApprove(address(synapseBridge), MAX_UINT256);\\n }\\n synapseBridge.redeemAndRemove(\\n to,\\n chainId,\\n token,\\n amount,\\n liqTokenIndex,\\n liqMinAmount,\\n liqDeadline\\n );\\n }\\n\\n /**\\n * @notice Wraps SynapseBridge redeemv2() function\\n * @param to address on other chain to bridge assets to\\n * @param chainId which chain to bridge assets onto\\n * @param token ERC20 compatible token to redeem into the bridge\\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\\n **/\\n function redeemv2(\\n bytes32 to,\\n uint256 chainId,\\n IERC20 token,\\n uint256 amount\\n ) external {\\n token.safeTransferFrom(msg.sender, address(this), amount);\\n\\n if (token.allowance(address(this), address(synapseBridge)) < amount) {\\n token.safeApprove(address(synapseBridge), MAX_UINT256);\\n }\\n synapseBridge.redeemv2(to, chainId, token, amount);\\n }\\n}\\n\",\"keccak256\":\"0xe3e092af9fc82c82e4c0669ecc817318ea599480d33cf876f5bf5eaa61ebca56\",\"license\":\"MIT\"}},\"version\":1}", + "bytecode": "0x60a06040523480156200001157600080fd5b5060405162002f7938038062002f79833981810160405260c08110156200003757600080fd5b50805160208083015160408085015160608087015160808089015160a0909901519288901b6001600160601b0319169052600080546001600160a01b03199081166001600160a01b038086169190911783558086168352600190985285822080548216898916908117909155888b168352959091208054909116968216969096179095559495929490939291156200022d5760005b60208160ff161015620001e357856001600160a01b03166382b86600826040518263ffffffff1660e01b8152600401808260ff16815260200191505060206040518083038186803b1580156200012157600080fd5b505afa9250505080156200014857506040513d60208110156200014357600080fd5b505160015b6200015357620001e3565b6001600160a01b038781166000908152600260209081526040822080546001810182559083529181902090910180546001600160a01b0319169284169283179055620001af9190899060001990620003ad811b6200213617901c565b600054620001d9906001600160a01b038381169116600019620003ad602090811b6200213617901c565b50600101620000cc565b60018160ff16116200022b576040805162461bcd60e51b8152602060048201819052602482015260008051602062002ef9833981519152604482015290519081900360640190fd5b505b6001600160a01b03831615620003a15760005b60208160ff1610156200035757836001600160a01b03166382b86600826040518263ffffffff1660e01b8152600401808260ff16815260200191505060206040518083038186803b1580156200029557600080fd5b505afa925050508015620002bc57506040513d6020811015620002b757600080fd5b505160015b620002c75762000357565b6001600160a01b038581166000908152600260209081526040822080546001810182559083529181902090910180546001600160a01b0319169284169283179055620003239190879060001990620003ad811b6200213617901c565b6000546200034d906001600160a01b038381169116600019620003ad602090811b6200213617901c565b5060010162000240565b60018160ff16116200039f576040805162461bcd60e51b8152602060048201819052602482015260008051602062002ef9833981519152604482015290519081900360640190fd5b505b505050505050620007c0565b80158062000437575060408051636eb1769f60e11b81523060048201526001600160a01b03848116602483015291519185169163dd62ed3e91604480820192602092909190829003018186803b1580156200040757600080fd5b505afa1580156200041c573d6000803e3d6000fd5b505050506040513d60208110156200043357600080fd5b5051155b620004745760405162461bcd60e51b815260040180806020018281038252603681526020018062002f436036913960400191505060405180910390fd5b604080516001600160a01b038416602482015260448082018490528251808303909101815260649091019091526020810180516001600160e01b0390811663095ea7b360e01b17909152620004cc918591620004d116565b505050565b60606200052d826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b03166200058d60201b62002295179092919060201c565b805190915015620004cc578080602001905160208110156200054e57600080fd5b5051620004cc5760405162461bcd60e51b815260040180806020018281038252602a81526020018062002f19602a913960400191505060405180910390fd5b60606200059e8484600085620005a8565b90505b9392505050565b606082471015620005eb5760405162461bcd60e51b815260040180806020018281038252602681526020018062002ed36026913960400191505060405180910390fd5b620005f68562000710565b62000648576040805162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000604482015290519081900360640190fd5b60006060866001600160a01b031685876040518082805190602001908083835b60208310620006895780518252601f19909201916020918201910162000668565b6001836020036101000a03801982511681845116808217855250505050505090500191505060006040518083038185875af1925050503d8060008114620006ed576040519150601f19603f3d011682016040523d82523d6000602084013e620006f2565b606091505b5090925090506200070582828662000716565b979650505050505050565b3b151590565b6060831562000727575081620005a1565b825115620007385782518084602001fd5b8160405162461bcd60e51b81526004018080602001828103825283818151815260200191508051906020019080838360005b83811015620007845781810151838201526020016200076a565b50505050905090810190601f168015620007b25780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b60805160601c6126cd620008066000398061064c5280610b6f5280610cb752806112e6528061142e5280611d345280611de75280611ec35280611f7652506126cd6000f3fe6080604052600436106100f35760003560e01c8063798af7201161008a5780639f330727116100595780639f330727146104fb578063a9fd8c5714610580578063ce0b63ce146105d1578063f3f094a114610603576100f3565b8063798af720146103bc578063839ed90a1461041a57806385528f0b1461048157806390d25074146104b4576100f3565b80633d5da164116100c65780633d5da1641461023e57806349b7cf84146102b65780634a517a55146102fb57806365749c9d14610362576100f3565b8063040141e5146100f8578063174dc9521461012957806336e712ed146101a9578063393494b814610205575b600080fd5b34801561010457600080fd5b5061010d61064a565b604080516001600160a01b039092168252519081900360200190f35b34801561013557600080fd5b506101a7600480360361016081101561014d57600080fd5b506001600160a01b0381358116916020810135916040820135169060ff6060820135811691608081013582169160a08201359160c08101359160e0820135916101008101359091169061012081013590610140013561066e565b005b3480156101b557600080fd5b506101a7600480360360e08110156101cc57600080fd5b506001600160a01b0381358116916020810135916040820135169060608101359060ff6080820135169060a08101359060c001356109b7565b34801561021157600080fd5b5061010d6004803603604081101561022857600080fd5b506001600160a01b038135169060200135610b38565b6101a7600480360361018081101561025557600080fd5b506001600160a01b0381358116916020810135916040820135169060ff6060820135811691608081013582169160a08201359160c08101359160e0820135916101008101358216916101208201351690610140810135906101600135610b6d565b3480156102c257600080fd5b506101a7600480360360808110156102d957600080fd5b508035906020810135906001600160a01b036040820135169060600135610e7d565b34801561030757600080fd5b506101a7600480360361010081101561031f57600080fd5b506001600160a01b0381358116916020810135916040820135169060ff606082013581169160808101359091169060a08101359060c08101359060e00135610fe3565b6101a7600480360361010081101561037957600080fd5b506001600160a01b0381358116916020810135916040820135169060ff606082013581169160808101359091169060a08101359060c08101359060e001356112e4565b3480156103c857600080fd5b50610408600480360360808110156103df57600080fd5b506001600160a01b038135169060ff6020820135811691604081013590911690606001356115f0565b60408051918252519081900360200190f35b34801561042657600080fd5b506101a7600480360361010081101561043e57600080fd5b506001600160a01b0381358116916020810135916040820135169060608101359060ff608082013581169160a08101359091169060c08101359060e001356116a9565b34801561048d57600080fd5b5061010d600480360360208110156104a457600080fd5b50356001600160a01b0316611834565b3480156104c057600080fd5b506101a7600480360360808110156104d757600080fd5b506001600160a01b038135811691602081013591604082013516906060013561184f565b34801561050757600080fd5b506101a7600480360361018081101561051f57600080fd5b506001600160a01b0381358116916020810135916040820135169060ff6060820135811691608081013582169160a08201359160c08101359160e0820135916101008101358216916101208201351690610140810135906101600135611998565b6101a7600480360360e081101561059657600080fd5b506001600160a01b038135169060208101359060408101359060ff606082013581169160808101359091169060a08101359060c00135611cd2565b6101a7600480360360608110156105e757600080fd5b506001600160a01b038135169060208101359060400135611e61565b34801561060f57600080fd5b506101a76004803603608081101561062657600080fd5b506001600160a01b0381358116916020810135916040820135169060600135611fed565b7f000000000000000000000000000000000000000000000000000000000000000081565b6001600160a01b03808a1660009081526001602052604090205416806106db576040805162461bcd60e51b815260206004820152600c60248201527f5377617020697320307830300000000000000000000000000000000000000000604482015290519081900360640190fd5b6001600160a01b03811660009081526002602090815260409182902080548351818402810184019094528084526060939283018282801561074557602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311610727575b5050505050905061078233308a848e60ff168151811061076157fe5b60200260200101516001600160a01b03166122ae909392919063ffffffff16565b604080517f9169558600000000000000000000000000000000000000000000000000000000815260ff808d1660048301528b166024820152604481018a9052606481018990526084810188905290516000916001600160a01b0385169163916955869160a48082019260209290919082900301818787803b15801561080657600080fd5b505af115801561081a573d6000803e3d6000fd5b505050506040513d602081101561083057600080fd5b5051600054604080517fdd62ed3e0000000000000000000000000000000000000000000000000000000081523060048201526001600160a01b03928316602482015290519293508392918f169163dd62ed3e91604480820192602092909190829003018186803b1580156108a357600080fd5b505afa1580156108b7573d6000803e3d6000fd5b505050506040513d60208110156108cd57600080fd5b505110156108f1576000546108f1906001600160a01b038e81169116600019612136565b60008054906101000a90046001600160a01b03166001600160a01b03166336e712ed8f8f8f858b8b8b6040518863ffffffff1660e01b815260040180886001600160a01b03168152602001878152602001866001600160a01b031681526020018581526020018460ff168152602001838152602001828152602001975050505050505050600060405180830381600087803b15801561098f57600080fd5b505af11580156109a3573d6000803e3d6000fd5b505050505050505050505050505050505050565b6109cc6001600160a01b0386163330876122ae565b600054604080517fdd62ed3e0000000000000000000000000000000000000000000000000000000081523060048201526001600160a01b0392831660248201529051869288169163dd62ed3e916044808301926020929190829003018186803b158015610a3857600080fd5b505afa158015610a4c573d6000803e3d6000fd5b505050506040513d6020811015610a6257600080fd5b50511015610a8657600054610a86906001600160a01b038781169116600019612136565b60008054604080517f36e712ed0000000000000000000000000000000000000000000000000000000081526001600160a01b038b81166004830152602482018b905289811660448301526064820189905260ff8816608483015260a4820187905260c48201869052915191909216926336e712ed9260e4808201939182900301818387803b158015610b1757600080fd5b505af1158015610b2b573d6000803e3d6000fd5b5050505050505050505050565b60026020528160005260406000208181548110610b5157fe5b6000918252602090912001546001600160a01b03169150829050565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316610be8576040805162461bcd60e51b815260206004820152600660248201527f5745544820300000000000000000000000000000000000000000000000000000604482015290519081900360640190fd5b600034118015610bf757508634145b610c48576040805162461bcd60e51b815260206004820152601360248201527f494e434f5252454354204d53472056414c554500000000000000000000000000604482015290519081900360640190fd5b6001600160a01b03808b166000908152600160205260409020541680610cb5576040805162461bcd60e51b815260206004820152600c60248201527f5377617020697320307830300000000000000000000000000000000000000000604482015290519081900360640190fd5b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663d0e30db0346040518263ffffffff1660e01b81526004016000604051808303818588803b158015610d1057600080fd5b505af1158015610d24573d6000803e3d6000fd5b50505050506000816001600160a01b031663916955868c8c8c8c8c6040518663ffffffff1660e01b8152600401808660ff1681526020018560ff16815260200184815260200183815260200182815260200195505050505050602060405180830381600087803b158015610d9757600080fd5b505af1158015610dab573d6000803e3d6000fd5b505050506040513d6020811015610dc157600080fd5b8101908080519060200190929190505050905060008054906101000a90046001600160a01b03166001600160a01b031663839ed90a8f8f8f858b8b8b8b6040518963ffffffff1660e01b815260040180896001600160a01b03168152602001888152602001876001600160a01b031681526020018681526020018560ff1681526020018460ff16815260200183815260200182815260200198505050505050505050600060405180830381600087803b15801561098f57600080fd5b610e926001600160a01b0383163330846122ae565b600054604080517fdd62ed3e0000000000000000000000000000000000000000000000000000000081523060048201526001600160a01b0392831660248201529051839285169163dd62ed3e916044808301926020929190829003018186803b158015610efe57600080fd5b505afa158015610f12573d6000803e3d6000fd5b505050506040513d6020811015610f2857600080fd5b50511015610f4c57600054610f4c906001600160a01b038481169116600019612136565b60008054604080517f49b7cf8400000000000000000000000000000000000000000000000000000000815260048101889052602481018790526001600160a01b03868116604483015260648201869052915191909216926349b7cf84926084808201939182900301818387803b158015610fc557600080fd5b505af1158015610fd9573d6000803e3d6000fd5b5050505050505050565b6001600160a01b038087166000908152600160205260409020541680611050576040805162461bcd60e51b815260206004820152600c60248201527f5377617020697320307830300000000000000000000000000000000000000000604482015290519081900360640190fd5b6001600160a01b0381166000908152600260209081526040918290208054835181840281018401909452808452606093928301828280156110ba57602002820191906000526020600020905b81546001600160a01b0316815260019091019060200180831161109c575b505050505090506110d6333087848b60ff168151811061076157fe5b604080517f9169558600000000000000000000000000000000000000000000000000000000815260ff808a1660048301528816602482015260448101879052606481018690526084810185905290516000916001600160a01b0385169163916955869160a48082019260209290919082900301818787803b15801561115a57600080fd5b505af115801561116e573d6000803e3d6000fd5b505050506040513d602081101561118457600080fd5b5051600054604080517fdd62ed3e0000000000000000000000000000000000000000000000000000000081523060048201526001600160a01b03928316602482015290519293508392918c169163dd62ed3e91604480820192602092909190829003018186803b1580156111f757600080fd5b505afa15801561120b573d6000803e3d6000fd5b505050506040513d602081101561122157600080fd5b5051101561124557600054611245906001600160a01b038b81169116600019612136565b60008054604080517ff3f094a10000000000000000000000000000000000000000000000000000000081526001600160a01b038f81166004830152602482018f90528d81166044830152606482018690529151919092169263f3f094a1926084808201939182900301818387803b1580156112bf57600080fd5b505af11580156112d3573d6000803e3d6000fd5b505050505050505050505050505050565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031661135f576040805162461bcd60e51b815260206004820152600660248201527f5745544820300000000000000000000000000000000000000000000000000000604482015290519081900360640190fd5b60003411801561136e57508234145b6113bf576040805162461bcd60e51b815260206004820152601360248201527f494e434f5252454354204d53472056414c554500000000000000000000000000604482015290519081900360640190fd5b6001600160a01b03808716600090815260016020526040902054168061142c576040805162461bcd60e51b815260206004820152600c60248201527f5377617020697320307830300000000000000000000000000000000000000000604482015290519081900360640190fd5b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663d0e30db0346040518263ffffffff1660e01b81526004016000604051808303818588803b15801561148757600080fd5b505af115801561149b573d6000803e3d6000fd5b5050604080517f9169558600000000000000000000000000000000000000000000000000000000815260ff808c1660048301528a1660248201526044810189905260648101889052608481018790529051600094506001600160a01b03861693506391695586925060a480830192602092919082900301818787803b15801561152357600080fd5b505af1158015611537573d6000803e3d6000fd5b505050506040513d602081101561154d57600080fd5b505160008054604080517ff3f094a10000000000000000000000000000000000000000000000000000000081526001600160a01b038f81166004830152602482018f90528d8116604483015260648201869052915194955091169263f3f094a19260848084019391929182900301818387803b1580156115cc57600080fd5b505af11580156115e0573d6000803e3d6000fd5b5050505050505050505050505050565b6001600160a01b0380851660009081526001602090815260408083205481517fa95b089f00000000000000000000000000000000000000000000000000000000815260ff808a1660048301528816602482015260448101879052915193941692839263a95b089f9260648082019391829003018186803b15801561167357600080fd5b505afa158015611687573d6000803e3d6000fd5b505050506040513d602081101561169d57600080fd5b50519695505050505050565b6116be6001600160a01b0387163330886122ae565b600054604080517fdd62ed3e0000000000000000000000000000000000000000000000000000000081523060048201526001600160a01b0392831660248201529051879289169163dd62ed3e916044808301926020929190829003018186803b15801561172a57600080fd5b505afa15801561173e573d6000803e3d6000fd5b505050506040513d602081101561175457600080fd5b5051101561177857600054611778906001600160a01b038881169116600019612136565b60008054604080517f839ed90a0000000000000000000000000000000000000000000000000000000081526001600160a01b038c81166004830152602482018c90528a81166044830152606482018a905260ff808a166084840152881660a483015260c4820187905260e482018690529151919092169263839ed90a92610104808201939182900301818387803b15801561181257600080fd5b505af1158015611826573d6000803e3d6000fd5b505050505050505050505050565b6001602052600090815260409020546001600160a01b031681565b6118646001600160a01b0383163330846122ae565b600054604080517fdd62ed3e0000000000000000000000000000000000000000000000000000000081523060048201526001600160a01b0392831660248201529051839285169163dd62ed3e916044808301926020929190829003018186803b1580156118d057600080fd5b505afa1580156118e4573d6000803e3d6000fd5b505050506040513d60208110156118fa57600080fd5b5051101561191e5760005461191e906001600160a01b038481169116600019612136565b60008054604080517f90d250740000000000000000000000000000000000000000000000000000000081526001600160a01b03888116600483015260248201889052868116604483015260648201869052915191909216926390d25074926084808201939182900301818387803b158015610fc557600080fd5b6001600160a01b038a811660009081526001602052604090205416611a04576040805162461bcd60e51b815260206004820152600c60248201527f5377617020697320307830300000000000000000000000000000000000000000604482015290519081900360640190fd5b6001600160a01b03808b1660009081526001602090815260408083205490931682526002815290829020805483518184028101840190945280845260609392830182828015611a7c57602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311611a5e575b50505050509050611a9833308a848e60ff168151811061076157fe5b6000600160008d6001600160a01b03166001600160a01b0316815260200190815260200160002060009054906101000a90046001600160a01b03166001600160a01b031663916955868c8c8c8c8c6040518663ffffffff1660e01b8152600401808660ff1681526020018560ff16815260200184815260200183815260200182815260200195505050505050602060405180830381600087803b158015611b3e57600080fd5b505af1158015611b52573d6000803e3d6000fd5b505050506040513d6020811015611b6857600080fd5b5051600054604080517fdd62ed3e0000000000000000000000000000000000000000000000000000000081523060048201526001600160a01b03928316602482015290519293508392918f169163dd62ed3e91604480820192602092909190829003018186803b158015611bdb57600080fd5b505afa158015611bef573d6000803e3d6000fd5b505050506040513d6020811015611c0557600080fd5b50511015611c2957600054611c29906001600160a01b038e81169116600019612136565b60008054906101000a90046001600160a01b03166001600160a01b031663839ed90a8f8f8f858b8b8b8b6040518963ffffffff1660e01b815260040180896001600160a01b03168152602001888152602001876001600160a01b031681526020018681526020018560ff1681526020018460ff16815260200183815260200182815260200198505050505050505050600060405180830381600087803b15801561098f57600080fd5b600034118015611ce157508434145b611d32576040805162461bcd60e51b815260206004820152601360248201527f494e434f5252454354204d53472056414c554500000000000000000000000000604482015290519081900360640190fd5b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663d0e30db0346040518263ffffffff1660e01b81526004016000604051808303818588803b158015611d8d57600080fd5b505af1158015611da1573d6000803e3d6000fd5b505060008054604080517fa2a2af0b0000000000000000000000000000000000000000000000000000000081526001600160a01b038e81166004830152602482018e90527f000000000000000000000000000000000000000000000000000000000000000081166044830152606482018d905260ff808d1660848401528b1660a483015260c482018a905260e48201899052915191909216955063a2a2af0b94506101048083019450909182900301818387803b158015610b1757600080fd5b600034118015611e7057508034145b611ec1576040805162461bcd60e51b815260206004820152601360248201527f494e434f5252454354204d53472056414c554500000000000000000000000000604482015290519081900360640190fd5b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663d0e30db0346040518263ffffffff1660e01b81526004016000604051808303818588803b158015611f1c57600080fd5b505af1158015611f30573d6000803e3d6000fd5b505060008054604080517f90d250740000000000000000000000000000000000000000000000000000000081526001600160a01b038a81166004830152602482018a90527f0000000000000000000000000000000000000000000000000000000000000000811660448301526064820189905291519190921695506390d25074945060848083019450909182900301818387803b158015611fd057600080fd5b505af1158015611fe4573d6000803e3d6000fd5b50505050505050565b6120026001600160a01b0383163330846122ae565b600054604080517fdd62ed3e0000000000000000000000000000000000000000000000000000000081523060048201526001600160a01b0392831660248201529051839285169163dd62ed3e916044808301926020929190829003018186803b15801561206e57600080fd5b505afa158015612082573d6000803e3d6000fd5b505050506040513d602081101561209857600080fd5b505110156120bc576000546120bc906001600160a01b038481169116600019612136565b60008054604080517ff3f094a10000000000000000000000000000000000000000000000000000000081526001600160a01b038881166004830152602482018890528681166044830152606482018690529151919092169263f3f094a1926084808201939182900301818387803b158015610fc557600080fd5b8015806121d55750604080517fdd62ed3e0000000000000000000000000000000000000000000000000000000081523060048201526001600160a01b03848116602483015291519185169163dd62ed3e91604480820192602092909190829003018186803b1580156121a757600080fd5b505afa1580156121bb573d6000803e3d6000fd5b505050506040513d60208110156121d157600080fd5b5051155b6122105760405162461bcd60e51b81526004018080602001828103825260368152602001806126626036913960400191505060405180910390fd5b604080516001600160a01b038416602482015260448082018490528251808303909101815260649091019091526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f095ea7b30000000000000000000000000000000000000000000000000000000017905261229090849061233c565b505050565b60606122a484846000856123ed565b90505b9392505050565b604080516001600160a01b0380861660248301528416604482015260648082018490528251808303909101815260849091019091526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f23b872dd0000000000000000000000000000000000000000000000000000000017905261233690859061233c565b50505050565b6060612391826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b03166122959092919063ffffffff16565b805190915015612290578080602001905160208110156123b057600080fd5b50516122905760405162461bcd60e51b815260040180806020018281038252602a815260200180612638602a913960400191505060405180910390fd5b60608247101561242e5760405162461bcd60e51b81526004018080602001828103825260268152602001806126126026913960400191505060405180910390fd5b61243785612567565b612488576040805162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000604482015290519081900360640190fd5b60006060866001600160a01b031685876040518082805190602001908083835b602083106124e557805182527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe090920191602091820191016124a8565b6001836020036101000a03801982511681845116808217855250505050505090500191505060006040518083038185875af1925050503d8060008114612547576040519150601f19603f3d011682016040523d82523d6000602084013e61254c565b606091505b509150915061255c82828661256d565b979650505050505050565b3b151590565b6060831561257c5750816122a7565b82511561258c5782518084602001fd5b8160405162461bcd60e51b81526004018080602001828103825283818151815260200191508051906020019080838360005b838110156125d65781810151838201526020016125be565b50505050905090810190601f1680156126035780820380516001836020036101000a031916815260200191505b509250505060405180910390fdfe416464726573733a20696e73756666696369656e742062616c616e636520666f722063616c6c5361666545524332303a204552433230206f7065726174696f6e20646964206e6f7420737563636565645361666545524332303a20617070726f76652066726f6d206e6f6e2d7a65726f20746f206e6f6e2d7a65726f20616c6c6f77616e6365a2646970667358221220c0cbd60ee4ae8bb12e3e27df87200ffd693bae496cf457aa6fb5b6c7684426fc64736f6c634300060c0033416464726573733a20696e73756666696369656e742062616c616e636520666f722063616c6c73776170206d7573742068617665206174206c65617374203220746f6b656e735361666545524332303a204552433230206f7065726174696f6e20646964206e6f7420737563636565645361666545524332303a20617070726f76652066726f6d206e6f6e2d7a65726f20746f206e6f6e2d7a65726f20616c6c6f77616e6365", + "deployedBytecode": "0x6080604052600436106100f35760003560e01c8063798af7201161008a5780639f330727116100595780639f330727146104fb578063a9fd8c5714610580578063ce0b63ce146105d1578063f3f094a114610603576100f3565b8063798af720146103bc578063839ed90a1461041a57806385528f0b1461048157806390d25074146104b4576100f3565b80633d5da164116100c65780633d5da1641461023e57806349b7cf84146102b65780634a517a55146102fb57806365749c9d14610362576100f3565b8063040141e5146100f8578063174dc9521461012957806336e712ed146101a9578063393494b814610205575b600080fd5b34801561010457600080fd5b5061010d61064a565b604080516001600160a01b039092168252519081900360200190f35b34801561013557600080fd5b506101a7600480360361016081101561014d57600080fd5b506001600160a01b0381358116916020810135916040820135169060ff6060820135811691608081013582169160a08201359160c08101359160e0820135916101008101359091169061012081013590610140013561066e565b005b3480156101b557600080fd5b506101a7600480360360e08110156101cc57600080fd5b506001600160a01b0381358116916020810135916040820135169060608101359060ff6080820135169060a08101359060c001356109b7565b34801561021157600080fd5b5061010d6004803603604081101561022857600080fd5b506001600160a01b038135169060200135610b38565b6101a7600480360361018081101561025557600080fd5b506001600160a01b0381358116916020810135916040820135169060ff6060820135811691608081013582169160a08201359160c08101359160e0820135916101008101358216916101208201351690610140810135906101600135610b6d565b3480156102c257600080fd5b506101a7600480360360808110156102d957600080fd5b508035906020810135906001600160a01b036040820135169060600135610e7d565b34801561030757600080fd5b506101a7600480360361010081101561031f57600080fd5b506001600160a01b0381358116916020810135916040820135169060ff606082013581169160808101359091169060a08101359060c08101359060e00135610fe3565b6101a7600480360361010081101561037957600080fd5b506001600160a01b0381358116916020810135916040820135169060ff606082013581169160808101359091169060a08101359060c08101359060e001356112e4565b3480156103c857600080fd5b50610408600480360360808110156103df57600080fd5b506001600160a01b038135169060ff6020820135811691604081013590911690606001356115f0565b60408051918252519081900360200190f35b34801561042657600080fd5b506101a7600480360361010081101561043e57600080fd5b506001600160a01b0381358116916020810135916040820135169060608101359060ff608082013581169160a08101359091169060c08101359060e001356116a9565b34801561048d57600080fd5b5061010d600480360360208110156104a457600080fd5b50356001600160a01b0316611834565b3480156104c057600080fd5b506101a7600480360360808110156104d757600080fd5b506001600160a01b038135811691602081013591604082013516906060013561184f565b34801561050757600080fd5b506101a7600480360361018081101561051f57600080fd5b506001600160a01b0381358116916020810135916040820135169060ff6060820135811691608081013582169160a08201359160c08101359160e0820135916101008101358216916101208201351690610140810135906101600135611998565b6101a7600480360360e081101561059657600080fd5b506001600160a01b038135169060208101359060408101359060ff606082013581169160808101359091169060a08101359060c00135611cd2565b6101a7600480360360608110156105e757600080fd5b506001600160a01b038135169060208101359060400135611e61565b34801561060f57600080fd5b506101a76004803603608081101561062657600080fd5b506001600160a01b0381358116916020810135916040820135169060600135611fed565b7f000000000000000000000000000000000000000000000000000000000000000081565b6001600160a01b03808a1660009081526001602052604090205416806106db576040805162461bcd60e51b815260206004820152600c60248201527f5377617020697320307830300000000000000000000000000000000000000000604482015290519081900360640190fd5b6001600160a01b03811660009081526002602090815260409182902080548351818402810184019094528084526060939283018282801561074557602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311610727575b5050505050905061078233308a848e60ff168151811061076157fe5b60200260200101516001600160a01b03166122ae909392919063ffffffff16565b604080517f9169558600000000000000000000000000000000000000000000000000000000815260ff808d1660048301528b166024820152604481018a9052606481018990526084810188905290516000916001600160a01b0385169163916955869160a48082019260209290919082900301818787803b15801561080657600080fd5b505af115801561081a573d6000803e3d6000fd5b505050506040513d602081101561083057600080fd5b5051600054604080517fdd62ed3e0000000000000000000000000000000000000000000000000000000081523060048201526001600160a01b03928316602482015290519293508392918f169163dd62ed3e91604480820192602092909190829003018186803b1580156108a357600080fd5b505afa1580156108b7573d6000803e3d6000fd5b505050506040513d60208110156108cd57600080fd5b505110156108f1576000546108f1906001600160a01b038e81169116600019612136565b60008054906101000a90046001600160a01b03166001600160a01b03166336e712ed8f8f8f858b8b8b6040518863ffffffff1660e01b815260040180886001600160a01b03168152602001878152602001866001600160a01b031681526020018581526020018460ff168152602001838152602001828152602001975050505050505050600060405180830381600087803b15801561098f57600080fd5b505af11580156109a3573d6000803e3d6000fd5b505050505050505050505050505050505050565b6109cc6001600160a01b0386163330876122ae565b600054604080517fdd62ed3e0000000000000000000000000000000000000000000000000000000081523060048201526001600160a01b0392831660248201529051869288169163dd62ed3e916044808301926020929190829003018186803b158015610a3857600080fd5b505afa158015610a4c573d6000803e3d6000fd5b505050506040513d6020811015610a6257600080fd5b50511015610a8657600054610a86906001600160a01b038781169116600019612136565b60008054604080517f36e712ed0000000000000000000000000000000000000000000000000000000081526001600160a01b038b81166004830152602482018b905289811660448301526064820189905260ff8816608483015260a4820187905260c48201869052915191909216926336e712ed9260e4808201939182900301818387803b158015610b1757600080fd5b505af1158015610b2b573d6000803e3d6000fd5b5050505050505050505050565b60026020528160005260406000208181548110610b5157fe5b6000918252602090912001546001600160a01b03169150829050565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316610be8576040805162461bcd60e51b815260206004820152600660248201527f5745544820300000000000000000000000000000000000000000000000000000604482015290519081900360640190fd5b600034118015610bf757508634145b610c48576040805162461bcd60e51b815260206004820152601360248201527f494e434f5252454354204d53472056414c554500000000000000000000000000604482015290519081900360640190fd5b6001600160a01b03808b166000908152600160205260409020541680610cb5576040805162461bcd60e51b815260206004820152600c60248201527f5377617020697320307830300000000000000000000000000000000000000000604482015290519081900360640190fd5b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663d0e30db0346040518263ffffffff1660e01b81526004016000604051808303818588803b158015610d1057600080fd5b505af1158015610d24573d6000803e3d6000fd5b50505050506000816001600160a01b031663916955868c8c8c8c8c6040518663ffffffff1660e01b8152600401808660ff1681526020018560ff16815260200184815260200183815260200182815260200195505050505050602060405180830381600087803b158015610d9757600080fd5b505af1158015610dab573d6000803e3d6000fd5b505050506040513d6020811015610dc157600080fd5b8101908080519060200190929190505050905060008054906101000a90046001600160a01b03166001600160a01b031663839ed90a8f8f8f858b8b8b8b6040518963ffffffff1660e01b815260040180896001600160a01b03168152602001888152602001876001600160a01b031681526020018681526020018560ff1681526020018460ff16815260200183815260200182815260200198505050505050505050600060405180830381600087803b15801561098f57600080fd5b610e926001600160a01b0383163330846122ae565b600054604080517fdd62ed3e0000000000000000000000000000000000000000000000000000000081523060048201526001600160a01b0392831660248201529051839285169163dd62ed3e916044808301926020929190829003018186803b158015610efe57600080fd5b505afa158015610f12573d6000803e3d6000fd5b505050506040513d6020811015610f2857600080fd5b50511015610f4c57600054610f4c906001600160a01b038481169116600019612136565b60008054604080517f49b7cf8400000000000000000000000000000000000000000000000000000000815260048101889052602481018790526001600160a01b03868116604483015260648201869052915191909216926349b7cf84926084808201939182900301818387803b158015610fc557600080fd5b505af1158015610fd9573d6000803e3d6000fd5b5050505050505050565b6001600160a01b038087166000908152600160205260409020541680611050576040805162461bcd60e51b815260206004820152600c60248201527f5377617020697320307830300000000000000000000000000000000000000000604482015290519081900360640190fd5b6001600160a01b0381166000908152600260209081526040918290208054835181840281018401909452808452606093928301828280156110ba57602002820191906000526020600020905b81546001600160a01b0316815260019091019060200180831161109c575b505050505090506110d6333087848b60ff168151811061076157fe5b604080517f9169558600000000000000000000000000000000000000000000000000000000815260ff808a1660048301528816602482015260448101879052606481018690526084810185905290516000916001600160a01b0385169163916955869160a48082019260209290919082900301818787803b15801561115a57600080fd5b505af115801561116e573d6000803e3d6000fd5b505050506040513d602081101561118457600080fd5b5051600054604080517fdd62ed3e0000000000000000000000000000000000000000000000000000000081523060048201526001600160a01b03928316602482015290519293508392918c169163dd62ed3e91604480820192602092909190829003018186803b1580156111f757600080fd5b505afa15801561120b573d6000803e3d6000fd5b505050506040513d602081101561122157600080fd5b5051101561124557600054611245906001600160a01b038b81169116600019612136565b60008054604080517ff3f094a10000000000000000000000000000000000000000000000000000000081526001600160a01b038f81166004830152602482018f90528d81166044830152606482018690529151919092169263f3f094a1926084808201939182900301818387803b1580156112bf57600080fd5b505af11580156112d3573d6000803e3d6000fd5b505050505050505050505050505050565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031661135f576040805162461bcd60e51b815260206004820152600660248201527f5745544820300000000000000000000000000000000000000000000000000000604482015290519081900360640190fd5b60003411801561136e57508234145b6113bf576040805162461bcd60e51b815260206004820152601360248201527f494e434f5252454354204d53472056414c554500000000000000000000000000604482015290519081900360640190fd5b6001600160a01b03808716600090815260016020526040902054168061142c576040805162461bcd60e51b815260206004820152600c60248201527f5377617020697320307830300000000000000000000000000000000000000000604482015290519081900360640190fd5b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663d0e30db0346040518263ffffffff1660e01b81526004016000604051808303818588803b15801561148757600080fd5b505af115801561149b573d6000803e3d6000fd5b5050604080517f9169558600000000000000000000000000000000000000000000000000000000815260ff808c1660048301528a1660248201526044810189905260648101889052608481018790529051600094506001600160a01b03861693506391695586925060a480830192602092919082900301818787803b15801561152357600080fd5b505af1158015611537573d6000803e3d6000fd5b505050506040513d602081101561154d57600080fd5b505160008054604080517ff3f094a10000000000000000000000000000000000000000000000000000000081526001600160a01b038f81166004830152602482018f90528d8116604483015260648201869052915194955091169263f3f094a19260848084019391929182900301818387803b1580156115cc57600080fd5b505af11580156115e0573d6000803e3d6000fd5b5050505050505050505050505050565b6001600160a01b0380851660009081526001602090815260408083205481517fa95b089f00000000000000000000000000000000000000000000000000000000815260ff808a1660048301528816602482015260448101879052915193941692839263a95b089f9260648082019391829003018186803b15801561167357600080fd5b505afa158015611687573d6000803e3d6000fd5b505050506040513d602081101561169d57600080fd5b50519695505050505050565b6116be6001600160a01b0387163330886122ae565b600054604080517fdd62ed3e0000000000000000000000000000000000000000000000000000000081523060048201526001600160a01b0392831660248201529051879289169163dd62ed3e916044808301926020929190829003018186803b15801561172a57600080fd5b505afa15801561173e573d6000803e3d6000fd5b505050506040513d602081101561175457600080fd5b5051101561177857600054611778906001600160a01b038881169116600019612136565b60008054604080517f839ed90a0000000000000000000000000000000000000000000000000000000081526001600160a01b038c81166004830152602482018c90528a81166044830152606482018a905260ff808a166084840152881660a483015260c4820187905260e482018690529151919092169263839ed90a92610104808201939182900301818387803b15801561181257600080fd5b505af1158015611826573d6000803e3d6000fd5b505050505050505050505050565b6001602052600090815260409020546001600160a01b031681565b6118646001600160a01b0383163330846122ae565b600054604080517fdd62ed3e0000000000000000000000000000000000000000000000000000000081523060048201526001600160a01b0392831660248201529051839285169163dd62ed3e916044808301926020929190829003018186803b1580156118d057600080fd5b505afa1580156118e4573d6000803e3d6000fd5b505050506040513d60208110156118fa57600080fd5b5051101561191e5760005461191e906001600160a01b038481169116600019612136565b60008054604080517f90d250740000000000000000000000000000000000000000000000000000000081526001600160a01b03888116600483015260248201889052868116604483015260648201869052915191909216926390d25074926084808201939182900301818387803b158015610fc557600080fd5b6001600160a01b038a811660009081526001602052604090205416611a04576040805162461bcd60e51b815260206004820152600c60248201527f5377617020697320307830300000000000000000000000000000000000000000604482015290519081900360640190fd5b6001600160a01b03808b1660009081526001602090815260408083205490931682526002815290829020805483518184028101840190945280845260609392830182828015611a7c57602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311611a5e575b50505050509050611a9833308a848e60ff168151811061076157fe5b6000600160008d6001600160a01b03166001600160a01b0316815260200190815260200160002060009054906101000a90046001600160a01b03166001600160a01b031663916955868c8c8c8c8c6040518663ffffffff1660e01b8152600401808660ff1681526020018560ff16815260200184815260200183815260200182815260200195505050505050602060405180830381600087803b158015611b3e57600080fd5b505af1158015611b52573d6000803e3d6000fd5b505050506040513d6020811015611b6857600080fd5b5051600054604080517fdd62ed3e0000000000000000000000000000000000000000000000000000000081523060048201526001600160a01b03928316602482015290519293508392918f169163dd62ed3e91604480820192602092909190829003018186803b158015611bdb57600080fd5b505afa158015611bef573d6000803e3d6000fd5b505050506040513d6020811015611c0557600080fd5b50511015611c2957600054611c29906001600160a01b038e81169116600019612136565b60008054906101000a90046001600160a01b03166001600160a01b031663839ed90a8f8f8f858b8b8b8b6040518963ffffffff1660e01b815260040180896001600160a01b03168152602001888152602001876001600160a01b031681526020018681526020018560ff1681526020018460ff16815260200183815260200182815260200198505050505050505050600060405180830381600087803b15801561098f57600080fd5b600034118015611ce157508434145b611d32576040805162461bcd60e51b815260206004820152601360248201527f494e434f5252454354204d53472056414c554500000000000000000000000000604482015290519081900360640190fd5b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663d0e30db0346040518263ffffffff1660e01b81526004016000604051808303818588803b158015611d8d57600080fd5b505af1158015611da1573d6000803e3d6000fd5b505060008054604080517fa2a2af0b0000000000000000000000000000000000000000000000000000000081526001600160a01b038e81166004830152602482018e90527f000000000000000000000000000000000000000000000000000000000000000081166044830152606482018d905260ff808d1660848401528b1660a483015260c482018a905260e48201899052915191909216955063a2a2af0b94506101048083019450909182900301818387803b158015610b1757600080fd5b600034118015611e7057508034145b611ec1576040805162461bcd60e51b815260206004820152601360248201527f494e434f5252454354204d53472056414c554500000000000000000000000000604482015290519081900360640190fd5b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663d0e30db0346040518263ffffffff1660e01b81526004016000604051808303818588803b158015611f1c57600080fd5b505af1158015611f30573d6000803e3d6000fd5b505060008054604080517f90d250740000000000000000000000000000000000000000000000000000000081526001600160a01b038a81166004830152602482018a90527f0000000000000000000000000000000000000000000000000000000000000000811660448301526064820189905291519190921695506390d25074945060848083019450909182900301818387803b158015611fd057600080fd5b505af1158015611fe4573d6000803e3d6000fd5b50505050505050565b6120026001600160a01b0383163330846122ae565b600054604080517fdd62ed3e0000000000000000000000000000000000000000000000000000000081523060048201526001600160a01b0392831660248201529051839285169163dd62ed3e916044808301926020929190829003018186803b15801561206e57600080fd5b505afa158015612082573d6000803e3d6000fd5b505050506040513d602081101561209857600080fd5b505110156120bc576000546120bc906001600160a01b038481169116600019612136565b60008054604080517ff3f094a10000000000000000000000000000000000000000000000000000000081526001600160a01b038881166004830152602482018890528681166044830152606482018690529151919092169263f3f094a1926084808201939182900301818387803b158015610fc557600080fd5b8015806121d55750604080517fdd62ed3e0000000000000000000000000000000000000000000000000000000081523060048201526001600160a01b03848116602483015291519185169163dd62ed3e91604480820192602092909190829003018186803b1580156121a757600080fd5b505afa1580156121bb573d6000803e3d6000fd5b505050506040513d60208110156121d157600080fd5b5051155b6122105760405162461bcd60e51b81526004018080602001828103825260368152602001806126626036913960400191505060405180910390fd5b604080516001600160a01b038416602482015260448082018490528251808303909101815260649091019091526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f095ea7b30000000000000000000000000000000000000000000000000000000017905261229090849061233c565b505050565b60606122a484846000856123ed565b90505b9392505050565b604080516001600160a01b0380861660248301528416604482015260648082018490528251808303909101815260849091019091526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f23b872dd0000000000000000000000000000000000000000000000000000000017905261233690859061233c565b50505050565b6060612391826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b03166122959092919063ffffffff16565b805190915015612290578080602001905160208110156123b057600080fd5b50516122905760405162461bcd60e51b815260040180806020018281038252602a815260200180612638602a913960400191505060405180910390fd5b60608247101561242e5760405162461bcd60e51b81526004018080602001828103825260268152602001806126126026913960400191505060405180910390fd5b61243785612567565b612488576040805162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000604482015290519081900360640190fd5b60006060866001600160a01b031685876040518082805190602001908083835b602083106124e557805182527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe090920191602091820191016124a8565b6001836020036101000a03801982511681845116808217855250505050505090500191505060006040518083038185875af1925050503d8060008114612547576040519150601f19603f3d011682016040523d82523d6000602084013e61254c565b606091505b509150915061255c82828661256d565b979650505050505050565b3b151590565b6060831561257c5750816122a7565b82511561258c5782518084602001fd5b8160405162461bcd60e51b81526004018080602001828103825283818151815260200191508051906020019080838360005b838110156125d65781810151838201526020016125be565b50505050905090810190601f1680156126035780820380516001836020036101000a031916815260200191505b509250505060405180910390fdfe416464726573733a20696e73756666696369656e742062616c616e636520666f722063616c6c5361666545524332303a204552433230206f7065726174696f6e20646964206e6f7420737563636565645361666545524332303a20617070726f76652066726f6d206e6f6e2d7a65726f20746f206e6f6e2d7a65726f20616c6c6f77616e6365a2646970667358221220c0cbd60ee4ae8bb12e3e27df87200ffd693bae496cf457aa6fb5b6c7684426fc64736f6c634300060c0033", "devdoc": { "kind": "dev", "methods": { @@ -676,6 +826,24 @@ "token": "ERC20 compatible token to deposit into the bridge" } }, + "depositETH(address,uint256,uint256)": { + "params": { + "amount": "Amount in native token decimals to transfer cross-chain pre-fees*", + "chainId": "which chain to bridge assets onto", + "to": "address on other chain to bridge assets to" + } + }, + "depositETHAndSwap(address,uint256,uint256,uint8,uint8,uint256,uint256)": { + "params": { + "amount": "Amount in native token decimals to transfer cross-chain pre-fees", + "chainId": "which chain to bridge assets onto", + "deadline": "latest timestamp to accept this transaction*", + "minDy": "the min amount the user would like to receive, or revert to only minting the SynERC20 token crosschain.", + "to": "address on other chain to bridge assets to", + "tokenIndexFrom": "the token the user wants to swap from", + "tokenIndexTo": "the token the user wants to swap to" + } + }, "redeem(address,uint256,address,uint256)": { "params": { "amount": "Amount in native token decimals to transfer cross-chain pre-fees*", @@ -706,6 +874,14 @@ "tokenIndexFrom": "the token the user wants to swap from", "tokenIndexTo": "the token the user wants to swap to" } + }, + "redeemv2(bytes32,uint256,address,uint256)": { + "params": { + "amount": "Amount in native token decimals to transfer cross-chain pre-fees*", + "chainId": "which chain to bridge assets onto", + "to": "address on other chain to bridge assets to", + "token": "ERC20 compatible token to redeem into the bridge" + } } }, "version": 1 @@ -719,6 +895,12 @@ "deposit(address,uint256,address,uint256)": { "notice": "wraps SynapseBridge redeem()" }, + "depositETH(address,uint256,uint256)": { + "notice": "Wraps SynapseBridge deposit() function to make it compatible w/ ETH -> WETH conversions" + }, + "depositETHAndSwap(address,uint256,uint256,uint8,uint8,uint256,uint256)": { + "notice": "Wraps SynapseBridge depositAndSwap() function to make it compatible w/ ETH -> WETH conversions" + }, "redeem(address,uint256,address,uint256)": { "notice": "wraps SynapseBridge redeem()" }, @@ -727,6 +909,9 @@ }, "redeemAndSwap(address,uint256,address,uint256,uint8,uint8,uint256,uint256)": { "notice": "Wraps redeemAndSwap on SynapseBridge.sol Relays to nodes that (typically) a wrapped synAsset ERC20 token has been burned and the underlying needs to be redeeemed on the native chain. This function indicates to the nodes that they should attempt to redeem the LP token for the underlying assets (E.g \"swap\" out of the LP token)" + }, + "redeemv2(bytes32,uint256,address,uint256)": { + "notice": "Wraps SynapseBridge redeemv2() function" } }, "version": 1 @@ -734,15 +919,15 @@ "storageLayout": { "storage": [ { - "astId": 22273, + "astId": 24361, "contract": "contracts/bridge/wrappers/L2BridgeZap.sol:L2BridgeZap", "label": "synapseBridge", "offset": 0, "slot": "0", - "type": "t_contract(ISynapseBridge)21521" + "type": "t_contract(ISynapseBridge)20970" }, { - "astId": 22279, + "astId": 24367, "contract": "contracts/bridge/wrappers/L2BridgeZap.sol:L2BridgeZap", "label": "swapMap", "offset": 0, @@ -750,7 +935,7 @@ "type": "t_mapping(t_address,t_address)" }, { - "astId": 22284, + "astId": 24372, "contract": "contracts/bridge/wrappers/L2BridgeZap.sol:L2BridgeZap", "label": "swapTokensMap", "offset": 0, @@ -775,7 +960,7 @@ "label": "contract IERC20", "numberOfBytes": "20" }, - "t_contract(ISynapseBridge)21521": { + "t_contract(ISynapseBridge)20970": { "encoding": "inplace", "label": "contract ISynapseBridge", "numberOfBytes": "20" diff --git a/deployments/optimism/nUSDPoolV3-LPToken.json b/deployments/optimism/nUSDPoolV3-LPToken.json new file mode 100644 index 000000000..1d73f5c89 --- /dev/null +++ b/deployments/optimism/nUSDPoolV3-LPToken.json @@ -0,0 +1,668 @@ +{ + "address": "0x2c6d91accC5Aa38c84653F28A80AEC69325BDd12", + "abi": [ + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "Approval", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "bytes32", + "name": "previousAdminRole", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "bytes32", + "name": "newAdminRole", + "type": "bytes32" + } + ], + "name": "RoleAdminChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "sender", + "type": "address" + } + ], + "name": "RoleGranted", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "sender", + "type": "address" + } + ], + "name": "RoleRevoked", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "Transfer", + "type": "event" + }, + { + "inputs": [], + "name": "DEFAULT_ADMIN_ROLE", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "DOMAIN_SEPARATOR", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "MINTER_ROLE", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "address", + "name": "spender", + "type": "address" + } + ], + "name": "allowance", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "approve", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "balanceOf", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "burn", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "burnFrom", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "decimals", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "subtractedValue", + "type": "uint256" + } + ], + "name": "decreaseAllowance", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + } + ], + "name": "getRoleAdmin", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "internalType": "uint256", + "name": "index", + "type": "uint256" + } + ], + "name": "getRoleMember", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + } + ], + "name": "getRoleMemberCount", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "grantRole", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "hasRole", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "addedValue", + "type": "uint256" + } + ], + "name": "increaseAllowance", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "name", + "type": "string" + }, + { + "internalType": "string", + "name": "symbol", + "type": "string" + }, + { + "internalType": "uint8", + "name": "decimals", + "type": "uint8" + }, + { + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "initialize", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "mint", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "name", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "nonces", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" + }, + { + "internalType": "uint8", + "name": "v", + "type": "uint8" + }, + { + "internalType": "bytes32", + "name": "r", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "s", + "type": "bytes32" + } + ], + "name": "permit", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "renounceRole", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "revokeRole", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "symbol", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "totalSupply", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "recipient", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "transfer", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "internalType": "address", + "name": "recipient", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "transferFrom", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + } + ] +} \ No newline at end of file diff --git a/deployments/optimism/nUSDPoolV3.json b/deployments/optimism/nUSDPoolV3.json new file mode 100644 index 000000000..65825e900 --- /dev/null +++ b/deployments/optimism/nUSDPoolV3.json @@ -0,0 +1,1001 @@ +{ + "address": "0xF44938b0125A6662f9536281aD2CD6c499F22004", + "abi": [ + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "provider", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256[]", + "name": "tokenAmounts", + "type": "uint256[]" + }, + { + "indexed": false, + "internalType": "uint256[]", + "name": "fees", + "type": "uint256[]" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "invariant", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "lpTokenSupply", + "type": "uint256" + } + ], + "name": "AddLiquidity", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "receiver", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint8", + "name": "tokenIndex", + "type": "uint8" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amountFee", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "protocolFee", + "type": "uint256" + } + ], + "name": "FlashLoan", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "newAdminFee", + "type": "uint256" + } + ], + "name": "NewAdminFee", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "newSwapFee", + "type": "uint256" + } + ], + "name": "NewSwapFee", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "previousOwner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "OwnershipTransferred", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "Paused", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "oldA", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newA", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "initialTime", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "futureTime", + "type": "uint256" + } + ], + "name": "RampA", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "provider", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256[]", + "name": "tokenAmounts", + "type": "uint256[]" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "lpTokenSupply", + "type": "uint256" + } + ], + "name": "RemoveLiquidity", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "provider", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256[]", + "name": "tokenAmounts", + "type": "uint256[]" + }, + { + "indexed": false, + "internalType": "uint256[]", + "name": "fees", + "type": "uint256[]" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "invariant", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "lpTokenSupply", + "type": "uint256" + } + ], + "name": "RemoveLiquidityImbalance", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "provider", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "lpTokenAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "lpTokenSupply", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "boughtId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "tokensBought", + "type": "uint256" + } + ], + "name": "RemoveLiquidityOne", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "currentA", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "time", + "type": "uint256" + } + ], + "name": "StopRampA", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "buyer", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "tokensSold", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "tokensBought", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint128", + "name": "soldId", + "type": "uint128" + }, + { + "indexed": false, + "internalType": "uint128", + "name": "boughtId", + "type": "uint128" + } + ], + "name": "TokenSwap", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "Unpaused", + "type": "event" + }, + { + "inputs": [], + "name": "MAX_BPS", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256[]", + "name": "amounts", + "type": "uint256[]" + }, + { + "internalType": "uint256", + "name": "minToMint", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" + } + ], + "name": "addLiquidity", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "calculateRemoveLiquidity", + "outputs": [ + { + "internalType": "uint256[]", + "name": "", + "type": "uint256[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "tokenAmount", + "type": "uint256" + }, + { + "internalType": "uint8", + "name": "tokenIndex", + "type": "uint8" + } + ], + "name": "calculateRemoveLiquidityOneToken", + "outputs": [ + { + "internalType": "uint256", + "name": "availableTokenAmount", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint8", + "name": "tokenIndexFrom", + "type": "uint8" + }, + { + "internalType": "uint8", + "name": "tokenIndexTo", + "type": "uint8" + }, + { + "internalType": "uint256", + "name": "dx", + "type": "uint256" + } + ], + "name": "calculateSwap", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256[]", + "name": "amounts", + "type": "uint256[]" + }, + { + "internalType": "bool", + "name": "deposit", + "type": "bool" + } + ], + "name": "calculateTokenAmount", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "receiver", + "type": "address" + }, + { + "internalType": "contract IERC20", + "name": "token", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "params", + "type": "bytes" + } + ], + "name": "flashLoan", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "flashLoanFeeBPS", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getA", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getAPrecise", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "index", + "type": "uint256" + } + ], + "name": "getAdminBalance", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint8", + "name": "index", + "type": "uint8" + } + ], + "name": "getToken", + "outputs": [ + { + "internalType": "contract IERC20", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint8", + "name": "index", + "type": "uint8" + } + ], + "name": "getTokenBalance", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "tokenAddress", + "type": "address" + } + ], + "name": "getTokenIndex", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getVirtualPrice", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract IERC20[]", + "name": "_pooledTokens", + "type": "address[]" + }, + { + "internalType": "uint8[]", + "name": "decimals", + "type": "uint8[]" + }, + { + "internalType": "string", + "name": "lpTokenName", + "type": "string" + }, + { + "internalType": "string", + "name": "lpTokenSymbol", + "type": "string" + }, + { + "internalType": "uint256", + "name": "_a", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_fee", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_adminFee", + "type": "uint256" + }, + { + "internalType": "address", + "name": "lpTokenTargetAddress", + "type": "address" + } + ], + "name": "initialize", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "pause", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "paused", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "protocolFeeShareBPS", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "futureA", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "futureTime", + "type": "uint256" + } + ], + "name": "rampA", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "internalType": "uint256[]", + "name": "minAmounts", + "type": "uint256[]" + }, + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" + } + ], + "name": "removeLiquidity", + "outputs": [ + { + "internalType": "uint256[]", + "name": "", + "type": "uint256[]" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256[]", + "name": "amounts", + "type": "uint256[]" + }, + { + "internalType": "uint256", + "name": "maxBurnAmount", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" + } + ], + "name": "removeLiquidityImbalance", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "tokenAmount", + "type": "uint256" + }, + { + "internalType": "uint8", + "name": "tokenIndex", + "type": "uint8" + }, + { + "internalType": "uint256", + "name": "minAmount", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" + } + ], + "name": "removeLiquidityOneToken", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "renounceOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "newAdminFee", + "type": "uint256" + } + ], + "name": "setAdminFee", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "newFlashLoanFeeBPS", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "newProtocolFeeShareBPS", + "type": "uint256" + } + ], + "name": "setFlashLoanFees", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "newSwapFee", + "type": "uint256" + } + ], + "name": "setSwapFee", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "stopRampA", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint8", + "name": "tokenIndexFrom", + "type": "uint8" + }, + { + "internalType": "uint8", + "name": "tokenIndexTo", + "type": "uint8" + }, + { + "internalType": "uint256", + "name": "dx", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "minDy", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" + } + ], + "name": "swap", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "swapStorage", + "outputs": [ + { + "internalType": "uint256", + "name": "initialA", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "futureA", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "initialATime", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "futureATime", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "swapFee", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "adminFee", + "type": "uint256" + }, + { + "internalType": "contract LPToken", + "name": "lpToken", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "unpause", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "withdrawAdminFees", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } + ] +} \ No newline at end of file diff --git a/deployments/optimism/solcInputs/c16492a84c84927e5b757d9d97068ec0.json b/deployments/optimism/solcInputs/c16492a84c84927e5b757d9d97068ec0.json new file mode 100644 index 000000000..7c895e2bf --- /dev/null +++ b/deployments/optimism/solcInputs/c16492a84c84927e5b757d9d97068ec0.json @@ -0,0 +1,301 @@ +{ + "language": "Solidity", + "sources": { + "contracts/amm/AaveSwap.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.6.12;\n\nimport \"./Swap.sol\";\n\n/**\n * @title AaveSwap - A StableSwap implementation in solidity, integrated with Aave.\n * @notice This contract is responsible for custody of closely pegged assets (eg. group of stablecoins)\n * and automatic market making system. Users become an LP (Liquidity Provider) by depositing their tokens\n * in desired ratios for an exchange of the pool token that represents their share of the pool.\n * Users can burn pool tokens and withdraw their share of token(s).\n *\n * Each time a swap between the pooled tokens happens, a set fee incurs which effectively gets\n * distributed to the LPs.\n *\n * In case of emergencies, admin can pause additional deposits, swaps, or single-asset withdraws - which\n * stops the ratio of the tokens in the pool from changing.\n * Users can always withdraw their tokens via multi-asset withdraws.\n *\n * @dev Most of the logic is stored as a library `SwapUtils` for the sake of reducing contract's\n * deployment size.\n */\n\ncontract AaveSwap is Swap {\n address internal AAVE_REWARDS;\n address internal AAVE_LENDING_POOL;\n address internal REWARD_TOKEN;\n address internal REWARD_RECEIVER;\n address[] internal AAVE_ASSETS;\n\n /**\n * @notice Initializes this Swap contract with the given parameters.\n * This will also clone a LPToken contract that represents users'\n * LP positions. The owner of LPToken will be this contract - which means\n * only this contract is allowed to mint/burn tokens.\n *\n * @param _pooledTokens an array of ERC20s this pool will accept\n * @param decimals the decimals to use for each pooled token,\n * eg 8 for WBTC. Cannot be larger than POOL_PRECISION_DECIMALS\n * @param lpTokenName the long-form name of the token to be deployed\n * @param lpTokenSymbol the short symbol for the token to be deployed\n * @param _a the amplification coefficient * n * (n - 1). See the\n * StableSwap paper for details\n * @param _fee default swap fee to be initialized with\n * @param _adminFee default adminFee to be initialized with\n * @param lpTokenTargetAddress the address of an existing LPToken contract to use as a target\n */\n function initialize(\n IERC20[] memory _pooledTokens,\n uint8[] memory decimals,\n string memory lpTokenName,\n string memory lpTokenSymbol,\n uint256 _a,\n uint256 _fee,\n uint256 _adminFee,\n address lpTokenTargetAddress\n ) public virtual override initializer {\n Swap.initialize(\n _pooledTokens,\n decimals,\n lpTokenName,\n lpTokenSymbol,\n _a,\n _fee,\n _adminFee,\n lpTokenTargetAddress\n );\n AAVE_REWARDS = 0x01D83Fe6A10D2f2B7AF17034343746188272cAc9;\n AAVE_LENDING_POOL = 0x4F01AeD16D97E3aB5ab2B501154DC9bb0F1A5A2C;\n REWARD_TOKEN = 0xB31f66AA3C1e785363F0875A1B74E27b85FD66c7;\n AAVE_ASSETS = [0x53f7c5869a859F0AeC3D334ee8B4Cf01E3492f21];\n REWARD_RECEIVER = msg.sender;\n }\n\n function setRewardReceiver(address _reward_receiver) external onlyOwner {\n REWARD_RECEIVER = _reward_receiver;\n }\n\n function claimAaveRewards() external {\n AAVE_REWARDS.call(\n abi.encodeWithSignature(\n \"claimRewards(address[],uint256,address)\",\n AAVE_ASSETS,\n type(uint256).max,\n REWARD_RECEIVER\n )\n );\n }\n}\n" + }, + "contracts/amm/Swap.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.6.12;\n\nimport \"@openzeppelin/contracts/math/SafeMath.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/SafeERC20.sol\";\nimport \"@openzeppelin/contracts/proxy/Clones.sol\";\nimport \"@openzeppelin/contracts-upgradeable/utils/ReentrancyGuardUpgradeable.sol\";\nimport \"./OwnerPausableUpgradeable.sol\";\nimport \"./SwapUtils.sol\";\nimport \"./AmplificationUtils.sol\";\n\n/**\n * @title Swap - A StableSwap implementation in solidity.\n * @notice This contract is responsible for custody of closely pegged assets (eg. group of stablecoins)\n * and automatic market making system. Users become an LP (Liquidity Provider) by depositing their tokens\n * in desired ratios for an exchange of the pool token that represents their share of the pool.\n * Users can burn pool tokens and withdraw their share of token(s).\n *\n * Each time a swap between the pooled tokens happens, a set fee incurs which effectively gets\n * distributed to the LPs.\n *\n * In case of emergencies, admin can pause additional deposits, swaps, or single-asset withdraws - which\n * stops the ratio of the tokens in the pool from changing.\n * Users can always withdraw their tokens via multi-asset withdraws.\n *\n * @dev Most of the logic is stored as a library `SwapUtils` for the sake of reducing contract's\n * deployment size.\n */\ncontract Swap is OwnerPausableUpgradeable, ReentrancyGuardUpgradeable {\n using SafeERC20 for IERC20;\n using SafeMath for uint256;\n using SwapUtils for SwapUtils.Swap;\n using AmplificationUtils for SwapUtils.Swap;\n\n // Struct storing data responsible for automatic market maker functionalities. In order to\n // access this data, this contract uses SwapUtils library. For more details, see SwapUtils.sol\n SwapUtils.Swap public swapStorage;\n\n // Maps token address to an index in the pool. Used to prevent duplicate tokens in the pool.\n // getTokenIndex function also relies on this mapping to retrieve token index.\n mapping(address => uint8) private tokenIndexes;\n\n /*** EVENTS ***/\n\n // events replicated from SwapUtils to make the ABI easier for dumb\n // clients\n event TokenSwap(\n address indexed buyer,\n uint256 tokensSold,\n uint256 tokensBought,\n uint128 soldId,\n uint128 boughtId\n );\n event AddLiquidity(\n address indexed provider,\n uint256[] tokenAmounts,\n uint256[] fees,\n uint256 invariant,\n uint256 lpTokenSupply\n );\n event RemoveLiquidity(\n address indexed provider,\n uint256[] tokenAmounts,\n uint256 lpTokenSupply\n );\n event RemoveLiquidityOne(\n address indexed provider,\n uint256 lpTokenAmount,\n uint256 lpTokenSupply,\n uint256 boughtId,\n uint256 tokensBought\n );\n event RemoveLiquidityImbalance(\n address indexed provider,\n uint256[] tokenAmounts,\n uint256[] fees,\n uint256 invariant,\n uint256 lpTokenSupply\n );\n event NewAdminFee(uint256 newAdminFee);\n event NewSwapFee(uint256 newSwapFee);\n event RampA(\n uint256 oldA,\n uint256 newA,\n uint256 initialTime,\n uint256 futureTime\n );\n event StopRampA(uint256 currentA, uint256 time);\n\n /**\n * @notice Initializes this Swap contract with the given parameters.\n * This will also clone a LPToken contract that represents users'\n * LP positions. The owner of LPToken will be this contract - which means\n * only this contract is allowed to mint/burn tokens.\n *\n * @param _pooledTokens an array of ERC20s this pool will accept\n * @param decimals the decimals to use for each pooled token,\n * eg 8 for WBTC. Cannot be larger than POOL_PRECISION_DECIMALS\n * @param lpTokenName the long-form name of the token to be deployed\n * @param lpTokenSymbol the short symbol for the token to be deployed\n * @param _a the amplification coefficient * n * (n - 1). See the\n * StableSwap paper for details\n * @param _fee default swap fee to be initialized with\n * @param _adminFee default adminFee to be initialized with\n * @param lpTokenTargetAddress the address of an existing LPToken contract to use as a target\n */\n function initialize(\n IERC20[] memory _pooledTokens,\n uint8[] memory decimals,\n string memory lpTokenName,\n string memory lpTokenSymbol,\n uint256 _a,\n uint256 _fee,\n uint256 _adminFee,\n address lpTokenTargetAddress\n ) public virtual initializer {\n __OwnerPausable_init();\n __ReentrancyGuard_init();\n // Check _pooledTokens and precisions parameter\n require(_pooledTokens.length > 1, \"_pooledTokens.length <= 1\");\n require(_pooledTokens.length <= 32, \"_pooledTokens.length > 32\");\n require(\n _pooledTokens.length == decimals.length,\n \"_pooledTokens decimals mismatch\"\n );\n\n uint256[] memory precisionMultipliers = new uint256[](decimals.length);\n\n for (uint8 i = 0; i < _pooledTokens.length; i++) {\n if (i > 0) {\n // Check if index is already used. Check if 0th element is a duplicate.\n require(\n tokenIndexes[address(_pooledTokens[i])] == 0 &&\n _pooledTokens[0] != _pooledTokens[i],\n \"Duplicate tokens\"\n );\n }\n require(\n address(_pooledTokens[i]) != address(0),\n \"The 0 address isn't an ERC-20\"\n );\n require(\n decimals[i] <= SwapUtils.POOL_PRECISION_DECIMALS,\n \"Token decimals exceeds max\"\n );\n precisionMultipliers[i] =\n 10 **\n uint256(SwapUtils.POOL_PRECISION_DECIMALS).sub(\n uint256(decimals[i])\n );\n tokenIndexes[address(_pooledTokens[i])] = i;\n }\n\n // Check _a, _fee, _adminFee parameters\n require(_a < AmplificationUtils.MAX_A, \"_a exceeds maximum\");\n require(_fee < SwapUtils.MAX_SWAP_FEE, \"_fee exceeds maximum\");\n require(\n _adminFee < SwapUtils.MAX_ADMIN_FEE,\n \"_adminFee exceeds maximum\"\n );\n\n // Clone and initialize a LPToken contract\n LPToken lpToken = LPToken(Clones.clone(lpTokenTargetAddress));\n require(\n lpToken.initialize(lpTokenName, lpTokenSymbol),\n \"could not init lpToken clone\"\n );\n\n // Initialize swapStorage struct\n swapStorage.lpToken = lpToken;\n swapStorage.pooledTokens = _pooledTokens;\n swapStorage.tokenPrecisionMultipliers = precisionMultipliers;\n swapStorage.balances = new uint256[](_pooledTokens.length);\n swapStorage.initialA = _a.mul(AmplificationUtils.A_PRECISION);\n swapStorage.futureA = _a.mul(AmplificationUtils.A_PRECISION);\n // swapStorage.initialATime = 0;\n // swapStorage.futureATime = 0;\n swapStorage.swapFee = _fee;\n swapStorage.adminFee = _adminFee;\n }\n\n /*** MODIFIERS ***/\n\n /**\n * @notice Modifier to check deadline against current timestamp\n * @param deadline latest timestamp to accept this transaction\n */\n modifier deadlineCheck(uint256 deadline) {\n require(block.timestamp <= deadline, \"Deadline not met\");\n _;\n }\n\n /*** VIEW FUNCTIONS ***/\n\n /**\n * @notice Return A, the amplification coefficient * n * (n - 1)\n * @dev See the StableSwap paper for details\n * @return A parameter\n */\n function getA() external view virtual returns (uint256) {\n return swapStorage.getA();\n }\n\n /**\n * @notice Return A in its raw precision form\n * @dev See the StableSwap paper for details\n * @return A parameter in its raw precision form\n */\n function getAPrecise() external view virtual returns (uint256) {\n return swapStorage.getAPrecise();\n }\n\n /**\n * @notice Return address of the pooled token at given index. Reverts if tokenIndex is out of range.\n * @param index the index of the token\n * @return address of the token at given index\n */\n function getToken(uint8 index) public view virtual returns (IERC20) {\n require(index < swapStorage.pooledTokens.length, \"Out of range\");\n return swapStorage.pooledTokens[index];\n }\n\n /**\n * @notice Return the index of the given token address. Reverts if no matching\n * token is found.\n * @param tokenAddress address of the token\n * @return the index of the given token address\n */\n function getTokenIndex(address tokenAddress)\n public\n view\n virtual\n returns (uint8)\n {\n uint8 index = tokenIndexes[tokenAddress];\n require(\n address(getToken(index)) == tokenAddress,\n \"Token does not exist\"\n );\n return index;\n }\n\n /**\n * @notice Return current balance of the pooled token at given index\n * @param index the index of the token\n * @return current balance of the pooled token at given index with token's native precision\n */\n function getTokenBalance(uint8 index)\n external\n view\n virtual\n returns (uint256)\n {\n require(index < swapStorage.pooledTokens.length, \"Index out of range\");\n return swapStorage.balances[index];\n }\n\n /**\n * @notice Get the virtual price, to help calculate profit\n * @return the virtual price, scaled to the POOL_PRECISION_DECIMALS\n */\n function getVirtualPrice() external view virtual returns (uint256) {\n return swapStorage.getVirtualPrice();\n }\n\n /**\n * @notice Calculate amount of tokens you receive on swap\n * @param tokenIndexFrom the token the user wants to sell\n * @param tokenIndexTo the token the user wants to buy\n * @param dx the amount of tokens the user wants to sell. If the token charges\n * a fee on transfers, use the amount that gets transferred after the fee.\n * @return amount of tokens the user will receive\n */\n function calculateSwap(\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx\n ) external view virtual returns (uint256) {\n return swapStorage.calculateSwap(tokenIndexFrom, tokenIndexTo, dx);\n }\n\n /**\n * @notice A simple method to calculate prices from deposits or\n * withdrawals, excluding fees but including slippage. This is\n * helpful as an input into the various \"min\" parameters on calls\n * to fight front-running\n *\n * @dev This shouldn't be used outside frontends for user estimates.\n *\n * @param amounts an array of token amounts to deposit or withdrawal,\n * corresponding to pooledTokens. The amount should be in each\n * pooled token's native precision. If a token charges a fee on transfers,\n * use the amount that gets transferred after the fee.\n * @param deposit whether this is a deposit or a withdrawal\n * @return token amount the user will receive\n */\n function calculateTokenAmount(uint256[] calldata amounts, bool deposit)\n external\n view\n virtual\n returns (uint256)\n {\n return swapStorage.calculateTokenAmount(amounts, deposit);\n }\n\n /**\n * @notice A simple method to calculate amount of each underlying\n * tokens that is returned upon burning given amount of LP tokens\n * @param amount the amount of LP tokens that would be burned on withdrawal\n * @return array of token balances that the user will receive\n */\n function calculateRemoveLiquidity(uint256 amount)\n external\n view\n virtual\n returns (uint256[] memory)\n {\n return swapStorage.calculateRemoveLiquidity(amount);\n }\n\n /**\n * @notice Calculate the amount of underlying token available to withdraw\n * when withdrawing via only single token\n * @param tokenAmount the amount of LP token to burn\n * @param tokenIndex index of which token will be withdrawn\n * @return availableTokenAmount calculated amount of underlying token\n * available to withdraw\n */\n function calculateRemoveLiquidityOneToken(\n uint256 tokenAmount,\n uint8 tokenIndex\n ) external view virtual returns (uint256 availableTokenAmount) {\n return swapStorage.calculateWithdrawOneToken(tokenAmount, tokenIndex);\n }\n\n /**\n * @notice This function reads the accumulated amount of admin fees of the token with given index\n * @param index Index of the pooled token\n * @return admin's token balance in the token's precision\n */\n function getAdminBalance(uint256 index)\n external\n view\n virtual\n returns (uint256)\n {\n return swapStorage.getAdminBalance(index);\n }\n\n /*** STATE MODIFYING FUNCTIONS ***/\n\n /**\n * @notice Swap two tokens using this pool\n * @param tokenIndexFrom the token the user wants to swap from\n * @param tokenIndexTo the token the user wants to swap to\n * @param dx the amount of tokens the user wants to swap from\n * @param minDy the min amount the user would like to receive, or revert.\n * @param deadline latest timestamp to accept this transaction\n */\n function swap(\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx,\n uint256 minDy,\n uint256 deadline\n )\n external\n virtual\n nonReentrant\n whenNotPaused\n deadlineCheck(deadline)\n returns (uint256)\n {\n return swapStorage.swap(tokenIndexFrom, tokenIndexTo, dx, minDy);\n }\n\n /**\n * @notice Add liquidity to the pool with the given amounts of tokens\n * @param amounts the amounts of each token to add, in their native precision\n * @param minToMint the minimum LP tokens adding this amount of liquidity\n * should mint, otherwise revert. Handy for front-running mitigation\n * @param deadline latest timestamp to accept this transaction\n * @return amount of LP token user minted and received\n */\n function addLiquidity(\n uint256[] calldata amounts,\n uint256 minToMint,\n uint256 deadline\n )\n external\n virtual\n nonReentrant\n whenNotPaused\n deadlineCheck(deadline)\n returns (uint256)\n {\n return swapStorage.addLiquidity(amounts, minToMint);\n }\n\n /**\n * @notice Burn LP tokens to remove liquidity from the pool. Withdraw fee that decays linearly\n * over period of 4 weeks since last deposit will apply.\n * @dev Liquidity can always be removed, even when the pool is paused.\n * @param amount the amount of LP tokens to burn\n * @param minAmounts the minimum amounts of each token in the pool\n * acceptable for this burn. Useful as a front-running mitigation\n * @param deadline latest timestamp to accept this transaction\n * @return amounts of tokens user received\n */\n function removeLiquidity(\n uint256 amount,\n uint256[] calldata minAmounts,\n uint256 deadline\n )\n external\n virtual\n nonReentrant\n deadlineCheck(deadline)\n returns (uint256[] memory)\n {\n return swapStorage.removeLiquidity(amount, minAmounts);\n }\n\n /**\n * @notice Remove liquidity from the pool all in one token. Withdraw fee that decays linearly\n * over period of 4 weeks since last deposit will apply.\n * @param tokenAmount the amount of the token you want to receive\n * @param tokenIndex the index of the token you want to receive\n * @param minAmount the minimum amount to withdraw, otherwise revert\n * @param deadline latest timestamp to accept this transaction\n * @return amount of chosen token user received\n */\n function removeLiquidityOneToken(\n uint256 tokenAmount,\n uint8 tokenIndex,\n uint256 minAmount,\n uint256 deadline\n )\n external\n virtual\n nonReentrant\n whenNotPaused\n deadlineCheck(deadline)\n returns (uint256)\n {\n return\n swapStorage.removeLiquidityOneToken(\n tokenAmount,\n tokenIndex,\n minAmount\n );\n }\n\n /**\n * @notice Remove liquidity from the pool, weighted differently than the\n * pool's current balances. Withdraw fee that decays linearly\n * over period of 4 weeks since last deposit will apply.\n * @param amounts how much of each token to withdraw\n * @param maxBurnAmount the max LP token provider is willing to pay to\n * remove liquidity. Useful as a front-running mitigation.\n * @param deadline latest timestamp to accept this transaction\n * @return amount of LP tokens burned\n */\n function removeLiquidityImbalance(\n uint256[] calldata amounts,\n uint256 maxBurnAmount,\n uint256 deadline\n )\n external\n virtual\n nonReentrant\n whenNotPaused\n deadlineCheck(deadline)\n returns (uint256)\n {\n return swapStorage.removeLiquidityImbalance(amounts, maxBurnAmount);\n }\n\n /*** ADMIN FUNCTIONS ***/\n\n /**\n * @notice Withdraw all admin fees to the contract owner\n */\n function withdrawAdminFees() external onlyOwner {\n swapStorage.withdrawAdminFees(owner());\n }\n\n /**\n * @notice Update the admin fee. Admin fee takes portion of the swap fee.\n * @param newAdminFee new admin fee to be applied on future transactions\n */\n function setAdminFee(uint256 newAdminFee) external onlyOwner {\n swapStorage.setAdminFee(newAdminFee);\n }\n\n /**\n * @notice Update the swap fee to be applied on swaps\n * @param newSwapFee new swap fee to be applied on future transactions\n */\n function setSwapFee(uint256 newSwapFee) external onlyOwner {\n swapStorage.setSwapFee(newSwapFee);\n }\n\n /**\n * @notice Start ramping up or down A parameter towards given futureA and futureTime\n * Checks if the change is too rapid, and commits the new A value only when it falls under\n * the limit range.\n * @param futureA the new A to ramp towards\n * @param futureTime timestamp when the new A should be reached\n */\n function rampA(uint256 futureA, uint256 futureTime) external onlyOwner {\n swapStorage.rampA(futureA, futureTime);\n }\n\n /**\n * @notice Stop ramping A immediately. Reverts if ramp A is already stopped.\n */\n function stopRampA() external onlyOwner {\n swapStorage.stopRampA();\n }\n}\n" + }, + "@openzeppelin/contracts/math/SafeMath.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <0.8.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" + }, + "@openzeppelin/contracts/token/ERC20/SafeERC20.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <0.8.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" + }, + "@openzeppelin/contracts/proxy/Clones.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <0.8.0;\n\n/**\n * @dev https://eips.ethereum.org/EIPS/eip-1167[EIP 1167] is a standard for\n * deploying minimal proxy contracts, also known as \"clones\".\n *\n * > To simply and cheaply clone contract functionality in an immutable way, this standard specifies\n * > a minimal bytecode implementation that delegates all calls to a known, fixed address.\n *\n * The library includes functions to deploy a proxy using either `create` (traditional deployment) or `create2`\n * (salted deterministic deployment). It also includes functions to predict the addresses of clones deployed using the\n * deterministic method.\n *\n * _Available since v3.4._\n */\nlibrary Clones {\n /**\n * @dev Deploys and returns the address of a clone that mimics the behaviour of `master`.\n *\n * This function uses the create opcode, which should never revert.\n */\n function clone(address master) internal returns (address instance) {\n // solhint-disable-next-line no-inline-assembly\n assembly {\n let ptr := mload(0x40)\n mstore(ptr, 0x3d602d80600a3d3981f3363d3d373d3d3d363d73000000000000000000000000)\n mstore(add(ptr, 0x14), shl(0x60, master))\n mstore(add(ptr, 0x28), 0x5af43d82803e903d91602b57fd5bf30000000000000000000000000000000000)\n instance := create(0, ptr, 0x37)\n }\n require(instance != address(0), \"ERC1167: create failed\");\n }\n\n /**\n * @dev Deploys and returns the address of a clone that mimics the behaviour of `master`.\n *\n * This function uses the create2 opcode and a `salt` to deterministically deploy\n * the clone. Using the same `master` and `salt` multiple time will revert, since\n * the clones cannot be deployed twice at the same address.\n */\n function cloneDeterministic(address master, bytes32 salt) internal returns (address instance) {\n // solhint-disable-next-line no-inline-assembly\n assembly {\n let ptr := mload(0x40)\n mstore(ptr, 0x3d602d80600a3d3981f3363d3d373d3d3d363d73000000000000000000000000)\n mstore(add(ptr, 0x14), shl(0x60, master))\n mstore(add(ptr, 0x28), 0x5af43d82803e903d91602b57fd5bf30000000000000000000000000000000000)\n instance := create2(0, ptr, 0x37, salt)\n }\n require(instance != address(0), \"ERC1167: create2 failed\");\n }\n\n /**\n * @dev Computes the address of a clone deployed using {Clones-cloneDeterministic}.\n */\n function predictDeterministicAddress(address master, bytes32 salt, address deployer) internal pure returns (address predicted) {\n // solhint-disable-next-line no-inline-assembly\n assembly {\n let ptr := mload(0x40)\n mstore(ptr, 0x3d602d80600a3d3981f3363d3d373d3d3d363d73000000000000000000000000)\n mstore(add(ptr, 0x14), shl(0x60, master))\n mstore(add(ptr, 0x28), 0x5af43d82803e903d91602b57fd5bf3ff00000000000000000000000000000000)\n mstore(add(ptr, 0x38), shl(0x60, deployer))\n mstore(add(ptr, 0x4c), salt)\n mstore(add(ptr, 0x6c), keccak256(ptr, 0x37))\n predicted := keccak256(add(ptr, 0x37), 0x55)\n }\n }\n\n /**\n * @dev Computes the address of a clone deployed using {Clones-cloneDeterministic}.\n */\n function predictDeterministicAddress(address master, bytes32 salt) internal view returns (address predicted) {\n return predictDeterministicAddress(master, salt, address(this));\n }\n}\n" + }, + "@openzeppelin/contracts-upgradeable/utils/ReentrancyGuardUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <0.8.0;\nimport \"../proxy/Initializable.sol\";\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 ReentrancyGuardUpgradeable is Initializable {\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 function __ReentrancyGuard_init() internal initializer {\n __ReentrancyGuard_init_unchained();\n }\n\n function __ReentrancyGuard_init_unchained() internal initializer {\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 uint256[49] private __gap;\n}\n" + }, + "contracts/amm/OwnerPausableUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.6.12;\n\nimport \"@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol\";\nimport \"@openzeppelin/contracts-upgradeable/utils/PausableUpgradeable.sol\";\n\n/**\n * @title OwnerPausable\n * @notice An ownable contract allows the owner to pause and unpause the\n * contract without a delay.\n * @dev Only methods using the provided modifiers will be paused.\n */\nabstract contract OwnerPausableUpgradeable is\n OwnableUpgradeable,\n PausableUpgradeable\n{\n function __OwnerPausable_init() internal initializer {\n __Context_init_unchained();\n __Ownable_init_unchained();\n __Pausable_init_unchained();\n }\n\n /**\n * @notice Pause the contract. Revert if already paused.\n */\n function pause() external onlyOwner {\n PausableUpgradeable._pause();\n }\n\n /**\n * @notice Unpause the contract. Revert if already unpaused.\n */\n function unpause() external onlyOwner {\n PausableUpgradeable._unpause();\n }\n}\n" + }, + "contracts/amm/SwapUtils.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.6.12;\n\nimport \"@openzeppelin/contracts/math/SafeMath.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/SafeERC20.sol\";\nimport \"./AmplificationUtils.sol\";\nimport \"./LPToken.sol\";\nimport \"./MathUtils.sol\";\n\n/**\n * @title SwapUtils library\n * @notice A library to be used within Swap.sol. Contains functions responsible for custody and AMM functionalities.\n * @dev Contracts relying on this library must initialize SwapUtils.Swap struct then use this library\n * for SwapUtils.Swap struct. Note that this library contains both functions called by users and admins.\n * Admin functions should be protected within contracts using this library.\n */\nlibrary SwapUtils {\n using SafeERC20 for IERC20;\n using SafeMath for uint256;\n using MathUtils for uint256;\n\n /*** EVENTS ***/\n\n event TokenSwap(\n address indexed buyer,\n uint256 tokensSold,\n uint256 tokensBought,\n uint128 soldId,\n uint128 boughtId\n );\n event AddLiquidity(\n address indexed provider,\n uint256[] tokenAmounts,\n uint256[] fees,\n uint256 invariant,\n uint256 lpTokenSupply\n );\n event RemoveLiquidity(\n address indexed provider,\n uint256[] tokenAmounts,\n uint256 lpTokenSupply\n );\n event RemoveLiquidityOne(\n address indexed provider,\n uint256 lpTokenAmount,\n uint256 lpTokenSupply,\n uint256 boughtId,\n uint256 tokensBought\n );\n event RemoveLiquidityImbalance(\n address indexed provider,\n uint256[] tokenAmounts,\n uint256[] fees,\n uint256 invariant,\n uint256 lpTokenSupply\n );\n event NewAdminFee(uint256 newAdminFee);\n event NewSwapFee(uint256 newSwapFee);\n\n struct Swap {\n // variables around the ramp management of A,\n // the amplification coefficient * n * (n - 1)\n // see https://www.curve.fi/stableswap-paper.pdf for details\n uint256 initialA;\n uint256 futureA;\n uint256 initialATime;\n uint256 futureATime;\n // fee calculation\n uint256 swapFee;\n uint256 adminFee;\n LPToken lpToken;\n // contract references for all tokens being pooled\n IERC20[] pooledTokens;\n // multipliers for each pooled token's precision to get to POOL_PRECISION_DECIMALS\n // for example, TBTC has 18 decimals, so the multiplier should be 1. WBTC\n // has 8, so the multiplier should be 10 ** 18 / 10 ** 8 => 10 ** 10\n uint256[] tokenPrecisionMultipliers;\n // the pool balance of each token, in the token's precision\n // the contract's actual token balance might differ\n uint256[] balances;\n }\n\n // Struct storing variables used in calculations in the\n // calculateWithdrawOneTokenDY function to avoid stack too deep errors\n struct CalculateWithdrawOneTokenDYInfo {\n uint256 d0;\n uint256 d1;\n uint256 newY;\n uint256 feePerToken;\n uint256 preciseA;\n }\n\n // Struct storing variables used in calculations in the\n // {add,remove}Liquidity functions to avoid stack too deep errors\n struct ManageLiquidityInfo {\n uint256 d0;\n uint256 d1;\n uint256 d2;\n uint256 preciseA;\n LPToken lpToken;\n uint256 totalSupply;\n uint256[] balances;\n uint256[] multipliers;\n }\n\n // the precision all pools tokens will be converted to\n uint8 public constant POOL_PRECISION_DECIMALS = 18;\n\n // the denominator used to calculate admin and LP fees. For example, an\n // LP fee might be something like tradeAmount.mul(fee).div(FEE_DENOMINATOR)\n uint256 private constant FEE_DENOMINATOR = 10**10;\n\n // Max swap fee is 1% or 100bps of each swap\n uint256 public constant MAX_SWAP_FEE = 10**8;\n\n // Max adminFee is 100% of the swapFee\n // adminFee does not add additional fee on top of swapFee\n // Instead it takes a certain % of the swapFee. Therefore it has no impact on the\n // users but only on the earnings of LPs\n uint256 public constant MAX_ADMIN_FEE = 10**10;\n\n // Constant value used as max loop limit\n uint256 private constant MAX_LOOP_LIMIT = 256;\n\n /*** VIEW & PURE FUNCTIONS ***/\n\n function _getAPrecise(Swap storage self) internal view returns (uint256) {\n return AmplificationUtils._getAPrecise(self);\n }\n\n /**\n * @notice Calculate the dy, the amount of selected token that user receives and\n * the fee of withdrawing in one token\n * @param tokenAmount the amount to withdraw in the pool's precision\n * @param tokenIndex which token will be withdrawn\n * @param self Swap struct to read from\n * @return the amount of token user will receive\n */\n function calculateWithdrawOneToken(\n Swap storage self,\n uint256 tokenAmount,\n uint8 tokenIndex\n ) external view returns (uint256) {\n (uint256 availableTokenAmount, ) = _calculateWithdrawOneToken(\n self,\n tokenAmount,\n tokenIndex,\n self.lpToken.totalSupply()\n );\n return availableTokenAmount;\n }\n\n function _calculateWithdrawOneToken(\n Swap storage self,\n uint256 tokenAmount,\n uint8 tokenIndex,\n uint256 totalSupply\n ) internal view returns (uint256, uint256) {\n uint256 dy;\n uint256 newY;\n uint256 currentY;\n\n (dy, newY, currentY) = calculateWithdrawOneTokenDY(\n self,\n tokenIndex,\n tokenAmount,\n totalSupply\n );\n\n // dy_0 (without fees)\n // dy, dy_0 - dy\n\n uint256 dySwapFee = currentY\n .sub(newY)\n .div(self.tokenPrecisionMultipliers[tokenIndex])\n .sub(dy);\n\n return (dy, dySwapFee);\n }\n\n /**\n * @notice Calculate the dy of withdrawing in one token\n * @param self Swap struct to read from\n * @param tokenIndex which token will be withdrawn\n * @param tokenAmount the amount to withdraw in the pools precision\n * @return the d and the new y after withdrawing one token\n */\n function calculateWithdrawOneTokenDY(\n Swap storage self,\n uint8 tokenIndex,\n uint256 tokenAmount,\n uint256 totalSupply\n )\n internal\n view\n returns (\n uint256,\n uint256,\n uint256\n )\n {\n // Get the current D, then solve the stableswap invariant\n // y_i for D - tokenAmount\n uint256[] memory xp = _xp(self);\n\n require(tokenIndex < xp.length, \"Token index out of range\");\n\n\n CalculateWithdrawOneTokenDYInfo memory v\n = CalculateWithdrawOneTokenDYInfo(0, 0, 0, 0, 0);\n v.preciseA = _getAPrecise(self);\n v.d0 = getD(xp, v.preciseA);\n v.d1 = v.d0.sub(tokenAmount.mul(v.d0).div(totalSupply));\n\n require(tokenAmount <= xp[tokenIndex], \"Withdraw exceeds available\");\n\n v.newY = getYD(v.preciseA, tokenIndex, xp, v.d1);\n\n uint256[] memory xpReduced = new uint256[](xp.length);\n\n v.feePerToken = _feePerToken(self.swapFee, xp.length);\n for (uint256 i = 0; i < xp.length; i++) {\n uint256 xpi = xp[i];\n // if i == tokenIndex, dxExpected = xp[i] * d1 / d0 - newY\n // else dxExpected = xp[i] - (xp[i] * d1 / d0)\n // xpReduced[i] -= dxExpected * fee / FEE_DENOMINATOR\n xpReduced[i] = xpi.sub(\n (\n (i == tokenIndex)\n ? xpi.mul(v.d1).div(v.d0).sub(v.newY)\n : xpi.sub(xpi.mul(v.d1).div(v.d0))\n )\n .mul(v.feePerToken)\n .div(FEE_DENOMINATOR)\n );\n }\n\n uint256 dy = xpReduced[tokenIndex].sub(\n getYD(v.preciseA, tokenIndex, xpReduced, v.d1)\n );\n dy = dy.sub(1).div(self.tokenPrecisionMultipliers[tokenIndex]);\n\n return (dy, v.newY, xp[tokenIndex]);\n }\n\n /**\n * @notice Calculate the price of a token in the pool with given\n * precision-adjusted balances and a particular D.\n *\n * @dev This is accomplished via solving the invariant iteratively.\n * See the StableSwap paper and Curve.fi implementation for further details.\n *\n * x_1**2 + x1 * (sum' - (A*n**n - 1) * D / (A * n**n)) = D ** (n + 1) / (n ** (2 * n) * prod' * A)\n * x_1**2 + b*x_1 = c\n * x_1 = (x_1**2 + c) / (2*x_1 + b)\n *\n * @param a the amplification coefficient * n * (n - 1). See the StableSwap paper for details.\n * @param tokenIndex Index of token we are calculating for.\n * @param xp a precision-adjusted set of pool balances. Array should be\n * the same cardinality as the pool.\n * @param d the stableswap invariant\n * @return the price of the token, in the same precision as in xp\n */\n function getYD(\n uint256 a,\n uint8 tokenIndex,\n uint256[] memory xp,\n uint256 d\n ) internal pure returns (uint256) {\n uint256 numTokens = xp.length;\n require(tokenIndex < numTokens, \"Token not found\");\n\n uint256 c = d;\n uint256 s;\n uint256 nA = a.mul(numTokens);\n\n for (uint256 i = 0; i < numTokens; i++) {\n if (i != tokenIndex) {\n s = s.add(xp[i]);\n c = c.mul(d).div(xp[i].mul(numTokens));\n // If we were to protect the division loss we would have to keep the denominator separate\n // and divide at the end. However this leads to overflow with large numTokens or/and D.\n // c = c * D * D * D * ... overflow!\n }\n }\n c = c.mul(d).mul(AmplificationUtils.A_PRECISION).div(nA.mul(numTokens));\n\n uint256 b = s.add(d.mul(AmplificationUtils.A_PRECISION).div(nA));\n uint256 yPrev;\n uint256 y = d;\n for (uint256 i = 0; i < MAX_LOOP_LIMIT; i++) {\n yPrev = y;\n y = y.mul(y).add(c).div(y.mul(2).add(b).sub(d));\n if (y.within1(yPrev)) {\n return y;\n }\n }\n revert(\"Approximation did not converge\");\n }\n\n /**\n * @notice Get D, the StableSwap invariant, based on a set of balances and a particular A.\n * @param xp a precision-adjusted set of pool balances. Array should be the same cardinality\n * as the pool.\n * @param a the amplification coefficient * n * (n - 1) in A_PRECISION.\n * See the StableSwap paper for details\n * @return the invariant, at the precision of the pool\n */\n function getD(uint256[] memory xp, uint256 a)\n internal\n pure\n returns (uint256)\n {\n uint256 numTokens = xp.length;\n uint256 s;\n for (uint256 i = 0; i < numTokens; i++) {\n s = s.add(xp[i]);\n }\n if (s == 0) {\n return 0;\n }\n\n uint256 prevD;\n uint256 d = s;\n uint256 nA = a.mul(numTokens);\n\n for (uint256 i = 0; i < MAX_LOOP_LIMIT; i++) {\n uint256 dP = d;\n for (uint256 j = 0; j < numTokens; j++) {\n dP = dP.mul(d).div(xp[j].mul(numTokens));\n // If we were to protect the division loss we would have to keep the denominator separate\n // and divide at the end. However this leads to overflow with large numTokens or/and D.\n // dP = dP * D * D * D * ... overflow!\n }\n prevD = d;\n d = nA\n .mul(s)\n .div(AmplificationUtils.A_PRECISION)\n .add(dP.mul(numTokens))\n .mul(d)\n .div(\n nA\n .sub(AmplificationUtils.A_PRECISION)\n .mul(d)\n .div(AmplificationUtils.A_PRECISION)\n .add(numTokens.add(1).mul(dP))\n );\n if (d.within1(prevD)) {\n return d;\n }\n }\n\n // Convergence should occur in 4 loops or less. If this is reached, there may be something wrong\n // with the pool. If this were to occur repeatedly, LPs should withdraw via `removeLiquidity()`\n // function which does not rely on D.\n revert(\"D does not converge\");\n }\n\n /**\n * @notice Given a set of balances and precision multipliers, return the\n * precision-adjusted balances.\n *\n * @param balances an array of token balances, in their native precisions.\n * These should generally correspond with pooled tokens.\n *\n * @param precisionMultipliers an array of multipliers, corresponding to\n * the amounts in the balances array. When multiplied together they\n * should yield amounts at the pool's precision.\n *\n * @return an array of amounts \"scaled\" to the pool's precision\n */\n function _xp(\n uint256[] memory balances,\n uint256[] memory precisionMultipliers\n ) internal pure returns (uint256[] memory) {\n uint256 numTokens = balances.length;\n require(\n numTokens == precisionMultipliers.length,\n \"Balances must match multipliers\"\n );\n uint256[] memory xp = new uint256[](numTokens);\n for (uint256 i = 0; i < numTokens; i++) {\n xp[i] = balances[i].mul(precisionMultipliers[i]);\n }\n return xp;\n }\n\n /**\n * @notice Return the precision-adjusted balances of all tokens in the pool\n * @param self Swap struct to read from\n * @return the pool balances \"scaled\" to the pool's precision, allowing\n * them to be more easily compared.\n */\n function _xp(Swap storage self) internal view returns (uint256[] memory) {\n return _xp(self.balances, self.tokenPrecisionMultipliers);\n }\n\n /**\n * @notice Get the virtual price, to help calculate profit\n * @param self Swap struct to read from\n * @return the virtual price, scaled to precision of POOL_PRECISION_DECIMALS\n */\n function getVirtualPrice(Swap storage self)\n external\n view\n returns (uint256)\n {\n uint256 d = getD(_xp(self), _getAPrecise(self));\n LPToken lpToken = self.lpToken;\n uint256 supply = lpToken.totalSupply();\n if (supply > 0) {\n return d.mul(10**uint256(POOL_PRECISION_DECIMALS)).div(supply);\n }\n return 0;\n }\n\n /**\n * @notice Calculate the new balances of the tokens given the indexes of the token\n * that is swapped from (FROM) and the token that is swapped to (TO).\n * This function is used as a helper function to calculate how much TO token\n * the user should receive on swap.\n *\n * @param preciseA precise form of amplification coefficient\n * @param tokenIndexFrom index of FROM token\n * @param tokenIndexTo index of TO token\n * @param x the new total amount of FROM token\n * @param xp balances of the tokens in the pool\n * @return the amount of TO token that should remain in the pool\n */\n function getY(\n uint256 preciseA,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 x,\n uint256[] memory xp\n ) internal pure returns (uint256) {\n uint256 numTokens = xp.length;\n require(\n tokenIndexFrom != tokenIndexTo,\n \"Can't compare token to itself\"\n );\n require(\n tokenIndexFrom < numTokens && tokenIndexTo < numTokens,\n \"Tokens must be in pool\"\n );\n\n uint256 d = getD(xp, preciseA);\n uint256 c = d;\n uint256 s;\n uint256 nA = numTokens.mul(preciseA);\n\n uint256 _x;\n for (uint256 i = 0; i < numTokens; i++) {\n if (i == tokenIndexFrom) {\n _x = x;\n } else if (i != tokenIndexTo) {\n _x = xp[i];\n } else {\n continue;\n }\n s = s.add(_x);\n c = c.mul(d).div(_x.mul(numTokens));\n // If we were to protect the division loss we would have to keep the denominator separate\n // and divide at the end. However this leads to overflow with large numTokens or/and D.\n // c = c * D * D * D * ... overflow!\n }\n c = c.mul(d).mul(AmplificationUtils.A_PRECISION).div(nA.mul(numTokens));\n uint256 b = s.add(d.mul(AmplificationUtils.A_PRECISION).div(nA));\n uint256 yPrev;\n uint256 y = d;\n\n // iterative approximation\n for (uint256 i = 0; i < MAX_LOOP_LIMIT; i++) {\n yPrev = y;\n y = y.mul(y).add(c).div(y.mul(2).add(b).sub(d));\n if (y.within1(yPrev)) {\n return y;\n }\n }\n revert(\"Approximation did not converge\");\n }\n\n /**\n * @notice Externally calculates a swap between two tokens.\n * @param self Swap struct to read from\n * @param tokenIndexFrom the token to sell\n * @param tokenIndexTo the token to buy\n * @param dx the number of tokens to sell. If the token charges a fee on transfers,\n * use the amount that gets transferred after the fee.\n * @return dy the number of tokens the user will get\n */\n function calculateSwap(\n Swap storage self,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx\n ) external view returns (uint256 dy) {\n (dy, ) = _calculateSwap(\n self,\n tokenIndexFrom,\n tokenIndexTo,\n dx,\n self.balances\n );\n }\n\n /**\n * @notice Internally calculates a swap between two tokens.\n *\n * @dev The caller is expected to transfer the actual amounts (dx and dy)\n * using the token contracts.\n *\n * @param self Swap struct to read from\n * @param tokenIndexFrom the token to sell\n * @param tokenIndexTo the token to buy\n * @param dx the number of tokens to sell. If the token charges a fee on transfers,\n * use the amount that gets transferred after the fee.\n * @return dy the number of tokens the user will get\n * @return dyFee the associated fee\n */\n function _calculateSwap(\n Swap storage self,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx,\n uint256[] memory balances\n ) internal view returns (uint256 dy, uint256 dyFee) {\n uint256[] memory multipliers = self.tokenPrecisionMultipliers;\n uint256[] memory xp = _xp(balances, multipliers);\n require(\n tokenIndexFrom < xp.length && tokenIndexTo < xp.length,\n \"Token index out of range\"\n );\n uint256 x = dx.mul(multipliers[tokenIndexFrom]).add(xp[tokenIndexFrom]);\n uint256 y = getY(\n _getAPrecise(self),\n tokenIndexFrom,\n tokenIndexTo,\n x,\n xp\n );\n dy = xp[tokenIndexTo].sub(y).sub(1);\n dyFee = dy.mul(self.swapFee).div(FEE_DENOMINATOR);\n dy = dy.sub(dyFee).div(multipliers[tokenIndexTo]);\n }\n\n /**\n * @notice A simple method to calculate amount of each underlying\n * tokens that is returned upon burning given amount of\n * LP tokens\n *\n * @param amount the amount of LP tokens that would to be burned on\n * withdrawal\n * @return array of amounts of tokens user will receive\n */\n function calculateRemoveLiquidity(Swap storage self, uint256 amount)\n external\n view\n returns (uint256[] memory)\n {\n return\n _calculateRemoveLiquidity(\n self.balances,\n amount,\n self.lpToken.totalSupply()\n );\n }\n\n function _calculateRemoveLiquidity(\n uint256[] memory balances,\n uint256 amount,\n uint256 totalSupply\n ) internal pure returns (uint256[] memory) {\n require(amount <= totalSupply, \"Cannot exceed total supply\");\n\n uint256[] memory amounts = new uint256[](balances.length);\n\n for (uint256 i = 0; i < balances.length; i++) {\n amounts[i] = balances[i].mul(amount).div(totalSupply);\n }\n return amounts;\n }\n\n /**\n * @notice A simple method to calculate prices from deposits or\n * withdrawals, excluding fees but including slippage. This is\n * helpful as an input into the various \"min\" parameters on calls\n * to fight front-running\n *\n * @dev This shouldn't be used outside frontends for user estimates.\n *\n * @param self Swap struct to read from\n * @param amounts an array of token amounts to deposit or withdrawal,\n * corresponding to pooledTokens. The amount should be in each\n * pooled token's native precision. If a token charges a fee on transfers,\n * use the amount that gets transferred after the fee.\n * @param deposit whether this is a deposit or a withdrawal\n * @return if deposit was true, total amount of lp token that will be minted and if\n * deposit was false, total amount of lp token that will be burned\n */\n function calculateTokenAmount(\n Swap storage self,\n uint256[] calldata amounts,\n bool deposit\n ) external view returns (uint256) {\n uint256 a = _getAPrecise(self);\n uint256[] memory balances = self.balances;\n uint256[] memory multipliers = self.tokenPrecisionMultipliers;\n\n uint256 d0 = getD(_xp(balances, multipliers), a);\n for (uint256 i = 0; i < balances.length; i++) {\n if (deposit) {\n balances[i] = balances[i].add(amounts[i]);\n } else {\n balances[i] = balances[i].sub(\n amounts[i],\n \"Cannot withdraw more than available\"\n );\n }\n }\n uint256 d1 = getD(_xp(balances, multipliers), a);\n uint256 totalSupply = self.lpToken.totalSupply();\n\n if (deposit) {\n return d1.sub(d0).mul(totalSupply).div(d0);\n } else {\n return d0.sub(d1).mul(totalSupply).div(d0);\n }\n }\n\n /**\n * @notice return accumulated amount of admin fees of the token with given index\n * @param self Swap struct to read from\n * @param index Index of the pooled token\n * @return admin balance in the token's precision\n */\n function getAdminBalance(Swap storage self, uint256 index)\n external\n view\n returns (uint256)\n {\n require(index < self.pooledTokens.length, \"Token index out of range\");\n return\n self.pooledTokens[index].balanceOf(address(this)).sub(\n self.balances[index]\n );\n }\n\n /**\n * @notice internal helper function to calculate fee per token multiplier used in\n * swap fee calculations\n * @param swapFee swap fee for the tokens\n * @param numTokens number of tokens pooled\n */\n function _feePerToken(uint256 swapFee, uint256 numTokens)\n internal\n pure\n returns (uint256)\n {\n return swapFee.mul(numTokens).div(numTokens.sub(1).mul(4));\n }\n\n /*** STATE MODIFYING FUNCTIONS ***/\n\n /**\n * @notice swap two tokens in the pool\n * @param self Swap struct to read from and write to\n * @param tokenIndexFrom the token the user wants to sell\n * @param tokenIndexTo the token the user wants to buy\n * @param dx the amount of tokens the user wants to sell\n * @param minDy the min amount the user would like to receive, or revert.\n * @return amount of token user received on swap\n */\n function swap(\n Swap storage self,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx,\n uint256 minDy\n ) external returns (uint256) {\n {\n IERC20 tokenFrom = self.pooledTokens[tokenIndexFrom];\n require(\n dx <= tokenFrom.balanceOf(msg.sender),\n \"Cannot swap more than you own\"\n );\n // Transfer tokens first to see if a fee was charged on transfer\n uint256 beforeBalance = tokenFrom.balanceOf(address(this));\n tokenFrom.safeTransferFrom(msg.sender, address(this), dx);\n\n // Use the actual transferred amount for AMM math\n dx = tokenFrom.balanceOf(address(this)).sub(beforeBalance);\n }\n\n uint256 dy;\n uint256 dyFee;\n uint256[] memory balances = self.balances;\n (dy, dyFee) = _calculateSwap(\n self,\n tokenIndexFrom,\n tokenIndexTo,\n dx,\n balances\n );\n require(dy >= minDy, \"Swap didn't result in min tokens\");\n\n uint256 dyAdminFee = dyFee.mul(self.adminFee).div(FEE_DENOMINATOR).div(\n self.tokenPrecisionMultipliers[tokenIndexTo]\n );\n\n self.balances[tokenIndexFrom] = balances[tokenIndexFrom].add(dx);\n self.balances[tokenIndexTo] = balances[tokenIndexTo].sub(dy).sub(\n dyAdminFee\n );\n\n self.pooledTokens[tokenIndexTo].safeTransfer(msg.sender, dy);\n\n emit TokenSwap(msg.sender, dx, dy, tokenIndexFrom, tokenIndexTo);\n\n return dy;\n }\n\n /**\n * @notice Add liquidity to the pool\n * @param self Swap struct to read from and write to\n * @param amounts the amounts of each token to add, in their native precision\n * @param minToMint the minimum LP tokens adding this amount of liquidity\n * should mint, otherwise revert. Handy for front-running mitigation\n * allowed addresses. If the pool is not in the guarded launch phase, this parameter will be ignored.\n * @return amount of LP token user received\n */\n function addLiquidity(\n Swap storage self,\n uint256[] memory amounts,\n uint256 minToMint\n ) external returns (uint256) {\n IERC20[] memory pooledTokens = self.pooledTokens;\n require(\n amounts.length == pooledTokens.length,\n \"Amounts must match pooled tokens\"\n );\n\n // current state\n ManageLiquidityInfo memory v = ManageLiquidityInfo(\n 0,\n 0,\n 0,\n _getAPrecise(self),\n self.lpToken,\n 0,\n self.balances,\n self.tokenPrecisionMultipliers\n );\n v.totalSupply = v.lpToken.totalSupply();\n\n if (v.totalSupply != 0) {\n v.d0 = getD(_xp(v.balances, v.multipliers), v.preciseA);\n }\n\n uint256[] memory newBalances = new uint256[](pooledTokens.length);\n\n for (uint256 i = 0; i < pooledTokens.length; i++) {\n require(\n v.totalSupply != 0 || amounts[i] > 0,\n \"Must supply all tokens in pool\"\n );\n\n // Transfer tokens first to see if a fee was charged on transfer\n if (amounts[i] != 0) {\n uint256 beforeBalance = pooledTokens[i].balanceOf(\n address(this)\n );\n pooledTokens[i].safeTransferFrom(\n msg.sender,\n address(this),\n amounts[i]\n );\n\n // Update the amounts[] with actual transfer amount\n amounts[i] = pooledTokens[i].balanceOf(address(this)).sub(\n beforeBalance\n );\n }\n\n newBalances[i] = v.balances[i].add(amounts[i]);\n }\n\n // invariant after change\n v.d1 = getD(_xp(newBalances, v.multipliers), v.preciseA);\n require(v.d1 > v.d0, \"D should increase\");\n\n // updated to reflect fees and calculate the user's LP tokens\n v.d2 = v.d1;\n uint256[] memory fees = new uint256[](pooledTokens.length);\n\n if (v.totalSupply != 0) {\n uint256 feePerToken = _feePerToken(\n self.swapFee,\n pooledTokens.length\n );\n for (uint256 i = 0; i < pooledTokens.length; i++) {\n uint256 idealBalance = v.d1.mul(v.balances[i]).div(v.d0);\n fees[i] = feePerToken\n .mul(idealBalance.difference(newBalances[i]))\n .div(FEE_DENOMINATOR);\n self.balances[i] = newBalances[i].sub(\n fees[i].mul(self.adminFee).div(FEE_DENOMINATOR)\n );\n newBalances[i] = newBalances[i].sub(fees[i]);\n }\n v.d2 = getD(_xp(newBalances, v.multipliers), v.preciseA);\n } else {\n // the initial depositor doesn't pay fees\n self.balances = newBalances;\n }\n\n uint256 toMint;\n if (v.totalSupply == 0) {\n toMint = v.d1;\n } else {\n toMint = v.d2.sub(v.d0).mul(v.totalSupply).div(v.d0);\n }\n\n require(toMint >= minToMint, \"Couldn't mint min requested\");\n\n // mint the user's LP tokens\n v.lpToken.mint(msg.sender, toMint);\n\n emit AddLiquidity(\n msg.sender,\n amounts,\n fees,\n v.d1,\n v.totalSupply.add(toMint)\n );\n\n return toMint;\n }\n\n /**\n * @notice Burn LP tokens to remove liquidity from the pool.\n * @dev Liquidity can always be removed, even when the pool is paused.\n * @param self Swap struct to read from and write to\n * @param amount the amount of LP tokens to burn\n * @param minAmounts the minimum amounts of each token in the pool\n * acceptable for this burn. Useful as a front-running mitigation\n * @return amounts of tokens the user received\n */\n function removeLiquidity(\n Swap storage self,\n uint256 amount,\n uint256[] calldata minAmounts\n ) external returns (uint256[] memory) {\n LPToken lpToken = self.lpToken;\n IERC20[] memory pooledTokens = self.pooledTokens;\n require(amount <= lpToken.balanceOf(msg.sender), \">LP.balanceOf\");\n require(\n minAmounts.length == pooledTokens.length,\n \"minAmounts must match poolTokens\"\n );\n\n uint256[] memory balances = self.balances;\n uint256 totalSupply = lpToken.totalSupply();\n\n uint256[] memory amounts = _calculateRemoveLiquidity(\n balances,\n amount,\n totalSupply\n );\n\n for (uint256 i = 0; i < amounts.length; i++) {\n require(amounts[i] >= minAmounts[i], \"amounts[i] < minAmounts[i]\");\n self.balances[i] = balances[i].sub(amounts[i]);\n pooledTokens[i].safeTransfer(msg.sender, amounts[i]);\n }\n\n lpToken.burnFrom(msg.sender, amount);\n\n emit RemoveLiquidity(msg.sender, amounts, totalSupply.sub(amount));\n\n return amounts;\n }\n\n /**\n * @notice Remove liquidity from the pool all in one token.\n * @param self Swap struct to read from and write to\n * @param tokenAmount the amount of the lp tokens to burn\n * @param tokenIndex the index of the token you want to receive\n * @param minAmount the minimum amount to withdraw, otherwise revert\n * @return amount chosen token that user received\n */\n function removeLiquidityOneToken(\n Swap storage self,\n uint256 tokenAmount,\n uint8 tokenIndex,\n uint256 minAmount\n ) external returns (uint256) {\n LPToken lpToken = self.lpToken;\n IERC20[] memory pooledTokens = self.pooledTokens;\n\n require(tokenAmount <= lpToken.balanceOf(msg.sender), \">LP.balanceOf\");\n require(tokenIndex < pooledTokens.length, \"Token not found\");\n\n uint256 totalSupply = lpToken.totalSupply();\n\n (uint256 dy, uint256 dyFee) = _calculateWithdrawOneToken(\n self,\n tokenAmount,\n tokenIndex,\n totalSupply\n );\n\n require(dy >= minAmount, \"dy < minAmount\");\n\n self.balances[tokenIndex] = self.balances[tokenIndex].sub(\n dy.add(dyFee.mul(self.adminFee).div(FEE_DENOMINATOR))\n );\n lpToken.burnFrom(msg.sender, tokenAmount);\n pooledTokens[tokenIndex].safeTransfer(msg.sender, dy);\n\n emit RemoveLiquidityOne(\n msg.sender,\n tokenAmount,\n totalSupply,\n tokenIndex,\n dy\n );\n\n return dy;\n }\n\n /**\n * @notice Remove liquidity from the pool, weighted differently than the\n * pool's current balances.\n *\n * @param self Swap struct to read from and write to\n * @param amounts how much of each token to withdraw\n * @param maxBurnAmount the max LP token provider is willing to pay to\n * remove liquidity. Useful as a front-running mitigation.\n * @return actual amount of LP tokens burned in the withdrawal\n */\n function removeLiquidityImbalance(\n Swap storage self,\n uint256[] memory amounts,\n uint256 maxBurnAmount\n ) public returns (uint256) {\n ManageLiquidityInfo memory v = ManageLiquidityInfo(\n 0,\n 0,\n 0,\n _getAPrecise(self),\n self.lpToken,\n 0,\n self.balances,\n self.tokenPrecisionMultipliers\n );\n v.totalSupply = v.lpToken.totalSupply();\n\n IERC20[] memory pooledTokens = self.pooledTokens;\n\n require(\n amounts.length == pooledTokens.length,\n \"Amounts should match pool tokens\"\n );\n\n require(\n maxBurnAmount <= v.lpToken.balanceOf(msg.sender) &&\n maxBurnAmount != 0,\n \">LP.balanceOf\"\n );\n\n uint256 feePerToken = _feePerToken(self.swapFee, pooledTokens.length);\n uint256[] memory fees = new uint256[](pooledTokens.length);\n {\n uint256[] memory balances1 = new uint256[](pooledTokens.length);\n v.d0 = getD(_xp(v.balances, v.multipliers), v.preciseA);\n for (uint256 i = 0; i < pooledTokens.length; i++) {\n balances1[i] = v.balances[i].sub(\n amounts[i],\n \"Cannot withdraw more than available\"\n );\n }\n v.d1 = getD(_xp(balances1, v.multipliers), v.preciseA);\n\n for (uint256 i = 0; i < pooledTokens.length; i++) {\n uint256 idealBalance = v.d1.mul(v.balances[i]).div(v.d0);\n uint256 difference = idealBalance.difference(balances1[i]);\n fees[i] = feePerToken.mul(difference).div(FEE_DENOMINATOR);\n self.balances[i] = balances1[i].sub(\n fees[i].mul(self.adminFee).div(FEE_DENOMINATOR)\n );\n balances1[i] = balances1[i].sub(fees[i]);\n }\n\n v.d2 = getD(_xp(balances1, v.multipliers), v.preciseA);\n }\n uint256 tokenAmount = v.d0.sub(v.d2).mul(v.totalSupply).div(v.d0);\n require(tokenAmount != 0, \"Burnt amount cannot be zero\");\n tokenAmount = tokenAmount.add(1);\n\n require(tokenAmount <= maxBurnAmount, \"tokenAmount > maxBurnAmount\");\n\n v.lpToken.burnFrom(msg.sender, tokenAmount);\n\n for (uint256 i = 0; i < pooledTokens.length; i++) {\n pooledTokens[i].safeTransfer(msg.sender, amounts[i]);\n }\n\n emit RemoveLiquidityImbalance(\n msg.sender,\n amounts,\n fees,\n v.d1,\n v.totalSupply.sub(tokenAmount)\n );\n\n return tokenAmount;\n }\n\n /**\n * @notice withdraw all admin fees to a given address\n * @param self Swap struct to withdraw fees from\n * @param to Address to send the fees to\n */\n function withdrawAdminFees(Swap storage self, address to) external {\n IERC20[] memory pooledTokens = self.pooledTokens;\n for (uint256 i = 0; i < pooledTokens.length; i++) {\n IERC20 token = pooledTokens[i];\n uint256 balance = token.balanceOf(address(this)).sub(\n self.balances[i]\n );\n if (balance != 0) {\n token.safeTransfer(to, balance);\n }\n }\n }\n\n /**\n * @notice Sets the admin fee\n * @dev adminFee cannot be higher than 100% of the swap fee\n * @param self Swap struct to update\n * @param newAdminFee new admin fee to be applied on future transactions\n */\n function setAdminFee(Swap storage self, uint256 newAdminFee) external {\n require(newAdminFee <= MAX_ADMIN_FEE, \"Fee is too high\");\n self.adminFee = newAdminFee;\n\n emit NewAdminFee(newAdminFee);\n }\n\n /**\n * @notice update the swap fee\n * @dev fee cannot be higher than 1% of each swap\n * @param self Swap struct to update\n * @param newSwapFee new swap fee to be applied on future transactions\n */\n function setSwapFee(Swap storage self, uint256 newSwapFee) external {\n require(newSwapFee <= MAX_SWAP_FEE, \"Fee is too high\");\n self.swapFee = newSwapFee;\n\n emit NewSwapFee(newSwapFee);\n }\n}\n" + }, + "contracts/amm/AmplificationUtils.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.6.12;\n\nimport \"@openzeppelin/contracts/token/ERC20/SafeERC20.sol\";\nimport \"./SwapUtils.sol\";\n\n/**\n * @title AmplificationUtils library\n * @notice A library to calculate and ramp the A parameter of a given `SwapUtils.Swap` struct.\n * This library assumes the struct is fully validated.\n */\nlibrary AmplificationUtils {\n using SafeMath for uint256;\n\n event RampA(\n uint256 oldA,\n uint256 newA,\n uint256 initialTime,\n uint256 futureTime\n );\n event StopRampA(uint256 currentA, uint256 time);\n\n // Constant values used in ramping A calculations\n uint256 public constant A_PRECISION = 100;\n uint256 public constant MAX_A = 10**6;\n uint256 private constant MAX_A_CHANGE = 2;\n uint256 private constant MIN_RAMP_TIME = 7 days;\n\n /**\n * @notice Return A, the amplification coefficient * n * (n - 1)\n * @dev See the StableSwap paper for details\n * @param self Swap struct to read from\n * @return A parameter\n */\n function getA(SwapUtils.Swap storage self) external view returns (uint256) {\n return _getAPrecise(self).div(A_PRECISION);\n }\n\n /**\n * @notice Return A in its raw precision\n * @dev See the StableSwap paper for details\n * @param self Swap struct to read from\n * @return A parameter in its raw precision form\n */\n function getAPrecise(SwapUtils.Swap storage self)\n external\n view\n returns (uint256)\n {\n return _getAPrecise(self);\n }\n\n /**\n * @notice Return A in its raw precision\n * @dev See the StableSwap paper for details\n * @param self Swap struct to read from\n * @return A parameter in its raw precision form\n */\n function _getAPrecise(SwapUtils.Swap storage self)\n internal\n view\n returns (uint256)\n {\n uint256 t1 = self.futureATime; // time when ramp is finished\n uint256 a1 = self.futureA; // final A value when ramp is finished\n\n if (block.timestamp < t1) {\n uint256 t0 = self.initialATime; // time when ramp is started\n uint256 a0 = self.initialA; // initial A value when ramp is started\n if (a1 > a0) {\n // a0 + (a1 - a0) * (block.timestamp - t0) / (t1 - t0)\n return\n a0.add(\n a1.sub(a0).mul(block.timestamp.sub(t0)).div(t1.sub(t0))\n );\n } else {\n // a0 - (a0 - a1) * (block.timestamp - t0) / (t1 - t0)\n return\n a0.sub(\n a0.sub(a1).mul(block.timestamp.sub(t0)).div(t1.sub(t0))\n );\n }\n } else {\n return a1;\n }\n }\n\n /**\n * @notice Start ramping up or down A parameter towards given futureA_ and futureTime_\n * Checks if the change is too rapid, and commits the new A value only when it falls under\n * the limit range.\n * @param self Swap struct to update\n * @param futureA_ the new A to ramp towards\n * @param futureTime_ timestamp when the new A should be reached\n */\n function rampA(\n SwapUtils.Swap storage self,\n uint256 futureA_,\n uint256 futureTime_\n ) external {\n require(\n block.timestamp >= self.initialATime.add(1 days),\n \"Wait 1 day before starting ramp\"\n );\n require(\n futureTime_ >= block.timestamp.add(MIN_RAMP_TIME),\n \"Insufficient ramp time\"\n );\n require(\n futureA_ > 0 && futureA_ < MAX_A,\n \"futureA_ must be > 0 and < MAX_A\"\n );\n\n uint256 initialAPrecise = _getAPrecise(self);\n uint256 futureAPrecise = futureA_.mul(A_PRECISION);\n\n if (futureAPrecise < initialAPrecise) {\n require(\n futureAPrecise.mul(MAX_A_CHANGE) >= initialAPrecise,\n \"futureA_ is too small\"\n );\n } else {\n require(\n futureAPrecise <= initialAPrecise.mul(MAX_A_CHANGE),\n \"futureA_ is too large\"\n );\n }\n\n self.initialA = initialAPrecise;\n self.futureA = futureAPrecise;\n self.initialATime = block.timestamp;\n self.futureATime = futureTime_;\n\n emit RampA(\n initialAPrecise,\n futureAPrecise,\n block.timestamp,\n futureTime_\n );\n }\n\n /**\n * @notice Stops ramping A immediately. Once this function is called, rampA()\n * cannot be called for another 24 hours\n * @param self Swap struct to update\n */\n function stopRampA(SwapUtils.Swap storage self) external {\n require(self.futureATime > block.timestamp, \"Ramp is already stopped\");\n\n uint256 currentA = _getAPrecise(self);\n self.initialA = currentA;\n self.futureA = currentA;\n self.initialATime = block.timestamp;\n self.futureATime = block.timestamp;\n\n emit StopRampA(currentA, block.timestamp);\n }\n}\n" + }, + "@openzeppelin/contracts/token/ERC20/IERC20.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <0.8.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" + }, + "@openzeppelin/contracts/utils/Address.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.2 <0.8.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" + }, + "@openzeppelin/contracts-upgradeable/proxy/Initializable.sol": { + "content": "// SPDX-License-Identifier: MIT\n\n// solhint-disable-next-line compiler-version\npragma solidity >=0.4.24 <0.8.0;\n\nimport \"../utils/AddressUpgradeable.sol\";\n\n/**\n * @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed\n * behind a proxy. Since a proxied contract can't have a constructor, it's common to move constructor logic to an\n * external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer\n * function so it can only be called once. The {initializer} modifier provided by this contract will have this effect.\n *\n * TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as\n * possible by providing the encoded function call as the `_data` argument to {UpgradeableProxy-constructor}.\n *\n * CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure\n * that all initializers are idempotent. This is not verified automatically as constructors are by Solidity.\n */\nabstract contract Initializable {\n\n /**\n * @dev Indicates that the contract has been initialized.\n */\n bool private _initialized;\n\n /**\n * @dev Indicates that the contract is in the process of being initialized.\n */\n bool private _initializing;\n\n /**\n * @dev Modifier to protect an initializer function from being invoked twice.\n */\n modifier initializer() {\n require(_initializing || _isConstructor() || !_initialized, \"Initializable: contract is already initialized\");\n\n bool isTopLevelCall = !_initializing;\n if (isTopLevelCall) {\n _initializing = true;\n _initialized = true;\n }\n\n _;\n\n if (isTopLevelCall) {\n _initializing = false;\n }\n }\n\n /// @dev Returns true if and only if the function is running in the constructor\n function _isConstructor() private view returns (bool) {\n return !AddressUpgradeable.isContract(address(this));\n }\n}\n" + }, + "@openzeppelin/contracts-upgradeable/utils/AddressUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.2 <0.8.0;\n\n/**\n * @dev Collection of functions related to the address type\n */\nlibrary AddressUpgradeable {\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 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" + }, + "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <0.8.0;\n\nimport \"../utils/ContextUpgradeable.sol\";\nimport \"../proxy/Initializable.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 OwnableUpgradeable is Initializable, ContextUpgradeable {\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 function __Ownable_init() internal initializer {\n __Context_init_unchained();\n __Ownable_init_unchained();\n }\n\n function __Ownable_init_unchained() internal initializer {\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 uint256[49] private __gap;\n}\n" + }, + "@openzeppelin/contracts-upgradeable/utils/PausableUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <0.8.0;\n\nimport \"./ContextUpgradeable.sol\";\nimport \"../proxy/Initializable.sol\";\n\n/**\n * @dev Contract module which allows children to implement an emergency stop\n * mechanism that can be triggered by an authorized account.\n *\n * This module is used through inheritance. It will make available the\n * modifiers `whenNotPaused` and `whenPaused`, which can be applied to\n * the functions of your contract. Note that they will not be pausable by\n * simply including this module, only once the modifiers are put in place.\n */\nabstract contract PausableUpgradeable is Initializable, ContextUpgradeable {\n /**\n * @dev Emitted when the pause is triggered by `account`.\n */\n event Paused(address account);\n\n /**\n * @dev Emitted when the pause is lifted by `account`.\n */\n event Unpaused(address account);\n\n bool private _paused;\n\n /**\n * @dev Initializes the contract in unpaused state.\n */\n function __Pausable_init() internal initializer {\n __Context_init_unchained();\n __Pausable_init_unchained();\n }\n\n function __Pausable_init_unchained() internal initializer {\n _paused = false;\n }\n\n /**\n * @dev Returns true if the contract is paused, and false otherwise.\n */\n function paused() public view virtual returns (bool) {\n return _paused;\n }\n\n /**\n * @dev Modifier to make a function callable only when the contract is not paused.\n *\n * Requirements:\n *\n * - The contract must not be paused.\n */\n modifier whenNotPaused() {\n require(!paused(), \"Pausable: paused\");\n _;\n }\n\n /**\n * @dev Modifier to make a function callable only when the contract is paused.\n *\n * Requirements:\n *\n * - The contract must be paused.\n */\n modifier whenPaused() {\n require(paused(), \"Pausable: not paused\");\n _;\n }\n\n /**\n * @dev Triggers stopped state.\n *\n * Requirements:\n *\n * - The contract must not be paused.\n */\n function _pause() internal virtual whenNotPaused {\n _paused = true;\n emit Paused(_msgSender());\n }\n\n /**\n * @dev Returns to normal state.\n *\n * Requirements:\n *\n * - The contract must be paused.\n */\n function _unpause() internal virtual whenPaused {\n _paused = false;\n emit Unpaused(_msgSender());\n }\n uint256[49] private __gap;\n}\n" + }, + "@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <0.8.0;\nimport \"../proxy/Initializable.sol\";\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 ContextUpgradeable is Initializable {\n function __Context_init() internal initializer {\n __Context_init_unchained();\n }\n\n function __Context_init_unchained() internal initializer {\n }\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 uint256[50] private __gap;\n}\n" + }, + "contracts/amm/LPToken.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.6.12;\n\nimport \"@openzeppelin/contracts-upgradeable/token/ERC20/ERC20BurnableUpgradeable.sol\";\nimport \"@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol\";\nimport \"./interfaces/ISwap.sol\";\n\n/**\n * @title Liquidity Provider Token\n * @notice This token is an ERC20 detailed token with added capability to be minted by the owner.\n * It is used to represent user's shares when providing liquidity to swap contracts.\n * @dev Only Swap contracts should initialize and own LPToken contracts.\n */\ncontract LPToken is ERC20BurnableUpgradeable, OwnableUpgradeable {\n using SafeMathUpgradeable for uint256;\n\n /**\n * @notice Initializes this LPToken contract with the given name and symbol\n * @dev The caller of this function will become the owner. A Swap contract should call this\n * in its initializer function.\n * @param name name of this token\n * @param symbol symbol of this token\n */\n function initialize(string memory name, string memory symbol)\n external\n initializer\n returns (bool)\n {\n __Context_init_unchained();\n __ERC20_init_unchained(name, symbol);\n __Ownable_init_unchained();\n return true;\n }\n\n /**\n * @notice Mints the given amount of LPToken to the recipient.\n * @dev only owner can call this mint function\n * @param recipient address of account to receive the tokens\n * @param amount amount of tokens to mint\n */\n function mint(address recipient, uint256 amount) external onlyOwner {\n require(amount != 0, \"LPToken: cannot mint 0\");\n _mint(recipient, amount);\n }\n\n /**\n * @dev Overrides ERC20._beforeTokenTransfer() which get called on every transfers including\n * minting and burning. * This assumes the owner is set to a Swap contract's address.\n */\n function _beforeTokenTransfer(\n address from,\n address to,\n uint256 amount\n ) internal virtual override(ERC20Upgradeable) {\n super._beforeTokenTransfer(from, to, amount);\n require(to != address(this), \"LPToken: cannot send to itself\");\n }\n}\n" + }, + "contracts/amm/MathUtils.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.6.12;\n\nimport \"@openzeppelin/contracts/math/SafeMath.sol\";\n\n/**\n * @title MathUtils library\n * @notice A library to be used in conjunction with SafeMath. Contains functions for calculating\n * differences between two uint256.\n */\nlibrary MathUtils {\n /**\n * @notice Compares a and b and returns true if the difference between a and b\n * is less than 1 or equal to each other.\n * @param a uint256 to compare with\n * @param b uint256 to compare with\n * @return True if the difference between a and b is less than 1 or equal,\n * otherwise return false\n */\n function within1(uint256 a, uint256 b) internal pure returns (bool) {\n return (difference(a, b) <= 1);\n }\n\n /**\n * @notice Calculates absolute difference between a and b\n * @param a uint256 to compare with\n * @param b uint256 to compare with\n * @return Difference between a and b\n */\n function difference(uint256 a, uint256 b) internal pure returns (uint256) {\n if (a > b) {\n return a - b;\n }\n return b - a;\n }\n}\n" + }, + "@openzeppelin/contracts-upgradeable/token/ERC20/ERC20BurnableUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <0.8.0;\n\nimport \"../../utils/ContextUpgradeable.sol\";\nimport \"./ERC20Upgradeable.sol\";\nimport \"../../proxy/Initializable.sol\";\n\n/**\n * @dev Extension of {ERC20} that allows token holders to destroy both their own\n * tokens and those that they have an allowance for, in a way that can be\n * recognized off-chain (via event analysis).\n */\nabstract contract ERC20BurnableUpgradeable is Initializable, ContextUpgradeable, ERC20Upgradeable {\n function __ERC20Burnable_init() internal initializer {\n __Context_init_unchained();\n __ERC20Burnable_init_unchained();\n }\n\n function __ERC20Burnable_init_unchained() internal initializer {\n }\n using SafeMathUpgradeable for uint256;\n\n /**\n * @dev Destroys `amount` tokens from the caller.\n *\n * See {ERC20-_burn}.\n */\n function burn(uint256 amount) public virtual {\n _burn(_msgSender(), amount);\n }\n\n /**\n * @dev Destroys `amount` tokens from `account`, deducting from the caller's\n * allowance.\n *\n * See {ERC20-_burn} and {ERC20-allowance}.\n *\n * Requirements:\n *\n * - the caller must have allowance for ``accounts``'s tokens of at least\n * `amount`.\n */\n function burnFrom(address account, uint256 amount) public virtual {\n uint256 decreasedAllowance = allowance(account, _msgSender()).sub(amount, \"ERC20: burn amount exceeds allowance\");\n\n _approve(account, _msgSender(), decreasedAllowance);\n _burn(account, amount);\n }\n uint256[50] private __gap;\n}\n" + }, + "contracts/amm/interfaces/ISwap.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.6.12;\n\nimport \"@openzeppelin/contracts/token/ERC20/ERC20.sol\";\n\ninterface ISwap {\n // pool data view functions\n function getA() external view returns (uint256);\n\n function getToken(uint8 index) external view returns (IERC20);\n\n function getTokenIndex(address tokenAddress) external view returns (uint8);\n\n function getTokenBalance(uint8 index) external view returns (uint256);\n\n function getVirtualPrice() external view returns (uint256);\n\n // min return calculation functions\n function calculateSwap(\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx\n ) external view returns (uint256);\n\n function calculateTokenAmount(uint256[] calldata amounts, bool deposit)\n external\n view\n returns (uint256);\n\n function calculateRemoveLiquidity(uint256 amount)\n external\n view\n returns (uint256[] memory);\n\n function calculateRemoveLiquidityOneToken(\n uint256 tokenAmount,\n uint8 tokenIndex\n ) external view returns (uint256 availableTokenAmount);\n\n // state modifying functions\n function initialize(\n IERC20[] memory pooledTokens,\n uint8[] memory decimals,\n string memory lpTokenName,\n string memory lpTokenSymbol,\n uint256 a,\n uint256 fee,\n uint256 adminFee,\n address lpTokenTargetAddress\n ) external;\n\n function swap(\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx,\n uint256 minDy,\n uint256 deadline\n ) external returns (uint256);\n\n function addLiquidity(\n uint256[] calldata amounts,\n uint256 minToMint,\n uint256 deadline\n ) external returns (uint256);\n\n function removeLiquidity(\n uint256 amount,\n uint256[] calldata minAmounts,\n uint256 deadline\n ) external returns (uint256[] memory);\n\n function removeLiquidityOneToken(\n uint256 tokenAmount,\n uint8 tokenIndex,\n uint256 minAmount,\n uint256 deadline\n ) external returns (uint256);\n\n function removeLiquidityImbalance(\n uint256[] calldata amounts,\n uint256 maxBurnAmount,\n uint256 deadline\n ) external returns (uint256);\n}\n" + }, + "@openzeppelin/contracts-upgradeable/token/ERC20/ERC20Upgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <0.8.0;\n\nimport \"../../utils/ContextUpgradeable.sol\";\nimport \"./IERC20Upgradeable.sol\";\nimport \"../../math/SafeMathUpgradeable.sol\";\nimport \"../../proxy/Initializable.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 ERC20Upgradeable is Initializable, ContextUpgradeable, IERC20Upgradeable {\n using SafeMathUpgradeable 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 function __ERC20_init(string memory name_, string memory symbol_) internal initializer {\n __Context_init_unchained();\n __ERC20_init_unchained(name_, symbol_);\n }\n\n function __ERC20_init_unchained(string memory name_, string memory symbol_) internal initializer {\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 uint256[44] private __gap;\n}\n" + }, + "@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <0.8.0;\n\n/**\n * @dev Interface of the ERC20 standard as defined in the EIP.\n */\ninterface IERC20Upgradeable {\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" + }, + "@openzeppelin/contracts-upgradeable/math/SafeMathUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <0.8.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 SafeMathUpgradeable {\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" + }, + "@openzeppelin/contracts/token/ERC20/ERC20.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <0.8.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_) public {\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" + }, + "@openzeppelin/contracts/utils/Context.sol": { + "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" + }, + "contracts/amm/SwapFlashLoan.sol": { + "content": "// SPDX-License-Identifier: MIT WITH AGPL-3.0-only\n\npragma solidity 0.6.12;\n\nimport \"./Swap.sol\";\nimport \"./interfaces/IFlashLoanReceiver.sol\";\n\n/**\n * @title Swap - A StableSwap implementation in solidity.\n * @notice This contract is responsible for custody of closely pegged assets (eg. group of stablecoins)\n * and automatic market making system. Users become an LP (Liquidity Provider) by depositing their tokens\n * in desired ratios for an exchange of the pool token that represents their share of the pool.\n * Users can burn pool tokens and withdraw their share of token(s).\n *\n * Each time a swap between the pooled tokens happens, a set fee incurs which effectively gets\n * distributed to the LPs.\n *\n * In case of emergencies, admin can pause additional deposits, swaps, or single-asset withdraws - which\n * stops the ratio of the tokens in the pool from changing.\n * Users can always withdraw their tokens via multi-asset withdraws.\n *\n * @dev Most of the logic is stored as a library `SwapUtils` for the sake of reducing contract's\n * deployment size.\n */\ncontract SwapFlashLoan is Swap {\n // Total fee that is charged on all flashloans in BPS. Borrowers must repay the amount plus the flash loan fee.\n // This fee is split between the protocol and the pool.\n uint256 public flashLoanFeeBPS;\n // Share of the flash loan fee that goes to the protocol in BPS. A portion of each flash loan fee is allocated\n // to the protocol rather than the pool.\n uint256 public protocolFeeShareBPS;\n // Max BPS for limiting flash loan fee settings.\n uint256 public constant MAX_BPS = 10000;\n\n /*** EVENTS ***/\n event FlashLoan(\n address indexed receiver,\n uint8 tokenIndex,\n uint256 amount,\n uint256 amountFee,\n uint256 protocolFee\n );\n\n /**\n * @notice Initializes this Swap contract with the given parameters.\n * This will also clone a LPToken contract that represents users'\n * LP positions. The owner of LPToken will be this contract - which means\n * only this contract is allowed to mint/burn tokens.\n *\n * @param _pooledTokens an array of ERC20s this pool will accept\n * @param decimals the decimals to use for each pooled token,\n * eg 8 for WBTC. Cannot be larger than POOL_PRECISION_DECIMALS\n * @param lpTokenName the long-form name of the token to be deployed\n * @param lpTokenSymbol the short symbol for the token to be deployed\n * @param _a the amplification coefficient * n * (n - 1). See the\n * StableSwap paper for details\n * @param _fee default swap fee to be initialized with\n * @param _adminFee default adminFee to be initialized with\n * @param lpTokenTargetAddress the address of an existing LPToken contract to use as a target\n */\n function initialize(\n IERC20[] memory _pooledTokens,\n uint8[] memory decimals,\n string memory lpTokenName,\n string memory lpTokenSymbol,\n uint256 _a,\n uint256 _fee,\n uint256 _adminFee,\n address lpTokenTargetAddress\n ) public virtual override initializer {\n Swap.initialize(\n _pooledTokens,\n decimals,\n lpTokenName,\n lpTokenSymbol,\n _a,\n _fee,\n _adminFee,\n lpTokenTargetAddress\n );\n flashLoanFeeBPS = 8; // 8 bps\n protocolFeeShareBPS = 0; // 0 bps\n }\n\n /*** STATE MODIFYING FUNCTIONS ***/\n\n /**\n * @notice Borrow the specified token from this pool for this transaction only. This function will call\n * `IFlashLoanReceiver(receiver).executeOperation` and the `receiver` must return the full amount of the token\n * and the associated fee by the end of the callback transaction. If the conditions are not met, this call\n * is reverted.\n * @param receiver the address of the receiver of the token. This address must implement the IFlashLoanReceiver\n * interface and the callback function `executeOperation`.\n * @param token the protocol fee in bps to be applied on the total flash loan fee\n * @param amount the total amount to borrow in this transaction\n * @param params optional data to pass along to the callback function\n */\n function flashLoan(\n address receiver,\n IERC20 token,\n uint256 amount,\n bytes memory params\n ) external nonReentrant {\n uint8 tokenIndex = getTokenIndex(address(token));\n uint256 availableLiquidityBefore = token.balanceOf(address(this));\n uint256 protocolBalanceBefore = availableLiquidityBefore.sub(\n swapStorage.balances[tokenIndex]\n );\n require(\n amount > 0 && availableLiquidityBefore >= amount,\n \"invalid amount\"\n );\n\n // Calculate the additional amount of tokens the pool should end up with\n uint256 amountFee = amount.mul(flashLoanFeeBPS).div(10000);\n // Calculate the portion of the fee that will go to the protocol\n uint256 protocolFee = amountFee.mul(protocolFeeShareBPS).div(10000);\n require(amountFee > 0, \"amount is small for a flashLoan\");\n\n // Transfer the requested amount of tokens\n token.safeTransfer(receiver, amount);\n\n // Execute callback function on receiver\n IFlashLoanReceiver(receiver).executeOperation(\n address(this),\n address(token),\n amount,\n amountFee,\n params\n );\n\n uint256 availableLiquidityAfter = token.balanceOf(address(this));\n require(\n availableLiquidityAfter >= availableLiquidityBefore.add(amountFee),\n \"flashLoan fee is not met\"\n );\n\n swapStorage.balances[tokenIndex] = availableLiquidityAfter\n .sub(protocolBalanceBefore)\n .sub(protocolFee);\n emit FlashLoan(receiver, tokenIndex, amount, amountFee, protocolFee);\n }\n\n /*** ADMIN FUNCTIONS ***/\n\n /**\n * @notice Updates the flash loan fee parameters. This function can only be called by the owner.\n * @param newFlashLoanFeeBPS the total fee in bps to be applied on future flash loans\n * @param newProtocolFeeShareBPS the protocol fee in bps to be applied on the total flash loan fee\n */\n function setFlashLoanFees(\n uint256 newFlashLoanFeeBPS,\n uint256 newProtocolFeeShareBPS\n ) external onlyOwner {\n require(\n newFlashLoanFeeBPS > 0 &&\n newFlashLoanFeeBPS <= MAX_BPS &&\n newProtocolFeeShareBPS <= MAX_BPS,\n \"fees are not in valid range\"\n );\n flashLoanFeeBPS = newFlashLoanFeeBPS;\n protocolFeeShareBPS = newProtocolFeeShareBPS;\n }\n}\n" + }, + "contracts/amm/interfaces/IFlashLoanReceiver.sol": { + "content": "// SPDX-License-Identifier: AGPL-3.0-only\n\npragma solidity 0.6.12;\n\n/**\n * @title IFlashLoanReceiver interface\n * @notice Interface for the Nerve fee IFlashLoanReceiver. Modified from Aave's IFlashLoanReceiver interface.\n * https://github.com/aave/aave-protocol/blob/4b4545fb583fd4f400507b10f3c3114f45b8a037/contracts/flashloan/interfaces/IFlashLoanReceiver.sol\n * @author Aave\n * @dev implement this interface to develop a flashloan-compatible flashLoanReceiver contract\n **/\ninterface IFlashLoanReceiver {\n function executeOperation(\n address pool,\n address token,\n uint256 amount,\n uint256 fee,\n bytes calldata params\n ) external;\n}\n" + }, + "contracts/amm/helper/FlashLoanBorrowerExample.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.6.12;\n\nimport \"@openzeppelin/contracts/math/SafeMath.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/SafeERC20.sol\";\nimport \"../interfaces/IFlashLoanReceiver.sol\";\nimport \"../interfaces/ISwapFlashLoan.sol\";\nimport \"hardhat/console.sol\";\n\ncontract FlashLoanBorrowerExample is IFlashLoanReceiver {\n using SafeMath for uint256;\n\n // Typical executeOperation function should do the 3 following actions\n // 1. Check if the flashLoan was successful\n // 2. Do actions with the borrowed tokens\n // 3. Repay the debt to the `pool`\n function executeOperation(\n address pool,\n address token,\n uint256 amount,\n uint256 fee,\n bytes calldata params\n ) external override {\n // 1. Check if the flashLoan was valid\n require(\n IERC20(token).balanceOf(address(this)) >= amount,\n \"flashloan is broken?\"\n );\n\n // 2. Do actions with the borrowed token\n bytes32 paramsHash = keccak256(params);\n if (paramsHash == keccak256(bytes(\"dontRepayDebt\"))) {\n return;\n } else if (paramsHash == keccak256(bytes(\"reentrancy_addLiquidity\"))) {\n ISwapFlashLoan(pool).addLiquidity(\n new uint256[](0),\n 0,\n block.timestamp\n );\n } else if (paramsHash == keccak256(bytes(\"reentrancy_swap\"))) {\n ISwapFlashLoan(pool).swap(1, 0, 1e6, 0, now);\n } else if (\n paramsHash == keccak256(bytes(\"reentrancy_removeLiquidity\"))\n ) {\n ISwapFlashLoan(pool).removeLiquidity(1e18, new uint256[](0), now);\n } else if (\n paramsHash == keccak256(bytes(\"reentrancy_removeLiquidityOneToken\"))\n ) {\n ISwapFlashLoan(pool).removeLiquidityOneToken(1e18, 0, 1e18, now);\n }\n\n // 3. Payback debt\n uint256 totalDebt = amount.add(fee);\n IERC20(token).transfer(pool, totalDebt);\n }\n\n function flashLoan(\n ISwapFlashLoan swap,\n IERC20 token,\n uint256 amount,\n bytes memory params\n ) external {\n swap.flashLoan(address(this), token, amount, params);\n }\n}\n" + }, + "contracts/amm/interfaces/ISwapFlashLoan.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.6.12;\n\nimport \"./ISwap.sol\";\n\ninterface ISwapFlashLoan is ISwap {\n function flashLoan(\n address receiver,\n IERC20 token,\n uint256 amount,\n bytes memory params\n ) external;\n}\n" + }, + "hardhat/console.sol": { + "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" + }, + "contracts/amm/helper/test/TestSwapReturnValues.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.6.12;\n\nimport \"../../interfaces/ISwap.sol\";\nimport \"hardhat/console.sol\";\n\ncontract TestSwapReturnValues {\n using SafeMath for uint256;\n\n ISwap public swap;\n IERC20 public lpToken;\n uint8 public n;\n\n uint256 public constant MAX_INT = 2**256 - 1;\n\n constructor(\n ISwap swapContract,\n IERC20 lpTokenContract,\n uint8 numOfTokens\n ) public {\n swap = swapContract;\n lpToken = lpTokenContract;\n n = numOfTokens;\n\n // Pre-approve tokens\n for (uint8 i; i < n; i++) {\n swap.getToken(i).approve(address(swap), MAX_INT);\n }\n lpToken.approve(address(swap), MAX_INT);\n }\n\n function test_swap(\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx,\n uint256 minDy\n ) public {\n uint256 balanceBefore =\n swap.getToken(tokenIndexTo).balanceOf(address(this));\n uint256 returnValue =\n swap.swap(tokenIndexFrom, tokenIndexTo, dx, minDy, block.timestamp);\n uint256 balanceAfter =\n swap.getToken(tokenIndexTo).balanceOf(address(this));\n\n console.log(\n \"swap: Expected %s, got %s\",\n balanceAfter.sub(balanceBefore),\n returnValue\n );\n\n require(\n returnValue == balanceAfter.sub(balanceBefore),\n \"swap()'s return value does not match received amount\"\n );\n }\n\n function test_addLiquidity(uint256[] calldata amounts, uint256 minToMint)\n public\n {\n uint256 balanceBefore = lpToken.balanceOf(address(this));\n uint256 returnValue = swap.addLiquidity(amounts, minToMint, MAX_INT);\n uint256 balanceAfter = lpToken.balanceOf(address(this));\n\n console.log(\n \"addLiquidity: Expected %s, got %s\",\n balanceAfter.sub(balanceBefore),\n returnValue\n );\n\n require(\n returnValue == balanceAfter.sub(balanceBefore),\n \"addLiquidity()'s return value does not match minted amount\"\n );\n }\n\n function test_removeLiquidity(uint256 amount, uint256[] memory minAmounts)\n public\n {\n uint256[] memory balanceBefore = new uint256[](n);\n uint256[] memory balanceAfter = new uint256[](n);\n\n for (uint8 i = 0; i < n; i++) {\n balanceBefore[i] = swap.getToken(i).balanceOf(address(this));\n }\n\n uint256[] memory returnValue =\n swap.removeLiquidity(amount, minAmounts, MAX_INT);\n\n for (uint8 i = 0; i < n; i++) {\n balanceAfter[i] = swap.getToken(i).balanceOf(address(this));\n console.log(\n \"removeLiquidity: Expected %s, got %s\",\n balanceAfter[i].sub(balanceBefore[i]),\n returnValue[i]\n );\n require(\n balanceAfter[i].sub(balanceBefore[i]) == returnValue[i],\n \"removeLiquidity()'s return value does not match received amounts of tokens\"\n );\n }\n }\n\n function test_removeLiquidityImbalance(\n uint256[] calldata amounts,\n uint256 maxBurnAmount\n ) public {\n uint256 balanceBefore = lpToken.balanceOf(address(this));\n uint256 returnValue =\n swap.removeLiquidityImbalance(amounts, maxBurnAmount, MAX_INT);\n uint256 balanceAfter = lpToken.balanceOf(address(this));\n\n console.log(\n \"removeLiquidityImbalance: Expected %s, got %s\",\n balanceBefore.sub(balanceAfter),\n returnValue\n );\n\n require(\n returnValue == balanceBefore.sub(balanceAfter),\n \"removeLiquidityImbalance()'s return value does not match burned lpToken amount\"\n );\n }\n\n function test_removeLiquidityOneToken(\n uint256 tokenAmount,\n uint8 tokenIndex,\n uint256 minAmount\n ) public {\n uint256 balanceBefore =\n swap.getToken(tokenIndex).balanceOf(address(this));\n uint256 returnValue =\n swap.removeLiquidityOneToken(\n tokenAmount,\n tokenIndex,\n minAmount,\n MAX_INT\n );\n uint256 balanceAfter =\n swap.getToken(tokenIndex).balanceOf(address(this));\n\n console.log(\n \"removeLiquidityOneToken: Expected %s, got %s\",\n balanceAfter.sub(balanceBefore),\n returnValue\n );\n\n require(\n returnValue == balanceAfter.sub(balanceBefore),\n \"removeLiquidityOneToken()'s return value does not match received token amount\"\n );\n }\n}\n" + }, + "contracts/amm/SwapDeployer.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.6.12;\n\nimport \"@openzeppelin/contracts/access/Ownable.sol\";\nimport \"@openzeppelin/contracts/proxy/Clones.sol\";\nimport \"./interfaces/ISwap.sol\";\n\ncontract SwapDeployer is Ownable {\n event NewSwapPool(\n address indexed deployer,\n address swapAddress,\n IERC20[] pooledTokens\n );\n\n constructor() public Ownable() {}\n\n function deploy(\n address swapAddress,\n IERC20[] memory _pooledTokens,\n uint8[] memory decimals,\n string memory lpTokenName,\n string memory lpTokenSymbol,\n uint256 _a,\n uint256 _fee,\n uint256 _adminFee,\n address lpTokenTargetAddress\n ) external returns (address) {\n address swapClone = Clones.clone(swapAddress);\n ISwap(swapClone).initialize(\n _pooledTokens,\n decimals,\n lpTokenName,\n lpTokenSymbol,\n _a,\n _fee,\n _adminFee,\n lpTokenTargetAddress\n );\n Ownable(swapClone).transferOwnership(owner());\n emit NewSwapPool(msg.sender, swapClone, _pooledTokens);\n return swapClone;\n }\n}\n" + }, + "@openzeppelin/contracts/access/Ownable.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <0.8.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 () internal {\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" + }, + "contracts/bridge/SynapseERC20Factory.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.6.12;\n\nimport \"@openzeppelin/contracts/access/Ownable.sol\";\nimport \"@openzeppelin/contracts/proxy/Clones.sol\";\nimport \"./interfaces/ISynapseERC20.sol\";\n\ncontract SynapseERC20Factory {\n constructor() public {}\n\n event SynapseERC20Created(address contractAddress);\n\n /**\n * @notice Deploys a new node\n * @param synapseERC20Address address of the synapseERC20Address contract to initialize with\n * @param name Token name\n * @param symbol Token symbol\n * @param decimals Token name\n * @param owner admin address to be initialized with\n * @return Address of the newest node management contract created\n **/\n function deploy(\n address synapseERC20Address,\n string memory name,\n string memory symbol,\n uint8 decimals,\n address owner\n ) external returns (address) {\n address synERC20Clone = Clones.clone(synapseERC20Address);\n ISynapseERC20(synERC20Clone).initialize(name, symbol, decimals, owner);\n\n emit SynapseERC20Created(synERC20Clone);\n\n return synERC20Clone;\n }\n}\n" + }, + "contracts/bridge/interfaces/ISynapseERC20.sol": { + "content": "// SPDX-License-Identifier: MIT\n\n\npragma solidity 0.6.12;\n\ninterface ISynapseERC20 { \n function initialize(\n string memory _name, string memory _symbol, uint8 _decimals, address owner) external;\n\n function mint(address to, uint256 amount) external;\n}\n\n" + }, + "contracts/bridge/wrappers/AvaxJewelMigrationV2.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.6.12;\n\nimport \"@openzeppelin/contracts/token/ERC20/ERC20.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/SafeERC20.sol\";\nimport \"@openzeppelin/contracts/access/Ownable.sol\";\n\nimport \"../interfaces/ISynapseBridge.sol\";\n\ninterface IERC20Mintable is IERC20 {\n function mint(address to, uint256 amount) external;\n}\n\ncontract AvaxJewelMigrationV2 is Ownable {\n using SafeERC20 for IERC20;\n using SafeERC20 for IERC20Mintable;\n\n ISynapseBridge public constant SYNAPSE_BRIDGE =\n ISynapseBridge(0xC05e61d0E7a63D27546389B7aD62FdFf5A91aACE);\n // MULTICHAIN JEWEL\n IERC20 public constant LEGACY_TOKEN =\n IERC20(0x4f60a160D8C2DDdaAfe16FCC57566dB84D674BD6);\n // SYNAPSE JEWEL\n IERC20Mintable public constant NEW_TOKEN =\n IERC20Mintable(0x997Ddaa07d716995DE90577C123Db411584E5E46);\n uint256 private constant MAX_UINT256 = 2**256 - 1;\n\n uint256 private constant HARMONY_ID = 1666600000;\n\n constructor() public {\n NEW_TOKEN.safeApprove(address(SYNAPSE_BRIDGE), MAX_UINT256);\n }\n\n function migrate(uint256 amount) external {\n _migrate(amount, msg.sender);\n }\n\n function migrateAndBridge(\n uint256 amount,\n address to,\n uint256 chainId\n ) external {\n // First, mint new tokens to this contract, as Bridge burns tokens\n // from msg.sender, which would be AvaxJewelMigration\n _migrate(amount, address(this));\n // Initiate bridging and specify `to` as receiver on destination chain\n if (chainId == HARMONY_ID) {\n SYNAPSE_BRIDGE.redeemAndSwap(\n to,\n chainId,\n NEW_TOKEN,\n amount,\n 1, // indexFrom\n 0, // indexTo\n 0, // minDy\n type(uint256).max // deadline\n );\n } else {\n SYNAPSE_BRIDGE.redeem(to, chainId, NEW_TOKEN, amount);\n }\n }\n\n /// @notice Pull old tokens from user and mint new ones to account\n function _migrate(uint256 amount, address account) internal {\n require(amount != 0, \"Amount must be greater than zero\");\n LEGACY_TOKEN.safeTransferFrom(msg.sender, address(this), amount);\n NEW_TOKEN.mint(account, amount);\n }\n\n function redeemLegacy() external onlyOwner {\n uint256 legacyBalance = LEGACY_TOKEN.balanceOf(address(this));\n LEGACY_TOKEN.safeTransfer(owner(), legacyBalance);\n }\n}\n" + }, + "contracts/bridge/interfaces/ISynapseBridge.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.6.12;\n\nimport '@openzeppelin/contracts/token/ERC20/SafeERC20.sol';\nimport '@openzeppelin/contracts/token/ERC20/ERC20Burnable.sol';\n\ninterface ISynapseBridge {\n using SafeERC20 for IERC20;\n\n function deposit(\n address to,\n uint256 chainId,\n IERC20 token,\n uint256 amount\n ) external;\n\n function depositAndSwap(\n address to,\n uint256 chainId,\n IERC20 token,\n uint256 amount,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 minDy,\n uint256 deadline\n ) external;\n\n function redeem(\n address to,\n uint256 chainId,\n IERC20 token,\n uint256 amount\n ) external;\n\n\n function redeemv2(\n bytes32 to,\n uint256 chainId,\n IERC20 token,\n uint256 amount\n ) external;\n\n\n function redeemAndSwap(\n address to,\n uint256 chainId,\n IERC20 token,\n uint256 amount,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 minDy,\n uint256 deadline\n ) external;\n\n function redeemAndRemove(\n address to,\n uint256 chainId,\n IERC20 token,\n uint256 amount,\n uint8 liqTokenIndex,\n uint256 liqMinAmount,\n uint256 liqDeadline\n ) external;\n}\n" + }, + "@openzeppelin/contracts/token/ERC20/ERC20Burnable.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <0.8.0;\n\nimport \"../../utils/Context.sol\";\nimport \"./ERC20.sol\";\n\n/**\n * @dev Extension of {ERC20} that allows token holders to destroy both their own\n * tokens and those that they have an allowance for, in a way that can be\n * recognized off-chain (via event analysis).\n */\nabstract contract ERC20Burnable is Context, ERC20 {\n using SafeMath for uint256;\n\n /**\n * @dev Destroys `amount` tokens from the caller.\n *\n * See {ERC20-_burn}.\n */\n function burn(uint256 amount) public virtual {\n _burn(_msgSender(), amount);\n }\n\n /**\n * @dev Destroys `amount` tokens from `account`, deducting from the caller's\n * allowance.\n *\n * See {ERC20-_burn} and {ERC20-allowance}.\n *\n * Requirements:\n *\n * - the caller must have allowance for ``accounts``'s tokens of at least\n * `amount`.\n */\n function burnFrom(address account, uint256 amount) public virtual {\n uint256 decreasedAllowance = allowance(account, _msgSender()).sub(amount, \"ERC20: burn amount exceeds allowance\");\n\n _approve(account, _msgSender(), decreasedAllowance);\n _burn(account, amount);\n }\n}\n" + }, + "contracts/bridge/wrappers/MoonriverBridgeZap.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.6.12;\n\nimport \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/SafeERC20.sol\";\nimport \"../interfaces/ISwap.sol\";\nimport \"../interfaces/ISynapseBridge.sol\";\nimport \"../interfaces/IWETH9.sol\";\n\ninterface IFrax {\n function exchangeCanonicalForOld(address bridge_token_address, uint256 token_amount) external returns (uint256);\n}\n\ncontract MoonriverBridgeZap {\n using SafeERC20 for IERC20;\n\n ISynapseBridge synapseBridge;\n address payable public immutable WETH_ADDRESS;\n IFrax private constant CANOLICAL_FRAX = IFrax(0x1A93B23281CC1CDE4C4741353F3064709A16197d);\n IERC20 private constant SYN_FRAX = IERC20(0xE96AC70907ffF3Efee79f502C985A7A21Bce407d);\n\n mapping(address => address) public swapMap;\n mapping(address => IERC20[]) public swapTokensMap;\n\n uint256 constant MAX_UINT256 = 2**256 - 1;\n\n constructor(\n address payable _wethAddress,\n address _swapOne,\n address tokenOne,\n address _swapTwo,\n address tokenTwo,\n ISynapseBridge _synapseBridge\n ) public {\n WETH_ADDRESS = _wethAddress;\n synapseBridge = _synapseBridge;\n swapMap[tokenOne] = _swapOne;\n swapMap[tokenTwo] = _swapTwo;\n IERC20(_wethAddress).safeIncreaseAllowance(address(_synapseBridge), MAX_UINT256);\n if (address(_swapOne) != address(0)) {\n {\n uint8 i;\n for (; i < 32; i++) {\n try ISwap(_swapOne).getToken(i) returns (\n IERC20 token\n ) {\n swapTokensMap[_swapOne].push(token);\n token.safeApprove(address(_swapOne), MAX_UINT256);\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n } catch {\n break;\n }\n }\n require(i > 1, \"swap must have at least 2 tokens\");\n }\n }\n if (address(_swapTwo) != address(0)) {\n {\n uint8 i;\n for (; i < 32; i++) {\n try ISwap(_swapTwo).getToken(i) returns (\n IERC20 token\n ) {\n swapTokensMap[_swapTwo].push(token);\n token.safeApprove(address(_swapTwo), MAX_UINT256);\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n } catch {\n break;\n }\n }\n require(i > 1, \"swap must have at least 2 tokens\");\n }\n }\n }\n\n /**\n * @notice Calculate amount of tokens you receive on swap\n * @param tokenIndexFrom the token the user wants to sell\n * @param tokenIndexTo the token the user wants to buy\n * @param dx the amount of tokens the user wants to sell. If the token charges\n * a fee on transfers, use the amount that gets transferred after the fee.\n * @return amount of tokens the user will receive\n */\n function calculateSwap(\n IERC20 token,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx\n ) external view virtual returns (uint256) {\n ISwap swap = ISwap(\n swapMap[address(token)]\n );\n return swap.calculateSwap(tokenIndexFrom, tokenIndexTo, dx);\n }\n\n function swapAndRedeem(\n address to,\n uint256 chainId,\n IERC20 token,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx,\n uint256 minDy,\n uint256 deadline\n ) external {\n ISwap swap = ISwap(swapMap[address(token)]);\n require(address(swap) != address(0), \"Swap is 0x00\");\n IERC20[] memory tokens = swapTokensMap[address(swap)];\n tokens[tokenIndexFrom].safeTransferFrom(\n msg.sender,\n address(this),\n dx\n );\n // swap\n\n uint256 swappedAmount = swap.swap(\n tokenIndexFrom,\n tokenIndexTo,\n dx,\n minDy,\n deadline\n );\n // deposit into bridge, gets nUSD\n if (\n token.allowance(address(this), address(synapseBridge)) <\n swappedAmount\n ) {\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n }\n synapseBridge.redeem(to, chainId, token, swappedAmount);\n }\n\n function swapAndRedeemAndSwap(\n address to,\n uint256 chainId,\n IERC20 token,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx,\n uint256 minDy,\n uint256 deadline,\n uint8 swapTokenIndexFrom,\n uint8 swapTokenIndexTo,\n uint256 swapMinDy,\n uint256 swapDeadline\n ) external {\n require(\n address(swapMap[address(token)]) != address(0),\n \"Swap is 0x00\"\n );\n IERC20[] memory tokens = swapTokensMap[\n swapMap[address(token)]\n ];\n tokens[tokenIndexFrom].safeTransferFrom(\n msg.sender,\n address(this),\n dx\n );\n // swap\n\n uint256 swappedAmount = ISwap(swapMap[address(token)]).swap(tokenIndexFrom, tokenIndexTo, dx, minDy, deadline);\n // deposit into bridge, gets nUSD\n if (\n token.allowance(address(this), address(synapseBridge)) <\n swappedAmount\n ) {\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n }\n synapseBridge.redeemAndSwap(\n to,\n chainId,\n token,\n swappedAmount,\n swapTokenIndexFrom,\n swapTokenIndexTo,\n swapMinDy,\n swapDeadline\n );\n }\n\n function swapAndRedeemAndRemove(\n address to,\n uint256 chainId,\n IERC20 token,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx,\n uint256 minDy,\n uint256 deadline,\n uint8 liqTokenIndex,\n uint256 liqMinAmount,\n uint256 liqDeadline\n ) external {\n ISwap swap = ISwap(swapMap[address(token)]);\n require(address(swap) != address(0), \"Swap is 0x00\");\n IERC20[] memory tokens = swapTokensMap[address(swap)];\n tokens[tokenIndexFrom].safeTransferFrom(\n msg.sender,\n address(this),\n dx\n );\n // swap\n\n uint256 swappedAmount = swap.swap(\n tokenIndexFrom,\n tokenIndexTo,\n dx,\n minDy,\n deadline\n );\n // deposit into bridge, gets nUSD\n if (\n token.allowance(address(this), address(synapseBridge)) <\n swappedAmount\n ) {\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n }\n synapseBridge.redeemAndRemove(\n to,\n chainId,\n token,\n swappedAmount,\n liqTokenIndex,\n liqMinAmount,\n liqDeadline\n );\n }\n\n /**\n * @notice wraps SynapseBridge redeem()\n * @param to address on other chain to redeem underlying assets to\n * @param chainId which underlying chain to bridge assets onto\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n **/\n function redeem(\n address to,\n uint256 chainId,\n IERC20 token,\n uint256 amount\n ) external {\n token.safeTransferFrom(msg.sender, address(this), amount);\n if (address(token) == address(CANOLICAL_FRAX)) {\n uint256 swappedAmount = CANOLICAL_FRAX.exchangeCanonicalForOld(address(SYN_FRAX), amount);\n if (SYN_FRAX.allowance(address(this), address(synapseBridge)) < amount) {\n SYN_FRAX.safeApprove(address(synapseBridge), MAX_UINT256);\n }\n synapseBridge.redeem(to, chainId, SYN_FRAX, swappedAmount);\n } else {\n if (token.allowance(address(this), address(synapseBridge)) < amount) {\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n }\n synapseBridge.redeem(to, chainId, token, amount);\n }\n }\n\n /**\n * @notice Wraps SynapseBridge redeemv2() function\n * @param to address on other chain to bridge assets to\n * @param chainId which chain to bridge assets onto\n * @param token ERC20 compatible token to redeem into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n **/\n function redeemv2(\n bytes32 to,\n uint256 chainId,\n IERC20 token,\n uint256 amount\n ) external {\n token.safeTransferFrom(msg.sender, address(this), amount);\n\n if (token.allowance(address(this), address(synapseBridge)) < amount) {\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n }\n synapseBridge.redeemv2(to, chainId, token, amount);\n }\n\n /**\n * @notice wraps SynapseBridge redeem()\n * @param to address on other chain to redeem underlying assets to\n * @param chainId which underlying chain to bridge assets onto\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n **/\n function deposit(\n address to,\n uint256 chainId,\n IERC20 token,\n uint256 amount\n ) external {\n token.safeTransferFrom(msg.sender, address(this), amount);\n if (token.allowance(address(this), address(synapseBridge)) < amount) {\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n }\n synapseBridge.deposit(to, chainId, token, amount);\n }\n\n /**\n * @notice Wraps SynapseBridge deposit() function to make it compatible w/ ETH -> WETH conversions\n * @param to address on other chain to bridge assets to\n * @param chainId which chain to bridge assets onto\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n **/\n function depositETH(\n address to,\n uint256 chainId,\n uint256 amount\n ) external payable {\n require(msg.value > 0 && msg.value == amount, 'INCORRECT MSG VALUE');\n IWETH9(WETH_ADDRESS).deposit{value: msg.value}();\n synapseBridge.deposit(to, chainId, IERC20(WETH_ADDRESS), amount);\n }\n\n\n\n function swapETHAndRedeem(\n address to,\n uint256 chainId,\n IERC20 token,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx,\n uint256 minDy,\n uint256 deadline\n ) external payable {\n require(WETH_ADDRESS != address(0), \"WETH 0\");\n require(msg.value > 0 && msg.value == dx, \"INCORRECT MSG VALUE\");\n ISwap swap = ISwap(swapMap[address(token)]);\n require(address(swap) != address(0), \"Swap is 0x00\");\n IWETH9(WETH_ADDRESS).deposit{value: msg.value}();\n\n // swap\n uint256 swappedAmount = swap.swap(\n tokenIndexFrom,\n tokenIndexTo,\n dx,\n minDy,\n deadline\n );\n synapseBridge.redeem(to, chainId, token, swappedAmount);\n }\n\n /**\n * @notice Wraps redeemAndSwap on SynapseBridge.sol\n * Relays to nodes that (typically) a wrapped synAsset ERC20 token has been burned and the underlying needs to be redeeemed on the native chain. This function indicates to the nodes that they should attempt to redeem the LP token for the underlying assets (E.g \"swap\" out of the LP token)\n * @param to address on other chain to redeem underlying assets to\n * @param chainId which underlying chain to bridge assets onto\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n * @param tokenIndexFrom the token the user wants to swap from\n * @param tokenIndexTo the token the user wants to swap to\n * @param minDy the min amount the user would like to receive, or revert to only minting the SynERC20 token crosschain.\n * @param deadline latest timestamp to accept this transaction\n **/\n function redeemAndSwap(\n address to,\n uint256 chainId,\n IERC20 token,\n uint256 amount,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 minDy,\n uint256 deadline\n ) external {\n token.safeTransferFrom(msg.sender, address(this), amount);\n if (token.allowance(address(this), address(synapseBridge)) < amount) {\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n }\n synapseBridge.redeemAndSwap(\n to,\n chainId,\n token,\n amount,\n tokenIndexFrom,\n tokenIndexTo,\n minDy,\n deadline\n );\n }\n\n /**\n * @notice Wraps redeemAndRemove on SynapseBridge\n * Relays to nodes that (typically) a wrapped synAsset ERC20 token has been burned and the underlying needs to be redeeemed on the native chain. This function indicates to the nodes that they should attempt to redeem the LP token for the underlying assets (E.g \"swap\" out of the LP token)\n * @param to address on other chain to redeem underlying assets to\n * @param chainId which underlying chain to bridge assets onto\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount of (typically) LP token to pass to the nodes to attempt to removeLiquidity() with to redeem for the underlying assets of the LP token\n * @param liqTokenIndex Specifies which of the underlying LP assets the nodes should attempt to redeem for\n * @param liqMinAmount Specifies the minimum amount of the underlying asset needed for the nodes to execute the redeem/swap\n * @param liqDeadline Specificies the deadline that the nodes are allowed to try to redeem/swap the LP token\n **/\n function redeemAndRemove(\n address to,\n uint256 chainId,\n IERC20 token,\n uint256 amount,\n uint8 liqTokenIndex,\n uint256 liqMinAmount,\n uint256 liqDeadline\n ) external {\n token.safeTransferFrom(msg.sender, address(this), amount);\n if (token.allowance(address(this), address(synapseBridge)) < amount) {\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n }\n synapseBridge.redeemAndRemove(\n to,\n chainId,\n token,\n amount,\n liqTokenIndex,\n liqMinAmount,\n liqDeadline\n );\n }\n}\n" + }, + "contracts/bridge/interfaces/ISwap.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.6.12;\n\nimport '@openzeppelin/contracts/token/ERC20/ERC20.sol';\n\ninterface ISwap {\n // pool data view functions\n function getA() external view returns (uint256);\n\n function getToken(uint8 index) external view returns (IERC20);\n\n function getTokenIndex(address tokenAddress) external view returns (uint8);\n\n function getTokenBalance(uint8 index) external view returns (uint256);\n\n function getVirtualPrice() external view returns (uint256);\n\n // min return calculation functions\n function calculateSwap(\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx\n ) external view returns (uint256);\n\n function calculateTokenAmount(uint256[] calldata amounts, bool deposit)\n external\n view\n returns (uint256);\n\n function calculateRemoveLiquidity(uint256 amount)\n external\n view\n returns (uint256[] memory);\n\n function calculateRemoveLiquidityOneToken(\n uint256 tokenAmount,\n uint8 tokenIndex\n ) external view returns (uint256 availableTokenAmount);\n\n // state modifying functions\n function initialize(\n IERC20[] memory pooledTokens,\n uint8[] memory decimals,\n string memory lpTokenName,\n string memory lpTokenSymbol,\n uint256 a,\n uint256 fee,\n uint256 adminFee,\n address lpTokenTargetAddress\n ) external;\n\n function swap(\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx,\n uint256 minDy,\n uint256 deadline\n ) external returns (uint256);\n\n function addLiquidity(\n uint256[] calldata amounts,\n uint256 minToMint,\n uint256 deadline\n ) external returns (uint256);\n\n function removeLiquidity(\n uint256 amount,\n uint256[] calldata minAmounts,\n uint256 deadline\n ) external returns (uint256[] memory);\n\n function removeLiquidityOneToken(\n uint256 tokenAmount,\n uint8 tokenIndex,\n uint256 minAmount,\n uint256 deadline\n ) external returns (uint256);\n\n function removeLiquidityImbalance(\n uint256[] calldata amounts,\n uint256 maxBurnAmount,\n uint256 deadline\n ) external returns (uint256);\n}\n" + }, + "contracts/bridge/interfaces/IWETH9.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.4.0;\n\ninterface IWETH9 {\n function name() external view returns (string memory);\n\n function symbol() external view returns (string memory);\n\n function decimals() external view returns (uint8);\n\n function balanceOf(address) external view returns (uint256);\n\n function allowance(address, address) external view returns (uint256);\n\n receive() external payable;\n\n function deposit() external payable;\n\n function withdraw(uint256 wad) external;\n\n function totalSupply() external view returns (uint256);\n\n function approve(address guy, uint256 wad) external returns (bool);\n\n function transfer(address dst, uint256 wad) external returns (bool);\n\n function transferFrom(\n address src,\n address dst,\n uint256 wad\n ) external returns (bool);\n}" + }, + "contracts/bridge/wrappers/L2BridgeZap.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.6.12;\n\nimport \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/SafeERC20.sol\";\nimport \"../interfaces/ISwap.sol\";\nimport \"../interfaces/ISynapseBridge.sol\";\nimport \"../interfaces/IWETH9.sol\";\n\ncontract L2BridgeZap {\n using SafeERC20 for IERC20;\n\n ISynapseBridge synapseBridge;\n address payable public immutable WETH_ADDRESS;\n\n mapping(address => address) public swapMap;\n mapping(address => IERC20[]) public swapTokensMap;\n\n uint256 constant MAX_UINT256 = 2**256 - 1;\n\n constructor(\n address payable _wethAddress,\n address _swapOne,\n address tokenOne,\n address _swapTwo,\n address tokenTwo,\n ISynapseBridge _synapseBridge\n ) public {\n WETH_ADDRESS = _wethAddress;\n synapseBridge = _synapseBridge;\n swapMap[tokenOne] = _swapOne;\n swapMap[tokenTwo] = _swapTwo;\n // if (_wethAddress != address(0)) {\n // IERC20(_wethAddress).safeIncreaseAllowance(address(_synapseBridge), MAX_UINT256);\n // }\n if (address(_swapOne) != address(0)) {\n {\n uint8 i;\n for (; i < 32; i++) {\n try ISwap(_swapOne).getToken(i) returns (\n IERC20 token\n ) {\n swapTokensMap[_swapOne].push(token);\n token.safeApprove(address(_swapOne), MAX_UINT256);\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n } catch {\n break;\n }\n }\n require(i > 1, \"swap must have at least 2 tokens\");\n }\n }\n if (address(_swapTwo) != address(0)) {\n {\n uint8 i;\n for (; i < 32; i++) {\n try ISwap(_swapTwo).getToken(i) returns (\n IERC20 token\n ) {\n swapTokensMap[_swapTwo].push(token);\n token.safeApprove(address(_swapTwo), MAX_UINT256);\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n } catch {\n break;\n }\n }\n require(i > 1, \"swap must have at least 2 tokens\");\n }\n }\n }\n\n /**\n * @notice Calculate amount of tokens you receive on swap\n * @param tokenIndexFrom the token the user wants to sell\n * @param tokenIndexTo the token the user wants to buy\n * @param dx the amount of tokens the user wants to sell. If the token charges\n * a fee on transfers, use the amount that gets transferred after the fee.\n * @return amount of tokens the user will receive\n */\n function calculateSwap(\n IERC20 token,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx\n ) external view virtual returns (uint256) {\n ISwap swap = ISwap(\n swapMap[address(token)]\n );\n return swap.calculateSwap(tokenIndexFrom, tokenIndexTo, dx);\n }\n\n function swapAndRedeem(\n address to,\n uint256 chainId,\n IERC20 token,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx,\n uint256 minDy,\n uint256 deadline\n ) external {\n ISwap swap = ISwap(swapMap[address(token)]);\n require(address(swap) != address(0), \"Swap is 0x00\");\n IERC20[] memory tokens = swapTokensMap[address(swap)];\n tokens[tokenIndexFrom].safeTransferFrom(\n msg.sender,\n address(this),\n dx\n );\n // swap\n\n uint256 swappedAmount = swap.swap(\n tokenIndexFrom,\n tokenIndexTo,\n dx,\n minDy,\n deadline\n );\n // deposit into bridge, gets nUSD\n if (\n token.allowance(address(this), address(synapseBridge)) <\n swappedAmount\n ) {\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n }\n synapseBridge.redeem(to, chainId, token, swappedAmount);\n }\n\n function swapAndRedeemAndSwap(\n address to,\n uint256 chainId,\n IERC20 token,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx,\n uint256 minDy,\n uint256 deadline,\n uint8 swapTokenIndexFrom,\n uint8 swapTokenIndexTo,\n uint256 swapMinDy,\n uint256 swapDeadline\n ) external {\n require(\n address(swapMap[address(token)]) != address(0),\n \"Swap is 0x00\"\n );\n IERC20[] memory tokens = swapTokensMap[\n swapMap[address(token)]\n ];\n tokens[tokenIndexFrom].safeTransferFrom(\n msg.sender,\n address(this),\n dx\n );\n // swap\n\n uint256 swappedAmount = ISwap(swapMap[address(token)]).swap(tokenIndexFrom, tokenIndexTo, dx, minDy, deadline);\n // deposit into bridge, gets nUSD\n if (\n token.allowance(address(this), address(synapseBridge)) <\n swappedAmount\n ) {\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n }\n synapseBridge.redeemAndSwap(\n to,\n chainId,\n token,\n swappedAmount,\n swapTokenIndexFrom,\n swapTokenIndexTo,\n swapMinDy,\n swapDeadline\n );\n }\n\n function swapAndRedeemAndRemove(\n address to,\n uint256 chainId,\n IERC20 token,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx,\n uint256 minDy,\n uint256 deadline,\n uint8 liqTokenIndex,\n uint256 liqMinAmount,\n uint256 liqDeadline\n ) external {\n ISwap swap = ISwap(swapMap[address(token)]);\n require(address(swap) != address(0), \"Swap is 0x00\");\n IERC20[] memory tokens = swapTokensMap[address(swap)];\n tokens[tokenIndexFrom].safeTransferFrom(\n msg.sender,\n address(this),\n dx\n );\n // swap\n\n uint256 swappedAmount = swap.swap(\n tokenIndexFrom,\n tokenIndexTo,\n dx,\n minDy,\n deadline\n );\n // deposit into bridge, gets nUSD\n if (\n token.allowance(address(this), address(synapseBridge)) <\n swappedAmount\n ) {\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n }\n synapseBridge.redeemAndRemove(\n to,\n chainId,\n token,\n swappedAmount,\n liqTokenIndex,\n liqMinAmount,\n liqDeadline\n );\n }\n\n /**\n * @notice wraps SynapseBridge redeem()\n * @param to address on other chain to redeem underlying assets to\n * @param chainId which underlying chain to bridge assets onto\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n **/\n function redeem(\n address to,\n uint256 chainId,\n IERC20 token,\n uint256 amount\n ) external {\n token.safeTransferFrom(msg.sender, address(this), amount);\n if (token.allowance(address(this), address(synapseBridge)) < amount) {\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n }\n synapseBridge.redeem(to, chainId, token, amount);\n }\n\n /**\n * @notice wraps SynapseBridge redeem()\n * @param to address on other chain to redeem underlying assets to\n * @param chainId which underlying chain to bridge assets onto\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n **/\n function deposit(\n address to,\n uint256 chainId,\n IERC20 token,\n uint256 amount\n ) external {\n token.safeTransferFrom(msg.sender, address(this), amount);\n if (token.allowance(address(this), address(synapseBridge)) < amount) {\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n }\n synapseBridge.deposit(to, chainId, token, amount);\n }\n\n /**\n * @notice Wraps SynapseBridge deposit() function to make it compatible w/ ETH -> WETH conversions\n * @param to address on other chain to bridge assets to\n * @param chainId which chain to bridge assets onto\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n **/\n function depositETH(\n address to,\n uint256 chainId,\n uint256 amount\n ) external payable {\n require(msg.value > 0 && msg.value == amount, 'INCORRECT MSG VALUE');\n IWETH9(WETH_ADDRESS).deposit{value: msg.value}();\n synapseBridge.deposit(to, chainId, IERC20(WETH_ADDRESS), amount);\n }\n\n\n /**\n * @notice Wraps SynapseBridge depositAndSwap() function to make it compatible w/ ETH -> WETH conversions\n * @param to address on other chain to bridge assets to\n * @param chainId which chain to bridge assets onto\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n * @param tokenIndexFrom the token the user wants to swap from\n * @param tokenIndexTo the token the user wants to swap to\n * @param minDy the min amount the user would like to receive, or revert to only minting the SynERC20 token crosschain.\n * @param deadline latest timestamp to accept this transaction\n **/\n function depositETHAndSwap(\n address to,\n uint256 chainId,\n uint256 amount,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 minDy,\n uint256 deadline\n ) external payable {\n require(msg.value > 0 && msg.value == amount, 'INCORRECT MSG VALUE');\n IWETH9(WETH_ADDRESS).deposit{value: msg.value}();\n synapseBridge.depositAndSwap(to, chainId, IERC20(WETH_ADDRESS), amount, tokenIndexFrom, tokenIndexTo, minDy, deadline);\n }\n\n\n function swapETHAndRedeem(\n address to,\n uint256 chainId,\n IERC20 token,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx,\n uint256 minDy,\n uint256 deadline\n ) external payable {\n require(WETH_ADDRESS != address(0), \"WETH 0\");\n require(msg.value > 0 && msg.value == dx, \"INCORRECT MSG VALUE\");\n ISwap swap = ISwap(swapMap[address(token)]);\n require(address(swap) != address(0), \"Swap is 0x00\");\n IWETH9(WETH_ADDRESS).deposit{value: msg.value}();\n\n // swap\n uint256 swappedAmount = swap.swap(\n tokenIndexFrom,\n tokenIndexTo,\n dx,\n minDy,\n deadline\n );\n synapseBridge.redeem(to, chainId, token, swappedAmount);\n }\n\n\n function swapETHAndRedeemAndSwap(\n address to,\n uint256 chainId,\n IERC20 token,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx,\n uint256 minDy,\n uint256 deadline,\n uint8 swapTokenIndexFrom,\n uint8 swapTokenIndexTo,\n uint256 swapMinDy,\n uint256 swapDeadline\n ) external payable {\n require(WETH_ADDRESS != address(0), \"WETH 0\");\n require(msg.value > 0 && msg.value == dx, \"INCORRECT MSG VALUE\");\n ISwap swap = ISwap(swapMap[address(token)]);\n require(address(swap) != address(0), \"Swap is 0x00\");\n IWETH9(WETH_ADDRESS).deposit{value: msg.value}();\n\n // swap\n uint256 swappedAmount = swap.swap(\n tokenIndexFrom,\n tokenIndexTo,\n dx,\n minDy,\n deadline\n );\n synapseBridge.redeemAndSwap(to, chainId, token, swappedAmount,swapTokenIndexFrom,\n swapTokenIndexTo,\n swapMinDy,\n swapDeadline);\n }\n\n\n /**\n * @notice Wraps redeemAndSwap on SynapseBridge.sol\n * Relays to nodes that (typically) a wrapped synAsset ERC20 token has been burned and the underlying needs to be redeeemed on the native chain. This function indicates to the nodes that they should attempt to redeem the LP token for the underlying assets (E.g \"swap\" out of the LP token)\n * @param to address on other chain to redeem underlying assets to\n * @param chainId which underlying chain to bridge assets onto\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n * @param tokenIndexFrom the token the user wants to swap from\n * @param tokenIndexTo the token the user wants to swap to\n * @param minDy the min amount the user would like to receive, or revert to only minting the SynERC20 token crosschain.\n * @param deadline latest timestamp to accept this transaction\n **/\n function redeemAndSwap(\n address to,\n uint256 chainId,\n IERC20 token,\n uint256 amount,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 minDy,\n uint256 deadline\n ) external {\n token.safeTransferFrom(msg.sender, address(this), amount);\n if (token.allowance(address(this), address(synapseBridge)) < amount) {\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n }\n synapseBridge.redeemAndSwap(\n to,\n chainId,\n token,\n amount,\n tokenIndexFrom,\n tokenIndexTo,\n minDy,\n deadline\n );\n }\n\n /**\n * @notice Wraps redeemAndRemove on SynapseBridge\n * Relays to nodes that (typically) a wrapped synAsset ERC20 token has been burned and the underlying needs to be redeeemed on the native chain. This function indicates to the nodes that they should attempt to redeem the LP token for the underlying assets (E.g \"swap\" out of the LP token)\n * @param to address on other chain to redeem underlying assets to\n * @param chainId which underlying chain to bridge assets onto\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount of (typically) LP token to pass to the nodes to attempt to removeLiquidity() with to redeem for the underlying assets of the LP token\n * @param liqTokenIndex Specifies which of the underlying LP assets the nodes should attempt to redeem for\n * @param liqMinAmount Specifies the minimum amount of the underlying asset needed for the nodes to execute the redeem/swap\n * @param liqDeadline Specificies the deadline that the nodes are allowed to try to redeem/swap the LP token\n **/\n function redeemAndRemove(\n address to,\n uint256 chainId,\n IERC20 token,\n uint256 amount,\n uint8 liqTokenIndex,\n uint256 liqMinAmount,\n uint256 liqDeadline\n ) external {\n token.safeTransferFrom(msg.sender, address(this), amount);\n if (token.allowance(address(this), address(synapseBridge)) < amount) {\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n }\n synapseBridge.redeemAndRemove(\n to,\n chainId,\n token,\n amount,\n liqTokenIndex,\n liqMinAmount,\n liqDeadline\n );\n }\n\n /**\n * @notice Wraps SynapseBridge redeemv2() function\n * @param to address on other chain to bridge assets to\n * @param chainId which chain to bridge assets onto\n * @param token ERC20 compatible token to redeem into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n **/\n function redeemv2(\n bytes32 to,\n uint256 chainId,\n IERC20 token,\n uint256 amount\n ) external {\n token.safeTransferFrom(msg.sender, address(this), amount);\n\n if (token.allowance(address(this), address(synapseBridge)) < amount) {\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n }\n synapseBridge.redeemv2(to, chainId, token, amount);\n }\n}\n" + }, + "contracts/bridge/wrappers/L1BridgeZap.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.6.12;\n\nimport '@openzeppelin/contracts/token/ERC20/IERC20.sol';\nimport '@openzeppelin/contracts/token/ERC20/SafeERC20.sol';\nimport '../interfaces/ISwap.sol';\nimport '../interfaces/ISynapseBridge.sol';\nimport \"../interfaces/IWETH9.sol\";\n\n\n/**\n * @title L1BridgeZap\n * @notice This contract is responsible for handling user Zaps into the SynapseBridge contract, through the Synapse Swap contracts. It does so\n * It does so by combining the action of addLiquidity() to the base swap pool, and then calling either deposit() or depositAndSwap() on the bridge.\n * This is done in hopes of automating portions of the bridge user experience to users, while keeping the SynapseBridge contract logic small.\n *\n * @dev This contract should be deployed with a base Swap.sol address and a SynapseBridge.sol address, otherwise, it will not function.\n */\ncontract L1BridgeZap {\n using SafeERC20 for IERC20;\n\n uint256 constant MAX_UINT256 = 2**256 - 1;\n \n ISwap baseSwap;\n ISynapseBridge synapseBridge;\n IERC20[] public baseTokens;\n address payable public immutable WETH_ADDRESS;\n \n\n /**\n * @notice Constructs the contract, approves each token inside of baseSwap to be used by baseSwap (needed for addLiquidity())\n */\n constructor(address payable _wethAddress, ISwap _baseSwap, ISynapseBridge _synapseBridge) public {\n WETH_ADDRESS = _wethAddress;\n baseSwap = _baseSwap;\n synapseBridge = _synapseBridge;\n IERC20(_wethAddress).safeIncreaseAllowance(address(_synapseBridge), MAX_UINT256);\n if (address(_baseSwap) != address(0)) {\n {\n uint8 i;\n for (; i < 32; i++) {\n try _baseSwap.getToken(i) returns (IERC20 token) {\n baseTokens.push(token);\n token.safeIncreaseAllowance(address(_baseSwap), MAX_UINT256);\n } catch {\n break;\n }\n }\n require(i > 1, 'baseSwap must have at least 2 tokens');\n }\n }\n }\n \n /**\n * @notice Wraps SynapseBridge deposit() function to make it compatible w/ ETH -> WETH conversions\n * @param to address on other chain to bridge assets to\n * @param chainId which chain to bridge assets onto\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n **/\n function depositETH(\n address to,\n uint256 chainId,\n uint256 amount\n ) external payable {\n require(msg.value > 0 && msg.value == amount, 'INCORRECT MSG VALUE');\n IWETH9(WETH_ADDRESS).deposit{value: msg.value}();\n synapseBridge.deposit(to, chainId, IERC20(WETH_ADDRESS), amount);\n }\n\n /**\n * @notice Wraps SynapseBridge depositAndSwap() function to make it compatible w/ ETH -> WETH conversions\n * @param to address on other chain to bridge assets to\n * @param chainId which chain to bridge assets onto\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n * @param tokenIndexFrom the token the user wants to swap from\n * @param tokenIndexTo the token the user wants to swap to\n * @param minDy the min amount the user would like to receive, or revert to only minting the SynERC20 token crosschain.\n * @param deadline latest timestamp to accept this transaction\n **/\n function depositETHAndSwap(\n address to,\n uint256 chainId,\n uint256 amount,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 minDy,\n uint256 deadline\n ) external payable {\n require(msg.value > 0 && msg.value == amount, 'INCORRECT MSG VALUE');\n IWETH9(WETH_ADDRESS).deposit{value: msg.value}();\n synapseBridge.depositAndSwap(to, chainId, IERC20(WETH_ADDRESS), amount, tokenIndexFrom, tokenIndexTo, minDy, deadline);\n }\n\n\n /**\n * @notice A simple method to calculate prices from deposits or\n * withdrawals, excluding fees but including slippage. This is\n * helpful as an input into the various \"min\" parameters on calls\n * to fight front-running\n *\n * @dev This shouldn't be used outside frontends for user estimates.\n *\n * @param amounts an array of token amounts to deposit or withdrawal,\n * corresponding to pooledTokens. The amount should be in each\n * pooled token's native precision.\n * @param deposit whether this is a deposit or a withdrawal\n * @return token amount the user will receive\n */\n function calculateTokenAmount(uint256[] calldata amounts, bool deposit)\n external\n view\n virtual\n returns (uint256)\n {\n return baseSwap.calculateTokenAmount(amounts, deposit);\n }\n\n /**\n * @notice Calculate the amount of underlying token available to withdraw\n * when withdrawing via only single token\n * @param tokenAmount the amount of LP token to burn\n * @param tokenIndex index of which token will be withdrawn\n * @return availableTokenAmount calculated amount of underlying token\n * available to withdraw\n */\n function calculateRemoveLiquidityOneToken(\n uint256 tokenAmount,\n uint8 tokenIndex\n ) external view virtual returns (uint256 availableTokenAmount) {\n return baseSwap.calculateRemoveLiquidityOneToken(tokenAmount, tokenIndex);\n }\n\n\n /**\n * @notice Combines adding liquidity to the given Swap, and calls deposit() on the bridge using that LP token\n * @param to address on other chain to bridge assets to\n * @param chainId which chain to bridge assets onto\n * @param token ERC20 compatible token to deposit into the bridge\n * @param liquidityAmounts the amounts of each token to add, in their native precision\n * @param minToMint the minimum LP tokens adding this amount of liquidity\n * should mint, otherwise revert. Handy for front-running mitigation\n * @param deadline latest timestamp to accept this transaction\n **/\n function zapAndDeposit(\n address to,\n uint256 chainId,\n IERC20 token,\n uint256[] calldata liquidityAmounts,\n uint256 minToMint,\n uint256 deadline\n ) external {\n // add liquidity\n for (uint256 i = 0; i < baseTokens.length; i++) {\n if (liquidityAmounts[i] != 0) {\n baseTokens[i].safeTransferFrom(\n msg.sender,\n address(this),\n liquidityAmounts[i]\n );\n }\n }\n\n uint256 liqAdded = baseSwap.addLiquidity(\n liquidityAmounts,\n minToMint,\n deadline\n );\n // deposit into bridge, gets nUSD\n if (token.allowance(address(this), address(synapseBridge)) < liqAdded) {\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n }\n synapseBridge.deposit(to, chainId, token, liqAdded);\n }\n\n /**\n * @notice Combines adding liquidity to the given Swap, and calls depositAndSwap() on the bridge using that LP token\n * @param to address on other chain to bridge assets to\n * @param chainId which chain to bridge assets onto\n * @param token ERC20 compatible token to deposit into the bridge\n * @param liquidityAmounts the amounts of each token to add, in their native precision\n * @param minToMint the minimum LP tokens adding this amount of liquidity\n * should mint, otherwise revert. Handy for front-running mitigation\n * @param liqDeadline latest timestamp to accept this transaction\n * @param tokenIndexFrom the token the user wants to swap from\n * @param tokenIndexTo the token the user wants to swap to\n * @param minDy the min amount the user would like to receive, or revert to only minting the SynERC20 token crosschain.\n * @param swapDeadline latest timestamp to accept this transaction\n **/\n function zapAndDepositAndSwap(\n address to,\n uint256 chainId,\n IERC20 token,\n uint256[] calldata liquidityAmounts,\n uint256 minToMint,\n uint256 liqDeadline,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 minDy,\n uint256 swapDeadline\n ) external {\n // add liquidity\n for (uint256 i = 0; i < baseTokens.length; i++) {\n if (liquidityAmounts[i] != 0) {\n baseTokens[i].safeTransferFrom(\n msg.sender,\n address(this),\n liquidityAmounts[i]\n );\n }\n }\n\n uint256 liqAdded = baseSwap.addLiquidity(\n liquidityAmounts,\n minToMint,\n liqDeadline\n );\n // deposit into bridge, bridge attemps to swap into desired asset\n if (token.allowance(address(this), address(synapseBridge)) < liqAdded) {\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n }\n synapseBridge.depositAndSwap(\n to,\n chainId,\n token,\n liqAdded,\n tokenIndexFrom,\n tokenIndexTo,\n minDy,\n swapDeadline\n );\n }\n\n /**\n * @notice Wraps SynapseBridge deposit() function\n * @param to address on other chain to bridge assets to\n * @param chainId which chain to bridge assets onto\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n **/\n function deposit(\n address to,\n uint256 chainId,\n IERC20 token,\n uint256 amount\n ) external {\n token.safeTransferFrom(msg.sender, address(this), amount);\n\n if (token.allowance(address(this), address(synapseBridge)) < amount) {\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n }\n synapseBridge.deposit(to, chainId, token, amount);\n }\n \n /**\n * @notice Wraps SynapseBridge depositAndSwap() function\n * @param to address on other chain to bridge assets to\n * @param chainId which chain to bridge assets onto\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n * @param tokenIndexFrom the token the user wants to swap from\n * @param tokenIndexTo the token the user wants to swap to\n * @param minDy the min amount the user would like to receive, or revert to only minting the SynERC20 token crosschain.\n * @param deadline latest timestamp to accept this transaction\n **/\n function depositAndSwap(\n address to,\n uint256 chainId,\n IERC20 token,\n uint256 amount,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 minDy,\n uint256 deadline\n ) external {\n token.safeTransferFrom(msg.sender, address(this), amount);\n \n if (token.allowance(address(this), address(synapseBridge)) < amount) {\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n }\n synapseBridge.depositAndSwap(to, chainId, token, amount, tokenIndexFrom, tokenIndexTo, minDy, deadline);\n }\n\n\n /**\n * @notice Wraps SynapseBridge redeem() function\n * @param to address on other chain to bridge assets to\n * @param chainId which chain to bridge assets onto\n * @param token ERC20 compatible token to redeem into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n **/\n function redeem(\n address to,\n uint256 chainId,\n IERC20 token,\n uint256 amount\n ) external {\n token.safeTransferFrom(msg.sender, address(this), amount);\n\n if (token.allowance(address(this), address(synapseBridge)) < amount) {\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n }\n synapseBridge.redeem(to, chainId, token, amount);\n }\n\n /**\n * @notice Wraps redeemAndSwap on SynapseBridge.sol\n * Relays to nodes that (typically) a wrapped synAsset ERC20 token has been burned and the underlying needs to be redeeemed on the native chain. This function indicates to the nodes that they should attempt to redeem the LP token for the underlying assets (E.g \"swap\" out of the LP token)\n * @param to address on other chain to redeem underlying assets to\n * @param chainId which underlying chain to bridge assets onto\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n * @param tokenIndexFrom the token the user wants to swap from\n * @param tokenIndexTo the token the user wants to swap to\n * @param minDy the min amount the user would like to receive, or revert to only minting the SynERC20 token crosschain.\n * @param deadline latest timestamp to accept this transaction\n **/\n function redeemAndSwap(\n address to,\n uint256 chainId,\n IERC20 token,\n uint256 amount,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 minDy,\n uint256 deadline\n ) external {\n token.safeTransferFrom(msg.sender, address(this), amount);\n if (token.allowance(address(this), address(synapseBridge)) < amount) {\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n }\n synapseBridge.redeemAndSwap(\n to,\n chainId,\n token,\n amount,\n tokenIndexFrom,\n tokenIndexTo,\n minDy,\n deadline\n );\n }\n\n /**\n * @notice Wraps redeemAndRemove on SynapseBridge\n * Relays to nodes that (typically) a wrapped synAsset ERC20 token has been burned and the underlying needs to be redeeemed on the native chain. This function indicates to the nodes that they should attempt to redeem the LP token for the underlying assets (E.g \"swap\" out of the LP token)\n * @param to address on other chain to redeem underlying assets to\n * @param chainId which underlying chain to bridge assets onto\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount of (typically) LP token to pass to the nodes to attempt to removeLiquidity() with to redeem for the underlying assets of the LP token\n * @param liqTokenIndex Specifies which of the underlying LP assets the nodes should attempt to redeem for\n * @param liqMinAmount Specifies the minimum amount of the underlying asset needed for the nodes to execute the redeem/swap\n * @param liqDeadline Specificies the deadline that the nodes are allowed to try to redeem/swap the LP token\n **/\n function redeemAndRemove(\n address to,\n uint256 chainId,\n IERC20 token,\n uint256 amount,\n uint8 liqTokenIndex,\n uint256 liqMinAmount,\n uint256 liqDeadline\n ) external {\n token.safeTransferFrom(msg.sender, address(this), amount);\n if (token.allowance(address(this), address(synapseBridge)) < amount) {\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n }\n synapseBridge.redeemAndRemove(\n to,\n chainId,\n token,\n amount,\n liqTokenIndex,\n liqMinAmount,\n liqDeadline\n );\n }\n\n\n /**\n * @notice Wraps SynapseBridge redeemv2() function\n * @param to address on other chain to bridge assets to\n * @param chainId which chain to bridge assets onto\n * @param token ERC20 compatible token to redeem into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n **/\n function redeemv2(\n bytes32 to,\n uint256 chainId,\n IERC20 token,\n uint256 amount\n ) external {\n token.safeTransferFrom(msg.sender, address(this), amount);\n\n if (token.allowance(address(this), address(synapseBridge)) < amount) {\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n }\n synapseBridge.redeemv2(to, chainId, token, amount);\n }\n\n}\n" + }, + "contracts/bridge/wrappers/MigratorBridgeZap.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.6.12;\n\nimport '@openzeppelin/contracts/token/ERC20/IERC20.sol';\nimport '@openzeppelin/contracts/token/ERC20/SafeERC20.sol';\nimport '@openzeppelin/contracts/math/SafeMath.sol';\n\nimport '../interfaces/ISynapseBridge.sol';\nimport '../interfaces/IERC20Migrator.sol';\n\ncontract MigratorBridgeZap {\n using SafeERC20 for IERC20;\n using SafeMath for uint256;\n \n ISynapseBridge constant synapseBridge = ISynapseBridge(0xd123f70AE324d34A9E76b67a27bf77593bA8749f);\n IERC20Migrator constant erc20Migrator = IERC20Migrator(0xf0284FB86adA5E4D82555C529677eEA3B2C3E022); \n IERC20 constant legacyToken = IERC20(0x42F6f551ae042cBe50C739158b4f0CAC0Edb9096);\n IERC20 constant newToken = IERC20(0xa4080f1778e69467E905B8d6F72f6e441f9e9484);\n uint256 constant MAX_UINT256 = 2**256 - 1;\n\n constructor() public {\n legacyToken.safeApprove(address(erc20Migrator), MAX_UINT256);\n newToken.safeApprove(address(synapseBridge), MAX_UINT256);\n }\n\n function migrate(uint256 amount) external {\n legacyToken.safeTransferFrom(msg.sender, address(this), amount);\n erc20Migrator.migrate(amount);\n newToken.safeTransfer(msg.sender, amount.mul(5).div(2));\n }\n\n function migrateAndBridge(uint256 amount, address to, uint256 chainId) external {\n legacyToken.safeTransferFrom(msg.sender, address(this), amount);\n erc20Migrator.migrate(amount);\n synapseBridge.redeem(to, chainId, newToken, amount.mul(5).div(2));\n }\n}" + }, + "contracts/bridge/interfaces/IERC20Migrator.sol": { + "content": "// SPDX-License-Identifier: MIT\n\n\npragma solidity 0.6.12;\n\ninterface IERC20Migrator { \n function migrate(uint256 amount) external;\n}\n\n" + }, + "contracts/bridge/wrappers/GMXWrapper.sol": { + "content": "// SPDX-License-Identifier: MIT\n\nimport '@openzeppelin/contracts/math/SafeMath.sol';\n\npragma solidity 0.6.12;\n\ninterface IGMX {\n function burn(address _account, uint256 _amount) external;\n function balanceOf(address account) external view returns (uint256);\n function mint(address _account, uint256 _amount) external;\n}\n\ncontract GMXWrapper {\n using SafeMath for uint256;\n\n address constant public gmx = 0x62edc0692BD897D2295872a9FFCac5425011c661;\n address constant public bridge = 0xC05e61d0E7a63D27546389B7aD62FdFf5A91aACE;\n\n function transfer(address _recipient, uint256 _amount) external returns (bool) {\n require(msg.sender == bridge);\n _transfer(msg.sender, _recipient, _amount);\n return true;\n }\n\n function _transfer(address _sender, address _recipient, uint256 _amount) private {\n require(_sender != address(0), \"BaseToken: transfer from the zero address\");\n require(_recipient != address(0), \"BaseToken: transfer to the zero address\");\n IGMX(gmx).burn(_sender, _amount);\n IGMX(gmx).mint(_recipient, _amount);\n }\n\n function mint(address _addr, uint256 _amount) external {\n require(msg.sender == bridge);\n uint256 preMint = IGMX(gmx).balanceOf(_addr);\n IGMX(gmx).mint(_addr, _amount);\n uint256 postMint = IGMX(gmx).balanceOf(_addr);\n require(preMint.add(_amount) == postMint, \"Mint incomplete\");\n }\n\n function burnFrom(address _addr, uint256 _amount) external {\n require(msg.sender == bridge);\n uint256 preBurn = IGMX(gmx).balanceOf(_addr);\n IGMX(gmx).burn(_addr, _amount);\n uint256 postBurn = IGMX(gmx).balanceOf(_addr);\n require(postBurn.add(_amount) == preBurn, \"Burn incomplete\");\n }\n}" + }, + "@openzeppelin/contracts/utils/Counters.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <0.8.0;\n\nimport \"../math/SafeMath.sol\";\n\n/**\n * @title Counters\n * @author Matt Condon (@shrugs)\n * @dev Provides counters that can only be incremented or decremented by one. This can be used e.g. to track the number\n * of elements in a mapping, issuing ERC721 ids, or counting request ids.\n *\n * Include with `using Counters for Counters.Counter;`\n * Since it is not possible to overflow a 256 bit integer with increments of one, `increment` can skip the {SafeMath}\n * overflow check, thereby saving gas. This does assume however correct usage, in that the underlying `_value` is never\n * directly accessed.\n */\nlibrary Counters {\n using SafeMath for uint256;\n\n struct Counter {\n // This variable should never be directly accessed by users of the library: interactions must be restricted to\n // the library's function. As of Solidity v0.5.2, this cannot be enforced, though there is a proposal to add\n // this feature: see https://github.com/ethereum/solidity/issues/4637\n uint256 _value; // default: 0\n }\n\n function current(Counter storage counter) internal view returns (uint256) {\n return counter._value;\n }\n\n function increment(Counter storage counter) internal {\n // The {SafeMath} overflow check can be skipped here, see the comment at the top\n counter._value += 1;\n }\n\n function decrement(Counter storage counter) internal {\n counter._value = counter._value.sub(1);\n }\n}\n" + }, + "@openzeppelin/contracts/drafts/ERC20Permit.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.5 <0.8.0;\n\nimport \"../token/ERC20/ERC20.sol\";\nimport \"./IERC20Permit.sol\";\nimport \"../cryptography/ECDSA.sol\";\nimport \"../utils/Counters.sol\";\nimport \"./EIP712.sol\";\n\n/**\n * @dev Implementation of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in\n * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612].\n *\n * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by\n * presenting a message signed by the account. By not relying on `{IERC20-approve}`, the token holder account doesn't\n * need to send a transaction, and thus is not required to hold Ether at all.\n *\n * _Available since v3.4._\n */\nabstract contract ERC20Permit is ERC20, IERC20Permit, EIP712 {\n using Counters for Counters.Counter;\n\n mapping (address => Counters.Counter) private _nonces;\n\n // solhint-disable-next-line var-name-mixedcase\n bytes32 private immutable _PERMIT_TYPEHASH = keccak256(\"Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)\");\n\n /**\n * @dev Initializes the {EIP712} domain separator using the `name` parameter, and setting `version` to `\"1\"`.\n *\n * It's a good idea to use the same `name` that is defined as the ERC20 token name.\n */\n constructor(string memory name) internal EIP712(name, \"1\") {\n }\n\n /**\n * @dev See {IERC20Permit-permit}.\n */\n function permit(address owner, address spender, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s) public virtual override {\n // solhint-disable-next-line not-rely-on-time\n require(block.timestamp <= deadline, \"ERC20Permit: expired deadline\");\n\n bytes32 structHash = keccak256(\n abi.encode(\n _PERMIT_TYPEHASH,\n owner,\n spender,\n value,\n _nonces[owner].current(),\n deadline\n )\n );\n\n bytes32 hash = _hashTypedDataV4(structHash);\n\n address signer = ECDSA.recover(hash, v, r, s);\n require(signer == owner, \"ERC20Permit: invalid signature\");\n\n _nonces[owner].increment();\n _approve(owner, spender, value);\n }\n\n /**\n * @dev See {IERC20Permit-nonces}.\n */\n function nonces(address owner) public view override returns (uint256) {\n return _nonces[owner].current();\n }\n\n /**\n * @dev See {IERC20Permit-DOMAIN_SEPARATOR}.\n */\n // solhint-disable-next-line func-name-mixedcase\n function DOMAIN_SEPARATOR() external view override returns (bytes32) {\n return _domainSeparatorV4();\n }\n}\n" + }, + "@openzeppelin/contracts/drafts/IERC20Permit.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <0.8.0;\n\n/**\n * @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in\n * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612].\n *\n * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by\n * presenting a message signed by the account. By not relying on `{IERC20-approve}`, the token holder account doesn't\n * need to send a transaction, and thus is not required to hold Ether at all.\n */\ninterface IERC20Permit {\n /**\n * @dev Sets `value` as the allowance of `spender` over `owner`'s tokens,\n * given `owner`'s signed approval.\n *\n * IMPORTANT: The same issues {IERC20-approve} has related to transaction\n * ordering also apply here.\n *\n * Emits an {Approval} event.\n *\n * Requirements:\n *\n * - `spender` cannot be the zero address.\n * - `deadline` must be a timestamp in the future.\n * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner`\n * over the EIP712-formatted function arguments.\n * - the signature must use ``owner``'s current nonce (see {nonces}).\n *\n * For more information on the signature format, see the\n * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP\n * section].\n */\n function permit(address owner, address spender, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s) external;\n\n /**\n * @dev Returns the current nonce for `owner`. This value must be\n * included whenever a signature is generated for {permit}.\n *\n * Every successful call to {permit} increases ``owner``'s nonce by one. This\n * prevents a signature from being used multiple times.\n */\n function nonces(address owner) external view returns (uint256);\n\n /**\n * @dev Returns the domain separator used in the encoding of the signature for `permit`, as defined by {EIP712}.\n */\n // solhint-disable-next-line func-name-mixedcase\n function DOMAIN_SEPARATOR() external view returns (bytes32);\n}\n" + }, + "@openzeppelin/contracts/cryptography/ECDSA.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <0.8.0;\n\n/**\n * @dev Elliptic Curve Digital Signature Algorithm (ECDSA) operations.\n *\n * These functions can be used to verify that a message was signed by the holder\n * of the private keys of a given address.\n */\nlibrary ECDSA {\n /**\n * @dev Returns the address that signed a hashed message (`hash`) with\n * `signature`. This address can then be used for verification purposes.\n *\n * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:\n * this function rejects them by requiring the `s` value to be in the lower\n * half order, and the `v` value to be either 27 or 28.\n *\n * IMPORTANT: `hash` _must_ be the result of a hash operation for the\n * verification to be secure: it is possible to craft signatures that\n * recover to arbitrary addresses for non-hashed data. A safe way to ensure\n * this is by receiving a hash of the original message (which may otherwise\n * be too long), and then calling {toEthSignedMessageHash} on it.\n */\n function recover(bytes32 hash, bytes memory signature) internal pure returns (address) {\n // Check the signature length\n if (signature.length != 65) {\n revert(\"ECDSA: invalid signature length\");\n }\n\n // Divide the signature in r, s and v variables\n bytes32 r;\n bytes32 s;\n uint8 v;\n\n // ecrecover takes the signature parameters, and the only way to get them\n // currently is to use assembly.\n // solhint-disable-next-line no-inline-assembly\n assembly {\n r := mload(add(signature, 0x20))\n s := mload(add(signature, 0x40))\n v := byte(0, mload(add(signature, 0x60)))\n }\n\n return recover(hash, v, r, s);\n }\n\n /**\n * @dev Overload of {ECDSA-recover-bytes32-bytes-} that receives the `v`,\n * `r` and `s` signature fields separately.\n */\n function recover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) internal pure returns (address) {\n // EIP-2 still allows signature malleability for ecrecover(). Remove this possibility and make the signature\n // unique. Appendix F in the Ethereum Yellow paper (https://ethereum.github.io/yellowpaper/paper.pdf), defines\n // the valid range for s in (281): 0 < s < secp256k1n ÷ 2 + 1, and for v in (282): v ∈ {27, 28}. Most\n // signatures from current libraries generate a unique signature with an s-value in the lower half order.\n //\n // If your library generates malleable signatures, such as s-values in the upper range, calculate a new s-value\n // with 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 - s1 and flip v from 27 to 28 or\n // vice versa. If your library also generates signatures with 0/1 for v instead 27/28, add 27 to v to accept\n // these malleable signatures as well.\n require(uint256(s) <= 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0, \"ECDSA: invalid signature 's' value\");\n require(v == 27 || v == 28, \"ECDSA: invalid signature 'v' value\");\n\n // If the signature is valid (and not malleable), return the signer address\n address signer = ecrecover(hash, v, r, s);\n require(signer != address(0), \"ECDSA: invalid signature\");\n\n return signer;\n }\n\n /**\n * @dev Returns an Ethereum Signed Message, created from a `hash`. This\n * replicates the behavior of the\n * https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_sign[`eth_sign`]\n * JSON-RPC method.\n *\n * See {recover}.\n */\n function toEthSignedMessageHash(bytes32 hash) internal pure returns (bytes32) {\n // 32 is the length in bytes of hash,\n // enforced by the type signature above\n return keccak256(abi.encodePacked(\"\\x19Ethereum Signed Message:\\n32\", hash));\n }\n}\n" + }, + "@openzeppelin/contracts/drafts/EIP712.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <0.8.0;\n\n/**\n * @dev https://eips.ethereum.org/EIPS/eip-712[EIP 712] is a standard for hashing and signing of typed structured data.\n *\n * The encoding specified in the EIP is very generic, and such a generic implementation in Solidity is not feasible,\n * thus this contract does not implement the encoding itself. Protocols need to implement the type-specific encoding\n * they need in their contracts using a combination of `abi.encode` and `keccak256`.\n *\n * This contract implements the EIP 712 domain separator ({_domainSeparatorV4}) that is used as part of the encoding\n * scheme, and the final step of the encoding to obtain the message digest that is then signed via ECDSA\n * ({_hashTypedDataV4}).\n *\n * The implementation of the domain separator was designed to be as efficient as possible while still properly updating\n * the chain id to protect against replay attacks on an eventual fork of the chain.\n *\n * NOTE: This contract implements the version of the encoding known as \"v4\", as implemented by the JSON RPC method\n * https://docs.metamask.io/guide/signing-data.html[`eth_signTypedDataV4` in MetaMask].\n *\n * _Available since v3.4._\n */\nabstract contract EIP712 {\n /* solhint-disable var-name-mixedcase */\n // Cache the domain separator as an immutable value, but also store the chain id that it corresponds to, in order to\n // invalidate the cached domain separator if the chain id changes.\n bytes32 private immutable _CACHED_DOMAIN_SEPARATOR;\n uint256 private immutable _CACHED_CHAIN_ID;\n\n bytes32 private immutable _HASHED_NAME;\n bytes32 private immutable _HASHED_VERSION;\n bytes32 private immutable _TYPE_HASH;\n /* solhint-enable var-name-mixedcase */\n\n /**\n * @dev Initializes the domain separator and parameter caches.\n *\n * The meaning of `name` and `version` is specified in\n * https://eips.ethereum.org/EIPS/eip-712#definition-of-domainseparator[EIP 712]:\n *\n * - `name`: the user readable name of the signing domain, i.e. the name of the DApp or the protocol.\n * - `version`: the current major version of the signing domain.\n *\n * NOTE: These parameters cannot be changed except through a xref:learn::upgrading-smart-contracts.adoc[smart\n * contract upgrade].\n */\n constructor(string memory name, string memory version) internal {\n bytes32 hashedName = keccak256(bytes(name));\n bytes32 hashedVersion = keccak256(bytes(version));\n bytes32 typeHash = keccak256(\"EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)\");\n _HASHED_NAME = hashedName;\n _HASHED_VERSION = hashedVersion;\n _CACHED_CHAIN_ID = _getChainId();\n _CACHED_DOMAIN_SEPARATOR = _buildDomainSeparator(typeHash, hashedName, hashedVersion);\n _TYPE_HASH = typeHash;\n }\n\n /**\n * @dev Returns the domain separator for the current chain.\n */\n function _domainSeparatorV4() internal view virtual returns (bytes32) {\n if (_getChainId() == _CACHED_CHAIN_ID) {\n return _CACHED_DOMAIN_SEPARATOR;\n } else {\n return _buildDomainSeparator(_TYPE_HASH, _HASHED_NAME, _HASHED_VERSION);\n }\n }\n\n function _buildDomainSeparator(bytes32 typeHash, bytes32 name, bytes32 version) private view returns (bytes32) {\n return keccak256(\n abi.encode(\n typeHash,\n name,\n version,\n _getChainId(),\n address(this)\n )\n );\n }\n\n /**\n * @dev Given an already https://eips.ethereum.org/EIPS/eip-712#definition-of-hashstruct[hashed struct], this\n * function returns the hash of the fully encoded EIP712 message for this domain.\n *\n * This hash can be used together with {ECDSA-recover} to obtain the signer of a message. For example:\n *\n * ```solidity\n * bytes32 digest = _hashTypedDataV4(keccak256(abi.encode(\n * keccak256(\"Mail(address to,string contents)\"),\n * mailTo,\n * keccak256(bytes(mailContents))\n * )));\n * address signer = ECDSA.recover(digest, signature);\n * ```\n */\n function _hashTypedDataV4(bytes32 structHash) internal view virtual returns (bytes32) {\n return keccak256(abi.encodePacked(\"\\x19\\x01\", _domainSeparatorV4(), structHash));\n }\n\n function _getChainId() private view returns (uint256 chainId) {\n this; // silence state mutability warning without generating bytecode - see https://github.com/ethereum/solidity/issues/2691\n // solhint-disable-next-line no-inline-assembly\n assembly {\n chainId := chainid()\n }\n }\n}\n" + }, + "contracts/bridge/wrappers/AvaxJewelMigration.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.6.12;\n\nimport '@openzeppelin/contracts/token/ERC20/ERC20.sol';\nimport \"@openzeppelin/contracts/token/ERC20/SafeERC20.sol\";\nimport \"@openzeppelin/contracts/access/Ownable.sol\";\n\nimport '../interfaces/ISynapseBridge.sol';\n\ninterface IERC20Mintable is IERC20 {\n function mint(address to, uint256 amount) external;\n}\n\ncontract AvaxJewelMigration is Ownable {\n using SafeERC20 for IERC20;\n using SafeERC20 for IERC20Mintable;\n\n\n ISynapseBridge constant synapseBridge = ISynapseBridge(0xC05e61d0E7a63D27546389B7aD62FdFf5A91aACE);\n // MULTICHAIN JEWEL \n IERC20 constant legacyToken = IERC20(0x4f60a160D8C2DDdaAfe16FCC57566dB84D674BD6);\n // SYNAPSE JEWEL\n IERC20 constant newToken = IERC20(0x997Ddaa07d716995DE90577C123Db411584E5E46);\n uint256 constant MAX_UINT256 = 2**256 - 1;\n\n constructor() public {\n newToken.safeApprove(address(synapseBridge), MAX_UINT256);\n }\n\n function migrate(uint256 amount) public {\n legacyToken.safeTransferFrom(msg.sender, address(this), amount);\n IERC20Mintable(address(newToken)).mint(msg.sender, amount);\n }\n\n function migrateAndBridge(uint256 amount, address to, uint256 chainId) external {\n migrate(amount);\n synapseBridge.redeem(to, chainId, newToken, amount);\n }\n\n function redeemLegacy() external onlyOwner {\n uint256 legacyBalance = legacyToken.balanceOf(address(this));\n legacyToken.safeTransfer(owner(), legacyBalance);\n }\n} " + }, + "contracts/bridge/testing/SynapseToken.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity >=0.6.0 <0.8.0;\n\n\nimport \"@openzeppelin/contracts/token/ERC20/ERC20.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/ERC20Burnable.sol\";\nimport \"@openzeppelin/contracts/access/AccessControl.sol\";\nimport \"@openzeppelin/contracts/drafts/ERC20Permit.sol\";\n\ncontract Synapse is ERC20, ERC20Burnable, AccessControl, ERC20Permit {\n bytes32 public constant MINTER_ROLE = keccak256(\"MINTER_ROLE\");\n\n constructor() public ERC20(\"Synapse\", \"SYN\") ERC20Permit(\"Synapse\") {\n _setupRole(DEFAULT_ADMIN_ROLE, msg.sender);\n _setupRole(MINTER_ROLE, msg.sender);\n }\n\n function mint(address to, uint256 amount) external {\n require(hasRole(MINTER_ROLE, msg.sender));\n _mint(to, amount);\n }\n}" + }, + "@openzeppelin/contracts/access/AccessControl.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <0.8.0;\n\nimport \"../utils/EnumerableSet.sol\";\nimport \"../utils/Address.sol\";\nimport \"../utils/Context.sol\";\n\n/**\n * @dev Contract module that allows children to implement role-based access\n * control mechanisms.\n *\n * Roles are referred to by their `bytes32` identifier. These should be exposed\n * in the external API and be unique. The best way to achieve this is by\n * using `public constant` hash digests:\n *\n * ```\n * bytes32 public constant MY_ROLE = keccak256(\"MY_ROLE\");\n * ```\n *\n * Roles can be used to represent a set of permissions. To restrict access to a\n * function call, use {hasRole}:\n *\n * ```\n * function foo() public {\n * require(hasRole(MY_ROLE, msg.sender));\n * ...\n * }\n * ```\n *\n * Roles can be granted and revoked dynamically via the {grantRole} and\n * {revokeRole} functions. Each role has an associated admin role, and only\n * accounts that have a role's admin role can call {grantRole} and {revokeRole}.\n *\n * By default, the admin role for all roles is `DEFAULT_ADMIN_ROLE`, which means\n * that only accounts with this role will be able to grant or revoke other\n * roles. More complex role relationships can be created by using\n * {_setRoleAdmin}.\n *\n * WARNING: The `DEFAULT_ADMIN_ROLE` is also its own admin: it has permission to\n * grant and revoke this role. Extra precautions should be taken to secure\n * accounts that have been granted it.\n */\nabstract contract AccessControl is Context {\n using EnumerableSet for EnumerableSet.AddressSet;\n using Address for address;\n\n struct RoleData {\n EnumerableSet.AddressSet members;\n bytes32 adminRole;\n }\n\n mapping (bytes32 => RoleData) private _roles;\n\n bytes32 public constant DEFAULT_ADMIN_ROLE = 0x00;\n\n /**\n * @dev Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole`\n *\n * `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite\n * {RoleAdminChanged} not being emitted signaling this.\n *\n * _Available since v3.1._\n */\n event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole);\n\n /**\n * @dev Emitted when `account` is granted `role`.\n *\n * `sender` is the account that originated the contract call, an admin role\n * bearer except when using {_setupRole}.\n */\n event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender);\n\n /**\n * @dev Emitted when `account` is revoked `role`.\n *\n * `sender` is the account that originated the contract call:\n * - if using `revokeRole`, it is the admin role bearer\n * - if using `renounceRole`, it is the role bearer (i.e. `account`)\n */\n event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender);\n\n /**\n * @dev Returns `true` if `account` has been granted `role`.\n */\n function hasRole(bytes32 role, address account) public view returns (bool) {\n return _roles[role].members.contains(account);\n }\n\n /**\n * @dev Returns the number of accounts that have `role`. Can be used\n * together with {getRoleMember} to enumerate all bearers of a role.\n */\n function getRoleMemberCount(bytes32 role) public view returns (uint256) {\n return _roles[role].members.length();\n }\n\n /**\n * @dev Returns one of the accounts that have `role`. `index` must be a\n * value between 0 and {getRoleMemberCount}, non-inclusive.\n *\n * Role bearers are not sorted in any particular way, and their ordering may\n * change at any point.\n *\n * WARNING: When using {getRoleMember} and {getRoleMemberCount}, make sure\n * you perform all queries on the same block. See the following\n * https://forum.openzeppelin.com/t/iterating-over-elements-on-enumerableset-in-openzeppelin-contracts/2296[forum post]\n * for more information.\n */\n function getRoleMember(bytes32 role, uint256 index) public view returns (address) {\n return _roles[role].members.at(index);\n }\n\n /**\n * @dev Returns the admin role that controls `role`. See {grantRole} and\n * {revokeRole}.\n *\n * To change a role's admin, use {_setRoleAdmin}.\n */\n function getRoleAdmin(bytes32 role) public view returns (bytes32) {\n return _roles[role].adminRole;\n }\n\n /**\n * @dev Grants `role` to `account`.\n *\n * If `account` had not been already granted `role`, emits a {RoleGranted}\n * event.\n *\n * Requirements:\n *\n * - the caller must have ``role``'s admin role.\n */\n function grantRole(bytes32 role, address account) public virtual {\n require(hasRole(_roles[role].adminRole, _msgSender()), \"AccessControl: sender must be an admin to grant\");\n\n _grantRole(role, account);\n }\n\n /**\n * @dev Revokes `role` from `account`.\n *\n * If `account` had been granted `role`, emits a {RoleRevoked} event.\n *\n * Requirements:\n *\n * - the caller must have ``role``'s admin role.\n */\n function revokeRole(bytes32 role, address account) public virtual {\n require(hasRole(_roles[role].adminRole, _msgSender()), \"AccessControl: sender must be an admin to revoke\");\n\n _revokeRole(role, account);\n }\n\n /**\n * @dev Revokes `role` from the calling account.\n *\n * Roles are often managed via {grantRole} and {revokeRole}: this function's\n * purpose is to provide a mechanism for accounts to lose their privileges\n * if they are compromised (such as when a trusted device is misplaced).\n *\n * If the calling account had been granted `role`, emits a {RoleRevoked}\n * event.\n *\n * Requirements:\n *\n * - the caller must be `account`.\n */\n function renounceRole(bytes32 role, address account) public virtual {\n require(account == _msgSender(), \"AccessControl: can only renounce roles for self\");\n\n _revokeRole(role, account);\n }\n\n /**\n * @dev Grants `role` to `account`.\n *\n * If `account` had not been already granted `role`, emits a {RoleGranted}\n * event. Note that unlike {grantRole}, this function doesn't perform any\n * checks on the calling account.\n *\n * [WARNING]\n * ====\n * This function should only be called from the constructor when setting\n * up the initial roles for the system.\n *\n * Using this function in any other way is effectively circumventing the admin\n * system imposed by {AccessControl}.\n * ====\n */\n function _setupRole(bytes32 role, address account) internal virtual {\n _grantRole(role, account);\n }\n\n /**\n * @dev Sets `adminRole` as ``role``'s admin role.\n *\n * Emits a {RoleAdminChanged} event.\n */\n function _setRoleAdmin(bytes32 role, bytes32 adminRole) internal virtual {\n emit RoleAdminChanged(role, _roles[role].adminRole, adminRole);\n _roles[role].adminRole = adminRole;\n }\n\n function _grantRole(bytes32 role, address account) private {\n if (_roles[role].members.add(account)) {\n emit RoleGranted(role, account, _msgSender());\n }\n }\n\n function _revokeRole(bytes32 role, address account) private {\n if (_roles[role].members.remove(account)) {\n emit RoleRevoked(role, account, _msgSender());\n }\n }\n}\n" + }, + "@openzeppelin/contracts/utils/EnumerableSet.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <0.8.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" + }, + "contracts/bridge/testing/NodeEnv.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.6.12;\npragma experimental ABIEncoderV2;\n\nimport '@openzeppelin/contracts/access/AccessControl.sol';\nimport \"../utils/EnumerableStringMap.sol\";\n\n/**\n * @title NodeEnv contract\n * @author Synapse Authors\n * @notice This contract implements a key-value store for storing variables on which synapse nodes must coordinate\n * methods are purposely arbitrary to allow these fields to be defined in synapse improvement proposals.\n * @notice This token is used for configuring different tokens on the bridge and mapping them across chains.\n**/\ncontract NodeEnv is AccessControl {\n using EnumerableStringMap for EnumerableStringMap.StringToStringMap;\n // BRIDGEMANAGER_ROLE owns the bridge. They are the only user that can call setters on this contract\n bytes32 public constant BRIDGEMANAGER_ROLE = keccak256('BRIDGEMANAGER_ROLE');\n // _config stores the config\n EnumerableStringMap.StringToStringMap private _config; // key is tokenAddress,chainID\n\n // ConfigUpdate is emitted when the config is updated by the user\n event ConfigUpdate(\n string key\n );\n\n constructor() public {\n _setupRole(DEFAULT_ADMIN_ROLE, msg.sender);\n _setupRole(BRIDGEMANAGER_ROLE, msg.sender);\n }\n\n /**\n * @notice get the length of the config\n *\n * @dev this is useful for enumerating through all keys in the env\n */\n function keyCount()\n external\n view\n returns (uint256){\n return _config.length();\n }\n\n /**\n * @notice gets the key/value pair by it's index\n *\n * Requirements:\n *\n * - `index` must be strictly less than {length}.\n */\n function keyValueByIndex(uint256 index) external view returns(string memory, string memory){\n return _config.at(index);\n }\n\n /**\n * @notice gets the value associated with the key\n */\n function get(string calldata _key) external view returns(string memory){\n string memory key = _key;\n return _config.get(key);\n }\n\n /**\n * @notice sets the key\n *\n * @dev caller must have bridge manager role\n */\n function set(string calldata _key, string calldata _value) external returns(bool) {\n require(\n hasRole(BRIDGEMANAGER_ROLE, msg.sender),\n 'Caller is not Bridge Manager'\n );\n string memory key = _key;\n string memory value = _value;\n\n return _config.set(key, value);\n }\n}" + }, + "contracts/bridge/utils/EnumerableStringMap.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.6.12;\n\nimport \"@openzeppelin/contracts/utils/EnumerableSet.sol\";\n\n/**\n * @title EnumerableStringMap\n * @dev Library for managing an enumerable variant of Solidity's\n * https://solidity.readthedocs.io/en/latest/types.html#mapping-types[`mapping`]\n * type.\n *\n * Maps have the following properties:\n *\n * - Entries are added, removed, and checked for existence in constant time\n * (O(1)).\n * - Entries are enumerated in O(n). No guarantees are made on the ordering.\n *\n * this isn't a terribly gas efficient implementation because it emphasizes usability over gas efficiency\n * by allowing arbitrary length string memorys. If Gettetrs/Setters are going to be used frequently in contracts\n * consider using the OpenZeppeling Bytes32 implementation\n *\n * this also differs from the OpenZeppelin implementation by keccac256 hashing the string memorys\n * so we can use enumerable bytes32 set\n */\nlibrary EnumerableStringMap {\n using EnumerableSet for EnumerableSet.Bytes32Set;\n\n // To implement this library for multiple types with as little code\n // repetition as possible, we write it in terms of a generic Map type with\n // bytes32 keys and values.\n // The Map implementation uses private functions, and user-facing\n // implementations (such as Uint256ToAddressMap) are just wrappers around\n // the underlying Map.\n // This means that we can only create new EnumerableMaps for types that fit\n // in bytes32.\n\n struct Map {\n // Storage of keys as a set\n EnumerableSet.Bytes32Set _keys;\n // Mapping of keys to resulting values to allow key lookup in the set\n mapping(bytes32 => string) _hashKeyMap;\n // values\n mapping(bytes32 => string) _values;\n }\n\n /**\n * @dev Adds a key-value pair to a map, or updates the value for an existing\n * key. O(1).\n *\n * Returns true if the key was added to the map, that is if it was not\n * already present.\n */\n function _set(\n Map storage map,\n string memory key,\n string memory value\n ) private returns (bool) {\n bytes32 keyHash = keccak256(abi.encodePacked(key));\n map._values[keyHash] = value;\n map._hashKeyMap[keyHash] = key;\n return map._keys.add(keyHash);\n }\n\n /**\n * @dev Removes a key-value pair from a map. O(1).\n *\n * Returns true if the key was removed from the map, that is if it was present.\n */\n function _remove(Map storage map, bytes32 keyHash) private returns (bool) {\n delete map._values[keyHash];\n delete map._hashKeyMap[keyHash];\n return map._keys.remove(keyHash);\n }\n\n /**\n * @dev Returns true if the key is in the map. O(1).\n */\n function _contains(Map storage map, bytes32 keyHash) private view returns (bool) {\n return map._keys.contains(keyHash);\n }\n\n /**\n * @dev Returns the number of key-value pairs in the map. O(1).\n */\n function _length(Map storage map) private view returns (uint256) {\n return map._keys.length();\n }\n\n /**\n * @dev Returns the key-value pair stored at position `index` in the map. O(1).\n *\n * Note that there are no guarantees on the ordering of entries inside the\n * array, and it may change when more entries are added or removed.\n *\n * Requirements:\n *\n * - `index` must be strictly less than {length}.\n */\n function _at(Map storage map, uint256 index) private view returns (string memory, string memory) {\n bytes32 keyHash = map._keys.at(index);\n return (map._hashKeyMap[keyHash], map._values[keyHash]);\n }\n\n /**\n * @dev Tries to returns the value associated with `key`. O(1).\n * Does not revert if `key` is not in the map.\n */\n function _tryGet(Map storage map, bytes32 keyHash) private view returns (bool, string memory) {\n string memory value = map._values[keyHash];\n if (keccak256(bytes(value)) == keccak256(bytes(\"\"))) {\n return (_contains(map, keyHash), \"\");\n } else {\n return (true, value);\n }\n }\n\n /**\n * @dev Returns the value associated with `key`. O(1).\n *\n * Requirements:\n *\n * - `key` must be in the map.\n */\n function _get(Map storage map, bytes32 keyHash) private view returns (string memory) {\n string memory value = map._values[keyHash];\n require(_contains(map, keyHash), \"EnumerableMap: nonexistent key\");\n return value;\n }\n\n // StringToStringMap\n struct StringToStringMap {\n Map _inner;\n }\n\n /**\n * @dev Adds a key-value pair to a map, or updates the value for an existing\n * key. O(1).\n *\n * Returns true if the key was added to the map, that is if it was not\n * already present.\n */\n function set(\n StringToStringMap storage map,\n string memory key,\n string memory value\n ) internal returns (bool) {\n return _set(map._inner, key, value);\n }\n\n /**\n * @dev Removes a value from a set. O(1).\n *\n * Returns true if the key was removed from the map, that is if it was present.\n */\n function remove(StringToStringMap storage map, string memory key) internal returns (bool) {\n return _remove(map._inner, keccak256(abi.encodePacked(key)));\n }\n\n /**\n * @dev Returns true if the key is in the map. O(1).\n */\n function contains(StringToStringMap storage map, string memory key) internal view returns (bool) {\n return _contains(map._inner, keccak256(abi.encodePacked(key)));\n }\n\n /**\n * @dev Returns the number of elements in the map. O(1).\n */\n function length(StringToStringMap storage map) internal view returns (uint256) {\n return _length(map._inner);\n }\n\n /**\n * @dev Returns the element stored at position `index` in the set. O(1).\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(StringToStringMap storage map, uint256 index) internal view returns (string memory, string memory) {\n return _at(map._inner, index);\n }\n\n /**\n * @dev Tries to returns the value associated with `key`. O(1).\n * Does not revert if `key` is not in the map.\n *\n * _Available since v3.4._\n */\n function tryGet(StringToStringMap storage map, uint256 key) internal view returns (bool, string memory) {\n (bool success, string memory value) = _tryGet(map._inner, bytes32(key));\n return (success, value);\n }\n\n /**\n * @dev Returns the value associated with `key`. O(1).\n *\n * Requirements:\n *\n * - `key` must be in the map.\n */\n function get(StringToStringMap storage map, string memory key) internal view returns (string memory) {\n return _get(map._inner, keccak256(abi.encodePacked(key)));\n }\n}" + }, + "contracts/bridge/PoolConfig.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.6.12;\npragma experimental ABIEncoderV2;\n\nimport \"@openzeppelin/contracts/access/AccessControl.sol\";\n\ncontract PoolConfig is AccessControl {\n bytes32 public constant BRIDGEMANAGER_ROLE =\n keccak256(\"BRIDGEMANAGER_ROLE\");\n mapping(address => mapping(uint256 => Pool)) private _pool; // key is tokenAddress,chainID\n\n struct Pool {\n address tokenAddress;\n uint256 chainId;\n address poolAddress;\n bool metaswap;\n }\n\n constructor() public {\n _setupRole(DEFAULT_ADMIN_ROLE, msg.sender);\n _setupRole(BRIDGEMANAGER_ROLE, msg.sender);\n }\n\n function getPoolConfig(address tokenAddress, uint256 chainID)\n external\n view\n returns (Pool memory)\n {\n return _pool[tokenAddress][chainID];\n }\n\n function setPoolConfig(\n address tokenAddress,\n uint256 chainID,\n address poolAddress,\n bool metaswap\n ) external returns (Pool memory) {\n require(\n hasRole(BRIDGEMANAGER_ROLE, msg.sender),\n \"Caller is not Bridge Manager\"\n );\n Pool memory newPool = Pool(\n tokenAddress,\n chainID,\n poolAddress,\n metaswap\n );\n _pool[tokenAddress][chainID] = newPool;\n return newPool;\n }\n}\n" + }, + "contracts/bridge/SynapseBridge.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.6.12;\n\nimport \"@openzeppelin/contracts-upgradeable/proxy/Initializable.sol\";\nimport \"@openzeppelin/contracts-upgradeable/access/AccessControlUpgradeable.sol\";\nimport \"@openzeppelin/contracts-upgradeable/utils/ReentrancyGuardUpgradeable.sol\";\nimport \"@openzeppelin/contracts-upgradeable/utils/PausableUpgradeable.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/SafeERC20.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/ERC20Burnable.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport \"@openzeppelin/contracts/math/SafeMath.sol\";\n\nimport \"./interfaces/ISwap.sol\";\nimport \"./interfaces/IWETH9.sol\";\n\ninterface IERC20Mintable is IERC20 {\n function mint(address to, uint256 amount) external;\n}\n\ncontract SynapseBridge is\n Initializable,\n AccessControlUpgradeable,\n ReentrancyGuardUpgradeable,\n PausableUpgradeable\n{\n using SafeERC20 for IERC20;\n using SafeERC20 for IERC20Mintable;\n using SafeMath for uint256;\n\n bytes32 public constant NODEGROUP_ROLE = keccak256(\"NODEGROUP_ROLE\");\n bytes32 public constant GOVERNANCE_ROLE = keccak256(\"GOVERNANCE_ROLE\");\n\n mapping(address => uint256) private fees;\n\n uint256 public startBlockNumber;\n uint256 public constant bridgeVersion = 6;\n uint256 public chainGasAmount;\n address payable public WETH_ADDRESS;\n\n mapping(bytes32 => bool) private kappaMap;\n\n receive() external payable {}\n\n function initialize() external initializer {\n startBlockNumber = block.number;\n _setupRole(DEFAULT_ADMIN_ROLE, msg.sender);\n __AccessControl_init();\n }\n\n function setChainGasAmount(uint256 amount) external {\n require(hasRole(GOVERNANCE_ROLE, msg.sender), \"Not governance\");\n chainGasAmount = amount;\n }\n\n function setWethAddress(address payable _wethAddress) external {\n require(hasRole(DEFAULT_ADMIN_ROLE, msg.sender), \"Not admin\");\n WETH_ADDRESS = _wethAddress;\n }\n\n function addKappas(bytes32[] calldata kappas) external {\n require(hasRole(GOVERNANCE_ROLE, msg.sender), \"Not governance\");\n for (uint256 i = 0; i < kappas.length; ++i) {\n kappaMap[kappas[i]] = true;\n }\n }\n\n event TokenDeposit(\n address indexed to,\n uint256 chainId,\n IERC20 token,\n uint256 amount\n );\n event TokenRedeem(\n address indexed to,\n uint256 chainId,\n IERC20 token,\n uint256 amount\n );\n event TokenWithdraw(\n address indexed to,\n IERC20 token,\n uint256 amount,\n uint256 fee,\n bytes32 indexed kappa\n );\n event TokenMint(\n address indexed to,\n IERC20Mintable token,\n uint256 amount,\n uint256 fee,\n bytes32 indexed kappa\n );\n event TokenDepositAndSwap(\n address indexed to,\n uint256 chainId,\n IERC20 token,\n uint256 amount,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 minDy,\n uint256 deadline\n );\n event TokenMintAndSwap(\n address indexed to,\n IERC20Mintable token,\n uint256 amount,\n uint256 fee,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 minDy,\n uint256 deadline,\n bool swapSuccess,\n bytes32 indexed kappa\n );\n event TokenRedeemAndSwap(\n address indexed to,\n uint256 chainId,\n IERC20 token,\n uint256 amount,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 minDy,\n uint256 deadline\n );\n event TokenRedeemAndRemove(\n address indexed to,\n uint256 chainId,\n IERC20 token,\n uint256 amount,\n uint8 swapTokenIndex,\n uint256 swapMinAmount,\n uint256 swapDeadline\n );\n event TokenWithdrawAndRemove(\n address indexed to,\n IERC20 token,\n uint256 amount,\n uint256 fee,\n uint8 swapTokenIndex,\n uint256 swapMinAmount,\n uint256 swapDeadline,\n bool swapSuccess,\n bytes32 indexed kappa\n );\n\n // v2 events\n event TokenRedeemV2(\n bytes32 indexed to,\n uint256 chainId,\n IERC20 token,\n uint256 amount\n );\n\n // VIEW FUNCTIONS ***/\n function getFeeBalance(address tokenAddress)\n external\n view\n returns (uint256)\n {\n return fees[tokenAddress];\n }\n\n function kappaExists(bytes32 kappa) external view returns (bool) {\n return kappaMap[kappa];\n }\n\n // FEE FUNCTIONS ***/\n /**\n * * @notice withdraw specified ERC20 token fees to a given address\n * * @param token ERC20 token in which fees acccumulated to transfer\n * * @param to Address to send the fees to\n */\n function withdrawFees(IERC20 token, address to) external whenNotPaused {\n require(hasRole(GOVERNANCE_ROLE, msg.sender), \"Not governance\");\n require(to != address(0), \"Address is 0x000\");\n if (fees[address(token)] != 0) {\n token.safeTransfer(to, fees[address(token)]);\n fees[address(token)] = 0;\n }\n }\n\n // PAUSABLE FUNCTIONS ***/\n function pause() external {\n require(hasRole(GOVERNANCE_ROLE, msg.sender), \"Not governance\");\n _pause();\n }\n\n function unpause() external {\n require(hasRole(GOVERNANCE_ROLE, msg.sender), \"Not governance\");\n _unpause();\n }\n\n /**\n * @notice Relays to nodes to transfers an ERC20 token cross-chain\n * @param to address on other chain to bridge assets to\n * @param chainId which chain to bridge assets onto\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n **/\n function deposit(\n address to,\n uint256 chainId,\n IERC20 token,\n uint256 amount\n ) external nonReentrant whenNotPaused {\n emit TokenDeposit(to, chainId, token, amount);\n token.safeTransferFrom(msg.sender, address(this), amount);\n }\n\n /**\n * @notice Relays to nodes that (typically) a wrapped synAsset ERC20 token has been burned and the underlying needs to be redeeemed on the native chain\n * @param to address on other chain to redeem underlying assets to\n * @param chainId which underlying chain to bridge assets onto\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n **/\n function redeem(\n address to,\n uint256 chainId,\n ERC20Burnable token,\n uint256 amount\n ) external nonReentrant whenNotPaused {\n emit TokenRedeem(to, chainId, token, amount);\n token.burnFrom(msg.sender, amount);\n }\n\n /**\n * @notice Function to be called by the node group to withdraw the underlying assets from the contract\n * @param to address on chain to send underlying assets to\n * @param token ERC20 compatible token to withdraw from the bridge\n * @param amount Amount in native token decimals to withdraw\n * @param fee Amount in native token decimals to save to the contract as fees\n * @param kappa kappa\n **/\n function withdraw(\n address to,\n IERC20 token,\n uint256 amount,\n uint256 fee,\n bytes32 kappa\n ) external nonReentrant whenNotPaused {\n require(\n hasRole(NODEGROUP_ROLE, msg.sender),\n \"Caller is not a node group\"\n );\n require(amount > fee, \"Amount must be greater than fee\");\n require(!kappaMap[kappa], \"Kappa is already present\");\n kappaMap[kappa] = true;\n fees[address(token)] = fees[address(token)].add(fee);\n if (address(token) == WETH_ADDRESS && WETH_ADDRESS != address(0)) {\n IWETH9(WETH_ADDRESS).withdraw(amount.sub(fee));\n (bool success, ) = to.call{value: amount.sub(fee)}(\"\");\n require(success, \"ETH_TRANSFER_FAILED\");\n emit TokenWithdraw(to, token, amount, fee, kappa);\n } else {\n emit TokenWithdraw(to, token, amount, fee, kappa);\n token.safeTransfer(to, amount.sub(fee));\n }\n }\n\n /**\n * @notice Nodes call this function to mint a SynERC20 (or any asset that the bridge is given minter access to). This is called by the nodes after a TokenDeposit event is emitted.\n * @dev This means the SynapseBridge.sol contract must have minter access to the token attempting to be minted\n * @param to address on other chain to redeem underlying assets to\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain post-fees\n * @param fee Amount in native token decimals to save to the contract as fees\n * @param kappa kappa\n **/\n function mint(\n address payable to,\n IERC20Mintable token,\n uint256 amount,\n uint256 fee,\n bytes32 kappa\n ) external nonReentrant whenNotPaused {\n require(\n hasRole(NODEGROUP_ROLE, msg.sender),\n \"Caller is not a node group\"\n );\n require(amount > fee, \"Amount must be greater than fee\");\n require(!kappaMap[kappa], \"Kappa is already present\");\n kappaMap[kappa] = true;\n fees[address(token)] = fees[address(token)].add(fee);\n emit TokenMint(to, token, amount.sub(fee), fee, kappa);\n token.mint(address(this), amount);\n IERC20(token).safeTransfer(to, amount.sub(fee));\n if (chainGasAmount != 0 && address(this).balance > chainGasAmount) {\n to.call.value(chainGasAmount)(\"\");\n }\n }\n\n /**\n * @notice Relays to nodes to both transfer an ERC20 token cross-chain, and then have the nodes execute a swap through a liquidity pool on behalf of the user.\n * @param to address on other chain to bridge assets to\n * @param chainId which chain to bridge assets onto\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n * @param tokenIndexFrom the token the user wants to swap from\n * @param tokenIndexTo the token the user wants to swap to\n * @param minDy the min amount the user would like to receive, or revert to only minting the SynERC20 token crosschain.\n * @param deadline latest timestamp to accept this transaction\n **/\n function depositAndSwap(\n address to,\n uint256 chainId,\n IERC20 token,\n uint256 amount,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 minDy,\n uint256 deadline\n ) external nonReentrant whenNotPaused {\n emit TokenDepositAndSwap(\n to,\n chainId,\n token,\n amount,\n tokenIndexFrom,\n tokenIndexTo,\n minDy,\n deadline\n );\n token.safeTransferFrom(msg.sender, address(this), amount);\n }\n\n /**\n * @notice Relays to nodes that (typically) a wrapped synAsset ERC20 token has been burned and the underlying needs to be redeeemed on the native chain. This function indicates to the nodes that they should attempt to redeem the LP token for the underlying assets (E.g \"swap\" out of the LP token)\n * @param to address on other chain to redeem underlying assets to\n * @param chainId which underlying chain to bridge assets onto\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n * @param tokenIndexFrom the token the user wants to swap from\n * @param tokenIndexTo the token the user wants to swap to\n * @param minDy the min amount the user would like to receive, or revert to only minting the SynERC20 token crosschain.\n * @param deadline latest timestamp to accept this transaction\n **/\n function redeemAndSwap(\n address to,\n uint256 chainId,\n ERC20Burnable token,\n uint256 amount,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 minDy,\n uint256 deadline\n ) external nonReentrant whenNotPaused {\n emit TokenRedeemAndSwap(\n to,\n chainId,\n token,\n amount,\n tokenIndexFrom,\n tokenIndexTo,\n minDy,\n deadline\n );\n token.burnFrom(msg.sender, amount);\n }\n\n /**\n * @notice Relays to nodes that (typically) a wrapped synAsset ERC20 token has been burned and the underlying needs to be redeeemed on the native chain. This function indicates to the nodes that they should attempt to redeem the LP token for the underlying assets (E.g \"swap\" out of the LP token)\n * @param to address on other chain to redeem underlying assets to\n * @param chainId which underlying chain to bridge assets onto\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n * @param swapTokenIndex Specifies which of the underlying LP assets the nodes should attempt to redeem for\n * @param swapMinAmount Specifies the minimum amount of the underlying asset needed for the nodes to execute the redeem/swap\n * @param swapDeadline Specificies the deadline that the nodes are allowed to try to redeem/swap the LP token\n **/\n function redeemAndRemove(\n address to,\n uint256 chainId,\n ERC20Burnable token,\n uint256 amount,\n uint8 swapTokenIndex,\n uint256 swapMinAmount,\n uint256 swapDeadline\n ) external nonReentrant whenNotPaused {\n emit TokenRedeemAndRemove(\n to,\n chainId,\n token,\n amount,\n swapTokenIndex,\n swapMinAmount,\n swapDeadline\n );\n token.burnFrom(msg.sender, amount);\n }\n\n /**\n * @notice Nodes call this function to mint a SynERC20 (or any asset that the bridge is given minter access to), and then attempt to swap the SynERC20 into the desired destination asset. This is called by the nodes after a TokenDepositAndSwap event is emitted.\n * @dev This means the BridgeDeposit.sol contract must have minter access to the token attempting to be minted\n * @param to address on other chain to redeem underlying assets to\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain post-fees\n * @param fee Amount in native token decimals to save to the contract as fees\n * @param pool Destination chain's pool to use to swap SynERC20 -> Asset. The nodes determine this by using PoolConfig.sol.\n * @param tokenIndexFrom Index of the SynERC20 asset in the pool\n * @param tokenIndexTo Index of the desired final asset\n * @param minDy Minumum amount (in final asset decimals) that must be swapped for, otherwise the user will receive the SynERC20.\n * @param deadline Epoch time of the deadline that the swap is allowed to be executed.\n * @param kappa kappa\n **/\n function mintAndSwap(\n address payable to,\n IERC20Mintable token,\n uint256 amount,\n uint256 fee,\n ISwap pool,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 minDy,\n uint256 deadline,\n bytes32 kappa\n ) external nonReentrant whenNotPaused {\n require(\n hasRole(NODEGROUP_ROLE, msg.sender),\n \"Caller is not a node group\"\n );\n require(amount > fee, \"Amount must be greater than fee\");\n require(!kappaMap[kappa], \"Kappa is already present\");\n kappaMap[kappa] = true;\n fees[address(token)] = fees[address(token)].add(fee);\n // Transfer gas airdrop\n if (chainGasAmount != 0 && address(this).balance > chainGasAmount) {\n to.call.value(chainGasAmount)(\"\");\n }\n // first check to make sure more will be given than min amount required\n uint256 expectedOutput = ISwap(pool).calculateSwap(\n tokenIndexFrom,\n tokenIndexTo,\n amount.sub(fee)\n );\n\n if (expectedOutput >= minDy) {\n // proceed with swap\n token.mint(address(this), amount);\n token.safeIncreaseAllowance(address(pool), amount);\n try\n ISwap(pool).swap(\n tokenIndexFrom,\n tokenIndexTo,\n amount.sub(fee),\n minDy,\n deadline\n )\n returns (uint256 finalSwappedAmount) {\n // Swap succeeded, transfer swapped asset\n IERC20 swappedTokenTo = ISwap(pool).getToken(tokenIndexTo);\n if (\n address(swappedTokenTo) == WETH_ADDRESS &&\n WETH_ADDRESS != address(0)\n ) {\n IWETH9(WETH_ADDRESS).withdraw(finalSwappedAmount);\n (bool success, ) = to.call{value: finalSwappedAmount}(\"\");\n require(success, \"ETH_TRANSFER_FAILED\");\n emit TokenMintAndSwap(\n to,\n token,\n finalSwappedAmount,\n fee,\n tokenIndexFrom,\n tokenIndexTo,\n minDy,\n deadline,\n true,\n kappa\n );\n } else {\n swappedTokenTo.safeTransfer(to, finalSwappedAmount);\n emit TokenMintAndSwap(\n to,\n token,\n finalSwappedAmount,\n fee,\n tokenIndexFrom,\n tokenIndexTo,\n minDy,\n deadline,\n true,\n kappa\n );\n }\n } catch {\n IERC20(token).safeTransfer(to, amount.sub(fee));\n emit TokenMintAndSwap(\n to,\n token,\n amount.sub(fee),\n fee,\n tokenIndexFrom,\n tokenIndexTo,\n minDy,\n deadline,\n false,\n kappa\n );\n }\n } else {\n token.mint(address(this), amount);\n IERC20(token).safeTransfer(to, amount.sub(fee));\n emit TokenMintAndSwap(\n to,\n token,\n amount.sub(fee),\n fee,\n tokenIndexFrom,\n tokenIndexTo,\n minDy,\n deadline,\n false,\n kappa\n );\n }\n }\n\n /**\n * @notice Function to be called by the node group to withdraw the underlying assets from the contract\n * @param to address on chain to send underlying assets to\n * @param token ERC20 compatible token to withdraw from the bridge\n * @param amount Amount in native token decimals to withdraw\n * @param fee Amount in native token decimals to save to the contract as fees\n * @param pool Destination chain's pool to use to swap SynERC20 -> Asset. The nodes determine this by using PoolConfig.sol.\n * @param swapTokenIndex Specifies which of the underlying LP assets the nodes should attempt to redeem for\n * @param swapMinAmount Specifies the minimum amount of the underlying asset needed for the nodes to execute the redeem/swap\n * @param swapDeadline Specificies the deadline that the nodes are allowed to try to redeem/swap the LP token\n * @param kappa kappa\n **/\n function withdrawAndRemove(\n address to,\n IERC20 token,\n uint256 amount,\n uint256 fee,\n ISwap pool,\n uint8 swapTokenIndex,\n uint256 swapMinAmount,\n uint256 swapDeadline,\n bytes32 kappa\n ) external nonReentrant whenNotPaused {\n require(\n hasRole(NODEGROUP_ROLE, msg.sender),\n \"Caller is not a node group\"\n );\n require(amount > fee, \"Amount must be greater than fee\");\n require(!kappaMap[kappa], \"Kappa is already present\");\n kappaMap[kappa] = true;\n fees[address(token)] = fees[address(token)].add(fee);\n // first check to make sure more will be given than min amount required\n uint256 expectedOutput = ISwap(pool).calculateRemoveLiquidityOneToken(\n amount.sub(fee),\n swapTokenIndex\n );\n\n if (expectedOutput >= swapMinAmount) {\n token.safeIncreaseAllowance(address(pool), amount.sub(fee));\n try\n ISwap(pool).removeLiquidityOneToken(\n amount.sub(fee),\n swapTokenIndex,\n swapMinAmount,\n swapDeadline\n )\n returns (uint256 finalSwappedAmount) {\n // Swap succeeded, transfer swapped asset\n IERC20 swappedTokenTo = ISwap(pool).getToken(swapTokenIndex);\n swappedTokenTo.safeTransfer(to, finalSwappedAmount);\n emit TokenWithdrawAndRemove(\n to,\n token,\n finalSwappedAmount,\n fee,\n swapTokenIndex,\n swapMinAmount,\n swapDeadline,\n true,\n kappa\n );\n } catch {\n IERC20(token).safeTransfer(to, amount.sub(fee));\n emit TokenWithdrawAndRemove(\n to,\n token,\n amount.sub(fee),\n fee,\n swapTokenIndex,\n swapMinAmount,\n swapDeadline,\n false,\n kappa\n );\n }\n } else {\n token.safeTransfer(to, amount.sub(fee));\n emit TokenWithdrawAndRemove(\n to,\n token,\n amount.sub(fee),\n fee,\n swapTokenIndex,\n swapMinAmount,\n swapDeadline,\n false,\n kappa\n );\n }\n }\n\n // BRIDGE FUNCTIONS TO HANDLE DIFF ADDRESSES\n /**\n * @notice Relays to nodes that (typically) a wrapped synAsset ERC20 token has been burned and the underlying needs to be redeeemed on the native chain\n * @param to address on other chain to redeem underlying assets to\n * @param chainId which underlying chain to bridge assets onto\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n **/\n function redeemV2(\n bytes32 to,\n uint256 chainId,\n ERC20Burnable token,\n uint256 amount\n ) external nonReentrant whenNotPaused {\n emit TokenRedeemV2(to, chainId, token, amount);\n token.burnFrom(msg.sender, amount);\n }\n}\n" + }, + "@openzeppelin/contracts-upgradeable/access/AccessControlUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <0.8.0;\n\nimport \"../utils/EnumerableSetUpgradeable.sol\";\nimport \"../utils/AddressUpgradeable.sol\";\nimport \"../utils/ContextUpgradeable.sol\";\nimport \"../proxy/Initializable.sol\";\n\n/**\n * @dev Contract module that allows children to implement role-based access\n * control mechanisms.\n *\n * Roles are referred to by their `bytes32` identifier. These should be exposed\n * in the external API and be unique. The best way to achieve this is by\n * using `public constant` hash digests:\n *\n * ```\n * bytes32 public constant MY_ROLE = keccak256(\"MY_ROLE\");\n * ```\n *\n * Roles can be used to represent a set of permissions. To restrict access to a\n * function call, use {hasRole}:\n *\n * ```\n * function foo() public {\n * require(hasRole(MY_ROLE, msg.sender));\n * ...\n * }\n * ```\n *\n * Roles can be granted and revoked dynamically via the {grantRole} and\n * {revokeRole} functions. Each role has an associated admin role, and only\n * accounts that have a role's admin role can call {grantRole} and {revokeRole}.\n *\n * By default, the admin role for all roles is `DEFAULT_ADMIN_ROLE`, which means\n * that only accounts with this role will be able to grant or revoke other\n * roles. More complex role relationships can be created by using\n * {_setRoleAdmin}.\n *\n * WARNING: The `DEFAULT_ADMIN_ROLE` is also its own admin: it has permission to\n * grant and revoke this role. Extra precautions should be taken to secure\n * accounts that have been granted it.\n */\nabstract contract AccessControlUpgradeable is Initializable, ContextUpgradeable {\n function __AccessControl_init() internal initializer {\n __Context_init_unchained();\n __AccessControl_init_unchained();\n }\n\n function __AccessControl_init_unchained() internal initializer {\n }\n using EnumerableSetUpgradeable for EnumerableSetUpgradeable.AddressSet;\n using AddressUpgradeable for address;\n\n struct RoleData {\n EnumerableSetUpgradeable.AddressSet members;\n bytes32 adminRole;\n }\n\n mapping (bytes32 => RoleData) private _roles;\n\n bytes32 public constant DEFAULT_ADMIN_ROLE = 0x00;\n\n /**\n * @dev Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole`\n *\n * `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite\n * {RoleAdminChanged} not being emitted signaling this.\n *\n * _Available since v3.1._\n */\n event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole);\n\n /**\n * @dev Emitted when `account` is granted `role`.\n *\n * `sender` is the account that originated the contract call, an admin role\n * bearer except when using {_setupRole}.\n */\n event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender);\n\n /**\n * @dev Emitted when `account` is revoked `role`.\n *\n * `sender` is the account that originated the contract call:\n * - if using `revokeRole`, it is the admin role bearer\n * - if using `renounceRole`, it is the role bearer (i.e. `account`)\n */\n event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender);\n\n /**\n * @dev Returns `true` if `account` has been granted `role`.\n */\n function hasRole(bytes32 role, address account) public view returns (bool) {\n return _roles[role].members.contains(account);\n }\n\n /**\n * @dev Returns the number of accounts that have `role`. Can be used\n * together with {getRoleMember} to enumerate all bearers of a role.\n */\n function getRoleMemberCount(bytes32 role) public view returns (uint256) {\n return _roles[role].members.length();\n }\n\n /**\n * @dev Returns one of the accounts that have `role`. `index` must be a\n * value between 0 and {getRoleMemberCount}, non-inclusive.\n *\n * Role bearers are not sorted in any particular way, and their ordering may\n * change at any point.\n *\n * WARNING: When using {getRoleMember} and {getRoleMemberCount}, make sure\n * you perform all queries on the same block. See the following\n * https://forum.openzeppelin.com/t/iterating-over-elements-on-enumerableset-in-openzeppelin-contracts/2296[forum post]\n * for more information.\n */\n function getRoleMember(bytes32 role, uint256 index) public view returns (address) {\n return _roles[role].members.at(index);\n }\n\n /**\n * @dev Returns the admin role that controls `role`. See {grantRole} and\n * {revokeRole}.\n *\n * To change a role's admin, use {_setRoleAdmin}.\n */\n function getRoleAdmin(bytes32 role) public view returns (bytes32) {\n return _roles[role].adminRole;\n }\n\n /**\n * @dev Grants `role` to `account`.\n *\n * If `account` had not been already granted `role`, emits a {RoleGranted}\n * event.\n *\n * Requirements:\n *\n * - the caller must have ``role``'s admin role.\n */\n function grantRole(bytes32 role, address account) public virtual {\n require(hasRole(_roles[role].adminRole, _msgSender()), \"AccessControl: sender must be an admin to grant\");\n\n _grantRole(role, account);\n }\n\n /**\n * @dev Revokes `role` from `account`.\n *\n * If `account` had been granted `role`, emits a {RoleRevoked} event.\n *\n * Requirements:\n *\n * - the caller must have ``role``'s admin role.\n */\n function revokeRole(bytes32 role, address account) public virtual {\n require(hasRole(_roles[role].adminRole, _msgSender()), \"AccessControl: sender must be an admin to revoke\");\n\n _revokeRole(role, account);\n }\n\n /**\n * @dev Revokes `role` from the calling account.\n *\n * Roles are often managed via {grantRole} and {revokeRole}: this function's\n * purpose is to provide a mechanism for accounts to lose their privileges\n * if they are compromised (such as when a trusted device is misplaced).\n *\n * If the calling account had been granted `role`, emits a {RoleRevoked}\n * event.\n *\n * Requirements:\n *\n * - the caller must be `account`.\n */\n function renounceRole(bytes32 role, address account) public virtual {\n require(account == _msgSender(), \"AccessControl: can only renounce roles for self\");\n\n _revokeRole(role, account);\n }\n\n /**\n * @dev Grants `role` to `account`.\n *\n * If `account` had not been already granted `role`, emits a {RoleGranted}\n * event. Note that unlike {grantRole}, this function doesn't perform any\n * checks on the calling account.\n *\n * [WARNING]\n * ====\n * This function should only be called from the constructor when setting\n * up the initial roles for the system.\n *\n * Using this function in any other way is effectively circumventing the admin\n * system imposed by {AccessControl}.\n * ====\n */\n function _setupRole(bytes32 role, address account) internal virtual {\n _grantRole(role, account);\n }\n\n /**\n * @dev Sets `adminRole` as ``role``'s admin role.\n *\n * Emits a {RoleAdminChanged} event.\n */\n function _setRoleAdmin(bytes32 role, bytes32 adminRole) internal virtual {\n emit RoleAdminChanged(role, _roles[role].adminRole, adminRole);\n _roles[role].adminRole = adminRole;\n }\n\n function _grantRole(bytes32 role, address account) private {\n if (_roles[role].members.add(account)) {\n emit RoleGranted(role, account, _msgSender());\n }\n }\n\n function _revokeRole(bytes32 role, address account) private {\n if (_roles[role].members.remove(account)) {\n emit RoleRevoked(role, account, _msgSender());\n }\n }\n uint256[49] private __gap;\n}\n" + }, + "@openzeppelin/contracts-upgradeable/utils/EnumerableSetUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <0.8.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 EnumerableSetUpgradeable {\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" + }, + "contracts/bridge/wrappers/HarmonyBridgeZap.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.6.12;\n\nimport \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/SafeERC20.sol\";\nimport \"../interfaces/ISwap.sol\";\nimport \"../interfaces/ISynapseBridge.sol\";\nimport \"../interfaces/IWETH9.sol\";\n\ninterface IFrax {\n function exchangeCanonicalForOld(address bridge_token_address, uint256 token_amount) external returns (uint256);\n}\n\ncontract HarmonyBridgeZap {\n using SafeERC20 for IERC20;\n\n ISynapseBridge synapseBridge;\n address payable public immutable WETH_ADDRESS;\n IFrax private constant CANOLICAL_FRAX = IFrax(0xFa7191D292d5633f702B0bd7E3E3BcCC0e633200);\n IERC20 private constant SYN_FRAX = IERC20(0x1852F70512298d56e9c8FDd905e02581E04ddb2a);\n\n mapping(address => address) public swapMap;\n mapping(address => IERC20[]) public swapTokensMap;\n\n uint256 constant MAX_UINT256 = 2**256 - 1;\n\n constructor(\n address payable _wethAddress,\n address _swapOne,\n address tokenOne,\n address _swapTwo,\n address tokenTwo,\n address _swapThree,\n address tokenThree,\n address _swapFour,\n address tokenFour,\n ISynapseBridge _synapseBridge\n ) public {\n WETH_ADDRESS = _wethAddress;\n synapseBridge = _synapseBridge;\n swapMap[tokenOne] = _swapOne;\n swapMap[tokenTwo] = _swapTwo;\n swapMap[tokenThree] = _swapThree;\n swapMap[tokenFour] = _swapFour;\n\n if (address(_swapOne) != address(0)) {\n {\n uint8 i;\n for (; i < 32; i++) {\n try ISwap(_swapOne).getToken(i) returns (\n IERC20 token\n ) {\n swapTokensMap[_swapOne].push(token);\n token.safeApprove(address(_swapOne), MAX_UINT256);\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n } catch {\n break;\n }\n }\n require(i > 1, \"swap must have at least 2 tokens\");\n }\n }\n if (address(_swapTwo) != address(0)) {\n {\n uint8 i;\n for (; i < 32; i++) {\n try ISwap(_swapTwo).getToken(i) returns (\n IERC20 token\n ) {\n swapTokensMap[_swapTwo].push(token);\n token.safeApprove(address(_swapTwo), MAX_UINT256);\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n } catch {\n break;\n }\n }\n require(i > 1, \"swap must have at least 2 tokens\");\n }\n }\n\n if (address(_swapThree) != address(0)) {\n {\n uint8 i;\n for (; i < 32; i++) {\n try ISwap(_swapThree).getToken(i) returns (\n IERC20 token\n ) {\n swapTokensMap[_swapThree].push(token);\n token.safeApprove(address(_swapThree), MAX_UINT256);\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n } catch {\n break;\n }\n }\n require(i > 1, \"swap must have at least 2 tokens\");\n }\n }\n\n if (address(_swapFour) != address(0)) {\n {\n uint8 i;\n for (; i < 32; i++) {\n try ISwap(_swapFour).getToken(i) returns (\n IERC20 token\n ) {\n swapTokensMap[_swapFour].push(token);\n token.safeApprove(address(_swapFour), MAX_UINT256);\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n } catch {\n break;\n }\n }\n require(i > 1, \"swap must have at least 2 tokens\");\n }\n }\n }\n\n /**\n * @notice Calculate amount of tokens you receive on swap\n * @param tokenIndexFrom the token the user wants to sell\n * @param tokenIndexTo the token the user wants to buy\n * @param dx the amount of tokens the user wants to sell. If the token charges\n * a fee on transfers, use the amount that gets transferred after the fee.\n * @return amount of tokens the user will receive\n */\n function calculateSwap(\n IERC20 token,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx\n ) external view virtual returns (uint256) {\n ISwap swap = ISwap(\n swapMap[address(token)]\n );\n return swap.calculateSwap(tokenIndexFrom, tokenIndexTo, dx);\n }\n\n function swapAndRedeem(\n address to,\n uint256 chainId,\n IERC20 token,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx,\n uint256 minDy,\n uint256 deadline\n ) external {\n ISwap swap = ISwap(swapMap[address(token)]);\n require(address(swap) != address(0), \"Swap is 0x00\");\n IERC20[] memory tokens = swapTokensMap[address(swap)];\n tokens[tokenIndexFrom].safeTransferFrom(\n msg.sender,\n address(this),\n dx\n );\n // swap\n\n uint256 swappedAmount = swap.swap(\n tokenIndexFrom,\n tokenIndexTo,\n dx,\n minDy,\n deadline\n );\n // deposit into bridge, gets nUSD\n if (\n token.allowance(address(this), address(synapseBridge)) <\n swappedAmount\n ) {\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n }\n synapseBridge.redeem(to, chainId, token, swappedAmount);\n }\n\n function swapAndRedeemAndSwap(\n address to,\n uint256 chainId,\n IERC20 token,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx,\n uint256 minDy,\n uint256 deadline,\n uint8 swapTokenIndexFrom,\n uint8 swapTokenIndexTo,\n uint256 swapMinDy,\n uint256 swapDeadline\n ) external {\n require(\n address(swapMap[address(token)]) != address(0),\n \"Swap is 0x00\"\n );\n IERC20[] memory tokens = swapTokensMap[\n swapMap[address(token)]\n ];\n tokens[tokenIndexFrom].safeTransferFrom(\n msg.sender,\n address(this),\n dx\n );\n // swap\n\n uint256 swappedAmount = ISwap(swapMap[address(token)]).swap(tokenIndexFrom, tokenIndexTo, dx, minDy, deadline);\n // deposit into bridge, gets nUSD\n if (\n token.allowance(address(this), address(synapseBridge)) <\n swappedAmount\n ) {\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n }\n synapseBridge.redeemAndSwap(\n to,\n chainId,\n token,\n swappedAmount,\n swapTokenIndexFrom,\n swapTokenIndexTo,\n swapMinDy,\n swapDeadline\n );\n }\n\n function swapAndRedeemAndRemove(\n address to,\n uint256 chainId,\n IERC20 token,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx,\n uint256 minDy,\n uint256 deadline,\n uint8 liqTokenIndex,\n uint256 liqMinAmount,\n uint256 liqDeadline\n ) external {\n ISwap swap = ISwap(swapMap[address(token)]);\n require(address(swap) != address(0), \"Swap is 0x00\");\n IERC20[] memory tokens = swapTokensMap[address(swap)];\n tokens[tokenIndexFrom].safeTransferFrom(\n msg.sender,\n address(this),\n dx\n );\n // swap\n\n uint256 swappedAmount = swap.swap(\n tokenIndexFrom,\n tokenIndexTo,\n dx,\n minDy,\n deadline\n );\n // deposit into bridge, gets nUSD\n if (\n token.allowance(address(this), address(synapseBridge)) <\n swappedAmount\n ) {\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n }\n synapseBridge.redeemAndRemove(\n to,\n chainId,\n token,\n swappedAmount,\n liqTokenIndex,\n liqMinAmount,\n liqDeadline\n );\n }\n\n /**\n * @notice wraps SynapseBridge redeem()\n * @param to address on other chain to redeem underlying assets to\n * @param chainId which underlying chain to bridge assets onto\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n **/\n function redeem(\n address to,\n uint256 chainId,\n IERC20 token,\n uint256 amount\n ) external {\n token.safeTransferFrom(msg.sender, address(this), amount);\n if (address(token) == address(CANOLICAL_FRAX)) {\n uint256 swappedAmount = CANOLICAL_FRAX.exchangeCanonicalForOld(address(SYN_FRAX), amount);\n if (SYN_FRAX.allowance(address(this), address(synapseBridge)) < amount) {\n SYN_FRAX.safeApprove(address(synapseBridge), MAX_UINT256);\n }\n synapseBridge.redeem(to, chainId, SYN_FRAX, swappedAmount);\n } else {\n if (token.allowance(address(this), address(synapseBridge)) < amount) {\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n }\n synapseBridge.redeem(to, chainId, token, amount);\n }\n \n }\n\n /**\n * @notice Wraps SynapseBridge redeemv2() function\n * @param to address on other chain to bridge assets to\n * @param chainId which chain to bridge assets onto\n * @param token ERC20 compatible token to redeem into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n **/\n function redeemv2(\n bytes32 to,\n uint256 chainId,\n IERC20 token,\n uint256 amount\n ) external {\n token.safeTransferFrom(msg.sender, address(this), amount);\n\n if (token.allowance(address(this), address(synapseBridge)) < amount) {\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n }\n synapseBridge.redeemv2(to, chainId, token, amount);\n }\n\n /**\n * @notice wraps SynapseBridge redeem()\n * @param to address on other chain to redeem underlying assets to\n * @param chainId which underlying chain to bridge assets onto\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n **/\n function deposit(\n address to,\n uint256 chainId,\n IERC20 token,\n uint256 amount\n ) external {\n token.safeTransferFrom(msg.sender, address(this), amount);\n if (token.allowance(address(this), address(synapseBridge)) < amount) {\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n }\n synapseBridge.deposit(to, chainId, token, amount);\n }\n\n function swapETHAndRedeem(\n address to,\n uint256 chainId,\n IERC20 token,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx,\n uint256 minDy,\n uint256 deadline\n ) external payable {\n require(WETH_ADDRESS != address(0), \"WETH 0\");\n require(msg.value > 0 && msg.value == dx, \"INCORRECT MSG VALUE\");\n ISwap swap = ISwap(swapMap[address(token)]);\n require(address(swap) != address(0), \"Swap is 0x00\");\n IWETH9(WETH_ADDRESS).deposit{value: msg.value}();\n\n // swap\n uint256 swappedAmount = swap.swap(\n tokenIndexFrom,\n tokenIndexTo,\n dx,\n minDy,\n deadline\n );\n synapseBridge.redeem(to, chainId, token, swappedAmount);\n }\n\n /**\n * @notice Wraps redeemAndSwap on SynapseBridge.sol\n * Relays to nodes that (typically) a wrapped synAsset ERC20 token has been burned and the underlying needs to be redeeemed on the native chain. This function indicates to the nodes that they should attempt to redeem the LP token for the underlying assets (E.g \"swap\" out of the LP token)\n * @param to address on other chain to redeem underlying assets to\n * @param chainId which underlying chain to bridge assets onto\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n * @param tokenIndexFrom the token the user wants to swap from\n * @param tokenIndexTo the token the user wants to swap to\n * @param minDy the min amount the user would like to receive, or revert to only minting the SynERC20 token crosschain.\n * @param deadline latest timestamp to accept this transaction\n **/\n function redeemAndSwap(\n address to,\n uint256 chainId,\n IERC20 token,\n uint256 amount,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 minDy,\n uint256 deadline\n ) external {\n token.safeTransferFrom(msg.sender, address(this), amount);\n if (token.allowance(address(this), address(synapseBridge)) < amount) {\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n }\n synapseBridge.redeemAndSwap(\n to,\n chainId,\n token,\n amount,\n tokenIndexFrom,\n tokenIndexTo,\n minDy,\n deadline\n );\n }\n\n /**\n * @notice Wraps redeemAndRemove on SynapseBridge\n * Relays to nodes that (typically) a wrapped synAsset ERC20 token has been burned and the underlying needs to be redeeemed on the native chain. This function indicates to the nodes that they should attempt to redeem the LP token for the underlying assets (E.g \"swap\" out of the LP token)\n * @param to address on other chain to redeem underlying assets to\n * @param chainId which underlying chain to bridge assets onto\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount of (typically) LP token to pass to the nodes to attempt to removeLiquidity() with to redeem for the underlying assets of the LP token\n * @param liqTokenIndex Specifies which of the underlying LP assets the nodes should attempt to redeem for\n * @param liqMinAmount Specifies the minimum amount of the underlying asset needed for the nodes to execute the redeem/swap\n * @param liqDeadline Specificies the deadline that the nodes are allowed to try to redeem/swap the LP token\n **/\n function redeemAndRemove(\n address to,\n uint256 chainId,\n IERC20 token,\n uint256 amount,\n uint8 liqTokenIndex,\n uint256 liqMinAmount,\n uint256 liqDeadline\n ) external {\n token.safeTransferFrom(msg.sender, address(this), amount);\n if (token.allowance(address(this), address(synapseBridge)) < amount) {\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n }\n synapseBridge.redeemAndRemove(\n to,\n chainId,\n token,\n amount,\n liqTokenIndex,\n liqMinAmount,\n liqDeadline\n );\n }\n}\n" + }, + "contracts/bridge/MoonriverSynapseBridge.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.6.12;\n\nimport \"@openzeppelin/contracts-upgradeable/proxy/Initializable.sol\";\nimport \"@openzeppelin/contracts-upgradeable/access/AccessControlUpgradeable.sol\";\nimport \"@openzeppelin/contracts-upgradeable/utils/ReentrancyGuardUpgradeable.sol\";\nimport \"@openzeppelin/contracts-upgradeable/utils/PausableUpgradeable.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/SafeERC20.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/ERC20Burnable.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport \"@openzeppelin/contracts/math/SafeMath.sol\";\n\nimport \"./interfaces/ISwap.sol\";\nimport \"./interfaces/IWETH9.sol\";\n\ninterface IERC20Mintable is IERC20 {\n function mint(address to, uint256 amount) external;\n}\n\ninterface IFrax {\n function exchangeOldForCanonical(\n address bridge_token_address,\n uint256 token_amount\n ) external returns (uint256);\n}\n\ncontract MRSynapseBridge is\n Initializable,\n AccessControlUpgradeable,\n ReentrancyGuardUpgradeable,\n PausableUpgradeable\n{\n using SafeERC20 for IERC20;\n using SafeERC20 for IERC20Mintable;\n using SafeMath for uint256;\n\n bytes32 public constant NODEGROUP_ROLE = keccak256(\"NODEGROUP_ROLE\");\n bytes32 public constant GOVERNANCE_ROLE = keccak256(\"GOVERNANCE_ROLE\");\n\n mapping(address => uint256) private fees;\n\n uint256 public startBlockNumber;\n uint256 public constant bridgeVersion = 6;\n uint256 public chainGasAmount;\n address payable public WETH_ADDRESS;\n\n mapping(bytes32 => bool) private kappaMap;\n\n receive() external payable {}\n\n function initialize() external initializer {\n startBlockNumber = block.number;\n _setupRole(DEFAULT_ADMIN_ROLE, msg.sender);\n __AccessControl_init();\n }\n\n function setChainGasAmount(uint256 amount) external {\n require(hasRole(GOVERNANCE_ROLE, msg.sender), \"Not governance\");\n chainGasAmount = amount;\n }\n\n function setWethAddress(address payable _wethAddress) external {\n require(hasRole(DEFAULT_ADMIN_ROLE, msg.sender), \"Not admin\");\n WETH_ADDRESS = _wethAddress;\n }\n\n function addKappas(bytes32[] calldata kappas) external {\n require(hasRole(GOVERNANCE_ROLE, msg.sender), \"Not governance\");\n for (uint256 i = 0; i < kappas.length; ++i) {\n kappaMap[kappas[i]] = true;\n }\n }\n\n event TokenDeposit(\n address indexed to,\n uint256 chainId,\n IERC20 token,\n uint256 amount\n );\n event TokenRedeem(\n address indexed to,\n uint256 chainId,\n IERC20 token,\n uint256 amount\n );\n event TokenWithdraw(\n address indexed to,\n IERC20 token,\n uint256 amount,\n uint256 fee,\n bytes32 indexed kappa\n );\n event TokenMint(\n address indexed to,\n IERC20Mintable token,\n uint256 amount,\n uint256 fee,\n bytes32 indexed kappa\n );\n event TokenDepositAndSwap(\n address indexed to,\n uint256 chainId,\n IERC20 token,\n uint256 amount,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 minDy,\n uint256 deadline\n );\n event TokenMintAndSwap(\n address indexed to,\n IERC20Mintable token,\n uint256 amount,\n uint256 fee,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 minDy,\n uint256 deadline,\n bool swapSuccess,\n bytes32 indexed kappa\n );\n event TokenRedeemAndSwap(\n address indexed to,\n uint256 chainId,\n IERC20 token,\n uint256 amount,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 minDy,\n uint256 deadline\n );\n event TokenRedeemAndRemove(\n address indexed to,\n uint256 chainId,\n IERC20 token,\n uint256 amount,\n uint8 swapTokenIndex,\n uint256 swapMinAmount,\n uint256 swapDeadline\n );\n event TokenWithdrawAndRemove(\n address indexed to,\n IERC20 token,\n uint256 amount,\n uint256 fee,\n uint8 swapTokenIndex,\n uint256 swapMinAmount,\n uint256 swapDeadline,\n bool swapSuccess,\n bytes32 indexed kappa\n );\n\n // v2 events\n event TokenRedeemV2(\n bytes32 indexed to,\n uint256 chainId,\n IERC20 token,\n uint256 amount\n );\n\n // VIEW FUNCTIONS ***/\n function getFeeBalance(address tokenAddress)\n external\n view\n returns (uint256)\n {\n return fees[tokenAddress];\n }\n\n function kappaExists(bytes32 kappa) external view returns (bool) {\n return kappaMap[kappa];\n }\n\n // FEE FUNCTIONS ***/\n /**\n * * @notice withdraw specified ERC20 token fees to a given address\n * * @param token ERC20 token in which fees acccumulated to transfer\n * * @param to Address to send the fees to\n */\n function withdrawFees(IERC20 token, address to) external whenNotPaused {\n require(hasRole(GOVERNANCE_ROLE, msg.sender), \"Not governance\");\n require(to != address(0), \"Address is 0x000\");\n if (fees[address(token)] != 0) {\n token.safeTransfer(to, fees[address(token)]);\n fees[address(token)] = 0;\n }\n }\n\n // PAUSABLE FUNCTIONS ***/\n function pause() external {\n require(hasRole(GOVERNANCE_ROLE, msg.sender), \"Not governance\");\n _pause();\n }\n\n function unpause() external {\n require(hasRole(GOVERNANCE_ROLE, msg.sender), \"Not governance\");\n _unpause();\n }\n\n /**\n * @notice Relays to nodes to transfers an ERC20 token cross-chain\n * @param to address on other chain to bridge assets to\n * @param chainId which chain to bridge assets onto\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n **/\n function deposit(\n address to,\n uint256 chainId,\n IERC20 token,\n uint256 amount\n ) external nonReentrant whenNotPaused {\n emit TokenDeposit(to, chainId, token, amount);\n token.safeTransferFrom(msg.sender, address(this), amount);\n }\n\n /**\n * @notice Relays to nodes that (typically) a wrapped synAsset ERC20 token has been burned and the underlying needs to be redeeemed on the native chain\n * @param to address on other chain to redeem underlying assets to\n * @param chainId which underlying chain to bridge assets onto\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n **/\n function redeem(\n address to,\n uint256 chainId,\n ERC20Burnable token,\n uint256 amount\n ) external nonReentrant whenNotPaused {\n emit TokenRedeem(to, chainId, token, amount);\n token.burnFrom(msg.sender, amount);\n }\n\n /**\n * @notice Function to be called by the node group to withdraw the underlying assets from the contract\n * @param to address on chain to send underlying assets to\n * @param token ERC20 compatible token to withdraw from the bridge\n * @param amount Amount in native token decimals to withdraw\n * @param fee Amount in native token decimals to save to the contract as fees\n * @param kappa kappa\n **/\n function withdraw(\n address to,\n IERC20 token,\n uint256 amount,\n uint256 fee,\n bytes32 kappa\n ) external nonReentrant whenNotPaused {\n require(\n hasRole(NODEGROUP_ROLE, msg.sender),\n \"Caller is not a node group\"\n );\n require(amount > fee, \"Amount must be greater than fee\");\n require(!kappaMap[kappa], \"Kappa is already present\");\n kappaMap[kappa] = true;\n fees[address(token)] = fees[address(token)].add(fee);\n if (address(token) == WETH_ADDRESS && WETH_ADDRESS != address(0)) {\n IWETH9(WETH_ADDRESS).withdraw(amount.sub(fee));\n (bool success, ) = to.call{value: amount.sub(fee)}(\"\");\n require(success, \"ETH_TRANSFER_FAILED\");\n emit TokenWithdraw(to, token, amount, fee, kappa);\n } else {\n emit TokenWithdraw(to, token, amount, fee, kappa);\n token.safeTransfer(to, amount.sub(fee));\n }\n }\n\n /**\n * @notice Nodes call this function to mint a SynERC20 (or any asset that the bridge is given minter access to). This is called by the nodes after a TokenDeposit event is emitted.\n * @dev This means the SynapseBridge.sol contract must have minter access to the token attempting to be minted\n * @param to address on other chain to redeem underlying assets to\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain post-fees\n * @param fee Amount in native token decimals to save to the contract as fees\n * @param kappa kappa\n **/\n function mint(\n address payable to,\n IERC20Mintable token,\n uint256 amount,\n uint256 fee,\n bytes32 kappa\n ) external nonReentrant whenNotPaused {\n require(\n hasRole(NODEGROUP_ROLE, msg.sender),\n \"Caller is not a node group\"\n );\n require(amount > fee, \"Amount must be greater than fee\");\n require(!kappaMap[kappa], \"Kappa is already present\");\n kappaMap[kappa] = true;\n fees[address(token)] = fees[address(token)].add(fee);\n emit TokenMint(to, token, amount.sub(fee), fee, kappa);\n token.mint(address(this), amount);\n // checks if synFRAX\n if (address(token) == 0xE96AC70907ffF3Efee79f502C985A7A21Bce407d) {\n token.safeIncreaseAllowance(\n 0x1A93B23281CC1CDE4C4741353F3064709A16197d,\n amount.sub(fee)\n );\n try\n IFrax(0x1A93B23281CC1CDE4C4741353F3064709A16197d)\n .exchangeOldForCanonical(address(token), amount.sub(fee))\n returns (uint256 canolical_tokens_out) {\n IERC20(0x1A93B23281CC1CDE4C4741353F3064709A16197d).safeTransfer(\n to,\n canolical_tokens_out\n );\n } catch {\n IERC20(token).safeTransfer(to, amount.sub(fee));\n }\n } else {\n IERC20(token).safeTransfer(to, amount.sub(fee));\n }\n if (chainGasAmount != 0 && address(this).balance > chainGasAmount) {\n to.call.value(chainGasAmount)(\"\");\n }\n }\n\n /**\n * @notice Relays to nodes to both transfer an ERC20 token cross-chain, and then have the nodes execute a swap through a liquidity pool on behalf of the user.\n * @param to address on other chain to bridge assets to\n * @param chainId which chain to bridge assets onto\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n * @param tokenIndexFrom the token the user wants to swap from\n * @param tokenIndexTo the token the user wants to swap to\n * @param minDy the min amount the user would like to receive, or revert to only minting the SynERC20 token crosschain.\n * @param deadline latest timestamp to accept this transaction\n **/\n function depositAndSwap(\n address to,\n uint256 chainId,\n IERC20 token,\n uint256 amount,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 minDy,\n uint256 deadline\n ) external nonReentrant whenNotPaused {\n emit TokenDepositAndSwap(\n to,\n chainId,\n token,\n amount,\n tokenIndexFrom,\n tokenIndexTo,\n minDy,\n deadline\n );\n token.safeTransferFrom(msg.sender, address(this), amount);\n }\n\n /**\n * @notice Relays to nodes that (typically) a wrapped synAsset ERC20 token has been burned and the underlying needs to be redeeemed on the native chain. This function indicates to the nodes that they should attempt to redeem the LP token for the underlying assets (E.g \"swap\" out of the LP token)\n * @param to address on other chain to redeem underlying assets to\n * @param chainId which underlying chain to bridge assets onto\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n * @param tokenIndexFrom the token the user wants to swap from\n * @param tokenIndexTo the token the user wants to swap to\n * @param minDy the min amount the user would like to receive, or revert to only minting the SynERC20 token crosschain.\n * @param deadline latest timestamp to accept this transaction\n **/\n function redeemAndSwap(\n address to,\n uint256 chainId,\n ERC20Burnable token,\n uint256 amount,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 minDy,\n uint256 deadline\n ) external nonReentrant whenNotPaused {\n emit TokenRedeemAndSwap(\n to,\n chainId,\n token,\n amount,\n tokenIndexFrom,\n tokenIndexTo,\n minDy,\n deadline\n );\n token.burnFrom(msg.sender, amount);\n }\n\n /**\n * @notice Relays to nodes that (typically) a wrapped synAsset ERC20 token has been burned and the underlying needs to be redeeemed on the native chain. This function indicates to the nodes that they should attempt to redeem the LP token for the underlying assets (E.g \"swap\" out of the LP token)\n * @param to address on other chain to redeem underlying assets to\n * @param chainId which underlying chain to bridge assets onto\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n * @param swapTokenIndex Specifies which of the underlying LP assets the nodes should attempt to redeem for\n * @param swapMinAmount Specifies the minimum amount of the underlying asset needed for the nodes to execute the redeem/swap\n * @param swapDeadline Specificies the deadline that the nodes are allowed to try to redeem/swap the LP token\n **/\n function redeemAndRemove(\n address to,\n uint256 chainId,\n ERC20Burnable token,\n uint256 amount,\n uint8 swapTokenIndex,\n uint256 swapMinAmount,\n uint256 swapDeadline\n ) external nonReentrant whenNotPaused {\n emit TokenRedeemAndRemove(\n to,\n chainId,\n token,\n amount,\n swapTokenIndex,\n swapMinAmount,\n swapDeadline\n );\n token.burnFrom(msg.sender, amount);\n }\n\n /**\n * @notice Nodes call this function to mint a SynERC20 (or any asset that the bridge is given minter access to), and then attempt to swap the SynERC20 into the desired destination asset. This is called by the nodes after a TokenDepositAndSwap event is emitted.\n * @dev This means the BridgeDeposit.sol contract must have minter access to the token attempting to be minted\n * @param to address on other chain to redeem underlying assets to\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain post-fees\n * @param fee Amount in native token decimals to save to the contract as fees\n * @param pool Destination chain's pool to use to swap SynERC20 -> Asset. The nodes determine this by using PoolConfig.sol.\n * @param tokenIndexFrom Index of the SynERC20 asset in the pool\n * @param tokenIndexTo Index of the desired final asset\n * @param minDy Minumum amount (in final asset decimals) that must be swapped for, otherwise the user will receive the SynERC20.\n * @param deadline Epoch time of the deadline that the swap is allowed to be executed.\n * @param kappa kappa\n **/\n function mintAndSwap(\n address payable to,\n IERC20Mintable token,\n uint256 amount,\n uint256 fee,\n ISwap pool,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 minDy,\n uint256 deadline,\n bytes32 kappa\n ) external nonReentrant whenNotPaused {\n require(\n hasRole(NODEGROUP_ROLE, msg.sender),\n \"Caller is not a node group\"\n );\n require(amount > fee, \"Amount must be greater than fee\");\n require(!kappaMap[kappa], \"Kappa is already present\");\n kappaMap[kappa] = true;\n fees[address(token)] = fees[address(token)].add(fee);\n // Transfer gas airdrop\n if (chainGasAmount != 0 && address(this).balance > chainGasAmount) {\n to.call.value(chainGasAmount)(\"\");\n }\n // first check to make sure more will be given than min amount required\n uint256 expectedOutput = ISwap(pool).calculateSwap(\n tokenIndexFrom,\n tokenIndexTo,\n amount.sub(fee)\n );\n\n if (expectedOutput >= minDy) {\n // proceed with swap\n token.mint(address(this), amount);\n token.safeIncreaseAllowance(address(pool), amount);\n try\n ISwap(pool).swap(\n tokenIndexFrom,\n tokenIndexTo,\n amount.sub(fee),\n minDy,\n deadline\n )\n returns (uint256 finalSwappedAmount) {\n // Swap succeeded, transfer swapped asset\n IERC20 swappedTokenTo = ISwap(pool).getToken(tokenIndexTo);\n if (\n address(swappedTokenTo) == WETH_ADDRESS &&\n WETH_ADDRESS != address(0)\n ) {\n IWETH9(WETH_ADDRESS).withdraw(finalSwappedAmount);\n (bool success, ) = to.call{value: finalSwappedAmount}(\"\");\n require(success, \"ETH_TRANSFER_FAILED\");\n emit TokenMintAndSwap(\n to,\n token,\n finalSwappedAmount,\n fee,\n tokenIndexFrom,\n tokenIndexTo,\n minDy,\n deadline,\n true,\n kappa\n );\n } else {\n swappedTokenTo.safeTransfer(to, finalSwappedAmount);\n emit TokenMintAndSwap(\n to,\n token,\n finalSwappedAmount,\n fee,\n tokenIndexFrom,\n tokenIndexTo,\n minDy,\n deadline,\n true,\n kappa\n );\n }\n } catch {\n IERC20(token).safeTransfer(to, amount.sub(fee));\n emit TokenMintAndSwap(\n to,\n token,\n amount.sub(fee),\n fee,\n tokenIndexFrom,\n tokenIndexTo,\n minDy,\n deadline,\n false,\n kappa\n );\n }\n } else {\n token.mint(address(this), amount);\n IERC20(token).safeTransfer(to, amount.sub(fee));\n emit TokenMintAndSwap(\n to,\n token,\n amount.sub(fee),\n fee,\n tokenIndexFrom,\n tokenIndexTo,\n minDy,\n deadline,\n false,\n kappa\n );\n }\n }\n\n /**\n * @notice Function to be called by the node group to withdraw the underlying assets from the contract\n * @param to address on chain to send underlying assets to\n * @param token ERC20 compatible token to withdraw from the bridge\n * @param amount Amount in native token decimals to withdraw\n * @param fee Amount in native token decimals to save to the contract as fees\n * @param pool Destination chain's pool to use to swap SynERC20 -> Asset. The nodes determine this by using PoolConfig.sol.\n * @param swapTokenIndex Specifies which of the underlying LP assets the nodes should attempt to redeem for\n * @param swapMinAmount Specifies the minimum amount of the underlying asset needed for the nodes to execute the redeem/swap\n * @param swapDeadline Specificies the deadline that the nodes are allowed to try to redeem/swap the LP token\n * @param kappa kappa\n **/\n function withdrawAndRemove(\n address to,\n IERC20 token,\n uint256 amount,\n uint256 fee,\n ISwap pool,\n uint8 swapTokenIndex,\n uint256 swapMinAmount,\n uint256 swapDeadline,\n bytes32 kappa\n ) external nonReentrant whenNotPaused {\n require(\n hasRole(NODEGROUP_ROLE, msg.sender),\n \"Caller is not a node group\"\n );\n require(amount > fee, \"Amount must be greater than fee\");\n require(!kappaMap[kappa], \"Kappa is already present\");\n kappaMap[kappa] = true;\n fees[address(token)] = fees[address(token)].add(fee);\n // first check to make sure more will be given than min amount required\n uint256 expectedOutput = ISwap(pool).calculateRemoveLiquidityOneToken(\n amount.sub(fee),\n swapTokenIndex\n );\n\n if (expectedOutput >= swapMinAmount) {\n token.safeIncreaseAllowance(address(pool), amount.sub(fee));\n try\n ISwap(pool).removeLiquidityOneToken(\n amount.sub(fee),\n swapTokenIndex,\n swapMinAmount,\n swapDeadline\n )\n returns (uint256 finalSwappedAmount) {\n // Swap succeeded, transfer swapped asset\n IERC20 swappedTokenTo = ISwap(pool).getToken(swapTokenIndex);\n swappedTokenTo.safeTransfer(to, finalSwappedAmount);\n emit TokenWithdrawAndRemove(\n to,\n token,\n finalSwappedAmount,\n fee,\n swapTokenIndex,\n swapMinAmount,\n swapDeadline,\n true,\n kappa\n );\n } catch {\n IERC20(token).safeTransfer(to, amount.sub(fee));\n emit TokenWithdrawAndRemove(\n to,\n token,\n amount.sub(fee),\n fee,\n swapTokenIndex,\n swapMinAmount,\n swapDeadline,\n false,\n kappa\n );\n }\n } else {\n token.safeTransfer(to, amount.sub(fee));\n emit TokenWithdrawAndRemove(\n to,\n token,\n amount.sub(fee),\n fee,\n swapTokenIndex,\n swapMinAmount,\n swapDeadline,\n false,\n kappa\n );\n }\n }\n\n // BRIDGE FUNCTIONS TO HANDLE DIFF ADDRESSES\n /**\n * @notice Relays to nodes that (typically) a wrapped synAsset ERC20 token has been burned and the underlying needs to be redeeemed on the native chain\n * @param to address on other chain to redeem underlying assets to\n * @param chainId which underlying chain to bridge assets onto\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n **/\n function redeemV2(\n bytes32 to,\n uint256 chainId,\n ERC20Burnable token,\n uint256 amount\n ) external nonReentrant whenNotPaused {\n emit TokenRedeemV2(to, chainId, token, amount);\n token.burnFrom(msg.sender, amount);\n }\n}\n" + }, + "contracts/bridge/HarmonySynapseBridge.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.6.12;\n\nimport \"@openzeppelin/contracts-upgradeable/proxy/Initializable.sol\";\nimport \"@openzeppelin/contracts-upgradeable/access/AccessControlUpgradeable.sol\";\nimport \"@openzeppelin/contracts-upgradeable/utils/ReentrancyGuardUpgradeable.sol\";\nimport \"@openzeppelin/contracts-upgradeable/utils/PausableUpgradeable.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/SafeERC20.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/ERC20Burnable.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport \"@openzeppelin/contracts/math/SafeMath.sol\";\n\nimport \"./interfaces/ISwap.sol\";\nimport \"./interfaces/IWETH9.sol\";\n\ninterface IERC20Mintable is IERC20 {\n function mint(address to, uint256 amount) external;\n}\n\ninterface IFrax {\n function exchangeOldForCanonical(\n address bridge_token_address,\n uint256 token_amount\n ) external returns (uint256);\n}\n\ncontract HarmonySynapseBridge is\n Initializable,\n AccessControlUpgradeable,\n ReentrancyGuardUpgradeable,\n PausableUpgradeable\n{\n using SafeERC20 for IERC20;\n using SafeERC20 for IERC20Mintable;\n using SafeMath for uint256;\n\n bytes32 public constant NODEGROUP_ROLE = keccak256(\"NODEGROUP_ROLE\");\n bytes32 public constant GOVERNANCE_ROLE = keccak256(\"GOVERNANCE_ROLE\");\n\n mapping(address => uint256) private fees;\n\n uint256 public startBlockNumber;\n uint256 public constant bridgeVersion = 6;\n uint256 public chainGasAmount;\n address payable public WETH_ADDRESS;\n\n mapping(bytes32 => bool) private kappaMap;\n\n receive() external payable {}\n\n function initialize() external initializer {\n startBlockNumber = block.number;\n _setupRole(DEFAULT_ADMIN_ROLE, msg.sender);\n __AccessControl_init();\n }\n\n function setChainGasAmount(uint256 amount) external {\n require(hasRole(GOVERNANCE_ROLE, msg.sender), \"Not governance\");\n chainGasAmount = amount;\n }\n\n function setWethAddress(address payable _wethAddress) external {\n require(hasRole(DEFAULT_ADMIN_ROLE, msg.sender), \"Not admin\");\n WETH_ADDRESS = _wethAddress;\n }\n\n function addKappas(bytes32[] calldata kappas) external {\n require(hasRole(GOVERNANCE_ROLE, msg.sender), \"Not governance\");\n for (uint256 i = 0; i < kappas.length; ++i) {\n kappaMap[kappas[i]] = true;\n }\n }\n\n event TokenDeposit(\n address indexed to,\n uint256 chainId,\n IERC20 token,\n uint256 amount\n );\n event TokenRedeem(\n address indexed to,\n uint256 chainId,\n IERC20 token,\n uint256 amount\n );\n event TokenWithdraw(\n address indexed to,\n IERC20 token,\n uint256 amount,\n uint256 fee,\n bytes32 indexed kappa\n );\n event TokenMint(\n address indexed to,\n IERC20Mintable token,\n uint256 amount,\n uint256 fee,\n bytes32 indexed kappa\n );\n event TokenDepositAndSwap(\n address indexed to,\n uint256 chainId,\n IERC20 token,\n uint256 amount,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 minDy,\n uint256 deadline\n );\n event TokenMintAndSwap(\n address indexed to,\n IERC20Mintable token,\n uint256 amount,\n uint256 fee,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 minDy,\n uint256 deadline,\n bool swapSuccess,\n bytes32 indexed kappa\n );\n event TokenRedeemAndSwap(\n address indexed to,\n uint256 chainId,\n IERC20 token,\n uint256 amount,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 minDy,\n uint256 deadline\n );\n event TokenRedeemAndRemove(\n address indexed to,\n uint256 chainId,\n IERC20 token,\n uint256 amount,\n uint8 swapTokenIndex,\n uint256 swapMinAmount,\n uint256 swapDeadline\n );\n event TokenWithdrawAndRemove(\n address indexed to,\n IERC20 token,\n uint256 amount,\n uint256 fee,\n uint8 swapTokenIndex,\n uint256 swapMinAmount,\n uint256 swapDeadline,\n bool swapSuccess,\n bytes32 indexed kappa\n );\n\n // v2 events\n event TokenRedeemV2(\n bytes32 indexed to,\n uint256 chainId,\n IERC20 token,\n uint256 amount\n );\n\n // VIEW FUNCTIONS ***/\n function getFeeBalance(address tokenAddress)\n external\n view\n returns (uint256)\n {\n return fees[tokenAddress];\n }\n\n function kappaExists(bytes32 kappa) external view returns (bool) {\n return kappaMap[kappa];\n }\n\n // FEE FUNCTIONS ***/\n /**\n * * @notice withdraw specified ERC20 token fees to a given address\n * * @param token ERC20 token in which fees acccumulated to transfer\n * * @param to Address to send the fees to\n */\n function withdrawFees(IERC20 token, address to) external whenNotPaused {\n require(hasRole(GOVERNANCE_ROLE, msg.sender), \"Not governance\");\n require(to != address(0), \"Address is 0x000\");\n if (fees[address(token)] != 0) {\n token.safeTransfer(to, fees[address(token)]);\n fees[address(token)] = 0;\n }\n }\n\n // PAUSABLE FUNCTIONS ***/\n function pause() external {\n require(hasRole(GOVERNANCE_ROLE, msg.sender), \"Not governance\");\n _pause();\n }\n\n function unpause() external {\n require(hasRole(GOVERNANCE_ROLE, msg.sender), \"Not governance\");\n _unpause();\n }\n\n /**\n * @notice Relays to nodes to transfers an ERC20 token cross-chain\n * @param to address on other chain to bridge assets to\n * @param chainId which chain to bridge assets onto\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n **/\n function deposit(\n address to,\n uint256 chainId,\n IERC20 token,\n uint256 amount\n ) external nonReentrant whenNotPaused {\n emit TokenDeposit(to, chainId, token, amount);\n token.safeTransferFrom(msg.sender, address(this), amount);\n }\n\n /**\n * @notice Relays to nodes that (typically) a wrapped synAsset ERC20 token has been burned and the underlying needs to be redeeemed on the native chain\n * @param to address on other chain to redeem underlying assets to\n * @param chainId which underlying chain to bridge assets onto\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n **/\n function redeem(\n address to,\n uint256 chainId,\n ERC20Burnable token,\n uint256 amount\n ) external nonReentrant whenNotPaused {\n emit TokenRedeem(to, chainId, token, amount);\n token.burnFrom(msg.sender, amount);\n }\n\n /**\n * @notice Function to be called by the node group to withdraw the underlying assets from the contract\n * @param to address on chain to send underlying assets to\n * @param token ERC20 compatible token to withdraw from the bridge\n * @param amount Amount in native token decimals to withdraw\n * @param fee Amount in native token decimals to save to the contract as fees\n * @param kappa kappa\n **/\n function withdraw(\n address to,\n IERC20 token,\n uint256 amount,\n uint256 fee,\n bytes32 kappa\n ) external nonReentrant whenNotPaused {\n require(\n hasRole(NODEGROUP_ROLE, msg.sender),\n \"Caller is not a node group\"\n );\n require(amount > fee, \"Amount must be greater than fee\");\n require(!kappaMap[kappa], \"Kappa is already present\");\n kappaMap[kappa] = true;\n fees[address(token)] = fees[address(token)].add(fee);\n if (address(token) == WETH_ADDRESS && WETH_ADDRESS != address(0)) {\n IWETH9(WETH_ADDRESS).withdraw(amount.sub(fee));\n (bool success, ) = to.call{value: amount.sub(fee)}(\"\");\n require(success, \"ETH_TRANSFER_FAILED\");\n emit TokenWithdraw(to, token, amount, fee, kappa);\n } else {\n emit TokenWithdraw(to, token, amount, fee, kappa);\n token.safeTransfer(to, amount.sub(fee));\n }\n }\n\n /**\n * @notice Nodes call this function to mint a SynERC20 (or any asset that the bridge is given minter access to). This is called by the nodes after a TokenDeposit event is emitted.\n * @dev This means the SynapseBridge.sol contract must have minter access to the token attempting to be minted\n * @param to address on other chain to redeem underlying assets to\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain post-fees\n * @param fee Amount in native token decimals to save to the contract as fees\n * @param kappa kappa\n **/\n function mint(\n address payable to,\n IERC20Mintable token,\n uint256 amount,\n uint256 fee,\n bytes32 kappa\n ) external nonReentrant whenNotPaused {\n require(\n hasRole(NODEGROUP_ROLE, msg.sender),\n \"Caller is not a node group\"\n );\n require(amount > fee, \"Amount must be greater than fee\");\n require(!kappaMap[kappa], \"Kappa is already present\");\n kappaMap[kappa] = true;\n fees[address(token)] = fees[address(token)].add(fee);\n emit TokenMint(to, token, amount.sub(fee), fee, kappa);\n token.mint(address(this), amount);\n // checks if synFRAX\n if (address(token) == 0x1852F70512298d56e9c8FDd905e02581E04ddb2a) {\n if (\n token.allowance(\n address(this),\n 0xFa7191D292d5633f702B0bd7E3E3BcCC0e633200\n ) < amount.sub(fee)\n ) {\n token.safeApprove(\n address(0xFa7191D292d5633f702B0bd7E3E3BcCC0e633200),\n 0\n );\n token.safeApprove(\n address(0xFa7191D292d5633f702B0bd7E3E3BcCC0e633200),\n type(uint256).max\n );\n }\n try\n IFrax(0xFa7191D292d5633f702B0bd7E3E3BcCC0e633200)\n .exchangeOldForCanonical(address(token), amount.sub(fee))\n returns (uint256 canolical_tokens_out) {\n IERC20(0xFa7191D292d5633f702B0bd7E3E3BcCC0e633200).safeTransfer(\n to,\n canolical_tokens_out\n );\n } catch {\n IERC20(token).safeTransfer(to, amount.sub(fee));\n }\n } else {\n IERC20(token).safeTransfer(to, amount.sub(fee));\n }\n if (chainGasAmount != 0 && address(this).balance > chainGasAmount) {\n to.call.value(chainGasAmount)(\"\");\n }\n }\n\n /**\n * @notice Relays to nodes to both transfer an ERC20 token cross-chain, and then have the nodes execute a swap through a liquidity pool on behalf of the user.\n * @param to address on other chain to bridge assets to\n * @param chainId which chain to bridge assets onto\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n * @param tokenIndexFrom the token the user wants to swap from\n * @param tokenIndexTo the token the user wants to swap to\n * @param minDy the min amount the user would like to receive, or revert to only minting the SynERC20 token crosschain.\n * @param deadline latest timestamp to accept this transaction\n **/\n function depositAndSwap(\n address to,\n uint256 chainId,\n IERC20 token,\n uint256 amount,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 minDy,\n uint256 deadline\n ) external nonReentrant whenNotPaused {\n emit TokenDepositAndSwap(\n to,\n chainId,\n token,\n amount,\n tokenIndexFrom,\n tokenIndexTo,\n minDy,\n deadline\n );\n token.safeTransferFrom(msg.sender, address(this), amount);\n }\n\n /**\n * @notice Relays to nodes that (typically) a wrapped synAsset ERC20 token has been burned and the underlying needs to be redeeemed on the native chain. This function indicates to the nodes that they should attempt to redeem the LP token for the underlying assets (E.g \"swap\" out of the LP token)\n * @param to address on other chain to redeem underlying assets to\n * @param chainId which underlying chain to bridge assets onto\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n * @param tokenIndexFrom the token the user wants to swap from\n * @param tokenIndexTo the token the user wants to swap to\n * @param minDy the min amount the user would like to receive, or revert to only minting the SynERC20 token crosschain.\n * @param deadline latest timestamp to accept this transaction\n **/\n function redeemAndSwap(\n address to,\n uint256 chainId,\n ERC20Burnable token,\n uint256 amount,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 minDy,\n uint256 deadline\n ) external nonReentrant whenNotPaused {\n emit TokenRedeemAndSwap(\n to,\n chainId,\n token,\n amount,\n tokenIndexFrom,\n tokenIndexTo,\n minDy,\n deadline\n );\n token.burnFrom(msg.sender, amount);\n }\n\n /**\n * @notice Relays to nodes that (typically) a wrapped synAsset ERC20 token has been burned and the underlying needs to be redeeemed on the native chain. This function indicates to the nodes that they should attempt to redeem the LP token for the underlying assets (E.g \"swap\" out of the LP token)\n * @param to address on other chain to redeem underlying assets to\n * @param chainId which underlying chain to bridge assets onto\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n * @param swapTokenIndex Specifies which of the underlying LP assets the nodes should attempt to redeem for\n * @param swapMinAmount Specifies the minimum amount of the underlying asset needed for the nodes to execute the redeem/swap\n * @param swapDeadline Specificies the deadline that the nodes are allowed to try to redeem/swap the LP token\n **/\n function redeemAndRemove(\n address to,\n uint256 chainId,\n ERC20Burnable token,\n uint256 amount,\n uint8 swapTokenIndex,\n uint256 swapMinAmount,\n uint256 swapDeadline\n ) external nonReentrant whenNotPaused {\n emit TokenRedeemAndRemove(\n to,\n chainId,\n token,\n amount,\n swapTokenIndex,\n swapMinAmount,\n swapDeadline\n );\n token.burnFrom(msg.sender, amount);\n }\n\n /**\n * @notice Nodes call this function to mint a SynERC20 (or any asset that the bridge is given minter access to), and then attempt to swap the SynERC20 into the desired destination asset. This is called by the nodes after a TokenDepositAndSwap event is emitted.\n * @dev This means the BridgeDeposit.sol contract must have minter access to the token attempting to be minted\n * @param to address on other chain to redeem underlying assets to\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain post-fees\n * @param fee Amount in native token decimals to save to the contract as fees\n * @param pool Destination chain's pool to use to swap SynERC20 -> Asset. The nodes determine this by using PoolConfig.sol.\n * @param tokenIndexFrom Index of the SynERC20 asset in the pool\n * @param tokenIndexTo Index of the desired final asset\n * @param minDy Minumum amount (in final asset decimals) that must be swapped for, otherwise the user will receive the SynERC20.\n * @param deadline Epoch time of the deadline that the swap is allowed to be executed.\n * @param kappa kappa\n **/\n function mintAndSwap(\n address payable to,\n IERC20Mintable token,\n uint256 amount,\n uint256 fee,\n ISwap pool,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 minDy,\n uint256 deadline,\n bytes32 kappa\n ) external nonReentrant whenNotPaused {\n require(\n hasRole(NODEGROUP_ROLE, msg.sender),\n \"Caller is not a node group\"\n );\n require(amount > fee, \"Amount must be greater than fee\");\n require(!kappaMap[kappa], \"Kappa is already present\");\n kappaMap[kappa] = true;\n fees[address(token)] = fees[address(token)].add(fee);\n // Transfer gas airdrop\n if (chainGasAmount != 0 && address(this).balance > chainGasAmount) {\n to.call.value(chainGasAmount)(\"\");\n }\n // first check to make sure more will be given than min amount required\n uint256 expectedOutput = ISwap(pool).calculateSwap(\n tokenIndexFrom,\n tokenIndexTo,\n amount.sub(fee)\n );\n\n if (expectedOutput >= minDy) {\n // proceed with swap\n token.mint(address(this), amount);\n token.safeIncreaseAllowance(address(pool), amount);\n try\n ISwap(pool).swap(\n tokenIndexFrom,\n tokenIndexTo,\n amount.sub(fee),\n minDy,\n deadline\n )\n returns (uint256 finalSwappedAmount) {\n // Swap succeeded, transfer swapped asset\n IERC20 swappedTokenTo = ISwap(pool).getToken(tokenIndexTo);\n if (\n address(swappedTokenTo) == WETH_ADDRESS &&\n WETH_ADDRESS != address(0)\n ) {\n IWETH9(WETH_ADDRESS).withdraw(finalSwappedAmount);\n (bool success, ) = to.call{value: finalSwappedAmount}(\"\");\n require(success, \"ETH_TRANSFER_FAILED\");\n emit TokenMintAndSwap(\n to,\n token,\n finalSwappedAmount,\n fee,\n tokenIndexFrom,\n tokenIndexTo,\n minDy,\n deadline,\n true,\n kappa\n );\n } else {\n swappedTokenTo.safeTransfer(to, finalSwappedAmount);\n emit TokenMintAndSwap(\n to,\n token,\n finalSwappedAmount,\n fee,\n tokenIndexFrom,\n tokenIndexTo,\n minDy,\n deadline,\n true,\n kappa\n );\n }\n } catch {\n IERC20(token).safeTransfer(to, amount.sub(fee));\n emit TokenMintAndSwap(\n to,\n token,\n amount.sub(fee),\n fee,\n tokenIndexFrom,\n tokenIndexTo,\n minDy,\n deadline,\n false,\n kappa\n );\n }\n } else {\n token.mint(address(this), amount);\n IERC20(token).safeTransfer(to, amount.sub(fee));\n emit TokenMintAndSwap(\n to,\n token,\n amount.sub(fee),\n fee,\n tokenIndexFrom,\n tokenIndexTo,\n minDy,\n deadline,\n false,\n kappa\n );\n }\n }\n\n /**\n * @notice Function to be called by the node group to withdraw the underlying assets from the contract\n * @param to address on chain to send underlying assets to\n * @param token ERC20 compatible token to withdraw from the bridge\n * @param amount Amount in native token decimals to withdraw\n * @param fee Amount in native token decimals to save to the contract as fees\n * @param pool Destination chain's pool to use to swap SynERC20 -> Asset. The nodes determine this by using PoolConfig.sol.\n * @param swapTokenIndex Specifies which of the underlying LP assets the nodes should attempt to redeem for\n * @param swapMinAmount Specifies the minimum amount of the underlying asset needed for the nodes to execute the redeem/swap\n * @param swapDeadline Specificies the deadline that the nodes are allowed to try to redeem/swap the LP token\n * @param kappa kappa\n **/\n function withdrawAndRemove(\n address to,\n IERC20 token,\n uint256 amount,\n uint256 fee,\n ISwap pool,\n uint8 swapTokenIndex,\n uint256 swapMinAmount,\n uint256 swapDeadline,\n bytes32 kappa\n ) external nonReentrant whenNotPaused {\n require(\n hasRole(NODEGROUP_ROLE, msg.sender),\n \"Caller is not a node group\"\n );\n require(amount > fee, \"Amount must be greater than fee\");\n require(!kappaMap[kappa], \"Kappa is already present\");\n kappaMap[kappa] = true;\n fees[address(token)] = fees[address(token)].add(fee);\n // first check to make sure more will be given than min amount required\n uint256 expectedOutput = ISwap(pool).calculateRemoveLiquidityOneToken(\n amount.sub(fee),\n swapTokenIndex\n );\n\n if (expectedOutput >= swapMinAmount) {\n token.safeIncreaseAllowance(address(pool), amount.sub(fee));\n try\n ISwap(pool).removeLiquidityOneToken(\n amount.sub(fee),\n swapTokenIndex,\n swapMinAmount,\n swapDeadline\n )\n returns (uint256 finalSwappedAmount) {\n // Swap succeeded, transfer swapped asset\n IERC20 swappedTokenTo = ISwap(pool).getToken(swapTokenIndex);\n swappedTokenTo.safeTransfer(to, finalSwappedAmount);\n emit TokenWithdrawAndRemove(\n to,\n token,\n finalSwappedAmount,\n fee,\n swapTokenIndex,\n swapMinAmount,\n swapDeadline,\n true,\n kappa\n );\n } catch {\n IERC20(token).safeTransfer(to, amount.sub(fee));\n emit TokenWithdrawAndRemove(\n to,\n token,\n amount.sub(fee),\n fee,\n swapTokenIndex,\n swapMinAmount,\n swapDeadline,\n false,\n kappa\n );\n }\n } else {\n token.safeTransfer(to, amount.sub(fee));\n emit TokenWithdrawAndRemove(\n to,\n token,\n amount.sub(fee),\n fee,\n swapTokenIndex,\n swapMinAmount,\n swapDeadline,\n false,\n kappa\n );\n }\n }\n\n // BRIDGE FUNCTIONS TO HANDLE DIFF ADDRESSES\n /**\n * @notice Relays to nodes that (typically) a wrapped synAsset ERC20 token has been burned and the underlying needs to be redeeemed on the native chain\n * @param to address on other chain to redeem underlying assets to\n * @param chainId which underlying chain to bridge assets onto\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n **/\n function redeemV2(\n bytes32 to,\n uint256 chainId,\n ERC20Burnable token,\n uint256 amount\n ) external nonReentrant whenNotPaused {\n emit TokenRedeemV2(to, chainId, token, amount);\n token.burnFrom(msg.sender, amount);\n }\n}\n" + }, + "@openzeppelin/contracts-upgradeable/drafts/EIP712Upgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <0.8.0;\nimport \"../proxy/Initializable.sol\";\n\n/**\n * @dev https://eips.ethereum.org/EIPS/eip-712[EIP 712] is a standard for hashing and signing of typed structured data.\n *\n * The encoding specified in the EIP is very generic, and such a generic implementation in Solidity is not feasible,\n * thus this contract does not implement the encoding itself. Protocols need to implement the type-specific encoding\n * they need in their contracts using a combination of `abi.encode` and `keccak256`.\n *\n * This contract implements the EIP 712 domain separator ({_domainSeparatorV4}) that is used as part of the encoding\n * scheme, and the final step of the encoding to obtain the message digest that is then signed via ECDSA\n * ({_hashTypedDataV4}).\n *\n * The implementation of the domain separator was designed to be as efficient as possible while still properly updating\n * the chain id to protect against replay attacks on an eventual fork of the chain.\n *\n * NOTE: This contract implements the version of the encoding known as \"v4\", as implemented by the JSON RPC method\n * https://docs.metamask.io/guide/signing-data.html[`eth_signTypedDataV4` in MetaMask].\n *\n * _Available since v3.4._\n */\nabstract contract EIP712Upgradeable is Initializable {\n /* solhint-disable var-name-mixedcase */\n bytes32 private _HASHED_NAME;\n bytes32 private _HASHED_VERSION;\n bytes32 private constant _TYPE_HASH = keccak256(\"EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)\");\n /* solhint-enable var-name-mixedcase */\n\n /**\n * @dev Initializes the domain separator and parameter caches.\n *\n * The meaning of `name` and `version` is specified in\n * https://eips.ethereum.org/EIPS/eip-712#definition-of-domainseparator[EIP 712]:\n *\n * - `name`: the user readable name of the signing domain, i.e. the name of the DApp or the protocol.\n * - `version`: the current major version of the signing domain.\n *\n * NOTE: These parameters cannot be changed except through a xref:learn::upgrading-smart-contracts.adoc[smart\n * contract upgrade].\n */\n function __EIP712_init(string memory name, string memory version) internal initializer {\n __EIP712_init_unchained(name, version);\n }\n\n function __EIP712_init_unchained(string memory name, string memory version) internal initializer {\n bytes32 hashedName = keccak256(bytes(name));\n bytes32 hashedVersion = keccak256(bytes(version));\n _HASHED_NAME = hashedName;\n _HASHED_VERSION = hashedVersion;\n }\n\n /**\n * @dev Returns the domain separator for the current chain.\n */\n function _domainSeparatorV4() internal view returns (bytes32) {\n return _buildDomainSeparator(_TYPE_HASH, _EIP712NameHash(), _EIP712VersionHash());\n }\n\n function _buildDomainSeparator(bytes32 typeHash, bytes32 name, bytes32 version) private view returns (bytes32) {\n return keccak256(\n abi.encode(\n typeHash,\n name,\n version,\n _getChainId(),\n address(this)\n )\n );\n }\n\n /**\n * @dev Given an already https://eips.ethereum.org/EIPS/eip-712#definition-of-hashstruct[hashed struct], this\n * function returns the hash of the fully encoded EIP712 message for this domain.\n *\n * This hash can be used together with {ECDSA-recover} to obtain the signer of a message. For example:\n *\n * ```solidity\n * bytes32 digest = _hashTypedDataV4(keccak256(abi.encode(\n * keccak256(\"Mail(address to,string contents)\"),\n * mailTo,\n * keccak256(bytes(mailContents))\n * )));\n * address signer = ECDSA.recover(digest, signature);\n * ```\n */\n function _hashTypedDataV4(bytes32 structHash) internal view virtual returns (bytes32) {\n return keccak256(abi.encodePacked(\"\\x19\\x01\", _domainSeparatorV4(), structHash));\n }\n\n function _getChainId() private view returns (uint256 chainId) {\n this; // silence state mutability warning without generating bytecode - see https://github.com/ethereum/solidity/issues/2691\n // solhint-disable-next-line no-inline-assembly\n assembly {\n chainId := chainid()\n }\n }\n\n /**\n * @dev The hash of the name parameter for the EIP712 domain.\n *\n * NOTE: This function reads from storage by default, but can be redefined to return a constant value if gas costs\n * are a concern.\n */\n function _EIP712NameHash() internal virtual view returns (bytes32) {\n return _HASHED_NAME;\n }\n\n /**\n * @dev The hash of the version parameter for the EIP712 domain.\n *\n * NOTE: This function reads from storage by default, but can be redefined to return a constant value if gas costs\n * are a concern.\n */\n function _EIP712VersionHash() internal virtual view returns (bytes32) {\n return _HASHED_VERSION;\n }\n uint256[50] private __gap;\n}\n" + }, + "@openzeppelin/contracts-upgradeable/drafts/ERC20PermitUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.5 <0.8.0;\n\nimport \"../token/ERC20/ERC20Upgradeable.sol\";\nimport \"./IERC20PermitUpgradeable.sol\";\nimport \"../cryptography/ECDSAUpgradeable.sol\";\nimport \"../utils/CountersUpgradeable.sol\";\nimport \"./EIP712Upgradeable.sol\";\nimport \"../proxy/Initializable.sol\";\n\n/**\n * @dev Implementation of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in\n * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612].\n *\n * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by\n * presenting a message signed by the account. By not relying on `{IERC20-approve}`, the token holder account doesn't\n * need to send a transaction, and thus is not required to hold Ether at all.\n *\n * _Available since v3.4._\n */\nabstract contract ERC20PermitUpgradeable is Initializable, ERC20Upgradeable, IERC20PermitUpgradeable, EIP712Upgradeable {\n using CountersUpgradeable for CountersUpgradeable.Counter;\n\n mapping (address => CountersUpgradeable.Counter) private _nonces;\n\n // solhint-disable-next-line var-name-mixedcase\n bytes32 private _PERMIT_TYPEHASH;\n\n /**\n * @dev Initializes the {EIP712} domain separator using the `name` parameter, and setting `version` to `\"1\"`.\n *\n * It's a good idea to use the same `name` that is defined as the ERC20 token name.\n */\n function __ERC20Permit_init(string memory name) internal initializer {\n __Context_init_unchained();\n __EIP712_init_unchained(name, \"1\");\n __ERC20Permit_init_unchained(name);\n }\n\n function __ERC20Permit_init_unchained(string memory name) internal initializer {\n _PERMIT_TYPEHASH = keccak256(\"Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)\");\n }\n\n /**\n * @dev See {IERC20Permit-permit}.\n */\n function permit(address owner, address spender, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s) public virtual override {\n // solhint-disable-next-line not-rely-on-time\n require(block.timestamp <= deadline, \"ERC20Permit: expired deadline\");\n\n bytes32 structHash = keccak256(\n abi.encode(\n _PERMIT_TYPEHASH,\n owner,\n spender,\n value,\n _nonces[owner].current(),\n deadline\n )\n );\n\n bytes32 hash = _hashTypedDataV4(structHash);\n\n address signer = ECDSAUpgradeable.recover(hash, v, r, s);\n require(signer == owner, \"ERC20Permit: invalid signature\");\n\n _nonces[owner].increment();\n _approve(owner, spender, value);\n }\n\n /**\n * @dev See {IERC20Permit-nonces}.\n */\n function nonces(address owner) public view override returns (uint256) {\n return _nonces[owner].current();\n }\n\n /**\n * @dev See {IERC20Permit-DOMAIN_SEPARATOR}.\n */\n // solhint-disable-next-line func-name-mixedcase\n function DOMAIN_SEPARATOR() external view override returns (bytes32) {\n return _domainSeparatorV4();\n }\n uint256[49] private __gap;\n}\n" + }, + "@openzeppelin/contracts-upgradeable/drafts/IERC20PermitUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <0.8.0;\n\n/**\n * @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in\n * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612].\n *\n * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by\n * presenting a message signed by the account. By not relying on `{IERC20-approve}`, the token holder account doesn't\n * need to send a transaction, and thus is not required to hold Ether at all.\n */\ninterface IERC20PermitUpgradeable {\n /**\n * @dev Sets `value` as the allowance of `spender` over `owner`'s tokens,\n * given `owner`'s signed approval.\n *\n * IMPORTANT: The same issues {IERC20-approve} has related to transaction\n * ordering also apply here.\n *\n * Emits an {Approval} event.\n *\n * Requirements:\n *\n * - `spender` cannot be the zero address.\n * - `deadline` must be a timestamp in the future.\n * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner`\n * over the EIP712-formatted function arguments.\n * - the signature must use ``owner``'s current nonce (see {nonces}).\n *\n * For more information on the signature format, see the\n * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP\n * section].\n */\n function permit(address owner, address spender, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s) external;\n\n /**\n * @dev Returns the current nonce for `owner`. This value must be\n * included whenever a signature is generated for {permit}.\n *\n * Every successful call to {permit} increases ``owner``'s nonce by one. This\n * prevents a signature from being used multiple times.\n */\n function nonces(address owner) external view returns (uint256);\n\n /**\n * @dev Returns the domain separator used in the encoding of the signature for `permit`, as defined by {EIP712}.\n */\n // solhint-disable-next-line func-name-mixedcase\n function DOMAIN_SEPARATOR() external view returns (bytes32);\n}\n" + }, + "@openzeppelin/contracts-upgradeable/cryptography/ECDSAUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <0.8.0;\n\n/**\n * @dev Elliptic Curve Digital Signature Algorithm (ECDSA) operations.\n *\n * These functions can be used to verify that a message was signed by the holder\n * of the private keys of a given address.\n */\nlibrary ECDSAUpgradeable {\n /**\n * @dev Returns the address that signed a hashed message (`hash`) with\n * `signature`. This address can then be used for verification purposes.\n *\n * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:\n * this function rejects them by requiring the `s` value to be in the lower\n * half order, and the `v` value to be either 27 or 28.\n *\n * IMPORTANT: `hash` _must_ be the result of a hash operation for the\n * verification to be secure: it is possible to craft signatures that\n * recover to arbitrary addresses for non-hashed data. A safe way to ensure\n * this is by receiving a hash of the original message (which may otherwise\n * be too long), and then calling {toEthSignedMessageHash} on it.\n */\n function recover(bytes32 hash, bytes memory signature) internal pure returns (address) {\n // Check the signature length\n if (signature.length != 65) {\n revert(\"ECDSA: invalid signature length\");\n }\n\n // Divide the signature in r, s and v variables\n bytes32 r;\n bytes32 s;\n uint8 v;\n\n // ecrecover takes the signature parameters, and the only way to get them\n // currently is to use assembly.\n // solhint-disable-next-line no-inline-assembly\n assembly {\n r := mload(add(signature, 0x20))\n s := mload(add(signature, 0x40))\n v := byte(0, mload(add(signature, 0x60)))\n }\n\n return recover(hash, v, r, s);\n }\n\n /**\n * @dev Overload of {ECDSA-recover-bytes32-bytes-} that receives the `v`,\n * `r` and `s` signature fields separately.\n */\n function recover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) internal pure returns (address) {\n // EIP-2 still allows signature malleability for ecrecover(). Remove this possibility and make the signature\n // unique. Appendix F in the Ethereum Yellow paper (https://ethereum.github.io/yellowpaper/paper.pdf), defines\n // the valid range for s in (281): 0 < s < secp256k1n ÷ 2 + 1, and for v in (282): v ∈ {27, 28}. Most\n // signatures from current libraries generate a unique signature with an s-value in the lower half order.\n //\n // If your library generates malleable signatures, such as s-values in the upper range, calculate a new s-value\n // with 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 - s1 and flip v from 27 to 28 or\n // vice versa. If your library also generates signatures with 0/1 for v instead 27/28, add 27 to v to accept\n // these malleable signatures as well.\n require(uint256(s) <= 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0, \"ECDSA: invalid signature 's' value\");\n require(v == 27 || v == 28, \"ECDSA: invalid signature 'v' value\");\n\n // If the signature is valid (and not malleable), return the signer address\n address signer = ecrecover(hash, v, r, s);\n require(signer != address(0), \"ECDSA: invalid signature\");\n\n return signer;\n }\n\n /**\n * @dev Returns an Ethereum Signed Message, created from a `hash`. This\n * replicates the behavior of the\n * https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_sign[`eth_sign`]\n * JSON-RPC method.\n *\n * See {recover}.\n */\n function toEthSignedMessageHash(bytes32 hash) internal pure returns (bytes32) {\n // 32 is the length in bytes of hash,\n // enforced by the type signature above\n return keccak256(abi.encodePacked(\"\\x19Ethereum Signed Message:\\n32\", hash));\n }\n}\n" + }, + "@openzeppelin/contracts-upgradeable/utils/CountersUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <0.8.0;\n\nimport \"../math/SafeMathUpgradeable.sol\";\n\n/**\n * @title Counters\n * @author Matt Condon (@shrugs)\n * @dev Provides counters that can only be incremented or decremented by one. This can be used e.g. to track the number\n * of elements in a mapping, issuing ERC721 ids, or counting request ids.\n *\n * Include with `using Counters for Counters.Counter;`\n * Since it is not possible to overflow a 256 bit integer with increments of one, `increment` can skip the {SafeMath}\n * overflow check, thereby saving gas. This does assume however correct usage, in that the underlying `_value` is never\n * directly accessed.\n */\nlibrary CountersUpgradeable {\n using SafeMathUpgradeable for uint256;\n\n struct Counter {\n // This variable should never be directly accessed by users of the library: interactions must be restricted to\n // the library's function. As of Solidity v0.5.2, this cannot be enforced, though there is a proposal to add\n // this feature: see https://github.com/ethereum/solidity/issues/4637\n uint256 _value; // default: 0\n }\n\n function current(Counter storage counter) internal view returns (uint256) {\n return counter._value;\n }\n\n function increment(Counter storage counter) internal {\n // The {SafeMath} overflow check can be skipped here, see the comment at the top\n counter._value += 1;\n }\n\n function decrement(Counter storage counter) internal {\n counter._value = counter._value.sub(1);\n }\n}\n" + }, + "contracts/bridge/SynapseERC20.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.6.12;\n\nimport \"@openzeppelin/contracts-upgradeable/token/ERC20/ERC20Upgradeable.sol\";\nimport \"@openzeppelin/contracts-upgradeable/token/ERC20/ERC20BurnableUpgradeable.sol\";\nimport \"@openzeppelin/contracts-upgradeable/drafts/ERC20PermitUpgradeable.sol\";\nimport \"@openzeppelin/contracts-upgradeable/access/AccessControlUpgradeable.sol\";\nimport \"@openzeppelin/contracts-upgradeable/proxy/Initializable.sol\";\n\ncontract SynapseERC20 is\n Initializable,\n ContextUpgradeable,\n AccessControlUpgradeable,\n ERC20BurnableUpgradeable,\n ERC20PermitUpgradeable\n{\n bytes32 public constant MINTER_ROLE = keccak256(\"MINTER_ROLE\");\n\n /**\n * @notice Initializes this ERC20 contract with the given parameters.\n * @param name Token name\n * @param symbol Token symbol\n * @param decimals Token name\n * @param owner admin address to be initialized with\n */\n function initialize(\n string memory name,\n string memory symbol,\n uint8 decimals,\n address owner\n ) external initializer {\n __Context_init_unchained();\n __AccessControl_init_unchained();\n __ERC20_init_unchained(name, symbol);\n __ERC20Burnable_init_unchained();\n _setupDecimals(decimals);\n __ERC20Permit_init(name);\n _setupRole(DEFAULT_ADMIN_ROLE, owner);\n }\n\n function mint(address to, uint256 amount) external {\n require(hasRole(MINTER_ROLE, msg.sender), \"Not a minter\");\n _mint(to, amount);\n }\n}\n" + }, + "contracts/auxiliary/DummyWethProxy.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.6.12;\nimport \"@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol\";\nimport \"@openzeppelin/contracts-upgradeable/proxy/Initializable.sol\";\n\ninterface IWETH9 {\n function name() external view returns (string memory);\n\n function symbol() external view returns (string memory);\n\n function decimals() external view returns (uint8);\n\n function balanceOf(address) external view returns (uint256);\n\n function allowance(address, address) external view returns (uint256);\n\n receive() external payable;\n\n function deposit() external payable;\n\n function withdraw(uint256 wad) external;\n\n function totalSupply() external view returns (uint256);\n\n function approve(address guy, uint256 wad) external returns (bool);\n\n function transfer(address dst, uint256 wad) external returns (bool);\n\n function transferFrom(\n address src,\n address dst,\n uint256 wad\n ) external returns (bool);\n}\n\ncontract DummyWethProxy is Initializable, OwnableUpgradeable {\n function initialize() external initializer {\n __Ownable_init();\n }\n\n IWETH9 public WETH;\n\n function setWETHAddress(address payable _weth) external onlyOwner {\n WETH = IWETH9(_weth);\n }\n\n function withdrawToSelf(uint256 amount) external {\n WETH.withdraw(amount);\n }\n\n function rescue(uint256 amount) external onlyOwner {\n WETH.transfer(owner(), amount);\n }\n\n receive() external payable {}\n\n fallback() external payable {}\n}\n" + }, + "contracts/amm/helper/test/TestMathUtils.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.6.12;\n\nimport \"../../MathUtils.sol\";\n\ncontract TestMathUtils {\n using MathUtils for uint256;\n\n function difference(uint256 a, uint256 b) public pure returns (uint256) {\n return a.difference(b);\n }\n\n function within1(uint256 a, uint256 b) public pure returns (bool) {\n return a.within1(b);\n }\n}\n" + }, + "contracts/bridge/ERC20Migrator.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.6.12;\n\nimport \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/SafeERC20.sol\";\nimport \"@openzeppelin/contracts/math/SafeMath.sol\";\n\n/**\n * @title ERC20Migrator\n * @dev This contract can be used to migrate an ERC20 token from one\n * contract to another, where each token holder has to opt-in to the migration.\n * To opt-in, users must approve for this contract the number of tokens they\n * want to migrate. Once the allowance is set up, anyone can trigger the\n * migration to the new token contract. In this way, token holders \"turn in\"\n * their old balance and will be minted an equal amount in the new token.\n * The new token contract must be mintable.\n * ```\n */\n\ninterface IERC20Mintable is IERC20 {\n function mint(address to, uint256 amount) external;\n}\n\ncontract ERC20Migrator {\n using SafeERC20 for IERC20;\n using SafeMath for uint256;\n\n // Address of the old token contract\n IERC20 private _legacyToken;\n\n // Address of the new token contract\n IERC20Mintable private _newToken;\n\n /**\n * @param legacyToken address of the old token contract\n */\n constructor(IERC20 legacyToken, IERC20Mintable newToken) public {\n _legacyToken = legacyToken;\n _newToken = newToken;\n }\n\n /**\n * @dev Returns the legacy token that is being migrated.\n */\n function legacyToken() external view returns (IERC20) {\n return _legacyToken;\n }\n\n /**\n * @dev Returns the new token to which we are migrating.\n */\n function newToken() external view returns (IERC20) {\n return _newToken;\n }\n\n /**\n * @dev Transfers part of an account's balance in the old token to this\n * contract, and mints the same amount of new tokens for that account.\n * @param amount amount of tokens to be migrated\n */\n function migrate(uint256 amount) external {\n _legacyToken.safeTransferFrom(msg.sender, address(this), amount);\n uint256 amountToMint = amount.mul(5).div(2);\n _newToken.mint(msg.sender, amountToMint);\n }\n}\n" + }, + "contracts/bridge/ECDSANodeManagement.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.6.12;\n\nimport \"./utils/AddressArrayUtils.sol\";\nimport \"@openzeppelin/contracts/math/SafeMath.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/SafeERC20.sol\";\n\ncontract ECDSANodeManagement {\n using AddressArrayUtils for address[];\n using SafeMath for uint256;\n using SafeERC20 for IERC20;\n\n // Status of the keep.\n // Active means the keep is active.\n // Closed means the keep was closed happily.\n // Terminated means the keep was closed due to misbehavior.\n enum Status {\n Active,\n Closed,\n Terminated\n }\n\n // Address of the keep's owner.\n address public owner;\n\n // List of keep members' addresses.\n address[] public members;\n\n // Minimum number of honest keep members required to produce a signature.\n uint256 public honestThreshold;\n\n // Keep's ECDSA public key serialized to 64-bytes, where X and Y coordinates\n // are padded with zeros to 32-byte each.\n bytes public publicKey;\n\n // The timestamp at which keep has been created and key generation process\n // started.\n uint256 internal keyGenerationStartTimestamp;\n\n // Map stores public key by member addresses. All members should submit the\n // same public key.\n mapping(address => bytes) internal submittedPublicKeys;\n\n // The current status of the keep.\n // If the keep is Active members monitor it and support requests from the\n // keep owner.\n // If the owner decides to close the keep the flag is set to Closed.\n // If the owner seizes member bonds the flag is set to Terminated.\n Status internal status;\n\n // Flags execution of contract initialization.\n bool internal isInitialized;\n\n // Notification that the submitted public key does not match a key submitted\n // by other member. The event contains address of the member who tried to\n // submit a public key and a conflicting public key submitted already by other\n // member.\n event ConflictingPublicKeySubmitted(\n address indexed submittingMember,\n bytes conflictingPublicKey\n );\n\n // Notification that keep's ECDSA public key has been successfully established.\n event PublicKeyPublished(bytes publicKey);\n\n // Notification that the keep was closed by the owner.\n // Members no longer need to support this keep.\n event KeepClosed();\n\n // Notification that the keep has been terminated by the owner.\n // Members no longer need to support this keep.\n event KeepTerminated();\n\n /// @notice Returns keep's ECDSA public key.\n /// @return Keep's ECDSA public key.\n function getPublicKey() external view returns (bytes memory) {\n return publicKey;\n }\n\n /// @notice Submits a public key to the keep.\n /// @dev Public key is published successfully if all members submit the same\n /// value. In case of conflicts with others members submissions it will emit\n /// `ConflictingPublicKeySubmitted` event. When all submitted keys match\n /// it will store the key as keep's public key and emit a `PublicKeyPublished`\n /// event.\n /// @param _publicKey Signer's public key.\n function submitPublicKey(bytes calldata _publicKey) external onlyMember {\n require(\n !hasMemberSubmittedPublicKey(msg.sender),\n \"Member already submitted a public key\"\n );\n\n require(_publicKey.length == 64, \"Public key must be 64 bytes long\");\n\n submittedPublicKeys[msg.sender] = _publicKey;\n\n // Check if public keys submitted by all keep members are the same as\n // the currently submitted one.\n uint256 matchingPublicKeysCount = 0;\n for (uint256 i = 0; i < members.length; i++) {\n if (\n keccak256(submittedPublicKeys[members[i]]) !=\n keccak256(_publicKey)\n ) {\n // Emit an event only if compared member already submitted a value.\n if (hasMemberSubmittedPublicKey(members[i])) {\n emit ConflictingPublicKeySubmitted(\n msg.sender,\n submittedPublicKeys[members[i]]\n );\n }\n } else {\n matchingPublicKeysCount++;\n }\n }\n\n if (matchingPublicKeysCount != members.length) {\n return;\n }\n\n // All submitted signatures match.\n publicKey = _publicKey;\n emit PublicKeyPublished(_publicKey);\n }\n\n /// @notice Gets the owner of the keep.\n /// @return Address of the keep owner.\n function getOwner() external view returns (address) {\n return owner;\n }\n\n /// @notice Gets the timestamp the keep was opened at.\n /// @return Timestamp the keep was opened at.\n function getOpenedTimestamp() external view returns (uint256) {\n return keyGenerationStartTimestamp;\n }\n\n /// @notice Closes keep when owner decides that they no longer need it.\n /// Releases bonds to the keep members.\n /// @dev The function can be called only by the owner of the keep and only\n /// if the keep has not been already closed.\n function closeKeep() public onlyOwner onlyWhenActive {\n markAsClosed();\n }\n\n /// @notice Returns true if the keep is active.\n /// @return true if the keep is active, false otherwise.\n function isActive() public view returns (bool) {\n return status == Status.Active;\n }\n\n /// @notice Returns true if the keep is closed and members no longer support\n /// this keep.\n /// @return true if the keep is closed, false otherwise.\n function isClosed() public view returns (bool) {\n return status == Status.Closed;\n }\n\n /// @notice Returns true if the keep has been terminated.\n /// Keep is terminated when bonds are seized and members no longer support\n /// this keep.\n /// @return true if the keep has been terminated, false otherwise.\n function isTerminated() public view returns (bool) {\n return status == Status.Terminated;\n }\n\n /// @notice Returns members of the keep.\n /// @return List of the keep members' addresses.\n function getMembers() public view returns (address[] memory) {\n return members;\n }\n\n /// @notice Initialization function.\n /// @dev We use clone factory to create new keep. That is why this contract\n /// doesn't have a constructor. We provide keep parameters for each instance\n /// function after cloning instances from the master contract.\n /// Initialization must happen in the same transaction in which the clone is\n /// created.\n /// @param _owner Address of the keep owner.\n /// @param _members Addresses of the keep members.\n /// @param _honestThreshold Minimum number of honest keep members.\n function initialize(\n address _owner,\n address[] memory _members,\n uint256 _honestThreshold\n ) public {\n require(!isInitialized, \"Contract already initialized\");\n require(_owner != address(0));\n owner = _owner;\n members = _members;\n honestThreshold = _honestThreshold;\n\n status = Status.Active;\n isInitialized = true;\n\n /* solium-disable-next-line security/no-block-members*/\n keyGenerationStartTimestamp = block.timestamp;\n }\n\n /// @notice Checks if the member already submitted a public key.\n /// @param _member Address of the member.\n /// @return True if member already submitted a public key, else false.\n function hasMemberSubmittedPublicKey(address _member)\n internal\n view\n returns (bool)\n {\n return submittedPublicKeys[_member].length != 0;\n }\n\n /// @notice Marks the keep as closed.\n /// Keep can be marked as closed only when there is no signing in progress\n /// or the requested signing process has timed out.\n function markAsClosed() internal {\n status = Status.Closed;\n emit KeepClosed();\n }\n\n /// @notice Marks the keep as terminated.\n /// Keep can be marked as terminated only when there is no signing in progress\n /// or the requested signing process has timed out.\n function markAsTerminated() internal {\n status = Status.Terminated;\n emit KeepTerminated();\n }\n\n /// @notice Coverts a public key to an ethereum address.\n /// @param _publicKey Public key provided as 64-bytes concatenation of\n /// X and Y coordinates (32-bytes each).\n /// @return Ethereum address.\n function publicKeyToAddress(bytes memory _publicKey)\n internal\n pure\n returns (address)\n {\n // We hash the public key and then truncate last 20 bytes of the digest\n // which is the ethereum address.\n return address(uint160(uint256(keccak256(_publicKey))));\n }\n\n /// @notice Terminates the keep.\n function terminateKeep() internal {\n markAsTerminated();\n }\n\n /// @notice Checks if the caller is the keep's owner.\n /// @dev Throws an error if called by any account other than owner.\n modifier onlyOwner() {\n require(owner == msg.sender, \"Caller is not the keep owner\");\n _;\n }\n\n /// @notice Checks if the caller is a keep member.\n /// @dev Throws an error if called by any account other than one of the members.\n modifier onlyMember() {\n require(members.contains(msg.sender), \"Caller is not the keep member\");\n _;\n }\n\n /// @notice Checks if the keep is currently active.\n /// @dev Throws an error if called when the keep has been already closed.\n modifier onlyWhenActive() {\n require(isActive(), \"Keep is not active\");\n _;\n }\n}\n" + }, + "contracts/bridge/utils/AddressArrayUtils.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.6.12;\n\nlibrary AddressArrayUtils {\n function contains(address[] memory self, address _address)\n internal\n pure\n returns (bool)\n {\n for (uint256 i = 0; i < self.length; i++) {\n if (_address == self[i]) {\n return true;\n }\n }\n return false;\n }\n}" + }, + "contracts/bridge/BridgeConfigV3.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.6.12;\npragma experimental ABIEncoderV2;\n\nimport \"@openzeppelin/contracts/access/AccessControl.sol\";\nimport \"@openzeppelin/contracts/math/SafeMath.sol\";\n\n/**\n * @title BridgeConfig contract\n * @notice This token is used for configuring different tokens on the bridge and mapping them across chains.\n **/\n\ncontract BridgeConfigV3 is AccessControl {\n using SafeMath for uint256;\n bytes32 public constant BRIDGEMANAGER_ROLE =\n keccak256(\"BRIDGEMANAGER_ROLE\");\n bytes32[] private _allTokenIDs;\n mapping(bytes32 => Token[]) private _allTokens; // key is tokenID\n mapping(uint256 => mapping(string => bytes32)) private _tokenIDMap; // key is chainID,tokenAddress\n mapping(bytes32 => mapping(uint256 => Token)) private _tokens; // key is tokenID,chainID\n mapping(address => mapping(uint256 => Pool)) private _pool; // key is tokenAddress,chainID\n mapping(uint256 => uint256) private _maxGasPrice; // key is tokenID,chainID\n uint256 public constant bridgeConfigVersion = 3;\n\n // the denominator used to calculate fees. For example, an\n // LP fee might be something like tradeAmount.mul(fee).div(FEE_DENOMINATOR)\n uint256 private constant FEE_DENOMINATOR = 10**10;\n\n // this struct must be initialized using setTokenConfig for each token that directly interacts with the bridge\n struct Token {\n uint256 chainId;\n string tokenAddress;\n uint8 tokenDecimals;\n uint256 maxSwap;\n uint256 minSwap;\n uint256 swapFee;\n uint256 maxSwapFee;\n uint256 minSwapFee;\n bool hasUnderlying;\n bool isUnderlying;\n }\n\n struct Pool {\n address tokenAddress;\n uint256 chainId;\n address poolAddress;\n bool metaswap;\n }\n\n constructor() public {\n _setupRole(DEFAULT_ADMIN_ROLE, msg.sender);\n }\n\n /**\n * @notice Returns a list of all existing token IDs converted to strings\n */\n function getAllTokenIDs() public view returns (string[] memory result) {\n uint256 length = _allTokenIDs.length;\n result = new string[](length);\n for (uint256 i = 0; i < length; ++i) {\n result[i] = toString(_allTokenIDs[i]);\n }\n }\n\n function _getTokenID(string memory tokenAddress, uint256 chainID)\n internal\n view\n returns (string memory)\n {\n return toString(_tokenIDMap[chainID][tokenAddress]);\n }\n\n function getTokenID(string memory tokenAddress, uint256 chainID)\n public\n view\n returns (string memory)\n {\n return _getTokenID(_toLower(tokenAddress), chainID);\n }\n\n /**\n * @notice Returns the token ID (string) of the cross-chain token inputted\n * @param tokenAddress address of token to get ID for\n * @param chainID chainID of which to get token ID for\n */\n function getTokenID(address tokenAddress, uint256 chainID)\n public\n view\n returns (string memory)\n {\n return _getTokenID(_toLower(toString(tokenAddress)), chainID);\n }\n\n /**\n * @notice Returns the full token config struct\n * @param tokenID String input of the token ID for the token\n * @param chainID Chain ID of which token address + config to get\n */\n function getToken(string memory tokenID, uint256 chainID)\n public\n view\n returns (Token memory token)\n {\n return _tokens[toBytes32(tokenID)][chainID];\n }\n\n /**\n * @notice Returns the full token config struct\n * @param tokenID String input of the token ID for the token\n * @param chainID Chain ID of which token address + config to get\n */\n function getTokenByID(string memory tokenID, uint256 chainID)\n public\n view\n returns (Token memory token)\n {\n return _tokens[toBytes32(tokenID)][chainID];\n }\n\n /**\n * @notice Returns token config struct, given an address and chainID\n * @param tokenAddress Matches the token ID by using a combo of address + chain ID\n * @param chainID Chain ID of which token to get config for\n */\n function getTokenByAddress(string memory tokenAddress, uint256 chainID)\n public\n view\n returns (Token memory token)\n {\n return _tokens[_tokenIDMap[chainID][_toLower(tokenAddress)]][chainID];\n }\n\n function getTokenByEVMAddress(address tokenAddress, uint256 chainID)\n public\n view\n returns (Token memory token)\n {\n return\n _tokens[_tokenIDMap[chainID][_toLower(toString(tokenAddress))]][\n chainID\n ];\n }\n\n /**\n * @notice Returns true if the token has an underlying token -- meaning the token is deposited into the bridge\n * @param tokenID String to check if it is a withdraw/underlying token\n */\n function hasUnderlyingToken(string memory tokenID)\n public\n view\n returns (bool)\n {\n bytes32 bytesTokenID = toBytes32(tokenID);\n Token[] memory _mcTokens = _allTokens[bytesTokenID];\n for (uint256 i = 0; i < _mcTokens.length; ++i) {\n if (_mcTokens[i].hasUnderlying) {\n return true;\n }\n }\n return false;\n }\n\n /**\n * @notice Returns which token is the underlying token to withdraw\n * @param tokenID string token ID\n */\n function getUnderlyingToken(string memory tokenID)\n public\n view\n returns (Token memory token)\n {\n bytes32 bytesTokenID = toBytes32(tokenID);\n Token[] memory _mcTokens = _allTokens[bytesTokenID];\n for (uint256 i = 0; i < _mcTokens.length; ++i) {\n if (_mcTokens[i].isUnderlying) {\n return _mcTokens[i];\n }\n }\n }\n\n /**\n @notice Public function returning if token ID exists given a string\n */\n function isTokenIDExist(string memory tokenID) public view returns (bool) {\n return _isTokenIDExist(toBytes32(tokenID));\n }\n\n /**\n @notice Internal function returning if token ID exists given bytes32 version of the ID\n */\n function _isTokenIDExist(bytes32 tokenID) internal view returns (bool) {\n for (uint256 i = 0; i < _allTokenIDs.length; ++i) {\n if (_allTokenIDs[i] == tokenID) {\n return true;\n }\n }\n return false;\n }\n\n /**\n * @notice Internal function which handles logic of setting token ID and dealing with mappings\n * @param tokenID bytes32 version of ID\n * @param chainID which chain to set the token config for\n * @param tokenToAdd Token object to set the mapping to\n */\n function _setTokenConfig(\n bytes32 tokenID,\n uint256 chainID,\n Token memory tokenToAdd\n ) internal returns (bool) {\n _tokens[tokenID][chainID] = tokenToAdd;\n if (!_isTokenIDExist(tokenID)) {\n _allTokenIDs.push(tokenID);\n }\n\n Token[] storage _mcTokens = _allTokens[tokenID];\n for (uint256 i = 0; i < _mcTokens.length; ++i) {\n if (_mcTokens[i].chainId == chainID) {\n string memory oldToken = _mcTokens[i].tokenAddress;\n if (!compareStrings(tokenToAdd.tokenAddress, oldToken)) {\n _mcTokens[i].tokenAddress = tokenToAdd.tokenAddress;\n _tokenIDMap[chainID][oldToken] = keccak256(\"\");\n _tokenIDMap[chainID][tokenToAdd.tokenAddress] = tokenID;\n }\n }\n }\n _mcTokens.push(tokenToAdd);\n _tokenIDMap[chainID][tokenToAdd.tokenAddress] = tokenID;\n return true;\n }\n\n /**\n * @notice Main write function of this contract - Handles creating the struct and passing it to the internal logic function\n * @param tokenID string ID to set the token config object form\n * @param chainID chain ID to use for the token config object\n * @param tokenAddress token address of the token on the given chain\n * @param tokenDecimals decimals of token\n * @param maxSwap maximum amount of token allowed to be transferred at once - in native token decimals\n * @param minSwap minimum amount of token needed to be transferred at once - in native token decimals\n * @param swapFee percent based swap fee -- 10e6 == 10bps\n * @param maxSwapFee max swap fee to be charged - in native token decimals\n * @param minSwapFee min swap fee to be charged - in native token decimals - especially useful for mainnet ETH\n * @param hasUnderlying bool which represents whether this is a global mint token or one to withdraw()\n * @param isUnderlying bool which represents if this token is the one to withdraw on the given chain\n */\n function setTokenConfig(\n string calldata tokenID,\n uint256 chainID,\n address tokenAddress,\n uint8 tokenDecimals,\n uint256 maxSwap,\n uint256 minSwap,\n uint256 swapFee,\n uint256 maxSwapFee,\n uint256 minSwapFee,\n bool hasUnderlying,\n bool isUnderlying\n ) public returns (bool) {\n require(hasRole(BRIDGEMANAGER_ROLE, msg.sender));\n return\n setTokenConfig(\n tokenID,\n chainID,\n toString(tokenAddress),\n tokenDecimals,\n maxSwap,\n minSwap,\n swapFee,\n maxSwapFee,\n minSwapFee,\n hasUnderlying,\n isUnderlying\n );\n }\n\n /**\n * @notice Main write function of this contract - Handles creating the struct and passing it to the internal logic function\n * @param tokenID string ID to set the token config object form\n * @param chainID chain ID to use for the token config object\n * @param tokenAddress token address of the token on the given chain\n * @param tokenDecimals decimals of token\n * @param maxSwap maximum amount of token allowed to be transferred at once - in native token decimals\n * @param minSwap minimum amount of token needed to be transferred at once - in native token decimals\n * @param swapFee percent based swap fee -- 10e6 == 10bps\n * @param maxSwapFee max swap fee to be charged - in native token decimals\n * @param minSwapFee min swap fee to be charged - in native token decimals - especially useful for mainnet ETH\n * @param hasUnderlying bool which represents whether this is a global mint token or one to withdraw()\n * @param isUnderlying bool which represents if this token is the one to withdraw on the given chain\n */\n function setTokenConfig(\n string calldata tokenID,\n uint256 chainID,\n string memory tokenAddress,\n uint8 tokenDecimals,\n uint256 maxSwap,\n uint256 minSwap,\n uint256 swapFee,\n uint256 maxSwapFee,\n uint256 minSwapFee,\n bool hasUnderlying,\n bool isUnderlying\n ) public returns (bool) {\n require(hasRole(BRIDGEMANAGER_ROLE, msg.sender));\n Token memory tokenToAdd;\n tokenToAdd.tokenAddress = _toLower(tokenAddress);\n tokenToAdd.tokenDecimals = tokenDecimals;\n tokenToAdd.maxSwap = maxSwap;\n tokenToAdd.minSwap = minSwap;\n tokenToAdd.swapFee = swapFee;\n tokenToAdd.maxSwapFee = maxSwapFee;\n tokenToAdd.minSwapFee = minSwapFee;\n tokenToAdd.hasUnderlying = hasUnderlying;\n tokenToAdd.isUnderlying = isUnderlying;\n tokenToAdd.chainId = chainID;\n\n return _setTokenConfig(toBytes32(tokenID), chainID, tokenToAdd);\n }\n\n function _calculateSwapFee(\n string memory tokenAddress,\n uint256 chainID,\n uint256 amount\n ) internal view returns (uint256) {\n Token memory token = _tokens[_tokenIDMap[chainID][tokenAddress]][\n chainID\n ];\n uint256 calculatedSwapFee = amount.mul(token.swapFee).div(\n FEE_DENOMINATOR\n );\n if (\n calculatedSwapFee > token.minSwapFee &&\n calculatedSwapFee < token.maxSwapFee\n ) {\n return calculatedSwapFee;\n } else if (calculatedSwapFee > token.maxSwapFee) {\n return token.maxSwapFee;\n } else {\n return token.minSwapFee;\n }\n }\n\n /**\n * @notice Calculates bridge swap fee based on the destination chain's token transfer.\n * @dev This means the fee should be calculated based on the chain that the nodes emit a tx on\n * @param tokenAddress address of the destination token to query token config for\n * @param chainID destination chain ID to query the token config for\n * @param amount in native token decimals\n * @return Fee calculated in token decimals\n */\n function calculateSwapFee(\n string memory tokenAddress,\n uint256 chainID,\n uint256 amount\n ) external view returns (uint256) {\n return _calculateSwapFee(_toLower(tokenAddress), chainID, amount);\n }\n\n /**\n * @notice Calculates bridge swap fee based on the destination chain's token transfer.\n * @dev This means the fee should be calculated based on the chain that the nodes emit a tx on\n * @param tokenAddress address of the destination token to query token config for\n * @param chainID destination chain ID to query the token config for\n * @param amount in native token decimals\n * @return Fee calculated in token decimals\n */\n function calculateSwapFee(\n address tokenAddress,\n uint256 chainID,\n uint256 amount\n ) external view returns (uint256) {\n return\n _calculateSwapFee(\n _toLower(toString(tokenAddress)),\n chainID,\n amount\n );\n }\n\n // GAS PRICING\n\n /**\n * @notice sets the max gas price for a chain\n */\n function setMaxGasPrice(uint256 chainID, uint256 maxPrice) public {\n require(hasRole(BRIDGEMANAGER_ROLE, msg.sender));\n _maxGasPrice[chainID] = maxPrice;\n }\n\n /**\n * @notice gets the max gas price for a chain\n */\n function getMaxGasPrice(uint256 chainID) public view returns (uint256) {\n return _maxGasPrice[chainID];\n }\n\n // POOL CONFIG\n\n function getPoolConfig(address tokenAddress, uint256 chainID)\n external\n view\n returns (Pool memory)\n {\n return _pool[tokenAddress][chainID];\n }\n\n function setPoolConfig(\n address tokenAddress,\n uint256 chainID,\n address poolAddress,\n bool metaswap\n ) external returns (Pool memory) {\n require(\n hasRole(BRIDGEMANAGER_ROLE, msg.sender),\n \"Caller is not Bridge Manager\"\n );\n Pool memory newPool = Pool(\n tokenAddress,\n chainID,\n poolAddress,\n metaswap\n );\n _pool[tokenAddress][chainID] = newPool;\n return newPool;\n }\n\n // UTILITY FUNCTIONS\n\n function toString(bytes32 data) internal pure returns (string memory) {\n uint8 i = 0;\n while (i < 32 && data[i] != 0) {\n ++i;\n }\n bytes memory bs = new bytes(i);\n for (uint8 j = 0; j < i; ++j) {\n bs[j] = data[j];\n }\n return string(bs);\n }\n\n // toBytes32 converts a string to a bytes 32\n function toBytes32(string memory str)\n internal\n pure\n returns (bytes32 result)\n {\n require(bytes(str).length <= 32);\n assembly {\n result := mload(add(str, 32))\n }\n }\n\n function toString(address x) internal pure returns (string memory) {\n bytes memory s = new bytes(40);\n for (uint256 i = 0; i < 20; i++) {\n bytes1 b = bytes1(uint8(uint256(uint160(x)) / (2**(8 * (19 - i)))));\n bytes1 hi = bytes1(uint8(b) / 16);\n bytes1 lo = bytes1(uint8(b) - 16 * uint8(hi));\n s[2 * i] = char(hi);\n s[2 * i + 1] = char(lo);\n }\n\n string memory addrPrefix = \"0x\";\n\n return concat(addrPrefix, string(s));\n }\n\n function concat(string memory _x, string memory _y)\n internal\n pure\n returns (string memory)\n {\n bytes memory _xBytes = bytes(_x);\n bytes memory _yBytes = bytes(_y);\n\n string memory _tmpValue = new string(_xBytes.length + _yBytes.length);\n bytes memory _newValue = bytes(_tmpValue);\n\n uint256 i;\n uint256 j;\n\n for (i = 0; i < _xBytes.length; i++) {\n _newValue[j++] = _xBytes[i];\n }\n\n for (i = 0; i < _yBytes.length; i++) {\n _newValue[j++] = _yBytes[i];\n }\n\n return string(_newValue);\n }\n\n function char(bytes1 b) internal pure returns (bytes1 c) {\n if (uint8(b) < 10) {\n c = bytes1(uint8(b) + 0x30);\n } else {\n c = bytes1(uint8(b) + 0x57);\n }\n }\n\n function compareStrings(string memory a, string memory b)\n internal\n pure\n returns (bool)\n {\n return (keccak256(abi.encodePacked((a))) ==\n keccak256(abi.encodePacked((b))));\n }\n\n function _toLower(string memory str) internal pure returns (string memory) {\n bytes memory bStr = bytes(str);\n bytes memory bLower = new bytes(bStr.length);\n for (uint256 i = 0; i < bStr.length; i++) {\n // Uppercase character...\n if ((uint8(bStr[i]) >= 65) && (uint8(bStr[i]) <= 90)) {\n // So we add 32 to make it lowercase\n bLower[i] = bytes1(uint8(bStr[i]) + 32);\n } else {\n bLower[i] = bStr[i];\n }\n }\n return string(bLower);\n }\n}\n" + }, + "contracts/bridge/mocks/ERC20Mock.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.6.12;\n\nimport \"@openzeppelin/contracts/token/ERC20/ERC20.sol\";\n\ncontract ERC20Mock is ERC20 {\n constructor(\n string memory name,\n string memory symbol,\n uint256 supply\n ) public ERC20(name, symbol) {\n _mint(msg.sender, supply);\n }\n\n function mint(address to, uint256 amount) external {\n _mint(to, amount);\n }\n}" + }, + "contracts/bridge/interfaces/IMetaSwapDeposit.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.6.12;\nimport '@openzeppelin/contracts/token/ERC20/ERC20.sol';\n\n/**\n * @title IMetaSwapDeposit interface\n * @notice Interface for the meta swap contract.\n * @dev implement this interface to develop a a factory-patterned ECDSA node management contract\n **/\ninterface IMetaSwapDeposit {\n // min return calculation functions\n function calculateSwap(\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx\n ) external view returns (uint256);\n\n function swap(\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx,\n uint256 minDy,\n uint256 deadline\n ) external returns (uint256);\n\n function getToken(uint256 index) external view returns (IERC20);\n}\n" + }, + "contracts/amm/interfaces/IMetaSwapDeposit.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.6.12;\n\nimport \"@openzeppelin/contracts/token/ERC20/ERC20.sol\";\nimport \"./ISwap.sol\";\nimport \"./IMetaSwap.sol\";\n\ninterface IMetaSwapDeposit {\n function initialize(\n ISwap baseSwap_,\n IMetaSwap metaSwap_,\n IERC20 metaLPToken_\n ) external;\n}\n" + }, + "contracts/amm/interfaces/IMetaSwap.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.6.12;\n\nimport \"@openzeppelin/contracts/token/ERC20/ERC20.sol\";\n\ninterface IMetaSwap {\n // pool data view functions\n function getA() external view returns (uint256);\n\n function getToken(uint8 index) external view returns (IERC20);\n\n function getTokenIndex(address tokenAddress) external view returns (uint8);\n\n function getTokenBalance(uint8 index) external view returns (uint256);\n\n function getVirtualPrice() external view returns (uint256);\n\n function isGuarded() external view returns (bool);\n\n // min return calculation functions\n function calculateSwap(\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx\n ) external view returns (uint256);\n\n function calculateSwapUnderlying(\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx\n ) external view returns (uint256);\n\n function calculateTokenAmount(uint256[] calldata amounts, bool deposit)\n external\n view\n returns (uint256);\n\n function calculateRemoveLiquidity(uint256 amount)\n external\n view\n returns (uint256[] memory);\n\n function calculateRemoveLiquidityOneToken(\n uint256 tokenAmount,\n uint8 tokenIndex\n ) external view returns (uint256 availableTokenAmount);\n\n // state modifying functions\n function initializeMetaSwap(\n IERC20[] memory pooledTokens,\n uint8[] memory decimals,\n string memory lpTokenName,\n string memory lpTokenSymbol,\n uint256 a,\n uint256 fee,\n uint256 adminFee,\n address lpTokenTargetAddress,\n address baseSwap\n ) external;\n\n function swap(\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx,\n uint256 minDy,\n uint256 deadline\n ) external returns (uint256);\n\n function swapUnderlying(\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx,\n uint256 minDy,\n uint256 deadline\n ) external returns (uint256);\n\n function addLiquidity(\n uint256[] calldata amounts,\n uint256 minToMint,\n uint256 deadline\n ) external returns (uint256);\n\n function removeLiquidity(\n uint256 amount,\n uint256[] calldata minAmounts,\n uint256 deadline\n ) external returns (uint256[] memory);\n\n function removeLiquidityOneToken(\n uint256 tokenAmount,\n uint8 tokenIndex,\n uint256 minAmount,\n uint256 deadline\n ) external returns (uint256);\n\n function removeLiquidityImbalance(\n uint256[] calldata amounts,\n uint256 maxBurnAmount,\n uint256 deadline\n ) external returns (uint256);\n\n function swapStorage()\n external\n view\n returns (\n uint256 initialA,\n uint256 futureA,\n uint256 initialATime,\n uint256 futureATime,\n uint256 swapFee,\n uint256 adminFee,\n address lpToken\n );\n}\n" + }, + "contracts/amm/helper/GenericERC20.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.6.12;\n\nimport \"@openzeppelin/contracts/token/ERC20/ERC20.sol\";\nimport \"@openzeppelin/contracts/access/Ownable.sol\";\n\n/**\n * @title Generic ERC20 token\n * @notice This contract simulates a generic ERC20 token that is mintable and burnable.\n */\ncontract GenericERC20 is ERC20, Ownable {\n /**\n * @notice Deploy this contract with given name, symbol, and decimals\n * @dev the caller of this constructor will become the owner of this contract\n * @param name_ name of this token\n * @param symbol_ symbol of this token\n * @param decimals_ number of decimals this token will be based on\n */\n constructor(\n string memory name_,\n string memory symbol_,\n uint8 decimals_\n ) public ERC20(name_, symbol_) {\n _setupDecimals(decimals_);\n }\n\n /**\n * @notice Mints given amount of tokens to recipient\n * @dev only owner can call this mint function\n * @param recipient address of account to receive the tokens\n * @param amount amount of tokens to mint\n */\n function mint(address recipient, uint256 amount) external onlyOwner {\n require(amount != 0, \"amount == 0\");\n _mint(recipient, amount);\n }\n}\n" + }, + "contracts/amm/SwapEthWrapper.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.6.12;\n\nimport \"@openzeppelin/contracts/math/SafeMath.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/SafeERC20.sol\";\nimport \"./Swap.sol\";\nimport \"./interfaces/IWETH9.sol\";\n\n/**\n * @title SwapEthWrapper\n * @notice A wrapper contract for Swap contracts that have WETH as one of the pooled tokens.\n * @author Jongseung Lim (@weeb_mcgee)\n */\ncontract SwapEthWrapper {\n using SafeERC20 for IERC20;\n using SafeMath for uint256;\n\n // constants\n uint8 private constant MAX_UINT8 = 2**8 - 1;\n uint256 private constant MAX_UINT256 = 2**256 - 1;\n\n // immutables\n Swap public immutable SWAP;\n LPToken public immutable LP_TOKEN;\n address payable public immutable WETH_ADDRESS;\n address public immutable OWNER;\n uint8 public immutable WETH_INDEX;\n\n IERC20[] public pooledTokens;\n\n /**\n * @notice Deploys this contract with given WETH9 address and Swap address. It will attempt to\n * fetch information about the given Swap pool. If the Swap pool does not contain WETH9,\n * this call will be reverted. Owner address must be given so that `rescue()` function\n * can be limited.\n * @param wethAddress address to the WETH9 contract\n * @param swap address to the Swap contract that has WETH9 as one of the tokens\n * @param owner address that will be allowed to call `rescue()`\n */\n constructor(\n address payable wethAddress,\n Swap swap,\n address owner\n ) public {\n (, , , , , , LPToken lpToken) = swap.swapStorage();\n uint8 wethIndex = MAX_UINT8;\n\n for (uint8 i = 0; i < MAX_UINT8; i++) {\n try swap.getToken(i) returns (IERC20 token) {\n pooledTokens.push(token);\n if (address(token) == wethAddress) {\n wethIndex = i;\n }\n // Approve pooled tokens to be used by Swap\n token.approve(address(swap), MAX_UINT256);\n } catch {\n break;\n }\n }\n require(wethIndex != MAX_UINT8, \"WETH was not found in the swap pool\");\n\n // Set immutable variables\n WETH_INDEX = wethIndex;\n WETH_ADDRESS = wethAddress;\n SWAP = swap;\n LP_TOKEN = lpToken;\n OWNER = owner;\n\n // Approve LPToken to be used by Swap\n lpToken.approve(address(swap), MAX_UINT256);\n }\n\n /**\n * @notice Add liquidity to the pool with the given amounts of tokens.\n * @dev The msg.value of this call should match the value in amounts array\n * in position of WETH9.\n * @param amounts the amounts of each token to add, in their native precision\n * @param minToMint the minimum LP tokens adding this amount of liquidity\n * should mint, otherwise revert. Handy for front-running mitigation\n * @param deadline latest timestamp to accept this transaction\n * @return amount of LP token user minted and received\n */\n function addLiquidity(\n uint256[] memory amounts,\n uint256 minToMint,\n uint256 deadline\n ) external payable returns (uint256) {\n // If using ETH, deposit them to WETH.\n require(msg.value == amounts[WETH_INDEX], \"INCORRECT_MSG_VALUE\");\n if (msg.value > 0) {\n IWETH9(WETH_ADDRESS).deposit{value: msg.value}();\n }\n // Go through amounts array and transfer respective tokens to this contract.\n for (uint256 i = 0; i < amounts.length; i++) {\n uint256 amount = amounts[i];\n if (i != WETH_INDEX && amount > 0) {\n pooledTokens[i].safeTransferFrom(\n msg.sender,\n address(this),\n amount\n );\n }\n }\n // Add the assets to the pool\n uint256 lpTokenAmount = SWAP.addLiquidity(amounts, minToMint, deadline);\n // Send the LPToken to msg.sender\n IERC20(address(LP_TOKEN)).safeTransfer(msg.sender, lpTokenAmount);\n return lpTokenAmount;\n }\n\n /**\n * @notice Burn LP tokens to remove liquidity from the pool.\n * @dev Liquidity can always be removed, even when the pool is paused. Caller\n * will receive ETH instead of WETH9.\n * @param amount the amount of LP tokens to burn\n * @param minAmounts the minimum amounts of each token in the pool\n * acceptable for this burn. Useful as a front-running mitigation\n * @param deadline latest timestamp to accept this transaction\n * @return amounts of tokens user received\n */\n function removeLiquidity(\n uint256 amount,\n uint256[] calldata minAmounts,\n uint256 deadline\n ) external returns (uint256[] memory) {\n // Transfer LPToken from msg.sender to this contract.\n IERC20(address(LP_TOKEN)).safeTransferFrom(\n msg.sender,\n address(this),\n amount\n );\n // Remove liquidity\n uint256[] memory amounts = SWAP.removeLiquidity(\n amount,\n minAmounts,\n deadline\n );\n // Send the tokens back to the user\n for (uint256 i = 0; i < amounts.length; i++) {\n if (i != WETH_INDEX) {\n pooledTokens[i].safeTransfer(msg.sender, amounts[i]);\n } else {\n IWETH9(WETH_ADDRESS).withdraw(amounts[i]);\n // slither-disable-next-line arbitrary-send\n (bool success, ) = msg.sender.call{value: amounts[i]}(\"\");\n require(success, \"ETH_TRANSFER_FAILED\");\n }\n }\n return amounts;\n }\n\n /**\n * @notice Remove liquidity from the pool all in one token.\n * @dev Caller will receive ETH instead of WETH9.\n * @param tokenAmount the amount of the token you want to receive\n * @param tokenIndex the index of the token you want to receive\n * @param minAmount the minimum amount to withdraw, otherwise revert\n * @param deadline latest timestamp to accept this transaction\n * @return amount of chosen token user received\n */\n function removeLiquidityOneToken(\n uint256 tokenAmount,\n uint8 tokenIndex,\n uint256 minAmount,\n uint256 deadline\n ) external returns (uint256) {\n // Transfer LPToken from msg.sender to this contract.\n IERC20(address(LP_TOKEN)).safeTransferFrom(\n msg.sender,\n address(this),\n tokenAmount\n );\n // Withdraw via single token\n uint256 amount = SWAP.removeLiquidityOneToken(\n tokenAmount,\n tokenIndex,\n minAmount,\n deadline\n );\n // Transfer the token to msg.sender accordingly\n if (tokenIndex != WETH_INDEX) {\n pooledTokens[tokenIndex].safeTransfer(msg.sender, amount);\n } else {\n IWETH9(WETH_ADDRESS).withdraw(amount);\n // slither-disable-next-line arbitrary-send\n (bool success, ) = msg.sender.call{value: amount}(\"\");\n require(success, \"ETH_TRANSFER_FAILED\");\n }\n return amount;\n }\n\n /**\n * @notice Remove liquidity from the pool, weighted differently than the\n * pool's current balances.\n * @dev Caller will receive ETH instead of WETH9.\n * @param amounts how much of each token to withdraw\n * @param maxBurnAmount the max LP token provider is willing to pay to\n * remove liquidity. Useful as a front-running mitigation.\n * @param deadline latest timestamp to accept this transaction\n * @return amount of LP tokens burned\n */\n function removeLiquidityImbalance(\n uint256[] calldata amounts,\n uint256 maxBurnAmount,\n uint256 deadline\n ) external returns (uint256) {\n // Transfer LPToken from msg.sender to this contract.\n IERC20(address(LP_TOKEN)).safeTransferFrom(\n msg.sender,\n address(this),\n maxBurnAmount\n );\n // Withdraw in imbalanced ratio\n uint256 burnedLpTokenAmount = SWAP.removeLiquidityImbalance(\n amounts,\n maxBurnAmount,\n deadline\n );\n // Send the tokens back to the user\n for (uint256 i = 0; i < amounts.length; i++) {\n if (i != WETH_INDEX) {\n pooledTokens[i].safeTransfer(msg.sender, amounts[i]);\n } else {\n IWETH9(WETH_ADDRESS).withdraw(amounts[i]);\n // slither-disable-next-line arbitrary-send\n (bool success, ) = msg.sender.call{value: amounts[i]}(\"\");\n require(success, \"ETH_TRANSFER_FAILED\");\n }\n }\n // Send any extra LP tokens back as well\n uint256 extraLpTokenAmount = maxBurnAmount.sub(burnedLpTokenAmount);\n if (extraLpTokenAmount > 0) {\n IERC20(address(LP_TOKEN)).safeTransfer(\n msg.sender,\n extraLpTokenAmount\n );\n }\n return burnedLpTokenAmount;\n }\n\n /**\n * @notice Swap two tokens using the underlying pool. If tokenIndexFrom\n * represents WETH9 in the pool, the caller must set msg.value equal to dx.\n * If the user is swapping to WETH9 in the pool, the user will receive ETH instead.\n * @param tokenIndexFrom the token the user wants to swap from\n * @param tokenIndexTo the token the user wants to swap to\n * @param dx the amount of tokens the user wants to swap from\n * @param minDy the min amount the user would like to receive, or revert.\n * @param deadline latest timestamp to accept this transaction\n */\n function swap(\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx,\n uint256 minDy,\n uint256 deadline\n ) external payable returns (uint256) {\n // Transfer tokens from msg.sender to this contract\n if (tokenIndexFrom != WETH_INDEX) {\n IERC20(pooledTokens[tokenIndexFrom]).safeTransferFrom(\n msg.sender,\n address(this),\n dx\n );\n } else {\n require(msg.value == dx, \"INCORRECT_MSG_VALUE\");\n IWETH9(WETH_ADDRESS).deposit{value: msg.value}();\n }\n // Execute swap\n uint256 dy = SWAP.swap(\n tokenIndexFrom,\n tokenIndexTo,\n dx,\n minDy,\n deadline\n );\n // Transfer the swapped tokens to msg.sender\n if (tokenIndexTo != WETH_INDEX) {\n IERC20(pooledTokens[tokenIndexTo]).safeTransfer(msg.sender, dy);\n } else {\n IWETH9(WETH_ADDRESS).withdraw(dy);\n // slither-disable-next-line arbitrary-send\n (bool success, ) = msg.sender.call{value: dy}(\"\");\n require(success, \"ETH_TRANSFER_FAILED\");\n }\n return dy;\n }\n\n /**\n * @notice Rescues any of the ETH, the pooled tokens, or the LPToken that may be stuck\n * in this contract. Only the OWNER can call this function.\n */\n function rescue() external {\n require(msg.sender == OWNER, \"CALLED_BY_NON_OWNER\");\n IERC20[] memory tokens = pooledTokens;\n for (uint256 i = 0; i < tokens.length; i++) {\n tokens[i].safeTransfer(\n msg.sender,\n tokens[i].balanceOf(address(this))\n );\n }\n IERC20 lpToken_ = IERC20(address(LP_TOKEN));\n lpToken_.safeTransfer(msg.sender, lpToken_.balanceOf(address(this)));\n // slither-disable-next-line arbitrary-send\n (bool success, ) = msg.sender.call{value: address(this).balance}(\"\");\n require(success, \"ETH_TRANSFER_FAILED\");\n }\n\n receive() external payable {}\n\n // VIEW FUNCTIONS\n\n /**\n * @notice A simple method to calculate prices from deposits or\n * withdrawals, excluding fees but including slippage. This is\n * helpful as an input into the various \"min\" parameters on calls\n * to fight front-running\n *\n * @dev This shouldn't be used outside frontends for user estimates.\n *\n * @param amounts an array of token amounts to deposit or withdrawal,\n * corresponding to pooledTokens. The amount should be in each\n * pooled token's native precision. If a token charges a fee on transfers,\n * use the amount that gets transferred after the fee.\n * @param deposit whether this is a deposit or a withdrawal\n * @return token amount the user will receive\n */\n function calculateTokenAmount(uint256[] calldata amounts, bool deposit)\n external\n view\n returns (uint256)\n {\n return SWAP.calculateTokenAmount(amounts, deposit);\n }\n\n /**\n * @notice A simple method to calculate amount of each underlying\n * tokens that is returned upon burning given amount of LP tokens\n * @param amount the amount of LP tokens that would be burned on withdrawal\n * @return array of token balances that the user will receive\n */\n function calculateRemoveLiquidity(uint256 amount)\n external\n view\n returns (uint256[] memory)\n {\n return SWAP.calculateRemoveLiquidity(amount);\n }\n\n /**\n * @notice Calculate the amount of underlying token available to withdraw\n * when withdrawing via only single token\n * @param tokenAmount the amount of LP token to burn\n * @param tokenIndex index of which token will be withdrawn\n * @return availableTokenAmount calculated amount of underlying token\n * available to withdraw\n */\n function calculateRemoveLiquidityOneToken(\n uint256 tokenAmount,\n uint8 tokenIndex\n ) external view returns (uint256 availableTokenAmount) {\n return SWAP.calculateRemoveLiquidityOneToken(tokenAmount, tokenIndex);\n }\n}\n" + }, + "contracts/amm/interfaces/IWETH9.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.4.0;\n\ninterface IWETH9 {\n function name() external view returns (string memory);\n\n function symbol() external view returns (string memory);\n\n function decimals() external view returns (uint8);\n\n function balanceOf(address) external view returns (uint256);\n\n function allowance(address, address) external view returns (uint256);\n\n receive() external payable;\n\n function deposit() external payable;\n\n function withdraw(uint256 wad) external;\n\n function totalSupply() external view returns (uint256);\n\n function approve(address guy, uint256 wad) external returns (bool);\n\n function transfer(address dst, uint256 wad) external returns (bool);\n\n function transferFrom(\n address src,\n address dst,\n uint256 wad\n ) external returns (bool);\n}\n" + }, + "contracts/amm/helper/BaseSwapDeposit.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.6.12;\n\nimport \"@openzeppelin/contracts/math/SafeMath.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/SafeERC20.sol\";\nimport \"../interfaces/ISwap.sol\";\nimport \"@openzeppelin/contracts/utils/ReentrancyGuard.sol\";\n\ncontract BaseSwapDeposit is ReentrancyGuard {\n using SafeERC20 for IERC20;\n using SafeMath for uint256;\n\n ISwap public baseSwap;\n IERC20[] public baseTokens;\n\n uint256 constant MAX_UINT256 = 2**256 - 1;\n\n constructor(ISwap _baseSwap) public {\n baseSwap = _baseSwap;\n // Check and approve base level tokens to be deposited to the base Swap contract\n {\n uint8 i;\n for (; i < 32; i++) {\n try _baseSwap.getToken(i) returns (IERC20 token) {\n baseTokens.push(token);\n token.safeApprove(address(_baseSwap), MAX_UINT256);\n } catch {\n break;\n }\n }\n require(i > 1, \"baseSwap must have at least 2 tokens\");\n }\n }\n\n // Mutative functions\n\n /**\n * @notice Swap two underlying tokens using the meta pool and the base pool\n * @param tokenIndexFrom the token the user wants to swap from\n * @param tokenIndexTo the token the user wants to swap to\n * @param dx the amount of tokens the user wants to swap from\n * @param minDy the min amount the user would like to receive, or revert.\n * @param deadline latest timestamp to accept this transaction\n */\n function swap(\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx,\n uint256 minDy,\n uint256 deadline\n ) external nonReentrant returns (uint256) {\n baseTokens[tokenIndexFrom].safeTransferFrom(msg.sender, address(this), dx);\n uint256 tokenToAmount =\n baseSwap.swap(\n tokenIndexFrom,\n tokenIndexTo,\n dx,\n minDy,\n deadline\n );\n baseTokens[tokenIndexTo].safeTransfer(msg.sender, tokenToAmount);\n return tokenToAmount;\n }\n\n /**\n * @notice Calculate amount of tokens you receive on swap\n * @param tokenIndexFrom the token the user wants to sell\n * @param tokenIndexTo the token the user wants to buy\n * @param dx the amount of tokens the user wants to sell. If the token charges\n * a fee on transfers, use the amount that gets transferred after the fee.\n * @return amount of tokens the user will receive\n */\n function calculateSwap(\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx\n ) external view returns (uint256) {\n return\n baseSwap.calculateSwap(tokenIndexFrom, tokenIndexTo, dx);\n }\n\n /**\n * @notice Returns the address of the pooled token at given index. Reverts if tokenIndex is out of range.\n * @param index the index of the token\n * @return address of the token at given index\n */\n function getToken(uint256 index) external view returns (IERC20) {\n require(index < baseTokens.length, \"index out of range\");\n return baseTokens[index];\n }\n\n}" + }, + "@openzeppelin/contracts/utils/ReentrancyGuard.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <0.8.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 () internal {\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" + }, + "contracts/amm/AaveSwapWrapper.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.6.12;\n\nimport \"@openzeppelin/contracts/math/SafeMath.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/SafeERC20.sol\";\nimport \"./Swap.sol\";\n\ninterface ILendingPool {\n /**\n * @dev Deposits an `amount` of underlying asset into the reserve, receiving in return overlying aTokens.\n * - E.g. User deposits 100 USDC and gets in return 100 aUSDC\n * @param asset The address of the underlying asset to deposit\n * @param amount The amount to be deposited\n * @param onBehalfOf The address that will receive the aTokens, same as msg.sender if the user\n * wants to receive them on his own wallet, or a different address if the beneficiary of aTokens\n * is a different wallet\n * @param referralCode Code used to register the integrator originating the operation, for potential rewards.\n * 0 if the action is executed directly by the user, without any middle-man\n **/\n function deposit(\n address asset,\n uint256 amount,\n address onBehalfOf,\n uint16 referralCode\n ) external;\n\n /**\n * @dev Withdraws an `amount` of underlying asset from the reserve, burning the equivalent aTokens owned\n * E.g. User has 100 aUSDC, calls withdraw() and receives 100 USDC, burning the 100 aUSDC\n * @param asset The address of the underlying asset to withdraw\n * @param amount The underlying amount to be withdrawn\n * - Send the value type(uint256).max in order to withdraw the whole aToken balance\n * @param to Address that will receive the underlying, same as msg.sender if the user\n * wants to receive it on his own wallet, or a different address if the beneficiary is a\n * different wallet\n * @return The final amount withdrawn\n **/\n function withdraw(\n address asset,\n uint256 amount,\n address to\n ) external returns (uint256);\n}\n\n/**\n * @title AaveSwapWrapper\n * @notice A wrapper contract for interacting with aTokens\n */\ncontract AaveSwapWrapper {\n using SafeERC20 for IERC20;\n using SafeMath for uint256;\n mapping(uint8 => bool) private isUnderlyingIndex;\n\n // constants\n uint8 private constant MAX_UINT8 = 2**8 - 1;\n uint256 private constant MAX_UINT256 = 2**256 - 1;\n\n // immutables\n Swap public immutable SWAP;\n LPToken public immutable LP_TOKEN;\n address public immutable OWNER;\n IERC20[] public POOLED_TOKENS;\n IERC20[] public UNDERLYING_TOKENS;\n ILendingPool public LENDING_POOL;\n\n constructor(\n Swap swap,\n IERC20[] memory underlyingTokens,\n address lendingPool,\n address owner\n ) public {\n (, , , , , , LPToken lpToken) = swap.swapStorage();\n for (uint8 i = 0; i < MAX_UINT8; i++) {\n try swap.getToken(i) returns (IERC20 token) {\n POOLED_TOKENS.push(token);\n // Approve pooled tokens to be used by Swap\n token.approve(address(swap), MAX_UINT256);\n } catch {\n break;\n }\n }\n\n for (uint8 i = 0; i < POOLED_TOKENS.length; i++) {\n if (POOLED_TOKENS[i] == underlyingTokens[i]) {\n isUnderlyingIndex[i] = true;\n } else {\n isUnderlyingIndex[i] = false;\n underlyingTokens[i].approve(lendingPool, MAX_UINT256);\n }\n }\n\n // Set immutable variables\n SWAP = swap;\n LP_TOKEN = lpToken;\n OWNER = owner;\n UNDERLYING_TOKENS = underlyingTokens;\n LENDING_POOL = ILendingPool(lendingPool);\n\n // Approve LPToken to be used by Swap\n lpToken.approve(address(swap), MAX_UINT256);\n }\n\n /**\n * @notice Add liquidity to the pool with the given amounts of tokens.\n * @param amounts the amounts of each token to add, in their native precision\n * @param minToMint the minimum LP tokens adding this amount of liquidity\n * should mint, otherwise revert. Handy for front-running mitigation\n * @param deadline latest timestamp to accept this transaction\n * @return amount of LP token user minted and received\n */\n function addLiquidity(\n uint256[] memory amounts,\n uint256 minToMint,\n uint256 deadline\n ) external returns (uint256) {\n // Go through amounts array and transfer respective tokens to this contract.\n for (uint8 i = 0; i < amounts.length; i++) {\n uint256 amount = amounts[i];\n if (amount > 0) {\n UNDERLYING_TOKENS[i].safeTransferFrom(\n msg.sender,\n address(this),\n amount\n );\n if (isUnderlyingIndex[i] == false) {\n LENDING_POOL.deposit(\n address(UNDERLYING_TOKENS[i]),\n amount,\n address(this),\n 0\n );\n }\n }\n }\n\n // Add the assets to the pool\n uint256 lpTokenAmount = SWAP.addLiquidity(amounts, minToMint, deadline);\n // Send the LPToken to msg.sender\n IERC20(address(LP_TOKEN)).safeTransfer(msg.sender, lpTokenAmount);\n return lpTokenAmount;\n }\n\n /**\n * @notice Burn LP tokens to remove liquidity from the pool.\n * @dev Liquidity can always be removed, even when the pool is paused. Caller\n * will receive ETH instead of WETH9.\n * @param amount the amount of LP tokens to burn\n * @param minAmounts the minimum amounts of each token in the pool\n * acceptable for this burn. Useful as a front-running mitigation\n * @param deadline latest timestamp to accept this transaction\n * @return amounts of tokens user received\n */\n function removeLiquidity(\n uint256 amount,\n uint256[] calldata minAmounts,\n uint256 deadline\n ) external returns (uint256[] memory) {\n // Transfer LPToken from msg.sender to this contract.\n IERC20(address(LP_TOKEN)).safeTransferFrom(\n msg.sender,\n address(this),\n amount\n );\n // Remove liquidity\n uint256[] memory amounts = SWAP.removeLiquidity(\n amount,\n minAmounts,\n deadline\n );\n // Send the tokens back to the user\n for (uint8 i = 0; i < amounts.length; i++) {\n if (isUnderlyingIndex[i] == true) {\n UNDERLYING_TOKENS[i].safeTransfer(msg.sender, amounts[i]);\n } else {\n LENDING_POOL.withdraw(\n address(UNDERLYING_TOKENS[i]),\n amounts[i],\n msg.sender\n );\n // underlyingTokens[i].safeTransfer(msg.sender, amounts[i]);\n }\n }\n return amounts;\n }\n\n /**\n * @notice Remove liquidity from the pool all in one token.\n * @dev Caller will receive ETH instead of WETH9.\n * @param tokenAmount the amount of the token you want to receive\n * @param tokenIndex the index of the token you want to receive\n * @param minAmount the minimum amount to withdraw, otherwise revert\n * @param deadline latest timestamp to accept this transaction\n * @return amount of chosen token user received\n */\n function removeLiquidityOneToken(\n uint256 tokenAmount,\n uint8 tokenIndex,\n uint256 minAmount,\n uint256 deadline\n ) external returns (uint256) {\n // Transfer LPToken from msg.sender to this contract.\n IERC20(address(LP_TOKEN)).safeTransferFrom(\n msg.sender,\n address(this),\n tokenAmount\n );\n // Withdraw via single token\n uint256 amount = SWAP.removeLiquidityOneToken(\n tokenAmount,\n tokenIndex,\n minAmount,\n deadline\n );\n // Transfer the token to msg.sender accordingly\n if (isUnderlyingIndex[tokenIndex] == true) {\n UNDERLYING_TOKENS[tokenIndex].safeTransfer(msg.sender, amount);\n } else {\n LENDING_POOL.withdraw(\n address(UNDERLYING_TOKENS[tokenIndex]),\n amount,\n msg.sender\n );\n }\n return amount;\n }\n\n /**\n * @notice Swap two tokens using the underlying pool. If tokenIndexFrom\n * represents WETH9 in the pool, the caller must set msg.value equal to dx.\n * If the user is swapping to WETH9 in the pool, the user will receive ETH instead.\n * @param tokenIndexFrom the token the user wants to swap from\n * @param tokenIndexTo the token the user wants to swap to\n * @param dx the amount of tokens the user wants to swap from\n * @param minDy the min amount the user would like to receive, or revert.\n * @param deadline latest timestamp to accept this transaction\n */\n function swap(\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx,\n uint256 minDy,\n uint256 deadline\n ) external returns (uint256) {\n // Transfer tokens from msg.sender to this contract\n UNDERLYING_TOKENS[tokenIndexFrom].safeTransferFrom(\n msg.sender,\n address(this),\n dx\n );\n if (isUnderlyingIndex[tokenIndexFrom] == false) {\n LENDING_POOL.deposit(\n address(UNDERLYING_TOKENS[tokenIndexFrom]),\n dx,\n address(this),\n 0\n );\n }\n // Execute swap\n uint256 dy = SWAP.swap(\n tokenIndexFrom,\n tokenIndexTo,\n dx,\n minDy,\n deadline\n );\n // Transfer the swapped tokens to msg.sender\n if (isUnderlyingIndex[tokenIndexTo] == false) {\n LENDING_POOL.withdraw(\n address(UNDERLYING_TOKENS[tokenIndexTo]),\n dy,\n msg.sender\n );\n } else {\n UNDERLYING_TOKENS[tokenIndexTo].safeTransfer(msg.sender, dy);\n }\n return dy;\n }\n\n /**\n * @notice Rescues any of the ETH, the pooled tokens, or the LPToken that may be stuck\n * in this contract. Only the OWNER can call this function.\n */\n function rescue() external {\n require(msg.sender == OWNER, \"CALLED_BY_NON_OWNER\");\n IERC20[] memory tokens = POOLED_TOKENS;\n for (uint256 i = 0; i < tokens.length; i++) {\n tokens[i].safeTransfer(\n msg.sender,\n tokens[i].balanceOf(address(this))\n );\n }\n\n for (uint256 i = 0; i < UNDERLYING_TOKENS.length; i++) {\n UNDERLYING_TOKENS[i].safeTransfer(\n msg.sender,\n UNDERLYING_TOKENS[i].balanceOf(address(this))\n );\n }\n\n IERC20 lpToken_ = IERC20(address(LP_TOKEN));\n lpToken_.safeTransfer(msg.sender, lpToken_.balanceOf(address(this)));\n }\n\n // VIEW FUNCTIONS\n\n /**\n * @notice Calculate amount of tokens you receive on swap\n * @param tokenIndexFrom the token the user wants to sell\n * @param tokenIndexTo the token the user wants to buy\n * @param dx the amount of tokens the user wants to sell. If the token charges\n * a fee on transfers, use the amount that gets transferred after the fee.\n * @return amount of tokens the user will receive\n */\n function calculateSwap(\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx\n ) external view virtual returns (uint256) {\n return SWAP.calculateSwap(tokenIndexFrom, tokenIndexTo, dx);\n }\n\n /**\n * @notice A simple method to calculate prices from deposits or\n * withdrawals, excluding fees but including slippage. This is\n * helpful as an input into the various \"min\" parameters on calls\n * to fight front-running\n *\n * @dev This shouldn't be used outside frontends for user estimates.\n *\n * @param amounts an array of token amounts to deposit or withdrawal,\n * corresponding to pooledTokens. The amount should be in each\n * pooled token's native precision. If a token charges a fee on transfers,\n * use the amount that gets transferred after the fee.\n * @param deposit whether this is a deposit or a withdrawal\n * @return token amount the user will receive\n */\n function calculateTokenAmount(uint256[] calldata amounts, bool deposit)\n external\n view\n returns (uint256)\n {\n return SWAP.calculateTokenAmount(amounts, deposit);\n }\n\n /**\n * @notice A simple method to calculate amount of each underlying\n * tokens that is returned upon burning given amount of LP tokens\n * @param amount the amount of LP tokens that would be burned on withdrawal\n * @return array of token balances that the user will receive\n */\n function calculateRemoveLiquidity(uint256 amount)\n external\n view\n returns (uint256[] memory)\n {\n return SWAP.calculateRemoveLiquidity(amount);\n }\n\n /**\n * @notice Calculate the amount of underlying token available to withdraw\n * when withdrawing via only single token\n * @param tokenAmount the amount of LP token to burn\n * @param tokenIndex index of which token will be withdrawn\n * @return availableTokenAmount calculated amount of underlying token\n * available to withdraw\n */\n function calculateRemoveLiquidityOneToken(\n uint256 tokenAmount,\n uint8 tokenIndex\n ) external view returns (uint256 availableTokenAmount) {\n return SWAP.calculateRemoveLiquidityOneToken(tokenAmount, tokenIndex);\n }\n\n /**\n * @notice Return address of the pooled token at given index. Reverts if tokenIndex is out of range.\n * @param index the index of the token\n * @return address of the token at given index\n */\n function getToken(uint8 index) public view virtual returns (IERC20) {\n if (index < UNDERLYING_TOKENS.length) {\n return UNDERLYING_TOKENS[index];\n } else {\n revert();\n }\n }\n}\n" + }, + "contracts/bridge/ECDSAFactory.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.6.12;\n\nimport \"@openzeppelin/contracts/access/Ownable.sol\";\nimport \"@openzeppelin/contracts/proxy/Clones.sol\";\nimport \"./interfaces/IECDSANodeManagement.sol\";\n\ncontract ECDSAFactory is Ownable {\n event ECDSANodeGroupCreated(\n address indexed keepAddress,\n address[] members,\n address indexed owner,\n uint256 honestThreshold\n );\n\n struct LatestNodeGroup {\n address keepAddress;\n address[] members;\n address owner;\n uint256 honestThreshold;\n }\n\n LatestNodeGroup public latestNodeGroup;\n\n constructor() public Ownable() {}\n\n /// @notice Returns members of the keep.\n /// @return List of the keep members' addresses.\n function getMembers() public view returns (address[] memory) {\n return latestNodeGroup.members;\n }\n\n /**\n @notice Deploys a new node \n @param nodeMgmtAddress address of the ECDSANodeManagement contract to initialize with\n @param owner Owner of the ECDSANodeManagement contract who can determine if the node group is closed or active\n @param members Array of node group members addresses\n @param honestThreshold Number of signers to process a transaction \n @return Address of the newest node management contract created\n **/\n function deploy(\n address nodeMgmtAddress,\n address owner,\n address[] memory members,\n uint256 honestThreshold\n ) external onlyOwner returns (address) {\n address nodeClone = Clones.clone(nodeMgmtAddress);\n IECDSANodeManagement(nodeClone).initialize(\n owner,\n members,\n honestThreshold\n );\n\n latestNodeGroup.keepAddress = nodeClone;\n latestNodeGroup.members = members;\n latestNodeGroup.owner = owner;\n latestNodeGroup.honestThreshold = honestThreshold;\n\n emit ECDSANodeGroupCreated(nodeClone, members, owner, honestThreshold);\n return nodeClone;\n }\n}\n" + }, + "contracts/bridge/interfaces/IECDSANodeManagement.sol": { + "content": "// SPDX-License-Identifier: MIT\n\n\npragma solidity 0.6.12;\n\n/**\n * @title IECDSANodeManagement interface\n * @notice Interface for the ECDSA node management interface.\n * @dev implement this interface to develop a a factory-patterned ECDSA node management contract\n **/\ninterface IECDSANodeManagement { \n function initialize(\n address _owner,\n address[] memory _members,\n uint256 _honestThreshold) external;\n}\n\n" + }, + "contracts/auxiliary/DummyWeth.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.6.12;\nimport \"@openzeppelin/contracts/access/Ownable.sol\";\n\ninterface IWETH9 {\n function name() external view returns (string memory);\n\n function symbol() external view returns (string memory);\n\n function decimals() external view returns (uint8);\n\n function balanceOf(address) external view returns (uint256);\n\n function allowance(address, address) external view returns (uint256);\n\n receive() external payable;\n\n function deposit() external payable;\n\n function withdraw(uint256 wad) external;\n\n function totalSupply() external view returns (uint256);\n\n function approve(address guy, uint256 wad) external returns (bool);\n\n function transfer(address dst, uint256 wad) external returns (bool);\n\n function transferFrom(\n address src,\n address dst,\n uint256 wad\n ) external returns (bool);\n}\n\ncontract DummyWeth is Ownable {\n IWETH9 public WETH;\n\n function setWETHAddress(address payable _weth) external onlyOwner {\n WETH = IWETH9(_weth);\n }\n\n function withdrawToSelf(uint256 amount) external {\n WETH.withdraw(amount);\n }\n\n function rescue(uint256 amount) external onlyOwner {\n WETH.transfer(owner(), amount);\n }\n\n receive() external payable {}\n\n fallback() external payable {}\n}\n" + } + }, + "settings": { + "optimizer": { + "enabled": true, + "runs": 10000 + }, + "outputSelection": { + "*": { + "*": [ + "abi", + "evm.bytecode", + "evm.deployedBytecode", + "evm.methodIdentifiers", + "metadata", + "devdoc", + "userdoc", + "storageLayout", + "evm.gasEstimates", + "devdoc", + "userdoc" + ], + "": [ + "ast" + ] + } + }, + "metadata": { + "useLiteralContent": true + } + } +} \ No newline at end of file diff --git a/deployments/optimism/solcInputs/e661cf0d58b25467456dc889376e25c1.json b/deployments/optimism/solcInputs/e661cf0d58b25467456dc889376e25c1.json new file mode 100644 index 000000000..a5cc3c162 --- /dev/null +++ b/deployments/optimism/solcInputs/e661cf0d58b25467456dc889376e25c1.json @@ -0,0 +1,301 @@ +{ + "language": "Solidity", + "sources": { + "contracts/amm/AaveSwap.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.6.12;\n\nimport \"./Swap.sol\";\n\n/**\n * @title AaveSwap - A StableSwap implementation in solidity, integrated with Aave.\n * @notice This contract is responsible for custody of closely pegged assets (eg. group of stablecoins)\n * and automatic market making system. Users become an LP (Liquidity Provider) by depositing their tokens\n * in desired ratios for an exchange of the pool token that represents their share of the pool.\n * Users can burn pool tokens and withdraw their share of token(s).\n *\n * Each time a swap between the pooled tokens happens, a set fee incurs which effectively gets\n * distributed to the LPs.\n *\n * In case of emergencies, admin can pause additional deposits, swaps, or single-asset withdraws - which\n * stops the ratio of the tokens in the pool from changing.\n * Users can always withdraw their tokens via multi-asset withdraws.\n *\n * @dev Most of the logic is stored as a library `SwapUtils` for the sake of reducing contract's\n * deployment size.\n */\n\ncontract AaveSwap is Swap {\n address internal AAVE_REWARDS;\n address internal AAVE_LENDING_POOL;\n address internal REWARD_TOKEN;\n address internal REWARD_RECEIVER;\n address[] internal AAVE_ASSETS;\n\n /**\n * @notice Initializes this Swap contract with the given parameters.\n * This will also clone a LPToken contract that represents users'\n * LP positions. The owner of LPToken will be this contract - which means\n * only this contract is allowed to mint/burn tokens.\n *\n * @param _pooledTokens an array of ERC20s this pool will accept\n * @param decimals the decimals to use for each pooled token,\n * eg 8 for WBTC. Cannot be larger than POOL_PRECISION_DECIMALS\n * @param lpTokenName the long-form name of the token to be deployed\n * @param lpTokenSymbol the short symbol for the token to be deployed\n * @param _a the amplification coefficient * n * (n - 1). See the\n * StableSwap paper for details\n * @param _fee default swap fee to be initialized with\n * @param _adminFee default adminFee to be initialized with\n * @param lpTokenTargetAddress the address of an existing LPToken contract to use as a target\n */\n function initialize(\n IERC20[] memory _pooledTokens,\n uint8[] memory decimals,\n string memory lpTokenName,\n string memory lpTokenSymbol,\n uint256 _a,\n uint256 _fee,\n uint256 _adminFee,\n address lpTokenTargetAddress\n ) public virtual override initializer {\n Swap.initialize(\n _pooledTokens,\n decimals,\n lpTokenName,\n lpTokenSymbol,\n _a,\n _fee,\n _adminFee,\n lpTokenTargetAddress\n );\n AAVE_REWARDS = 0x01D83Fe6A10D2f2B7AF17034343746188272cAc9;\n AAVE_LENDING_POOL = 0x4F01AeD16D97E3aB5ab2B501154DC9bb0F1A5A2C;\n REWARD_TOKEN = 0xB31f66AA3C1e785363F0875A1B74E27b85FD66c7;\n AAVE_ASSETS = [0x53f7c5869a859F0AeC3D334ee8B4Cf01E3492f21];\n REWARD_RECEIVER = msg.sender;\n }\n\n function setRewardReceiver(address _reward_receiver) external onlyOwner {\n REWARD_RECEIVER = _reward_receiver;\n }\n\n function claimAaveRewards() external {\n AAVE_REWARDS.call(\n abi.encodeWithSignature(\n \"claimRewards(address[],uint256,address)\",\n AAVE_ASSETS,\n type(uint256).max,\n REWARD_RECEIVER\n )\n );\n }\n}\n" + }, + "contracts/amm/Swap.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.6.12;\n\nimport \"@openzeppelin/contracts/math/SafeMath.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/SafeERC20.sol\";\nimport \"@openzeppelin/contracts/proxy/Clones.sol\";\nimport \"@openzeppelin/contracts-upgradeable/utils/ReentrancyGuardUpgradeable.sol\";\nimport \"./OwnerPausableUpgradeable.sol\";\nimport \"./SwapUtils.sol\";\nimport \"./AmplificationUtils.sol\";\n\n/**\n * @title Swap - A StableSwap implementation in solidity.\n * @notice This contract is responsible for custody of closely pegged assets (eg. group of stablecoins)\n * and automatic market making system. Users become an LP (Liquidity Provider) by depositing their tokens\n * in desired ratios for an exchange of the pool token that represents their share of the pool.\n * Users can burn pool tokens and withdraw their share of token(s).\n *\n * Each time a swap between the pooled tokens happens, a set fee incurs which effectively gets\n * distributed to the LPs.\n *\n * In case of emergencies, admin can pause additional deposits, swaps, or single-asset withdraws - which\n * stops the ratio of the tokens in the pool from changing.\n * Users can always withdraw their tokens via multi-asset withdraws.\n *\n * @dev Most of the logic is stored as a library `SwapUtils` for the sake of reducing contract's\n * deployment size.\n */\ncontract Swap is OwnerPausableUpgradeable, ReentrancyGuardUpgradeable {\n using SafeERC20 for IERC20;\n using SafeMath for uint256;\n using SwapUtils for SwapUtils.Swap;\n using AmplificationUtils for SwapUtils.Swap;\n\n // Struct storing data responsible for automatic market maker functionalities. In order to\n // access this data, this contract uses SwapUtils library. For more details, see SwapUtils.sol\n SwapUtils.Swap public swapStorage;\n\n // Maps token address to an index in the pool. Used to prevent duplicate tokens in the pool.\n // getTokenIndex function also relies on this mapping to retrieve token index.\n mapping(address => uint8) private tokenIndexes;\n\n /*** EVENTS ***/\n\n // events replicated from SwapUtils to make the ABI easier for dumb\n // clients\n event TokenSwap(\n address indexed buyer,\n uint256 tokensSold,\n uint256 tokensBought,\n uint128 soldId,\n uint128 boughtId\n );\n event AddLiquidity(\n address indexed provider,\n uint256[] tokenAmounts,\n uint256[] fees,\n uint256 invariant,\n uint256 lpTokenSupply\n );\n event RemoveLiquidity(\n address indexed provider,\n uint256[] tokenAmounts,\n uint256 lpTokenSupply\n );\n event RemoveLiquidityOne(\n address indexed provider,\n uint256 lpTokenAmount,\n uint256 lpTokenSupply,\n uint256 boughtId,\n uint256 tokensBought\n );\n event RemoveLiquidityImbalance(\n address indexed provider,\n uint256[] tokenAmounts,\n uint256[] fees,\n uint256 invariant,\n uint256 lpTokenSupply\n );\n event NewAdminFee(uint256 newAdminFee);\n event NewSwapFee(uint256 newSwapFee);\n event RampA(\n uint256 oldA,\n uint256 newA,\n uint256 initialTime,\n uint256 futureTime\n );\n event StopRampA(uint256 currentA, uint256 time);\n\n /**\n * @notice Initializes this Swap contract with the given parameters.\n * This will also clone a LPToken contract that represents users'\n * LP positions. The owner of LPToken will be this contract - which means\n * only this contract is allowed to mint/burn tokens.\n *\n * @param _pooledTokens an array of ERC20s this pool will accept\n * @param decimals the decimals to use for each pooled token,\n * eg 8 for WBTC. Cannot be larger than POOL_PRECISION_DECIMALS\n * @param lpTokenName the long-form name of the token to be deployed\n * @param lpTokenSymbol the short symbol for the token to be deployed\n * @param _a the amplification coefficient * n * (n - 1). See the\n * StableSwap paper for details\n * @param _fee default swap fee to be initialized with\n * @param _adminFee default adminFee to be initialized with\n * @param lpTokenTargetAddress the address of an existing LPToken contract to use as a target\n */\n function initialize(\n IERC20[] memory _pooledTokens,\n uint8[] memory decimals,\n string memory lpTokenName,\n string memory lpTokenSymbol,\n uint256 _a,\n uint256 _fee,\n uint256 _adminFee,\n address lpTokenTargetAddress\n ) public virtual initializer {\n __OwnerPausable_init();\n __ReentrancyGuard_init();\n // Check _pooledTokens and precisions parameter\n require(_pooledTokens.length > 1, \"_pooledTokens.length <= 1\");\n require(_pooledTokens.length <= 32, \"_pooledTokens.length > 32\");\n require(\n _pooledTokens.length == decimals.length,\n \"_pooledTokens decimals mismatch\"\n );\n\n uint256[] memory precisionMultipliers = new uint256[](decimals.length);\n\n for (uint8 i = 0; i < _pooledTokens.length; i++) {\n if (i > 0) {\n // Check if index is already used. Check if 0th element is a duplicate.\n require(\n tokenIndexes[address(_pooledTokens[i])] == 0 &&\n _pooledTokens[0] != _pooledTokens[i],\n \"Duplicate tokens\"\n );\n }\n require(\n address(_pooledTokens[i]) != address(0),\n \"The 0 address isn't an ERC-20\"\n );\n require(\n decimals[i] <= SwapUtils.POOL_PRECISION_DECIMALS,\n \"Token decimals exceeds max\"\n );\n precisionMultipliers[i] =\n 10 **\n uint256(SwapUtils.POOL_PRECISION_DECIMALS).sub(\n uint256(decimals[i])\n );\n tokenIndexes[address(_pooledTokens[i])] = i;\n }\n\n // Check _a, _fee, _adminFee parameters\n require(_a < AmplificationUtils.MAX_A, \"_a exceeds maximum\");\n require(_fee < SwapUtils.MAX_SWAP_FEE, \"_fee exceeds maximum\");\n require(\n _adminFee < SwapUtils.MAX_ADMIN_FEE,\n \"_adminFee exceeds maximum\"\n );\n\n // Clone and initialize a LPToken contract\n LPToken lpToken = LPToken(Clones.clone(lpTokenTargetAddress));\n require(\n lpToken.initialize(lpTokenName, lpTokenSymbol),\n \"could not init lpToken clone\"\n );\n\n // Initialize swapStorage struct\n swapStorage.lpToken = lpToken;\n swapStorage.pooledTokens = _pooledTokens;\n swapStorage.tokenPrecisionMultipliers = precisionMultipliers;\n swapStorage.balances = new uint256[](_pooledTokens.length);\n swapStorage.initialA = _a.mul(AmplificationUtils.A_PRECISION);\n swapStorage.futureA = _a.mul(AmplificationUtils.A_PRECISION);\n // swapStorage.initialATime = 0;\n // swapStorage.futureATime = 0;\n swapStorage.swapFee = _fee;\n swapStorage.adminFee = _adminFee;\n }\n\n /*** MODIFIERS ***/\n\n /**\n * @notice Modifier to check deadline against current timestamp\n * @param deadline latest timestamp to accept this transaction\n */\n modifier deadlineCheck(uint256 deadline) {\n require(block.timestamp <= deadline, \"Deadline not met\");\n _;\n }\n\n /*** VIEW FUNCTIONS ***/\n\n /**\n * @notice Return A, the amplification coefficient * n * (n - 1)\n * @dev See the StableSwap paper for details\n * @return A parameter\n */\n function getA() external view virtual returns (uint256) {\n return swapStorage.getA();\n }\n\n /**\n * @notice Return A in its raw precision form\n * @dev See the StableSwap paper for details\n * @return A parameter in its raw precision form\n */\n function getAPrecise() external view virtual returns (uint256) {\n return swapStorage.getAPrecise();\n }\n\n /**\n * @notice Return address of the pooled token at given index. Reverts if tokenIndex is out of range.\n * @param index the index of the token\n * @return address of the token at given index\n */\n function getToken(uint8 index) public view virtual returns (IERC20) {\n require(index < swapStorage.pooledTokens.length, \"Out of range\");\n return swapStorage.pooledTokens[index];\n }\n\n /**\n * @notice Return the index of the given token address. Reverts if no matching\n * token is found.\n * @param tokenAddress address of the token\n * @return the index of the given token address\n */\n function getTokenIndex(address tokenAddress)\n public\n view\n virtual\n returns (uint8)\n {\n uint8 index = tokenIndexes[tokenAddress];\n require(\n address(getToken(index)) == tokenAddress,\n \"Token does not exist\"\n );\n return index;\n }\n\n /**\n * @notice Return current balance of the pooled token at given index\n * @param index the index of the token\n * @return current balance of the pooled token at given index with token's native precision\n */\n function getTokenBalance(uint8 index)\n external\n view\n virtual\n returns (uint256)\n {\n require(index < swapStorage.pooledTokens.length, \"Index out of range\");\n return swapStorage.balances[index];\n }\n\n /**\n * @notice Get the virtual price, to help calculate profit\n * @return the virtual price, scaled to the POOL_PRECISION_DECIMALS\n */\n function getVirtualPrice() external view virtual returns (uint256) {\n return swapStorage.getVirtualPrice();\n }\n\n /**\n * @notice Calculate amount of tokens you receive on swap\n * @param tokenIndexFrom the token the user wants to sell\n * @param tokenIndexTo the token the user wants to buy\n * @param dx the amount of tokens the user wants to sell. If the token charges\n * a fee on transfers, use the amount that gets transferred after the fee.\n * @return amount of tokens the user will receive\n */\n function calculateSwap(\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx\n ) external view virtual returns (uint256) {\n return swapStorage.calculateSwap(tokenIndexFrom, tokenIndexTo, dx);\n }\n\n /**\n * @notice A simple method to calculate prices from deposits or\n * withdrawals, excluding fees but including slippage. This is\n * helpful as an input into the various \"min\" parameters on calls\n * to fight front-running\n *\n * @dev This shouldn't be used outside frontends for user estimates.\n *\n * @param amounts an array of token amounts to deposit or withdrawal,\n * corresponding to pooledTokens. The amount should be in each\n * pooled token's native precision. If a token charges a fee on transfers,\n * use the amount that gets transferred after the fee.\n * @param deposit whether this is a deposit or a withdrawal\n * @return token amount the user will receive\n */\n function calculateTokenAmount(uint256[] calldata amounts, bool deposit)\n external\n view\n virtual\n returns (uint256)\n {\n return swapStorage.calculateTokenAmount(amounts, deposit);\n }\n\n /**\n * @notice A simple method to calculate amount of each underlying\n * tokens that is returned upon burning given amount of LP tokens\n * @param amount the amount of LP tokens that would be burned on withdrawal\n * @return array of token balances that the user will receive\n */\n function calculateRemoveLiquidity(uint256 amount)\n external\n view\n virtual\n returns (uint256[] memory)\n {\n return swapStorage.calculateRemoveLiquidity(amount);\n }\n\n /**\n * @notice Calculate the amount of underlying token available to withdraw\n * when withdrawing via only single token\n * @param tokenAmount the amount of LP token to burn\n * @param tokenIndex index of which token will be withdrawn\n * @return availableTokenAmount calculated amount of underlying token\n * available to withdraw\n */\n function calculateRemoveLiquidityOneToken(\n uint256 tokenAmount,\n uint8 tokenIndex\n ) external view virtual returns (uint256 availableTokenAmount) {\n return swapStorage.calculateWithdrawOneToken(tokenAmount, tokenIndex);\n }\n\n /**\n * @notice This function reads the accumulated amount of admin fees of the token with given index\n * @param index Index of the pooled token\n * @return admin's token balance in the token's precision\n */\n function getAdminBalance(uint256 index)\n external\n view\n virtual\n returns (uint256)\n {\n return swapStorage.getAdminBalance(index);\n }\n\n /*** STATE MODIFYING FUNCTIONS ***/\n\n /**\n * @notice Swap two tokens using this pool\n * @param tokenIndexFrom the token the user wants to swap from\n * @param tokenIndexTo the token the user wants to swap to\n * @param dx the amount of tokens the user wants to swap from\n * @param minDy the min amount the user would like to receive, or revert.\n * @param deadline latest timestamp to accept this transaction\n */\n function swap(\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx,\n uint256 minDy,\n uint256 deadline\n )\n external\n virtual\n nonReentrant\n whenNotPaused\n deadlineCheck(deadline)\n returns (uint256)\n {\n return swapStorage.swap(tokenIndexFrom, tokenIndexTo, dx, minDy);\n }\n\n /**\n * @notice Add liquidity to the pool with the given amounts of tokens\n * @param amounts the amounts of each token to add, in their native precision\n * @param minToMint the minimum LP tokens adding this amount of liquidity\n * should mint, otherwise revert. Handy for front-running mitigation\n * @param deadline latest timestamp to accept this transaction\n * @return amount of LP token user minted and received\n */\n function addLiquidity(\n uint256[] calldata amounts,\n uint256 minToMint,\n uint256 deadline\n )\n external\n virtual\n nonReentrant\n whenNotPaused\n deadlineCheck(deadline)\n returns (uint256)\n {\n return swapStorage.addLiquidity(amounts, minToMint);\n }\n\n /**\n * @notice Burn LP tokens to remove liquidity from the pool. Withdraw fee that decays linearly\n * over period of 4 weeks since last deposit will apply.\n * @dev Liquidity can always be removed, even when the pool is paused.\n * @param amount the amount of LP tokens to burn\n * @param minAmounts the minimum amounts of each token in the pool\n * acceptable for this burn. Useful as a front-running mitigation\n * @param deadline latest timestamp to accept this transaction\n * @return amounts of tokens user received\n */\n function removeLiquidity(\n uint256 amount,\n uint256[] calldata minAmounts,\n uint256 deadline\n )\n external\n virtual\n nonReentrant\n deadlineCheck(deadline)\n returns (uint256[] memory)\n {\n return swapStorage.removeLiquidity(amount, minAmounts);\n }\n\n /**\n * @notice Remove liquidity from the pool all in one token. Withdraw fee that decays linearly\n * over period of 4 weeks since last deposit will apply.\n * @param tokenAmount the amount of the token you want to receive\n * @param tokenIndex the index of the token you want to receive\n * @param minAmount the minimum amount to withdraw, otherwise revert\n * @param deadline latest timestamp to accept this transaction\n * @return amount of chosen token user received\n */\n function removeLiquidityOneToken(\n uint256 tokenAmount,\n uint8 tokenIndex,\n uint256 minAmount,\n uint256 deadline\n )\n external\n virtual\n nonReentrant\n whenNotPaused\n deadlineCheck(deadline)\n returns (uint256)\n {\n return\n swapStorage.removeLiquidityOneToken(\n tokenAmount,\n tokenIndex,\n minAmount\n );\n }\n\n /**\n * @notice Remove liquidity from the pool, weighted differently than the\n * pool's current balances. Withdraw fee that decays linearly\n * over period of 4 weeks since last deposit will apply.\n * @param amounts how much of each token to withdraw\n * @param maxBurnAmount the max LP token provider is willing to pay to\n * remove liquidity. Useful as a front-running mitigation.\n * @param deadline latest timestamp to accept this transaction\n * @return amount of LP tokens burned\n */\n function removeLiquidityImbalance(\n uint256[] calldata amounts,\n uint256 maxBurnAmount,\n uint256 deadline\n )\n external\n virtual\n nonReentrant\n whenNotPaused\n deadlineCheck(deadline)\n returns (uint256)\n {\n return swapStorage.removeLiquidityImbalance(amounts, maxBurnAmount);\n }\n\n /*** ADMIN FUNCTIONS ***/\n\n /**\n * @notice Withdraw all admin fees to the contract owner\n */\n function withdrawAdminFees() external onlyOwner {\n swapStorage.withdrawAdminFees(owner());\n }\n\n /**\n * @notice Update the admin fee. Admin fee takes portion of the swap fee.\n * @param newAdminFee new admin fee to be applied on future transactions\n */\n function setAdminFee(uint256 newAdminFee) external onlyOwner {\n swapStorage.setAdminFee(newAdminFee);\n }\n\n /**\n * @notice Update the swap fee to be applied on swaps\n * @param newSwapFee new swap fee to be applied on future transactions\n */\n function setSwapFee(uint256 newSwapFee) external onlyOwner {\n swapStorage.setSwapFee(newSwapFee);\n }\n\n /**\n * @notice Start ramping up or down A parameter towards given futureA and futureTime\n * Checks if the change is too rapid, and commits the new A value only when it falls under\n * the limit range.\n * @param futureA the new A to ramp towards\n * @param futureTime timestamp when the new A should be reached\n */\n function rampA(uint256 futureA, uint256 futureTime) external onlyOwner {\n swapStorage.rampA(futureA, futureTime);\n }\n\n /**\n * @notice Stop ramping A immediately. Reverts if ramp A is already stopped.\n */\n function stopRampA() external onlyOwner {\n swapStorage.stopRampA();\n }\n}\n" + }, + "@openzeppelin/contracts/math/SafeMath.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <0.8.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" + }, + "@openzeppelin/contracts/token/ERC20/SafeERC20.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <0.8.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" + }, + "@openzeppelin/contracts/proxy/Clones.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <0.8.0;\n\n/**\n * @dev https://eips.ethereum.org/EIPS/eip-1167[EIP 1167] is a standard for\n * deploying minimal proxy contracts, also known as \"clones\".\n *\n * > To simply and cheaply clone contract functionality in an immutable way, this standard specifies\n * > a minimal bytecode implementation that delegates all calls to a known, fixed address.\n *\n * The library includes functions to deploy a proxy using either `create` (traditional deployment) or `create2`\n * (salted deterministic deployment). It also includes functions to predict the addresses of clones deployed using the\n * deterministic method.\n *\n * _Available since v3.4._\n */\nlibrary Clones {\n /**\n * @dev Deploys and returns the address of a clone that mimics the behaviour of `master`.\n *\n * This function uses the create opcode, which should never revert.\n */\n function clone(address master) internal returns (address instance) {\n // solhint-disable-next-line no-inline-assembly\n assembly {\n let ptr := mload(0x40)\n mstore(ptr, 0x3d602d80600a3d3981f3363d3d373d3d3d363d73000000000000000000000000)\n mstore(add(ptr, 0x14), shl(0x60, master))\n mstore(add(ptr, 0x28), 0x5af43d82803e903d91602b57fd5bf30000000000000000000000000000000000)\n instance := create(0, ptr, 0x37)\n }\n require(instance != address(0), \"ERC1167: create failed\");\n }\n\n /**\n * @dev Deploys and returns the address of a clone that mimics the behaviour of `master`.\n *\n * This function uses the create2 opcode and a `salt` to deterministically deploy\n * the clone. Using the same `master` and `salt` multiple time will revert, since\n * the clones cannot be deployed twice at the same address.\n */\n function cloneDeterministic(address master, bytes32 salt) internal returns (address instance) {\n // solhint-disable-next-line no-inline-assembly\n assembly {\n let ptr := mload(0x40)\n mstore(ptr, 0x3d602d80600a3d3981f3363d3d373d3d3d363d73000000000000000000000000)\n mstore(add(ptr, 0x14), shl(0x60, master))\n mstore(add(ptr, 0x28), 0x5af43d82803e903d91602b57fd5bf30000000000000000000000000000000000)\n instance := create2(0, ptr, 0x37, salt)\n }\n require(instance != address(0), \"ERC1167: create2 failed\");\n }\n\n /**\n * @dev Computes the address of a clone deployed using {Clones-cloneDeterministic}.\n */\n function predictDeterministicAddress(address master, bytes32 salt, address deployer) internal pure returns (address predicted) {\n // solhint-disable-next-line no-inline-assembly\n assembly {\n let ptr := mload(0x40)\n mstore(ptr, 0x3d602d80600a3d3981f3363d3d373d3d3d363d73000000000000000000000000)\n mstore(add(ptr, 0x14), shl(0x60, master))\n mstore(add(ptr, 0x28), 0x5af43d82803e903d91602b57fd5bf3ff00000000000000000000000000000000)\n mstore(add(ptr, 0x38), shl(0x60, deployer))\n mstore(add(ptr, 0x4c), salt)\n mstore(add(ptr, 0x6c), keccak256(ptr, 0x37))\n predicted := keccak256(add(ptr, 0x37), 0x55)\n }\n }\n\n /**\n * @dev Computes the address of a clone deployed using {Clones-cloneDeterministic}.\n */\n function predictDeterministicAddress(address master, bytes32 salt) internal view returns (address predicted) {\n return predictDeterministicAddress(master, salt, address(this));\n }\n}\n" + }, + "@openzeppelin/contracts-upgradeable/utils/ReentrancyGuardUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <0.8.0;\nimport \"../proxy/Initializable.sol\";\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 ReentrancyGuardUpgradeable is Initializable {\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 function __ReentrancyGuard_init() internal initializer {\n __ReentrancyGuard_init_unchained();\n }\n\n function __ReentrancyGuard_init_unchained() internal initializer {\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 uint256[49] private __gap;\n}\n" + }, + "contracts/amm/OwnerPausableUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.6.12;\n\nimport \"@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol\";\nimport \"@openzeppelin/contracts-upgradeable/utils/PausableUpgradeable.sol\";\n\n/**\n * @title OwnerPausable\n * @notice An ownable contract allows the owner to pause and unpause the\n * contract without a delay.\n * @dev Only methods using the provided modifiers will be paused.\n */\nabstract contract OwnerPausableUpgradeable is\n OwnableUpgradeable,\n PausableUpgradeable\n{\n function __OwnerPausable_init() internal initializer {\n __Context_init_unchained();\n __Ownable_init_unchained();\n __Pausable_init_unchained();\n }\n\n /**\n * @notice Pause the contract. Revert if already paused.\n */\n function pause() external onlyOwner {\n PausableUpgradeable._pause();\n }\n\n /**\n * @notice Unpause the contract. Revert if already unpaused.\n */\n function unpause() external onlyOwner {\n PausableUpgradeable._unpause();\n }\n}\n" + }, + "contracts/amm/SwapUtils.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.6.12;\n\nimport \"@openzeppelin/contracts/math/SafeMath.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/SafeERC20.sol\";\nimport \"./AmplificationUtils.sol\";\nimport \"./LPToken.sol\";\nimport \"./MathUtils.sol\";\n\n/**\n * @title SwapUtils library\n * @notice A library to be used within Swap.sol. Contains functions responsible for custody and AMM functionalities.\n * @dev Contracts relying on this library must initialize SwapUtils.Swap struct then use this library\n * for SwapUtils.Swap struct. Note that this library contains both functions called by users and admins.\n * Admin functions should be protected within contracts using this library.\n */\nlibrary SwapUtils {\n using SafeERC20 for IERC20;\n using SafeMath for uint256;\n using MathUtils for uint256;\n\n /*** EVENTS ***/\n\n event TokenSwap(\n address indexed buyer,\n uint256 tokensSold,\n uint256 tokensBought,\n uint128 soldId,\n uint128 boughtId\n );\n event AddLiquidity(\n address indexed provider,\n uint256[] tokenAmounts,\n uint256[] fees,\n uint256 invariant,\n uint256 lpTokenSupply\n );\n event RemoveLiquidity(\n address indexed provider,\n uint256[] tokenAmounts,\n uint256 lpTokenSupply\n );\n event RemoveLiquidityOne(\n address indexed provider,\n uint256 lpTokenAmount,\n uint256 lpTokenSupply,\n uint256 boughtId,\n uint256 tokensBought\n );\n event RemoveLiquidityImbalance(\n address indexed provider,\n uint256[] tokenAmounts,\n uint256[] fees,\n uint256 invariant,\n uint256 lpTokenSupply\n );\n event NewAdminFee(uint256 newAdminFee);\n event NewSwapFee(uint256 newSwapFee);\n\n struct Swap {\n // variables around the ramp management of A,\n // the amplification coefficient * n * (n - 1)\n // see https://www.curve.fi/stableswap-paper.pdf for details\n uint256 initialA;\n uint256 futureA;\n uint256 initialATime;\n uint256 futureATime;\n // fee calculation\n uint256 swapFee;\n uint256 adminFee;\n LPToken lpToken;\n // contract references for all tokens being pooled\n IERC20[] pooledTokens;\n // multipliers for each pooled token's precision to get to POOL_PRECISION_DECIMALS\n // for example, TBTC has 18 decimals, so the multiplier should be 1. WBTC\n // has 8, so the multiplier should be 10 ** 18 / 10 ** 8 => 10 ** 10\n uint256[] tokenPrecisionMultipliers;\n // the pool balance of each token, in the token's precision\n // the contract's actual token balance might differ\n uint256[] balances;\n }\n\n // Struct storing variables used in calculations in the\n // calculateWithdrawOneTokenDY function to avoid stack too deep errors\n struct CalculateWithdrawOneTokenDYInfo {\n uint256 d0;\n uint256 d1;\n uint256 newY;\n uint256 feePerToken;\n uint256 preciseA;\n }\n\n // Struct storing variables used in calculations in the\n // {add,remove}Liquidity functions to avoid stack too deep errors\n struct ManageLiquidityInfo {\n uint256 d0;\n uint256 d1;\n uint256 d2;\n uint256 preciseA;\n LPToken lpToken;\n uint256 totalSupply;\n uint256[] balances;\n uint256[] multipliers;\n }\n\n // the precision all pools tokens will be converted to\n uint8 public constant POOL_PRECISION_DECIMALS = 18;\n\n // the denominator used to calculate admin and LP fees. For example, an\n // LP fee might be something like tradeAmount.mul(fee).div(FEE_DENOMINATOR)\n uint256 private constant FEE_DENOMINATOR = 10**10;\n\n // Max swap fee is 1% or 100bps of each swap\n uint256 public constant MAX_SWAP_FEE = 10**8;\n\n // Max adminFee is 100% of the swapFee\n // adminFee does not add additional fee on top of swapFee\n // Instead it takes a certain % of the swapFee. Therefore it has no impact on the\n // users but only on the earnings of LPs\n uint256 public constant MAX_ADMIN_FEE = 10**10;\n\n // Constant value used as max loop limit\n uint256 private constant MAX_LOOP_LIMIT = 256;\n\n /*** VIEW & PURE FUNCTIONS ***/\n\n function _getAPrecise(Swap storage self) internal view returns (uint256) {\n return AmplificationUtils._getAPrecise(self);\n }\n\n /**\n * @notice Calculate the dy, the amount of selected token that user receives and\n * the fee of withdrawing in one token\n * @param tokenAmount the amount to withdraw in the pool's precision\n * @param tokenIndex which token will be withdrawn\n * @param self Swap struct to read from\n * @return the amount of token user will receive\n */\n function calculateWithdrawOneToken(\n Swap storage self,\n uint256 tokenAmount,\n uint8 tokenIndex\n ) external view returns (uint256) {\n (uint256 availableTokenAmount, ) = _calculateWithdrawOneToken(\n self,\n tokenAmount,\n tokenIndex,\n self.lpToken.totalSupply()\n );\n return availableTokenAmount;\n }\n\n function _calculateWithdrawOneToken(\n Swap storage self,\n uint256 tokenAmount,\n uint8 tokenIndex,\n uint256 totalSupply\n ) internal view returns (uint256, uint256) {\n uint256 dy;\n uint256 newY;\n uint256 currentY;\n\n (dy, newY, currentY) = calculateWithdrawOneTokenDY(\n self,\n tokenIndex,\n tokenAmount,\n totalSupply\n );\n\n // dy_0 (without fees)\n // dy, dy_0 - dy\n\n uint256 dySwapFee = currentY\n .sub(newY)\n .div(self.tokenPrecisionMultipliers[tokenIndex])\n .sub(dy);\n\n return (dy, dySwapFee);\n }\n\n /**\n * @notice Calculate the dy of withdrawing in one token\n * @param self Swap struct to read from\n * @param tokenIndex which token will be withdrawn\n * @param tokenAmount the amount to withdraw in the pools precision\n * @return the d and the new y after withdrawing one token\n */\n function calculateWithdrawOneTokenDY(\n Swap storage self,\n uint8 tokenIndex,\n uint256 tokenAmount,\n uint256 totalSupply\n )\n internal\n view\n returns (\n uint256,\n uint256,\n uint256\n )\n {\n // Get the current D, then solve the stableswap invariant\n // y_i for D - tokenAmount\n uint256[] memory xp = _xp(self);\n\n require(tokenIndex < xp.length, \"Token index out of range\");\n\n\n CalculateWithdrawOneTokenDYInfo memory v\n = CalculateWithdrawOneTokenDYInfo(0, 0, 0, 0, 0);\n v.preciseA = _getAPrecise(self);\n v.d0 = getD(xp, v.preciseA);\n v.d1 = v.d0.sub(tokenAmount.mul(v.d0).div(totalSupply));\n\n require(tokenAmount <= xp[tokenIndex], \"Withdraw exceeds available\");\n\n v.newY = getYD(v.preciseA, tokenIndex, xp, v.d1);\n\n uint256[] memory xpReduced = new uint256[](xp.length);\n\n v.feePerToken = _feePerToken(self.swapFee, xp.length);\n for (uint256 i = 0; i < xp.length; i++) {\n uint256 xpi = xp[i];\n // if i == tokenIndex, dxExpected = xp[i] * d1 / d0 - newY\n // else dxExpected = xp[i] - (xp[i] * d1 / d0)\n // xpReduced[i] -= dxExpected * fee / FEE_DENOMINATOR\n xpReduced[i] = xpi.sub(\n (\n (i == tokenIndex)\n ? xpi.mul(v.d1).div(v.d0).sub(v.newY)\n : xpi.sub(xpi.mul(v.d1).div(v.d0))\n )\n .mul(v.feePerToken)\n .div(FEE_DENOMINATOR)\n );\n }\n\n uint256 dy = xpReduced[tokenIndex].sub(\n getYD(v.preciseA, tokenIndex, xpReduced, v.d1)\n );\n dy = dy.sub(1).div(self.tokenPrecisionMultipliers[tokenIndex]);\n\n return (dy, v.newY, xp[tokenIndex]);\n }\n\n /**\n * @notice Calculate the price of a token in the pool with given\n * precision-adjusted balances and a particular D.\n *\n * @dev This is accomplished via solving the invariant iteratively.\n * See the StableSwap paper and Curve.fi implementation for further details.\n *\n * x_1**2 + x1 * (sum' - (A*n**n - 1) * D / (A * n**n)) = D ** (n + 1) / (n ** (2 * n) * prod' * A)\n * x_1**2 + b*x_1 = c\n * x_1 = (x_1**2 + c) / (2*x_1 + b)\n *\n * @param a the amplification coefficient * n * (n - 1). See the StableSwap paper for details.\n * @param tokenIndex Index of token we are calculating for.\n * @param xp a precision-adjusted set of pool balances. Array should be\n * the same cardinality as the pool.\n * @param d the stableswap invariant\n * @return the price of the token, in the same precision as in xp\n */\n function getYD(\n uint256 a,\n uint8 tokenIndex,\n uint256[] memory xp,\n uint256 d\n ) internal pure returns (uint256) {\n uint256 numTokens = xp.length;\n require(tokenIndex < numTokens, \"Token not found\");\n\n uint256 c = d;\n uint256 s;\n uint256 nA = a.mul(numTokens);\n\n for (uint256 i = 0; i < numTokens; i++) {\n if (i != tokenIndex) {\n s = s.add(xp[i]);\n c = c.mul(d).div(xp[i].mul(numTokens));\n // If we were to protect the division loss we would have to keep the denominator separate\n // and divide at the end. However this leads to overflow with large numTokens or/and D.\n // c = c * D * D * D * ... overflow!\n }\n }\n c = c.mul(d).mul(AmplificationUtils.A_PRECISION).div(nA.mul(numTokens));\n\n uint256 b = s.add(d.mul(AmplificationUtils.A_PRECISION).div(nA));\n uint256 yPrev;\n uint256 y = d;\n for (uint256 i = 0; i < MAX_LOOP_LIMIT; i++) {\n yPrev = y;\n y = y.mul(y).add(c).div(y.mul(2).add(b).sub(d));\n if (y.within1(yPrev)) {\n return y;\n }\n }\n revert(\"Approximation did not converge\");\n }\n\n /**\n * @notice Get D, the StableSwap invariant, based on a set of balances and a particular A.\n * @param xp a precision-adjusted set of pool balances. Array should be the same cardinality\n * as the pool.\n * @param a the amplification coefficient * n * (n - 1) in A_PRECISION.\n * See the StableSwap paper for details\n * @return the invariant, at the precision of the pool\n */\n function getD(uint256[] memory xp, uint256 a)\n internal\n pure\n returns (uint256)\n {\n uint256 numTokens = xp.length;\n uint256 s;\n for (uint256 i = 0; i < numTokens; i++) {\n s = s.add(xp[i]);\n }\n if (s == 0) {\n return 0;\n }\n\n uint256 prevD;\n uint256 d = s;\n uint256 nA = a.mul(numTokens);\n\n for (uint256 i = 0; i < MAX_LOOP_LIMIT; i++) {\n uint256 dP = d;\n for (uint256 j = 0; j < numTokens; j++) {\n dP = dP.mul(d).div(xp[j].mul(numTokens));\n // If we were to protect the division loss we would have to keep the denominator separate\n // and divide at the end. However this leads to overflow with large numTokens or/and D.\n // dP = dP * D * D * D * ... overflow!\n }\n prevD = d;\n d = nA\n .mul(s)\n .div(AmplificationUtils.A_PRECISION)\n .add(dP.mul(numTokens))\n .mul(d)\n .div(\n nA\n .sub(AmplificationUtils.A_PRECISION)\n .mul(d)\n .div(AmplificationUtils.A_PRECISION)\n .add(numTokens.add(1).mul(dP))\n );\n if (d.within1(prevD)) {\n return d;\n }\n }\n\n // Convergence should occur in 4 loops or less. If this is reached, there may be something wrong\n // with the pool. If this were to occur repeatedly, LPs should withdraw via `removeLiquidity()`\n // function which does not rely on D.\n revert(\"D does not converge\");\n }\n\n /**\n * @notice Given a set of balances and precision multipliers, return the\n * precision-adjusted balances.\n *\n * @param balances an array of token balances, in their native precisions.\n * These should generally correspond with pooled tokens.\n *\n * @param precisionMultipliers an array of multipliers, corresponding to\n * the amounts in the balances array. When multiplied together they\n * should yield amounts at the pool's precision.\n *\n * @return an array of amounts \"scaled\" to the pool's precision\n */\n function _xp(\n uint256[] memory balances,\n uint256[] memory precisionMultipliers\n ) internal pure returns (uint256[] memory) {\n uint256 numTokens = balances.length;\n require(\n numTokens == precisionMultipliers.length,\n \"Balances must match multipliers\"\n );\n uint256[] memory xp = new uint256[](numTokens);\n for (uint256 i = 0; i < numTokens; i++) {\n xp[i] = balances[i].mul(precisionMultipliers[i]);\n }\n return xp;\n }\n\n /**\n * @notice Return the precision-adjusted balances of all tokens in the pool\n * @param self Swap struct to read from\n * @return the pool balances \"scaled\" to the pool's precision, allowing\n * them to be more easily compared.\n */\n function _xp(Swap storage self) internal view returns (uint256[] memory) {\n return _xp(self.balances, self.tokenPrecisionMultipliers);\n }\n\n /**\n * @notice Get the virtual price, to help calculate profit\n * @param self Swap struct to read from\n * @return the virtual price, scaled to precision of POOL_PRECISION_DECIMALS\n */\n function getVirtualPrice(Swap storage self)\n external\n view\n returns (uint256)\n {\n uint256 d = getD(_xp(self), _getAPrecise(self));\n LPToken lpToken = self.lpToken;\n uint256 supply = lpToken.totalSupply();\n if (supply > 0) {\n return d.mul(10**uint256(POOL_PRECISION_DECIMALS)).div(supply);\n }\n return 0;\n }\n\n /**\n * @notice Calculate the new balances of the tokens given the indexes of the token\n * that is swapped from (FROM) and the token that is swapped to (TO).\n * This function is used as a helper function to calculate how much TO token\n * the user should receive on swap.\n *\n * @param preciseA precise form of amplification coefficient\n * @param tokenIndexFrom index of FROM token\n * @param tokenIndexTo index of TO token\n * @param x the new total amount of FROM token\n * @param xp balances of the tokens in the pool\n * @return the amount of TO token that should remain in the pool\n */\n function getY(\n uint256 preciseA,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 x,\n uint256[] memory xp\n ) internal pure returns (uint256) {\n uint256 numTokens = xp.length;\n require(\n tokenIndexFrom != tokenIndexTo,\n \"Can't compare token to itself\"\n );\n require(\n tokenIndexFrom < numTokens && tokenIndexTo < numTokens,\n \"Tokens must be in pool\"\n );\n\n uint256 d = getD(xp, preciseA);\n uint256 c = d;\n uint256 s;\n uint256 nA = numTokens.mul(preciseA);\n\n uint256 _x;\n for (uint256 i = 0; i < numTokens; i++) {\n if (i == tokenIndexFrom) {\n _x = x;\n } else if (i != tokenIndexTo) {\n _x = xp[i];\n } else {\n continue;\n }\n s = s.add(_x);\n c = c.mul(d).div(_x.mul(numTokens));\n // If we were to protect the division loss we would have to keep the denominator separate\n // and divide at the end. However this leads to overflow with large numTokens or/and D.\n // c = c * D * D * D * ... overflow!\n }\n c = c.mul(d).mul(AmplificationUtils.A_PRECISION).div(nA.mul(numTokens));\n uint256 b = s.add(d.mul(AmplificationUtils.A_PRECISION).div(nA));\n uint256 yPrev;\n uint256 y = d;\n\n // iterative approximation\n for (uint256 i = 0; i < MAX_LOOP_LIMIT; i++) {\n yPrev = y;\n y = y.mul(y).add(c).div(y.mul(2).add(b).sub(d));\n if (y.within1(yPrev)) {\n return y;\n }\n }\n revert(\"Approximation did not converge\");\n }\n\n /**\n * @notice Externally calculates a swap between two tokens.\n * @param self Swap struct to read from\n * @param tokenIndexFrom the token to sell\n * @param tokenIndexTo the token to buy\n * @param dx the number of tokens to sell. If the token charges a fee on transfers,\n * use the amount that gets transferred after the fee.\n * @return dy the number of tokens the user will get\n */\n function calculateSwap(\n Swap storage self,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx\n ) external view returns (uint256 dy) {\n (dy, ) = _calculateSwap(\n self,\n tokenIndexFrom,\n tokenIndexTo,\n dx,\n self.balances\n );\n }\n\n /**\n * @notice Internally calculates a swap between two tokens.\n *\n * @dev The caller is expected to transfer the actual amounts (dx and dy)\n * using the token contracts.\n *\n * @param self Swap struct to read from\n * @param tokenIndexFrom the token to sell\n * @param tokenIndexTo the token to buy\n * @param dx the number of tokens to sell. If the token charges a fee on transfers,\n * use the amount that gets transferred after the fee.\n * @return dy the number of tokens the user will get\n * @return dyFee the associated fee\n */\n function _calculateSwap(\n Swap storage self,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx,\n uint256[] memory balances\n ) internal view returns (uint256 dy, uint256 dyFee) {\n uint256[] memory multipliers = self.tokenPrecisionMultipliers;\n uint256[] memory xp = _xp(balances, multipliers);\n require(\n tokenIndexFrom < xp.length && tokenIndexTo < xp.length,\n \"Token index out of range\"\n );\n uint256 x = dx.mul(multipliers[tokenIndexFrom]).add(xp[tokenIndexFrom]);\n uint256 y = getY(\n _getAPrecise(self),\n tokenIndexFrom,\n tokenIndexTo,\n x,\n xp\n );\n dy = xp[tokenIndexTo].sub(y).sub(1);\n dyFee = dy.mul(self.swapFee).div(FEE_DENOMINATOR);\n dy = dy.sub(dyFee).div(multipliers[tokenIndexTo]);\n }\n\n /**\n * @notice A simple method to calculate amount of each underlying\n * tokens that is returned upon burning given amount of\n * LP tokens\n *\n * @param amount the amount of LP tokens that would to be burned on\n * withdrawal\n * @return array of amounts of tokens user will receive\n */\n function calculateRemoveLiquidity(Swap storage self, uint256 amount)\n external\n view\n returns (uint256[] memory)\n {\n return\n _calculateRemoveLiquidity(\n self.balances,\n amount,\n self.lpToken.totalSupply()\n );\n }\n\n function _calculateRemoveLiquidity(\n uint256[] memory balances,\n uint256 amount,\n uint256 totalSupply\n ) internal pure returns (uint256[] memory) {\n require(amount <= totalSupply, \"Cannot exceed total supply\");\n\n uint256[] memory amounts = new uint256[](balances.length);\n\n for (uint256 i = 0; i < balances.length; i++) {\n amounts[i] = balances[i].mul(amount).div(totalSupply);\n }\n return amounts;\n }\n\n /**\n * @notice A simple method to calculate prices from deposits or\n * withdrawals, excluding fees but including slippage. This is\n * helpful as an input into the various \"min\" parameters on calls\n * to fight front-running\n *\n * @dev This shouldn't be used outside frontends for user estimates.\n *\n * @param self Swap struct to read from\n * @param amounts an array of token amounts to deposit or withdrawal,\n * corresponding to pooledTokens. The amount should be in each\n * pooled token's native precision. If a token charges a fee on transfers,\n * use the amount that gets transferred after the fee.\n * @param deposit whether this is a deposit or a withdrawal\n * @return if deposit was true, total amount of lp token that will be minted and if\n * deposit was false, total amount of lp token that will be burned\n */\n function calculateTokenAmount(\n Swap storage self,\n uint256[] calldata amounts,\n bool deposit\n ) external view returns (uint256) {\n uint256 a = _getAPrecise(self);\n uint256[] memory balances = self.balances;\n uint256[] memory multipliers = self.tokenPrecisionMultipliers;\n\n uint256 d0 = getD(_xp(balances, multipliers), a);\n for (uint256 i = 0; i < balances.length; i++) {\n if (deposit) {\n balances[i] = balances[i].add(amounts[i]);\n } else {\n balances[i] = balances[i].sub(\n amounts[i],\n \"Cannot withdraw more than available\"\n );\n }\n }\n uint256 d1 = getD(_xp(balances, multipliers), a);\n uint256 totalSupply = self.lpToken.totalSupply();\n\n if (deposit) {\n return d1.sub(d0).mul(totalSupply).div(d0);\n } else {\n return d0.sub(d1).mul(totalSupply).div(d0);\n }\n }\n\n /**\n * @notice return accumulated amount of admin fees of the token with given index\n * @param self Swap struct to read from\n * @param index Index of the pooled token\n * @return admin balance in the token's precision\n */\n function getAdminBalance(Swap storage self, uint256 index)\n external\n view\n returns (uint256)\n {\n require(index < self.pooledTokens.length, \"Token index out of range\");\n return\n self.pooledTokens[index].balanceOf(address(this)).sub(\n self.balances[index]\n );\n }\n\n /**\n * @notice internal helper function to calculate fee per token multiplier used in\n * swap fee calculations\n * @param swapFee swap fee for the tokens\n * @param numTokens number of tokens pooled\n */\n function _feePerToken(uint256 swapFee, uint256 numTokens)\n internal\n pure\n returns (uint256)\n {\n return swapFee.mul(numTokens).div(numTokens.sub(1).mul(4));\n }\n\n /*** STATE MODIFYING FUNCTIONS ***/\n\n /**\n * @notice swap two tokens in the pool\n * @param self Swap struct to read from and write to\n * @param tokenIndexFrom the token the user wants to sell\n * @param tokenIndexTo the token the user wants to buy\n * @param dx the amount of tokens the user wants to sell\n * @param minDy the min amount the user would like to receive, or revert.\n * @return amount of token user received on swap\n */\n function swap(\n Swap storage self,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx,\n uint256 minDy\n ) external returns (uint256) {\n {\n IERC20 tokenFrom = self.pooledTokens[tokenIndexFrom];\n require(\n dx <= tokenFrom.balanceOf(msg.sender),\n \"Cannot swap more than you own\"\n );\n // Transfer tokens first to see if a fee was charged on transfer\n uint256 beforeBalance = tokenFrom.balanceOf(address(this));\n tokenFrom.safeTransferFrom(msg.sender, address(this), dx);\n\n // Use the actual transferred amount for AMM math\n dx = tokenFrom.balanceOf(address(this)).sub(beforeBalance);\n }\n\n uint256 dy;\n uint256 dyFee;\n uint256[] memory balances = self.balances;\n (dy, dyFee) = _calculateSwap(\n self,\n tokenIndexFrom,\n tokenIndexTo,\n dx,\n balances\n );\n require(dy >= minDy, \"Swap didn't result in min tokens\");\n\n uint256 dyAdminFee = dyFee.mul(self.adminFee).div(FEE_DENOMINATOR).div(\n self.tokenPrecisionMultipliers[tokenIndexTo]\n );\n\n self.balances[tokenIndexFrom] = balances[tokenIndexFrom].add(dx);\n self.balances[tokenIndexTo] = balances[tokenIndexTo].sub(dy).sub(\n dyAdminFee\n );\n\n self.pooledTokens[tokenIndexTo].safeTransfer(msg.sender, dy);\n\n emit TokenSwap(msg.sender, dx, dy, tokenIndexFrom, tokenIndexTo);\n\n return dy;\n }\n\n /**\n * @notice Add liquidity to the pool\n * @param self Swap struct to read from and write to\n * @param amounts the amounts of each token to add, in their native precision\n * @param minToMint the minimum LP tokens adding this amount of liquidity\n * should mint, otherwise revert. Handy for front-running mitigation\n * allowed addresses. If the pool is not in the guarded launch phase, this parameter will be ignored.\n * @return amount of LP token user received\n */\n function addLiquidity(\n Swap storage self,\n uint256[] memory amounts,\n uint256 minToMint\n ) external returns (uint256) {\n IERC20[] memory pooledTokens = self.pooledTokens;\n require(\n amounts.length == pooledTokens.length,\n \"Amounts must match pooled tokens\"\n );\n\n // current state\n ManageLiquidityInfo memory v = ManageLiquidityInfo(\n 0,\n 0,\n 0,\n _getAPrecise(self),\n self.lpToken,\n 0,\n self.balances,\n self.tokenPrecisionMultipliers\n );\n v.totalSupply = v.lpToken.totalSupply();\n\n if (v.totalSupply != 0) {\n v.d0 = getD(_xp(v.balances, v.multipliers), v.preciseA);\n }\n\n uint256[] memory newBalances = new uint256[](pooledTokens.length);\n\n for (uint256 i = 0; i < pooledTokens.length; i++) {\n require(\n v.totalSupply != 0 || amounts[i] > 0,\n \"Must supply all tokens in pool\"\n );\n\n // Transfer tokens first to see if a fee was charged on transfer\n if (amounts[i] != 0) {\n uint256 beforeBalance = pooledTokens[i].balanceOf(\n address(this)\n );\n pooledTokens[i].safeTransferFrom(\n msg.sender,\n address(this),\n amounts[i]\n );\n\n // Update the amounts[] with actual transfer amount\n amounts[i] = pooledTokens[i].balanceOf(address(this)).sub(\n beforeBalance\n );\n }\n\n newBalances[i] = v.balances[i].add(amounts[i]);\n }\n\n // invariant after change\n v.d1 = getD(_xp(newBalances, v.multipliers), v.preciseA);\n require(v.d1 > v.d0, \"D should increase\");\n\n // updated to reflect fees and calculate the user's LP tokens\n v.d2 = v.d1;\n uint256[] memory fees = new uint256[](pooledTokens.length);\n\n if (v.totalSupply != 0) {\n uint256 feePerToken = _feePerToken(\n self.swapFee,\n pooledTokens.length\n );\n for (uint256 i = 0; i < pooledTokens.length; i++) {\n uint256 idealBalance = v.d1.mul(v.balances[i]).div(v.d0);\n fees[i] = feePerToken\n .mul(idealBalance.difference(newBalances[i]))\n .div(FEE_DENOMINATOR);\n self.balances[i] = newBalances[i].sub(\n fees[i].mul(self.adminFee).div(FEE_DENOMINATOR)\n );\n newBalances[i] = newBalances[i].sub(fees[i]);\n }\n v.d2 = getD(_xp(newBalances, v.multipliers), v.preciseA);\n } else {\n // the initial depositor doesn't pay fees\n self.balances = newBalances;\n }\n\n uint256 toMint;\n if (v.totalSupply == 0) {\n toMint = v.d1;\n } else {\n toMint = v.d2.sub(v.d0).mul(v.totalSupply).div(v.d0);\n }\n\n require(toMint >= minToMint, \"Couldn't mint min requested\");\n\n // mint the user's LP tokens\n v.lpToken.mint(msg.sender, toMint);\n\n emit AddLiquidity(\n msg.sender,\n amounts,\n fees,\n v.d1,\n v.totalSupply.add(toMint)\n );\n\n return toMint;\n }\n\n /**\n * @notice Burn LP tokens to remove liquidity from the pool.\n * @dev Liquidity can always be removed, even when the pool is paused.\n * @param self Swap struct to read from and write to\n * @param amount the amount of LP tokens to burn\n * @param minAmounts the minimum amounts of each token in the pool\n * acceptable for this burn. Useful as a front-running mitigation\n * @return amounts of tokens the user received\n */\n function removeLiquidity(\n Swap storage self,\n uint256 amount,\n uint256[] calldata minAmounts\n ) external returns (uint256[] memory) {\n LPToken lpToken = self.lpToken;\n IERC20[] memory pooledTokens = self.pooledTokens;\n require(amount <= lpToken.balanceOf(msg.sender), \">LP.balanceOf\");\n require(\n minAmounts.length == pooledTokens.length,\n \"minAmounts must match poolTokens\"\n );\n\n uint256[] memory balances = self.balances;\n uint256 totalSupply = lpToken.totalSupply();\n\n uint256[] memory amounts = _calculateRemoveLiquidity(\n balances,\n amount,\n totalSupply\n );\n\n for (uint256 i = 0; i < amounts.length; i++) {\n require(amounts[i] >= minAmounts[i], \"amounts[i] < minAmounts[i]\");\n self.balances[i] = balances[i].sub(amounts[i]);\n pooledTokens[i].safeTransfer(msg.sender, amounts[i]);\n }\n\n lpToken.burnFrom(msg.sender, amount);\n\n emit RemoveLiquidity(msg.sender, amounts, totalSupply.sub(amount));\n\n return amounts;\n }\n\n /**\n * @notice Remove liquidity from the pool all in one token.\n * @param self Swap struct to read from and write to\n * @param tokenAmount the amount of the lp tokens to burn\n * @param tokenIndex the index of the token you want to receive\n * @param minAmount the minimum amount to withdraw, otherwise revert\n * @return amount chosen token that user received\n */\n function removeLiquidityOneToken(\n Swap storage self,\n uint256 tokenAmount,\n uint8 tokenIndex,\n uint256 minAmount\n ) external returns (uint256) {\n LPToken lpToken = self.lpToken;\n IERC20[] memory pooledTokens = self.pooledTokens;\n\n require(tokenAmount <= lpToken.balanceOf(msg.sender), \">LP.balanceOf\");\n require(tokenIndex < pooledTokens.length, \"Token not found\");\n\n uint256 totalSupply = lpToken.totalSupply();\n\n (uint256 dy, uint256 dyFee) = _calculateWithdrawOneToken(\n self,\n tokenAmount,\n tokenIndex,\n totalSupply\n );\n\n require(dy >= minAmount, \"dy < minAmount\");\n\n self.balances[tokenIndex] = self.balances[tokenIndex].sub(\n dy.add(dyFee.mul(self.adminFee).div(FEE_DENOMINATOR))\n );\n lpToken.burnFrom(msg.sender, tokenAmount);\n pooledTokens[tokenIndex].safeTransfer(msg.sender, dy);\n\n emit RemoveLiquidityOne(\n msg.sender,\n tokenAmount,\n totalSupply,\n tokenIndex,\n dy\n );\n\n return dy;\n }\n\n /**\n * @notice Remove liquidity from the pool, weighted differently than the\n * pool's current balances.\n *\n * @param self Swap struct to read from and write to\n * @param amounts how much of each token to withdraw\n * @param maxBurnAmount the max LP token provider is willing to pay to\n * remove liquidity. Useful as a front-running mitigation.\n * @return actual amount of LP tokens burned in the withdrawal\n */\n function removeLiquidityImbalance(\n Swap storage self,\n uint256[] memory amounts,\n uint256 maxBurnAmount\n ) public returns (uint256) {\n ManageLiquidityInfo memory v = ManageLiquidityInfo(\n 0,\n 0,\n 0,\n _getAPrecise(self),\n self.lpToken,\n 0,\n self.balances,\n self.tokenPrecisionMultipliers\n );\n v.totalSupply = v.lpToken.totalSupply();\n\n IERC20[] memory pooledTokens = self.pooledTokens;\n\n require(\n amounts.length == pooledTokens.length,\n \"Amounts should match pool tokens\"\n );\n\n require(\n maxBurnAmount <= v.lpToken.balanceOf(msg.sender) &&\n maxBurnAmount != 0,\n \">LP.balanceOf\"\n );\n\n uint256 feePerToken = _feePerToken(self.swapFee, pooledTokens.length);\n uint256[] memory fees = new uint256[](pooledTokens.length);\n {\n uint256[] memory balances1 = new uint256[](pooledTokens.length);\n v.d0 = getD(_xp(v.balances, v.multipliers), v.preciseA);\n for (uint256 i = 0; i < pooledTokens.length; i++) {\n balances1[i] = v.balances[i].sub(\n amounts[i],\n \"Cannot withdraw more than available\"\n );\n }\n v.d1 = getD(_xp(balances1, v.multipliers), v.preciseA);\n\n for (uint256 i = 0; i < pooledTokens.length; i++) {\n uint256 idealBalance = v.d1.mul(v.balances[i]).div(v.d0);\n uint256 difference = idealBalance.difference(balances1[i]);\n fees[i] = feePerToken.mul(difference).div(FEE_DENOMINATOR);\n self.balances[i] = balances1[i].sub(\n fees[i].mul(self.adminFee).div(FEE_DENOMINATOR)\n );\n balances1[i] = balances1[i].sub(fees[i]);\n }\n\n v.d2 = getD(_xp(balances1, v.multipliers), v.preciseA);\n }\n uint256 tokenAmount = v.d0.sub(v.d2).mul(v.totalSupply).div(v.d0);\n require(tokenAmount != 0, \"Burnt amount cannot be zero\");\n tokenAmount = tokenAmount.add(1);\n\n require(tokenAmount <= maxBurnAmount, \"tokenAmount > maxBurnAmount\");\n\n v.lpToken.burnFrom(msg.sender, tokenAmount);\n\n for (uint256 i = 0; i < pooledTokens.length; i++) {\n pooledTokens[i].safeTransfer(msg.sender, amounts[i]);\n }\n\n emit RemoveLiquidityImbalance(\n msg.sender,\n amounts,\n fees,\n v.d1,\n v.totalSupply.sub(tokenAmount)\n );\n\n return tokenAmount;\n }\n\n /**\n * @notice withdraw all admin fees to a given address\n * @param self Swap struct to withdraw fees from\n * @param to Address to send the fees to\n */\n function withdrawAdminFees(Swap storage self, address to) external {\n IERC20[] memory pooledTokens = self.pooledTokens;\n for (uint256 i = 0; i < pooledTokens.length; i++) {\n IERC20 token = pooledTokens[i];\n uint256 balance = token.balanceOf(address(this)).sub(\n self.balances[i]\n );\n if (balance != 0) {\n token.safeTransfer(to, balance);\n }\n }\n }\n\n /**\n * @notice Sets the admin fee\n * @dev adminFee cannot be higher than 100% of the swap fee\n * @param self Swap struct to update\n * @param newAdminFee new admin fee to be applied on future transactions\n */\n function setAdminFee(Swap storage self, uint256 newAdminFee) external {\n require(newAdminFee <= MAX_ADMIN_FEE, \"Fee is too high\");\n self.adminFee = newAdminFee;\n\n emit NewAdminFee(newAdminFee);\n }\n\n /**\n * @notice update the swap fee\n * @dev fee cannot be higher than 1% of each swap\n * @param self Swap struct to update\n * @param newSwapFee new swap fee to be applied on future transactions\n */\n function setSwapFee(Swap storage self, uint256 newSwapFee) external {\n require(newSwapFee <= MAX_SWAP_FEE, \"Fee is too high\");\n self.swapFee = newSwapFee;\n\n emit NewSwapFee(newSwapFee);\n }\n}\n" + }, + "contracts/amm/AmplificationUtils.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.6.12;\n\nimport \"@openzeppelin/contracts/token/ERC20/SafeERC20.sol\";\nimport \"./SwapUtils.sol\";\n\n/**\n * @title AmplificationUtils library\n * @notice A library to calculate and ramp the A parameter of a given `SwapUtils.Swap` struct.\n * This library assumes the struct is fully validated.\n */\nlibrary AmplificationUtils {\n using SafeMath for uint256;\n\n event RampA(\n uint256 oldA,\n uint256 newA,\n uint256 initialTime,\n uint256 futureTime\n );\n event StopRampA(uint256 currentA, uint256 time);\n\n // Constant values used in ramping A calculations\n uint256 public constant A_PRECISION = 100;\n uint256 public constant MAX_A = 10**6;\n uint256 private constant MAX_A_CHANGE = 2;\n uint256 private constant MIN_RAMP_TIME = 7 days;\n\n /**\n * @notice Return A, the amplification coefficient * n * (n - 1)\n * @dev See the StableSwap paper for details\n * @param self Swap struct to read from\n * @return A parameter\n */\n function getA(SwapUtils.Swap storage self) external view returns (uint256) {\n return _getAPrecise(self).div(A_PRECISION);\n }\n\n /**\n * @notice Return A in its raw precision\n * @dev See the StableSwap paper for details\n * @param self Swap struct to read from\n * @return A parameter in its raw precision form\n */\n function getAPrecise(SwapUtils.Swap storage self)\n external\n view\n returns (uint256)\n {\n return _getAPrecise(self);\n }\n\n /**\n * @notice Return A in its raw precision\n * @dev See the StableSwap paper for details\n * @param self Swap struct to read from\n * @return A parameter in its raw precision form\n */\n function _getAPrecise(SwapUtils.Swap storage self)\n internal\n view\n returns (uint256)\n {\n uint256 t1 = self.futureATime; // time when ramp is finished\n uint256 a1 = self.futureA; // final A value when ramp is finished\n\n if (block.timestamp < t1) {\n uint256 t0 = self.initialATime; // time when ramp is started\n uint256 a0 = self.initialA; // initial A value when ramp is started\n if (a1 > a0) {\n // a0 + (a1 - a0) * (block.timestamp - t0) / (t1 - t0)\n return\n a0.add(\n a1.sub(a0).mul(block.timestamp.sub(t0)).div(t1.sub(t0))\n );\n } else {\n // a0 - (a0 - a1) * (block.timestamp - t0) / (t1 - t0)\n return\n a0.sub(\n a0.sub(a1).mul(block.timestamp.sub(t0)).div(t1.sub(t0))\n );\n }\n } else {\n return a1;\n }\n }\n\n /**\n * @notice Start ramping up or down A parameter towards given futureA_ and futureTime_\n * Checks if the change is too rapid, and commits the new A value only when it falls under\n * the limit range.\n * @param self Swap struct to update\n * @param futureA_ the new A to ramp towards\n * @param futureTime_ timestamp when the new A should be reached\n */\n function rampA(\n SwapUtils.Swap storage self,\n uint256 futureA_,\n uint256 futureTime_\n ) external {\n require(\n block.timestamp >= self.initialATime.add(1 days),\n \"Wait 1 day before starting ramp\"\n );\n require(\n futureTime_ >= block.timestamp.add(MIN_RAMP_TIME),\n \"Insufficient ramp time\"\n );\n require(\n futureA_ > 0 && futureA_ < MAX_A,\n \"futureA_ must be > 0 and < MAX_A\"\n );\n\n uint256 initialAPrecise = _getAPrecise(self);\n uint256 futureAPrecise = futureA_.mul(A_PRECISION);\n\n if (futureAPrecise < initialAPrecise) {\n require(\n futureAPrecise.mul(MAX_A_CHANGE) >= initialAPrecise,\n \"futureA_ is too small\"\n );\n } else {\n require(\n futureAPrecise <= initialAPrecise.mul(MAX_A_CHANGE),\n \"futureA_ is too large\"\n );\n }\n\n self.initialA = initialAPrecise;\n self.futureA = futureAPrecise;\n self.initialATime = block.timestamp;\n self.futureATime = futureTime_;\n\n emit RampA(\n initialAPrecise,\n futureAPrecise,\n block.timestamp,\n futureTime_\n );\n }\n\n /**\n * @notice Stops ramping A immediately. Once this function is called, rampA()\n * cannot be called for another 24 hours\n * @param self Swap struct to update\n */\n function stopRampA(SwapUtils.Swap storage self) external {\n require(self.futureATime > block.timestamp, \"Ramp is already stopped\");\n\n uint256 currentA = _getAPrecise(self);\n self.initialA = currentA;\n self.futureA = currentA;\n self.initialATime = block.timestamp;\n self.futureATime = block.timestamp;\n\n emit StopRampA(currentA, block.timestamp);\n }\n}\n" + }, + "@openzeppelin/contracts/token/ERC20/IERC20.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <0.8.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" + }, + "@openzeppelin/contracts/utils/Address.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.2 <0.8.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" + }, + "@openzeppelin/contracts-upgradeable/proxy/Initializable.sol": { + "content": "// SPDX-License-Identifier: MIT\n\n// solhint-disable-next-line compiler-version\npragma solidity >=0.4.24 <0.8.0;\n\nimport \"../utils/AddressUpgradeable.sol\";\n\n/**\n * @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed\n * behind a proxy. Since a proxied contract can't have a constructor, it's common to move constructor logic to an\n * external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer\n * function so it can only be called once. The {initializer} modifier provided by this contract will have this effect.\n *\n * TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as\n * possible by providing the encoded function call as the `_data` argument to {UpgradeableProxy-constructor}.\n *\n * CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure\n * that all initializers are idempotent. This is not verified automatically as constructors are by Solidity.\n */\nabstract contract Initializable {\n\n /**\n * @dev Indicates that the contract has been initialized.\n */\n bool private _initialized;\n\n /**\n * @dev Indicates that the contract is in the process of being initialized.\n */\n bool private _initializing;\n\n /**\n * @dev Modifier to protect an initializer function from being invoked twice.\n */\n modifier initializer() {\n require(_initializing || _isConstructor() || !_initialized, \"Initializable: contract is already initialized\");\n\n bool isTopLevelCall = !_initializing;\n if (isTopLevelCall) {\n _initializing = true;\n _initialized = true;\n }\n\n _;\n\n if (isTopLevelCall) {\n _initializing = false;\n }\n }\n\n /// @dev Returns true if and only if the function is running in the constructor\n function _isConstructor() private view returns (bool) {\n return !AddressUpgradeable.isContract(address(this));\n }\n}\n" + }, + "@openzeppelin/contracts-upgradeable/utils/AddressUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.2 <0.8.0;\n\n/**\n * @dev Collection of functions related to the address type\n */\nlibrary AddressUpgradeable {\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 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" + }, + "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <0.8.0;\n\nimport \"../utils/ContextUpgradeable.sol\";\nimport \"../proxy/Initializable.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 OwnableUpgradeable is Initializable, ContextUpgradeable {\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 function __Ownable_init() internal initializer {\n __Context_init_unchained();\n __Ownable_init_unchained();\n }\n\n function __Ownable_init_unchained() internal initializer {\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 uint256[49] private __gap;\n}\n" + }, + "@openzeppelin/contracts-upgradeable/utils/PausableUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <0.8.0;\n\nimport \"./ContextUpgradeable.sol\";\nimport \"../proxy/Initializable.sol\";\n\n/**\n * @dev Contract module which allows children to implement an emergency stop\n * mechanism that can be triggered by an authorized account.\n *\n * This module is used through inheritance. It will make available the\n * modifiers `whenNotPaused` and `whenPaused`, which can be applied to\n * the functions of your contract. Note that they will not be pausable by\n * simply including this module, only once the modifiers are put in place.\n */\nabstract contract PausableUpgradeable is Initializable, ContextUpgradeable {\n /**\n * @dev Emitted when the pause is triggered by `account`.\n */\n event Paused(address account);\n\n /**\n * @dev Emitted when the pause is lifted by `account`.\n */\n event Unpaused(address account);\n\n bool private _paused;\n\n /**\n * @dev Initializes the contract in unpaused state.\n */\n function __Pausable_init() internal initializer {\n __Context_init_unchained();\n __Pausable_init_unchained();\n }\n\n function __Pausable_init_unchained() internal initializer {\n _paused = false;\n }\n\n /**\n * @dev Returns true if the contract is paused, and false otherwise.\n */\n function paused() public view virtual returns (bool) {\n return _paused;\n }\n\n /**\n * @dev Modifier to make a function callable only when the contract is not paused.\n *\n * Requirements:\n *\n * - The contract must not be paused.\n */\n modifier whenNotPaused() {\n require(!paused(), \"Pausable: paused\");\n _;\n }\n\n /**\n * @dev Modifier to make a function callable only when the contract is paused.\n *\n * Requirements:\n *\n * - The contract must be paused.\n */\n modifier whenPaused() {\n require(paused(), \"Pausable: not paused\");\n _;\n }\n\n /**\n * @dev Triggers stopped state.\n *\n * Requirements:\n *\n * - The contract must not be paused.\n */\n function _pause() internal virtual whenNotPaused {\n _paused = true;\n emit Paused(_msgSender());\n }\n\n /**\n * @dev Returns to normal state.\n *\n * Requirements:\n *\n * - The contract must be paused.\n */\n function _unpause() internal virtual whenPaused {\n _paused = false;\n emit Unpaused(_msgSender());\n }\n uint256[49] private __gap;\n}\n" + }, + "@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <0.8.0;\nimport \"../proxy/Initializable.sol\";\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 ContextUpgradeable is Initializable {\n function __Context_init() internal initializer {\n __Context_init_unchained();\n }\n\n function __Context_init_unchained() internal initializer {\n }\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 uint256[50] private __gap;\n}\n" + }, + "contracts/amm/LPToken.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.6.12;\n\nimport \"@openzeppelin/contracts-upgradeable/token/ERC20/ERC20BurnableUpgradeable.sol\";\nimport \"@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol\";\nimport \"./interfaces/ISwap.sol\";\n\n/**\n * @title Liquidity Provider Token\n * @notice This token is an ERC20 detailed token with added capability to be minted by the owner.\n * It is used to represent user's shares when providing liquidity to swap contracts.\n * @dev Only Swap contracts should initialize and own LPToken contracts.\n */\ncontract LPToken is ERC20BurnableUpgradeable, OwnableUpgradeable {\n using SafeMathUpgradeable for uint256;\n\n /**\n * @notice Initializes this LPToken contract with the given name and symbol\n * @dev The caller of this function will become the owner. A Swap contract should call this\n * in its initializer function.\n * @param name name of this token\n * @param symbol symbol of this token\n */\n function initialize(string memory name, string memory symbol)\n external\n initializer\n returns (bool)\n {\n __Context_init_unchained();\n __ERC20_init_unchained(name, symbol);\n __Ownable_init_unchained();\n return true;\n }\n\n /**\n * @notice Mints the given amount of LPToken to the recipient.\n * @dev only owner can call this mint function\n * @param recipient address of account to receive the tokens\n * @param amount amount of tokens to mint\n */\n function mint(address recipient, uint256 amount) external onlyOwner {\n require(amount != 0, \"LPToken: cannot mint 0\");\n _mint(recipient, amount);\n }\n\n /**\n * @dev Overrides ERC20._beforeTokenTransfer() which get called on every transfers including\n * minting and burning. * This assumes the owner is set to a Swap contract's address.\n */\n function _beforeTokenTransfer(\n address from,\n address to,\n uint256 amount\n ) internal virtual override(ERC20Upgradeable) {\n super._beforeTokenTransfer(from, to, amount);\n require(to != address(this), \"LPToken: cannot send to itself\");\n }\n}\n" + }, + "contracts/amm/MathUtils.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.6.12;\n\nimport \"@openzeppelin/contracts/math/SafeMath.sol\";\n\n/**\n * @title MathUtils library\n * @notice A library to be used in conjunction with SafeMath. Contains functions for calculating\n * differences between two uint256.\n */\nlibrary MathUtils {\n /**\n * @notice Compares a and b and returns true if the difference between a and b\n * is less than 1 or equal to each other.\n * @param a uint256 to compare with\n * @param b uint256 to compare with\n * @return True if the difference between a and b is less than 1 or equal,\n * otherwise return false\n */\n function within1(uint256 a, uint256 b) internal pure returns (bool) {\n return (difference(a, b) <= 1);\n }\n\n /**\n * @notice Calculates absolute difference between a and b\n * @param a uint256 to compare with\n * @param b uint256 to compare with\n * @return Difference between a and b\n */\n function difference(uint256 a, uint256 b) internal pure returns (uint256) {\n if (a > b) {\n return a - b;\n }\n return b - a;\n }\n}\n" + }, + "@openzeppelin/contracts-upgradeable/token/ERC20/ERC20BurnableUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <0.8.0;\n\nimport \"../../utils/ContextUpgradeable.sol\";\nimport \"./ERC20Upgradeable.sol\";\nimport \"../../proxy/Initializable.sol\";\n\n/**\n * @dev Extension of {ERC20} that allows token holders to destroy both their own\n * tokens and those that they have an allowance for, in a way that can be\n * recognized off-chain (via event analysis).\n */\nabstract contract ERC20BurnableUpgradeable is Initializable, ContextUpgradeable, ERC20Upgradeable {\n function __ERC20Burnable_init() internal initializer {\n __Context_init_unchained();\n __ERC20Burnable_init_unchained();\n }\n\n function __ERC20Burnable_init_unchained() internal initializer {\n }\n using SafeMathUpgradeable for uint256;\n\n /**\n * @dev Destroys `amount` tokens from the caller.\n *\n * See {ERC20-_burn}.\n */\n function burn(uint256 amount) public virtual {\n _burn(_msgSender(), amount);\n }\n\n /**\n * @dev Destroys `amount` tokens from `account`, deducting from the caller's\n * allowance.\n *\n * See {ERC20-_burn} and {ERC20-allowance}.\n *\n * Requirements:\n *\n * - the caller must have allowance for ``accounts``'s tokens of at least\n * `amount`.\n */\n function burnFrom(address account, uint256 amount) public virtual {\n uint256 decreasedAllowance = allowance(account, _msgSender()).sub(amount, \"ERC20: burn amount exceeds allowance\");\n\n _approve(account, _msgSender(), decreasedAllowance);\n _burn(account, amount);\n }\n uint256[50] private __gap;\n}\n" + }, + "contracts/amm/interfaces/ISwap.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.6.12;\n\nimport \"@openzeppelin/contracts/token/ERC20/ERC20.sol\";\n\ninterface ISwap {\n // pool data view functions\n function getA() external view returns (uint256);\n\n function getToken(uint8 index) external view returns (IERC20);\n\n function getTokenIndex(address tokenAddress) external view returns (uint8);\n\n function getTokenBalance(uint8 index) external view returns (uint256);\n\n function getVirtualPrice() external view returns (uint256);\n\n // min return calculation functions\n function calculateSwap(\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx\n ) external view returns (uint256);\n\n function calculateTokenAmount(uint256[] calldata amounts, bool deposit)\n external\n view\n returns (uint256);\n\n function calculateRemoveLiquidity(uint256 amount)\n external\n view\n returns (uint256[] memory);\n\n function calculateRemoveLiquidityOneToken(\n uint256 tokenAmount,\n uint8 tokenIndex\n ) external view returns (uint256 availableTokenAmount);\n\n // state modifying functions\n function initialize(\n IERC20[] memory pooledTokens,\n uint8[] memory decimals,\n string memory lpTokenName,\n string memory lpTokenSymbol,\n uint256 a,\n uint256 fee,\n uint256 adminFee,\n address lpTokenTargetAddress\n ) external;\n\n function swap(\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx,\n uint256 minDy,\n uint256 deadline\n ) external returns (uint256);\n\n function addLiquidity(\n uint256[] calldata amounts,\n uint256 minToMint,\n uint256 deadline\n ) external returns (uint256);\n\n function removeLiquidity(\n uint256 amount,\n uint256[] calldata minAmounts,\n uint256 deadline\n ) external returns (uint256[] memory);\n\n function removeLiquidityOneToken(\n uint256 tokenAmount,\n uint8 tokenIndex,\n uint256 minAmount,\n uint256 deadline\n ) external returns (uint256);\n\n function removeLiquidityImbalance(\n uint256[] calldata amounts,\n uint256 maxBurnAmount,\n uint256 deadline\n ) external returns (uint256);\n}\n" + }, + "@openzeppelin/contracts-upgradeable/token/ERC20/ERC20Upgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <0.8.0;\n\nimport \"../../utils/ContextUpgradeable.sol\";\nimport \"./IERC20Upgradeable.sol\";\nimport \"../../math/SafeMathUpgradeable.sol\";\nimport \"../../proxy/Initializable.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 ERC20Upgradeable is Initializable, ContextUpgradeable, IERC20Upgradeable {\n using SafeMathUpgradeable 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 function __ERC20_init(string memory name_, string memory symbol_) internal initializer {\n __Context_init_unchained();\n __ERC20_init_unchained(name_, symbol_);\n }\n\n function __ERC20_init_unchained(string memory name_, string memory symbol_) internal initializer {\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 uint256[44] private __gap;\n}\n" + }, + "@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <0.8.0;\n\n/**\n * @dev Interface of the ERC20 standard as defined in the EIP.\n */\ninterface IERC20Upgradeable {\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" + }, + "@openzeppelin/contracts-upgradeable/math/SafeMathUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <0.8.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 SafeMathUpgradeable {\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" + }, + "@openzeppelin/contracts/token/ERC20/ERC20.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <0.8.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_) public {\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" + }, + "@openzeppelin/contracts/utils/Context.sol": { + "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" + }, + "contracts/amm/SwapFlashLoan.sol": { + "content": "// SPDX-License-Identifier: MIT WITH AGPL-3.0-only\n\npragma solidity 0.6.12;\n\nimport \"./Swap.sol\";\nimport \"./interfaces/IFlashLoanReceiver.sol\";\n\n/**\n * @title Swap - A StableSwap implementation in solidity.\n * @notice This contract is responsible for custody of closely pegged assets (eg. group of stablecoins)\n * and automatic market making system. Users become an LP (Liquidity Provider) by depositing their tokens\n * in desired ratios for an exchange of the pool token that represents their share of the pool.\n * Users can burn pool tokens and withdraw their share of token(s).\n *\n * Each time a swap between the pooled tokens happens, a set fee incurs which effectively gets\n * distributed to the LPs.\n *\n * In case of emergencies, admin can pause additional deposits, swaps, or single-asset withdraws - which\n * stops the ratio of the tokens in the pool from changing.\n * Users can always withdraw their tokens via multi-asset withdraws.\n *\n * @dev Most of the logic is stored as a library `SwapUtils` for the sake of reducing contract's\n * deployment size.\n */\ncontract SwapFlashLoan is Swap {\n // Total fee that is charged on all flashloans in BPS. Borrowers must repay the amount plus the flash loan fee.\n // This fee is split between the protocol and the pool.\n uint256 public flashLoanFeeBPS;\n // Share of the flash loan fee that goes to the protocol in BPS. A portion of each flash loan fee is allocated\n // to the protocol rather than the pool.\n uint256 public protocolFeeShareBPS;\n // Max BPS for limiting flash loan fee settings.\n uint256 public constant MAX_BPS = 10000;\n\n /*** EVENTS ***/\n event FlashLoan(\n address indexed receiver,\n uint8 tokenIndex,\n uint256 amount,\n uint256 amountFee,\n uint256 protocolFee\n );\n\n /**\n * @notice Initializes this Swap contract with the given parameters.\n * This will also clone a LPToken contract that represents users'\n * LP positions. The owner of LPToken will be this contract - which means\n * only this contract is allowed to mint/burn tokens.\n *\n * @param _pooledTokens an array of ERC20s this pool will accept\n * @param decimals the decimals to use for each pooled token,\n * eg 8 for WBTC. Cannot be larger than POOL_PRECISION_DECIMALS\n * @param lpTokenName the long-form name of the token to be deployed\n * @param lpTokenSymbol the short symbol for the token to be deployed\n * @param _a the amplification coefficient * n * (n - 1). See the\n * StableSwap paper for details\n * @param _fee default swap fee to be initialized with\n * @param _adminFee default adminFee to be initialized with\n * @param lpTokenTargetAddress the address of an existing LPToken contract to use as a target\n */\n function initialize(\n IERC20[] memory _pooledTokens,\n uint8[] memory decimals,\n string memory lpTokenName,\n string memory lpTokenSymbol,\n uint256 _a,\n uint256 _fee,\n uint256 _adminFee,\n address lpTokenTargetAddress\n ) public virtual override initializer {\n Swap.initialize(\n _pooledTokens,\n decimals,\n lpTokenName,\n lpTokenSymbol,\n _a,\n _fee,\n _adminFee,\n lpTokenTargetAddress\n );\n flashLoanFeeBPS = 8; // 8 bps\n protocolFeeShareBPS = 0; // 0 bps\n }\n\n /*** STATE MODIFYING FUNCTIONS ***/\n\n /**\n * @notice Borrow the specified token from this pool for this transaction only. This function will call\n * `IFlashLoanReceiver(receiver).executeOperation` and the `receiver` must return the full amount of the token\n * and the associated fee by the end of the callback transaction. If the conditions are not met, this call\n * is reverted.\n * @param receiver the address of the receiver of the token. This address must implement the IFlashLoanReceiver\n * interface and the callback function `executeOperation`.\n * @param token the protocol fee in bps to be applied on the total flash loan fee\n * @param amount the total amount to borrow in this transaction\n * @param params optional data to pass along to the callback function\n */\n function flashLoan(\n address receiver,\n IERC20 token,\n uint256 amount,\n bytes memory params\n ) external nonReentrant {\n uint8 tokenIndex = getTokenIndex(address(token));\n uint256 availableLiquidityBefore = token.balanceOf(address(this));\n uint256 protocolBalanceBefore = availableLiquidityBefore.sub(\n swapStorage.balances[tokenIndex]\n );\n require(\n amount > 0 && availableLiquidityBefore >= amount,\n \"invalid amount\"\n );\n\n // Calculate the additional amount of tokens the pool should end up with\n uint256 amountFee = amount.mul(flashLoanFeeBPS).div(10000);\n // Calculate the portion of the fee that will go to the protocol\n uint256 protocolFee = amountFee.mul(protocolFeeShareBPS).div(10000);\n require(amountFee > 0, \"amount is small for a flashLoan\");\n\n // Transfer the requested amount of tokens\n token.safeTransfer(receiver, amount);\n\n // Execute callback function on receiver\n IFlashLoanReceiver(receiver).executeOperation(\n address(this),\n address(token),\n amount,\n amountFee,\n params\n );\n\n uint256 availableLiquidityAfter = token.balanceOf(address(this));\n require(\n availableLiquidityAfter >= availableLiquidityBefore.add(amountFee),\n \"flashLoan fee is not met\"\n );\n\n swapStorage.balances[tokenIndex] = availableLiquidityAfter\n .sub(protocolBalanceBefore)\n .sub(protocolFee);\n emit FlashLoan(receiver, tokenIndex, amount, amountFee, protocolFee);\n }\n\n /*** ADMIN FUNCTIONS ***/\n\n /**\n * @notice Updates the flash loan fee parameters. This function can only be called by the owner.\n * @param newFlashLoanFeeBPS the total fee in bps to be applied on future flash loans\n * @param newProtocolFeeShareBPS the protocol fee in bps to be applied on the total flash loan fee\n */\n function setFlashLoanFees(\n uint256 newFlashLoanFeeBPS,\n uint256 newProtocolFeeShareBPS\n ) external onlyOwner {\n require(\n newFlashLoanFeeBPS > 0 &&\n newFlashLoanFeeBPS <= MAX_BPS &&\n newProtocolFeeShareBPS <= MAX_BPS,\n \"fees are not in valid range\"\n );\n flashLoanFeeBPS = newFlashLoanFeeBPS;\n protocolFeeShareBPS = newProtocolFeeShareBPS;\n }\n}\n" + }, + "contracts/amm/interfaces/IFlashLoanReceiver.sol": { + "content": "// SPDX-License-Identifier: AGPL-3.0-only\n\npragma solidity 0.6.12;\n\n/**\n * @title IFlashLoanReceiver interface\n * @notice Interface for the Nerve fee IFlashLoanReceiver. Modified from Aave's IFlashLoanReceiver interface.\n * https://github.com/aave/aave-protocol/blob/4b4545fb583fd4f400507b10f3c3114f45b8a037/contracts/flashloan/interfaces/IFlashLoanReceiver.sol\n * @author Aave\n * @dev implement this interface to develop a flashloan-compatible flashLoanReceiver contract\n **/\ninterface IFlashLoanReceiver {\n function executeOperation(\n address pool,\n address token,\n uint256 amount,\n uint256 fee,\n bytes calldata params\n ) external;\n}\n" + }, + "contracts/amm/helper/FlashLoanBorrowerExample.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.6.12;\n\nimport \"@openzeppelin/contracts/math/SafeMath.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/SafeERC20.sol\";\nimport \"../interfaces/IFlashLoanReceiver.sol\";\nimport \"../interfaces/ISwapFlashLoan.sol\";\nimport \"hardhat/console.sol\";\n\ncontract FlashLoanBorrowerExample is IFlashLoanReceiver {\n using SafeMath for uint256;\n\n // Typical executeOperation function should do the 3 following actions\n // 1. Check if the flashLoan was successful\n // 2. Do actions with the borrowed tokens\n // 3. Repay the debt to the `pool`\n function executeOperation(\n address pool,\n address token,\n uint256 amount,\n uint256 fee,\n bytes calldata params\n ) external override {\n // 1. Check if the flashLoan was valid\n require(\n IERC20(token).balanceOf(address(this)) >= amount,\n \"flashloan is broken?\"\n );\n\n // 2. Do actions with the borrowed token\n bytes32 paramsHash = keccak256(params);\n if (paramsHash == keccak256(bytes(\"dontRepayDebt\"))) {\n return;\n } else if (paramsHash == keccak256(bytes(\"reentrancy_addLiquidity\"))) {\n ISwapFlashLoan(pool).addLiquidity(\n new uint256[](0),\n 0,\n block.timestamp\n );\n } else if (paramsHash == keccak256(bytes(\"reentrancy_swap\"))) {\n ISwapFlashLoan(pool).swap(1, 0, 1e6, 0, now);\n } else if (\n paramsHash == keccak256(bytes(\"reentrancy_removeLiquidity\"))\n ) {\n ISwapFlashLoan(pool).removeLiquidity(1e18, new uint256[](0), now);\n } else if (\n paramsHash == keccak256(bytes(\"reentrancy_removeLiquidityOneToken\"))\n ) {\n ISwapFlashLoan(pool).removeLiquidityOneToken(1e18, 0, 1e18, now);\n }\n\n // 3. Payback debt\n uint256 totalDebt = amount.add(fee);\n IERC20(token).transfer(pool, totalDebt);\n }\n\n function flashLoan(\n ISwapFlashLoan swap,\n IERC20 token,\n uint256 amount,\n bytes memory params\n ) external {\n swap.flashLoan(address(this), token, amount, params);\n }\n}\n" + }, + "contracts/amm/interfaces/ISwapFlashLoan.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.6.12;\n\nimport \"./ISwap.sol\";\n\ninterface ISwapFlashLoan is ISwap {\n function flashLoan(\n address receiver,\n IERC20 token,\n uint256 amount,\n bytes memory params\n ) external;\n}\n" + }, + "hardhat/console.sol": { + "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" + }, + "contracts/amm/helper/test/TestSwapReturnValues.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.6.12;\n\nimport \"../../interfaces/ISwap.sol\";\nimport \"hardhat/console.sol\";\n\ncontract TestSwapReturnValues {\n using SafeMath for uint256;\n\n ISwap public swap;\n IERC20 public lpToken;\n uint8 public n;\n\n uint256 public constant MAX_INT = 2**256 - 1;\n\n constructor(\n ISwap swapContract,\n IERC20 lpTokenContract,\n uint8 numOfTokens\n ) public {\n swap = swapContract;\n lpToken = lpTokenContract;\n n = numOfTokens;\n\n // Pre-approve tokens\n for (uint8 i; i < n; i++) {\n swap.getToken(i).approve(address(swap), MAX_INT);\n }\n lpToken.approve(address(swap), MAX_INT);\n }\n\n function test_swap(\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx,\n uint256 minDy\n ) public {\n uint256 balanceBefore =\n swap.getToken(tokenIndexTo).balanceOf(address(this));\n uint256 returnValue =\n swap.swap(tokenIndexFrom, tokenIndexTo, dx, minDy, block.timestamp);\n uint256 balanceAfter =\n swap.getToken(tokenIndexTo).balanceOf(address(this));\n\n console.log(\n \"swap: Expected %s, got %s\",\n balanceAfter.sub(balanceBefore),\n returnValue\n );\n\n require(\n returnValue == balanceAfter.sub(balanceBefore),\n \"swap()'s return value does not match received amount\"\n );\n }\n\n function test_addLiquidity(uint256[] calldata amounts, uint256 minToMint)\n public\n {\n uint256 balanceBefore = lpToken.balanceOf(address(this));\n uint256 returnValue = swap.addLiquidity(amounts, minToMint, MAX_INT);\n uint256 balanceAfter = lpToken.balanceOf(address(this));\n\n console.log(\n \"addLiquidity: Expected %s, got %s\",\n balanceAfter.sub(balanceBefore),\n returnValue\n );\n\n require(\n returnValue == balanceAfter.sub(balanceBefore),\n \"addLiquidity()'s return value does not match minted amount\"\n );\n }\n\n function test_removeLiquidity(uint256 amount, uint256[] memory minAmounts)\n public\n {\n uint256[] memory balanceBefore = new uint256[](n);\n uint256[] memory balanceAfter = new uint256[](n);\n\n for (uint8 i = 0; i < n; i++) {\n balanceBefore[i] = swap.getToken(i).balanceOf(address(this));\n }\n\n uint256[] memory returnValue =\n swap.removeLiquidity(amount, minAmounts, MAX_INT);\n\n for (uint8 i = 0; i < n; i++) {\n balanceAfter[i] = swap.getToken(i).balanceOf(address(this));\n console.log(\n \"removeLiquidity: Expected %s, got %s\",\n balanceAfter[i].sub(balanceBefore[i]),\n returnValue[i]\n );\n require(\n balanceAfter[i].sub(balanceBefore[i]) == returnValue[i],\n \"removeLiquidity()'s return value does not match received amounts of tokens\"\n );\n }\n }\n\n function test_removeLiquidityImbalance(\n uint256[] calldata amounts,\n uint256 maxBurnAmount\n ) public {\n uint256 balanceBefore = lpToken.balanceOf(address(this));\n uint256 returnValue =\n swap.removeLiquidityImbalance(amounts, maxBurnAmount, MAX_INT);\n uint256 balanceAfter = lpToken.balanceOf(address(this));\n\n console.log(\n \"removeLiquidityImbalance: Expected %s, got %s\",\n balanceBefore.sub(balanceAfter),\n returnValue\n );\n\n require(\n returnValue == balanceBefore.sub(balanceAfter),\n \"removeLiquidityImbalance()'s return value does not match burned lpToken amount\"\n );\n }\n\n function test_removeLiquidityOneToken(\n uint256 tokenAmount,\n uint8 tokenIndex,\n uint256 minAmount\n ) public {\n uint256 balanceBefore =\n swap.getToken(tokenIndex).balanceOf(address(this));\n uint256 returnValue =\n swap.removeLiquidityOneToken(\n tokenAmount,\n tokenIndex,\n minAmount,\n MAX_INT\n );\n uint256 balanceAfter =\n swap.getToken(tokenIndex).balanceOf(address(this));\n\n console.log(\n \"removeLiquidityOneToken: Expected %s, got %s\",\n balanceAfter.sub(balanceBefore),\n returnValue\n );\n\n require(\n returnValue == balanceAfter.sub(balanceBefore),\n \"removeLiquidityOneToken()'s return value does not match received token amount\"\n );\n }\n}\n" + }, + "contracts/amm/SwapDeployer.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.6.12;\n\nimport \"@openzeppelin/contracts/access/Ownable.sol\";\nimport \"@openzeppelin/contracts/proxy/Clones.sol\";\nimport \"./interfaces/ISwap.sol\";\n\ncontract SwapDeployer is Ownable {\n event NewSwapPool(\n address indexed deployer,\n address swapAddress,\n IERC20[] pooledTokens\n );\n\n constructor() public Ownable() {}\n\n function deploy(\n address swapAddress,\n IERC20[] memory _pooledTokens,\n uint8[] memory decimals,\n string memory lpTokenName,\n string memory lpTokenSymbol,\n uint256 _a,\n uint256 _fee,\n uint256 _adminFee,\n address lpTokenTargetAddress\n ) external returns (address) {\n address swapClone = Clones.clone(swapAddress);\n ISwap(swapClone).initialize(\n _pooledTokens,\n decimals,\n lpTokenName,\n lpTokenSymbol,\n _a,\n _fee,\n _adminFee,\n lpTokenTargetAddress\n );\n Ownable(swapClone).transferOwnership(owner());\n emit NewSwapPool(msg.sender, swapClone, _pooledTokens);\n return swapClone;\n }\n}\n" + }, + "@openzeppelin/contracts/access/Ownable.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <0.8.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 () internal {\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" + }, + "contracts/bridge/SynapseERC20Factory.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.6.12;\n\nimport \"@openzeppelin/contracts/access/Ownable.sol\";\nimport \"@openzeppelin/contracts/proxy/Clones.sol\";\nimport \"./interfaces/ISynapseERC20.sol\";\n\ncontract SynapseERC20Factory {\n constructor() public {}\n\n event SynapseERC20Created(address contractAddress);\n\n /**\n * @notice Deploys a new node\n * @param synapseERC20Address address of the synapseERC20Address contract to initialize with\n * @param name Token name\n * @param symbol Token symbol\n * @param decimals Token name\n * @param owner admin address to be initialized with\n * @return Address of the newest node management contract created\n **/\n function deploy(\n address synapseERC20Address,\n string memory name,\n string memory symbol,\n uint8 decimals,\n address owner\n ) external returns (address) {\n address synERC20Clone = Clones.clone(synapseERC20Address);\n ISynapseERC20(synERC20Clone).initialize(name, symbol, decimals, owner);\n\n emit SynapseERC20Created(synERC20Clone);\n\n return synERC20Clone;\n }\n}\n" + }, + "contracts/bridge/interfaces/ISynapseERC20.sol": { + "content": "// SPDX-License-Identifier: MIT\n\n\npragma solidity 0.6.12;\n\ninterface ISynapseERC20 { \n function initialize(\n string memory _name, string memory _symbol, uint8 _decimals, address owner) external;\n\n function mint(address to, uint256 amount) external;\n}\n\n" + }, + "contracts/bridge/wrappers/AvaxJewelMigrationV2.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.6.12;\n\nimport \"@openzeppelin/contracts/token/ERC20/ERC20.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/SafeERC20.sol\";\nimport \"@openzeppelin/contracts/access/Ownable.sol\";\n\nimport \"../interfaces/ISynapseBridge.sol\";\n\ninterface IERC20Mintable is IERC20 {\n function mint(address to, uint256 amount) external;\n}\n\ncontract AvaxJewelMigrationV2 is Ownable {\n using SafeERC20 for IERC20;\n using SafeERC20 for IERC20Mintable;\n\n ISynapseBridge public constant SYNAPSE_BRIDGE =\n ISynapseBridge(0xC05e61d0E7a63D27546389B7aD62FdFf5A91aACE);\n // MULTICHAIN JEWEL\n IERC20 public constant LEGACY_TOKEN =\n IERC20(0x4f60a160D8C2DDdaAfe16FCC57566dB84D674BD6);\n // SYNAPSE JEWEL\n IERC20Mintable public constant NEW_TOKEN =\n IERC20Mintable(0x997Ddaa07d716995DE90577C123Db411584E5E46);\n uint256 private constant MAX_UINT256 = 2**256 - 1;\n\n uint256 private constant HARMONY_ID = 1666600000;\n\n constructor() public {\n NEW_TOKEN.safeApprove(address(SYNAPSE_BRIDGE), MAX_UINT256);\n }\n\n function migrate(uint256 amount) external {\n _migrate(amount, msg.sender);\n }\n\n function migrateAndBridge(\n uint256 amount,\n address to,\n uint256 chainId\n ) external {\n // First, mint new tokens to this contract, as Bridge burns tokens\n // from msg.sender, which would be AvaxJewelMigration\n _migrate(amount, address(this));\n // Initiate bridging and specify `to` as receiver on destination chain\n if (chainId == HARMONY_ID) {\n SYNAPSE_BRIDGE.redeemAndSwap(\n to,\n chainId,\n NEW_TOKEN,\n amount,\n 1, // indexFrom\n 0, // indexTo\n 0, // minDy\n type(uint256).max // deadline\n );\n } else {\n SYNAPSE_BRIDGE.redeem(to, chainId, NEW_TOKEN, amount);\n }\n }\n\n /// @notice Pull old tokens from user and mint new ones to account\n function _migrate(uint256 amount, address account) internal {\n require(amount != 0, \"Amount must be greater than zero\");\n LEGACY_TOKEN.safeTransferFrom(msg.sender, address(this), amount);\n NEW_TOKEN.mint(account, amount);\n }\n\n function redeemLegacy() external onlyOwner {\n uint256 legacyBalance = LEGACY_TOKEN.balanceOf(address(this));\n LEGACY_TOKEN.safeTransfer(owner(), legacyBalance);\n }\n}\n" + }, + "contracts/bridge/interfaces/ISynapseBridge.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.6.12;\n\nimport '@openzeppelin/contracts/token/ERC20/SafeERC20.sol';\nimport '@openzeppelin/contracts/token/ERC20/ERC20Burnable.sol';\n\ninterface ISynapseBridge {\n using SafeERC20 for IERC20;\n\n function deposit(\n address to,\n uint256 chainId,\n IERC20 token,\n uint256 amount\n ) external;\n\n function depositAndSwap(\n address to,\n uint256 chainId,\n IERC20 token,\n uint256 amount,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 minDy,\n uint256 deadline\n ) external;\n\n function redeem(\n address to,\n uint256 chainId,\n IERC20 token,\n uint256 amount\n ) external;\n\n\n function redeemv2(\n bytes32 to,\n uint256 chainId,\n IERC20 token,\n uint256 amount\n ) external;\n\n\n function redeemAndSwap(\n address to,\n uint256 chainId,\n IERC20 token,\n uint256 amount,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 minDy,\n uint256 deadline\n ) external;\n\n function redeemAndRemove(\n address to,\n uint256 chainId,\n IERC20 token,\n uint256 amount,\n uint8 liqTokenIndex,\n uint256 liqMinAmount,\n uint256 liqDeadline\n ) external;\n}\n" + }, + "@openzeppelin/contracts/token/ERC20/ERC20Burnable.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <0.8.0;\n\nimport \"../../utils/Context.sol\";\nimport \"./ERC20.sol\";\n\n/**\n * @dev Extension of {ERC20} that allows token holders to destroy both their own\n * tokens and those that they have an allowance for, in a way that can be\n * recognized off-chain (via event analysis).\n */\nabstract contract ERC20Burnable is Context, ERC20 {\n using SafeMath for uint256;\n\n /**\n * @dev Destroys `amount` tokens from the caller.\n *\n * See {ERC20-_burn}.\n */\n function burn(uint256 amount) public virtual {\n _burn(_msgSender(), amount);\n }\n\n /**\n * @dev Destroys `amount` tokens from `account`, deducting from the caller's\n * allowance.\n *\n * See {ERC20-_burn} and {ERC20-allowance}.\n *\n * Requirements:\n *\n * - the caller must have allowance for ``accounts``'s tokens of at least\n * `amount`.\n */\n function burnFrom(address account, uint256 amount) public virtual {\n uint256 decreasedAllowance = allowance(account, _msgSender()).sub(amount, \"ERC20: burn amount exceeds allowance\");\n\n _approve(account, _msgSender(), decreasedAllowance);\n _burn(account, amount);\n }\n}\n" + }, + "contracts/bridge/wrappers/MoonriverBridgeZap.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.6.12;\n\nimport \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/SafeERC20.sol\";\nimport \"../interfaces/ISwap.sol\";\nimport \"../interfaces/ISynapseBridge.sol\";\nimport \"../interfaces/IWETH9.sol\";\n\ninterface IFrax {\n function exchangeCanonicalForOld(address bridge_token_address, uint256 token_amount) external returns (uint256);\n}\n\ncontract MoonriverBridgeZap {\n using SafeERC20 for IERC20;\n\n ISynapseBridge synapseBridge;\n address payable public immutable WETH_ADDRESS;\n IFrax private constant CANOLICAL_FRAX = IFrax(0x1A93B23281CC1CDE4C4741353F3064709A16197d);\n IERC20 private constant SYN_FRAX = IERC20(0xE96AC70907ffF3Efee79f502C985A7A21Bce407d);\n\n mapping(address => address) public swapMap;\n mapping(address => IERC20[]) public swapTokensMap;\n\n uint256 constant MAX_UINT256 = 2**256 - 1;\n\n constructor(\n address payable _wethAddress,\n address _swapOne,\n address tokenOne,\n address _swapTwo,\n address tokenTwo,\n ISynapseBridge _synapseBridge\n ) public {\n WETH_ADDRESS = _wethAddress;\n synapseBridge = _synapseBridge;\n swapMap[tokenOne] = _swapOne;\n swapMap[tokenTwo] = _swapTwo;\n IERC20(_wethAddress).safeIncreaseAllowance(address(_synapseBridge), MAX_UINT256);\n if (address(_swapOne) != address(0)) {\n {\n uint8 i;\n for (; i < 32; i++) {\n try ISwap(_swapOne).getToken(i) returns (\n IERC20 token\n ) {\n swapTokensMap[_swapOne].push(token);\n token.safeApprove(address(_swapOne), MAX_UINT256);\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n } catch {\n break;\n }\n }\n require(i > 1, \"swap must have at least 2 tokens\");\n }\n }\n if (address(_swapTwo) != address(0)) {\n {\n uint8 i;\n for (; i < 32; i++) {\n try ISwap(_swapTwo).getToken(i) returns (\n IERC20 token\n ) {\n swapTokensMap[_swapTwo].push(token);\n token.safeApprove(address(_swapTwo), MAX_UINT256);\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n } catch {\n break;\n }\n }\n require(i > 1, \"swap must have at least 2 tokens\");\n }\n }\n }\n\n /**\n * @notice Calculate amount of tokens you receive on swap\n * @param tokenIndexFrom the token the user wants to sell\n * @param tokenIndexTo the token the user wants to buy\n * @param dx the amount of tokens the user wants to sell. If the token charges\n * a fee on transfers, use the amount that gets transferred after the fee.\n * @return amount of tokens the user will receive\n */\n function calculateSwap(\n IERC20 token,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx\n ) external view virtual returns (uint256) {\n ISwap swap = ISwap(\n swapMap[address(token)]\n );\n return swap.calculateSwap(tokenIndexFrom, tokenIndexTo, dx);\n }\n\n function swapAndRedeem(\n address to,\n uint256 chainId,\n IERC20 token,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx,\n uint256 minDy,\n uint256 deadline\n ) external {\n ISwap swap = ISwap(swapMap[address(token)]);\n require(address(swap) != address(0), \"Swap is 0x00\");\n IERC20[] memory tokens = swapTokensMap[address(swap)];\n tokens[tokenIndexFrom].safeTransferFrom(\n msg.sender,\n address(this),\n dx\n );\n // swap\n\n uint256 swappedAmount = swap.swap(\n tokenIndexFrom,\n tokenIndexTo,\n dx,\n minDy,\n deadline\n );\n // deposit into bridge, gets nUSD\n if (\n token.allowance(address(this), address(synapseBridge)) <\n swappedAmount\n ) {\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n }\n synapseBridge.redeem(to, chainId, token, swappedAmount);\n }\n\n function swapAndRedeemAndSwap(\n address to,\n uint256 chainId,\n IERC20 token,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx,\n uint256 minDy,\n uint256 deadline,\n uint8 swapTokenIndexFrom,\n uint8 swapTokenIndexTo,\n uint256 swapMinDy,\n uint256 swapDeadline\n ) external {\n require(\n address(swapMap[address(token)]) != address(0),\n \"Swap is 0x00\"\n );\n IERC20[] memory tokens = swapTokensMap[\n swapMap[address(token)]\n ];\n tokens[tokenIndexFrom].safeTransferFrom(\n msg.sender,\n address(this),\n dx\n );\n // swap\n\n uint256 swappedAmount = ISwap(swapMap[address(token)]).swap(tokenIndexFrom, tokenIndexTo, dx, minDy, deadline);\n // deposit into bridge, gets nUSD\n if (\n token.allowance(address(this), address(synapseBridge)) <\n swappedAmount\n ) {\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n }\n synapseBridge.redeemAndSwap(\n to,\n chainId,\n token,\n swappedAmount,\n swapTokenIndexFrom,\n swapTokenIndexTo,\n swapMinDy,\n swapDeadline\n );\n }\n\n function swapAndRedeemAndRemove(\n address to,\n uint256 chainId,\n IERC20 token,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx,\n uint256 minDy,\n uint256 deadline,\n uint8 liqTokenIndex,\n uint256 liqMinAmount,\n uint256 liqDeadline\n ) external {\n ISwap swap = ISwap(swapMap[address(token)]);\n require(address(swap) != address(0), \"Swap is 0x00\");\n IERC20[] memory tokens = swapTokensMap[address(swap)];\n tokens[tokenIndexFrom].safeTransferFrom(\n msg.sender,\n address(this),\n dx\n );\n // swap\n\n uint256 swappedAmount = swap.swap(\n tokenIndexFrom,\n tokenIndexTo,\n dx,\n minDy,\n deadline\n );\n // deposit into bridge, gets nUSD\n if (\n token.allowance(address(this), address(synapseBridge)) <\n swappedAmount\n ) {\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n }\n synapseBridge.redeemAndRemove(\n to,\n chainId,\n token,\n swappedAmount,\n liqTokenIndex,\n liqMinAmount,\n liqDeadline\n );\n }\n\n /**\n * @notice wraps SynapseBridge redeem()\n * @param to address on other chain to redeem underlying assets to\n * @param chainId which underlying chain to bridge assets onto\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n **/\n function redeem(\n address to,\n uint256 chainId,\n IERC20 token,\n uint256 amount\n ) external {\n token.safeTransferFrom(msg.sender, address(this), amount);\n if (address(token) == address(CANOLICAL_FRAX)) {\n uint256 swappedAmount = CANOLICAL_FRAX.exchangeCanonicalForOld(address(SYN_FRAX), amount);\n if (SYN_FRAX.allowance(address(this), address(synapseBridge)) < amount) {\n SYN_FRAX.safeApprove(address(synapseBridge), MAX_UINT256);\n }\n synapseBridge.redeem(to, chainId, SYN_FRAX, swappedAmount);\n } else {\n if (token.allowance(address(this), address(synapseBridge)) < amount) {\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n }\n synapseBridge.redeem(to, chainId, token, amount);\n }\n }\n\n /**\n * @notice Wraps SynapseBridge redeemv2() function\n * @param to address on other chain to bridge assets to\n * @param chainId which chain to bridge assets onto\n * @param token ERC20 compatible token to redeem into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n **/\n function redeemv2(\n bytes32 to,\n uint256 chainId,\n IERC20 token,\n uint256 amount\n ) external {\n token.safeTransferFrom(msg.sender, address(this), amount);\n\n if (token.allowance(address(this), address(synapseBridge)) < amount) {\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n }\n synapseBridge.redeemv2(to, chainId, token, amount);\n }\n\n /**\n * @notice wraps SynapseBridge redeem()\n * @param to address on other chain to redeem underlying assets to\n * @param chainId which underlying chain to bridge assets onto\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n **/\n function deposit(\n address to,\n uint256 chainId,\n IERC20 token,\n uint256 amount\n ) external {\n token.safeTransferFrom(msg.sender, address(this), amount);\n if (token.allowance(address(this), address(synapseBridge)) < amount) {\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n }\n synapseBridge.deposit(to, chainId, token, amount);\n }\n\n /**\n * @notice Wraps SynapseBridge deposit() function to make it compatible w/ ETH -> WETH conversions\n * @param to address on other chain to bridge assets to\n * @param chainId which chain to bridge assets onto\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n **/\n function depositETH(\n address to,\n uint256 chainId,\n uint256 amount\n ) external payable {\n require(msg.value > 0 && msg.value == amount, 'INCORRECT MSG VALUE');\n IWETH9(WETH_ADDRESS).deposit{value: msg.value}();\n synapseBridge.deposit(to, chainId, IERC20(WETH_ADDRESS), amount);\n }\n\n\n\n function swapETHAndRedeem(\n address to,\n uint256 chainId,\n IERC20 token,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx,\n uint256 minDy,\n uint256 deadline\n ) external payable {\n require(WETH_ADDRESS != address(0), \"WETH 0\");\n require(msg.value > 0 && msg.value == dx, \"INCORRECT MSG VALUE\");\n ISwap swap = ISwap(swapMap[address(token)]);\n require(address(swap) != address(0), \"Swap is 0x00\");\n IWETH9(WETH_ADDRESS).deposit{value: msg.value}();\n\n // swap\n uint256 swappedAmount = swap.swap(\n tokenIndexFrom,\n tokenIndexTo,\n dx,\n minDy,\n deadline\n );\n synapseBridge.redeem(to, chainId, token, swappedAmount);\n }\n\n /**\n * @notice Wraps redeemAndSwap on SynapseBridge.sol\n * Relays to nodes that (typically) a wrapped synAsset ERC20 token has been burned and the underlying needs to be redeeemed on the native chain. This function indicates to the nodes that they should attempt to redeem the LP token for the underlying assets (E.g \"swap\" out of the LP token)\n * @param to address on other chain to redeem underlying assets to\n * @param chainId which underlying chain to bridge assets onto\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n * @param tokenIndexFrom the token the user wants to swap from\n * @param tokenIndexTo the token the user wants to swap to\n * @param minDy the min amount the user would like to receive, or revert to only minting the SynERC20 token crosschain.\n * @param deadline latest timestamp to accept this transaction\n **/\n function redeemAndSwap(\n address to,\n uint256 chainId,\n IERC20 token,\n uint256 amount,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 minDy,\n uint256 deadline\n ) external {\n token.safeTransferFrom(msg.sender, address(this), amount);\n if (token.allowance(address(this), address(synapseBridge)) < amount) {\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n }\n synapseBridge.redeemAndSwap(\n to,\n chainId,\n token,\n amount,\n tokenIndexFrom,\n tokenIndexTo,\n minDy,\n deadline\n );\n }\n\n /**\n * @notice Wraps redeemAndRemove on SynapseBridge\n * Relays to nodes that (typically) a wrapped synAsset ERC20 token has been burned and the underlying needs to be redeeemed on the native chain. This function indicates to the nodes that they should attempt to redeem the LP token for the underlying assets (E.g \"swap\" out of the LP token)\n * @param to address on other chain to redeem underlying assets to\n * @param chainId which underlying chain to bridge assets onto\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount of (typically) LP token to pass to the nodes to attempt to removeLiquidity() with to redeem for the underlying assets of the LP token\n * @param liqTokenIndex Specifies which of the underlying LP assets the nodes should attempt to redeem for\n * @param liqMinAmount Specifies the minimum amount of the underlying asset needed for the nodes to execute the redeem/swap\n * @param liqDeadline Specificies the deadline that the nodes are allowed to try to redeem/swap the LP token\n **/\n function redeemAndRemove(\n address to,\n uint256 chainId,\n IERC20 token,\n uint256 amount,\n uint8 liqTokenIndex,\n uint256 liqMinAmount,\n uint256 liqDeadline\n ) external {\n token.safeTransferFrom(msg.sender, address(this), amount);\n if (token.allowance(address(this), address(synapseBridge)) < amount) {\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n }\n synapseBridge.redeemAndRemove(\n to,\n chainId,\n token,\n amount,\n liqTokenIndex,\n liqMinAmount,\n liqDeadline\n );\n }\n}\n" + }, + "contracts/bridge/interfaces/ISwap.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.6.12;\n\nimport '@openzeppelin/contracts/token/ERC20/ERC20.sol';\n\ninterface ISwap {\n // pool data view functions\n function getA() external view returns (uint256);\n\n function getToken(uint8 index) external view returns (IERC20);\n\n function getTokenIndex(address tokenAddress) external view returns (uint8);\n\n function getTokenBalance(uint8 index) external view returns (uint256);\n\n function getVirtualPrice() external view returns (uint256);\n\n // min return calculation functions\n function calculateSwap(\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx\n ) external view returns (uint256);\n\n function calculateTokenAmount(uint256[] calldata amounts, bool deposit)\n external\n view\n returns (uint256);\n\n function calculateRemoveLiquidity(uint256 amount)\n external\n view\n returns (uint256[] memory);\n\n function calculateRemoveLiquidityOneToken(\n uint256 tokenAmount,\n uint8 tokenIndex\n ) external view returns (uint256 availableTokenAmount);\n\n // state modifying functions\n function initialize(\n IERC20[] memory pooledTokens,\n uint8[] memory decimals,\n string memory lpTokenName,\n string memory lpTokenSymbol,\n uint256 a,\n uint256 fee,\n uint256 adminFee,\n address lpTokenTargetAddress\n ) external;\n\n function swap(\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx,\n uint256 minDy,\n uint256 deadline\n ) external returns (uint256);\n\n function addLiquidity(\n uint256[] calldata amounts,\n uint256 minToMint,\n uint256 deadline\n ) external returns (uint256);\n\n function removeLiquidity(\n uint256 amount,\n uint256[] calldata minAmounts,\n uint256 deadline\n ) external returns (uint256[] memory);\n\n function removeLiquidityOneToken(\n uint256 tokenAmount,\n uint8 tokenIndex,\n uint256 minAmount,\n uint256 deadline\n ) external returns (uint256);\n\n function removeLiquidityImbalance(\n uint256[] calldata amounts,\n uint256 maxBurnAmount,\n uint256 deadline\n ) external returns (uint256);\n}\n" + }, + "contracts/bridge/interfaces/IWETH9.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.4.0;\n\ninterface IWETH9 {\n function name() external view returns (string memory);\n\n function symbol() external view returns (string memory);\n\n function decimals() external view returns (uint8);\n\n function balanceOf(address) external view returns (uint256);\n\n function allowance(address, address) external view returns (uint256);\n\n receive() external payable;\n\n function deposit() external payable;\n\n function withdraw(uint256 wad) external;\n\n function totalSupply() external view returns (uint256);\n\n function approve(address guy, uint256 wad) external returns (bool);\n\n function transfer(address dst, uint256 wad) external returns (bool);\n\n function transferFrom(\n address src,\n address dst,\n uint256 wad\n ) external returns (bool);\n}" + }, + "contracts/bridge/wrappers/L2BridgeZap.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.6.12;\n\nimport \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/SafeERC20.sol\";\nimport \"../interfaces/ISwap.sol\";\nimport \"../interfaces/ISynapseBridge.sol\";\nimport \"../interfaces/IWETH9.sol\";\n\ncontract L2BridgeZap {\n using SafeERC20 for IERC20;\n\n ISynapseBridge synapseBridge;\n address payable public immutable WETH_ADDRESS;\n\n mapping(address => address) public swapMap;\n mapping(address => IERC20[]) public swapTokensMap;\n\n uint256 constant MAX_UINT256 = 2**256 - 1;\n\n constructor(\n address payable _wethAddress,\n address _swapOne,\n address tokenOne,\n address _swapTwo,\n address tokenTwo,\n ISynapseBridge _synapseBridge\n ) public {\n WETH_ADDRESS = _wethAddress;\n synapseBridge = _synapseBridge;\n swapMap[tokenOne] = _swapOne;\n swapMap[tokenTwo] = _swapTwo;\n if (_wethAddress != address(0)) {\n IERC20(_wethAddress).safeIncreaseAllowance(address(_synapseBridge), MAX_UINT256);\n }\n if (address(_swapOne) != address(0)) {\n {\n uint8 i;\n for (; i < 32; i++) {\n try ISwap(_swapOne).getToken(i) returns (\n IERC20 token\n ) {\n swapTokensMap[_swapOne].push(token);\n token.safeApprove(address(_swapOne), MAX_UINT256);\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n } catch {\n break;\n }\n }\n require(i > 1, \"swap must have at least 2 tokens\");\n }\n }\n if (address(_swapTwo) != address(0)) {\n {\n uint8 i;\n for (; i < 32; i++) {\n try ISwap(_swapTwo).getToken(i) returns (\n IERC20 token\n ) {\n swapTokensMap[_swapTwo].push(token);\n token.safeApprove(address(_swapTwo), MAX_UINT256);\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n } catch {\n break;\n }\n }\n require(i > 1, \"swap must have at least 2 tokens\");\n }\n }\n }\n\n /**\n * @notice Calculate amount of tokens you receive on swap\n * @param tokenIndexFrom the token the user wants to sell\n * @param tokenIndexTo the token the user wants to buy\n * @param dx the amount of tokens the user wants to sell. If the token charges\n * a fee on transfers, use the amount that gets transferred after the fee.\n * @return amount of tokens the user will receive\n */\n function calculateSwap(\n IERC20 token,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx\n ) external view virtual returns (uint256) {\n ISwap swap = ISwap(\n swapMap[address(token)]\n );\n return swap.calculateSwap(tokenIndexFrom, tokenIndexTo, dx);\n }\n\n function swapAndRedeem(\n address to,\n uint256 chainId,\n IERC20 token,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx,\n uint256 minDy,\n uint256 deadline\n ) external {\n ISwap swap = ISwap(swapMap[address(token)]);\n require(address(swap) != address(0), \"Swap is 0x00\");\n IERC20[] memory tokens = swapTokensMap[address(swap)];\n tokens[tokenIndexFrom].safeTransferFrom(\n msg.sender,\n address(this),\n dx\n );\n // swap\n\n uint256 swappedAmount = swap.swap(\n tokenIndexFrom,\n tokenIndexTo,\n dx,\n minDy,\n deadline\n );\n // deposit into bridge, gets nUSD\n if (\n token.allowance(address(this), address(synapseBridge)) <\n swappedAmount\n ) {\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n }\n synapseBridge.redeem(to, chainId, token, swappedAmount);\n }\n\n function swapAndRedeemAndSwap(\n address to,\n uint256 chainId,\n IERC20 token,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx,\n uint256 minDy,\n uint256 deadline,\n uint8 swapTokenIndexFrom,\n uint8 swapTokenIndexTo,\n uint256 swapMinDy,\n uint256 swapDeadline\n ) external {\n require(\n address(swapMap[address(token)]) != address(0),\n \"Swap is 0x00\"\n );\n IERC20[] memory tokens = swapTokensMap[\n swapMap[address(token)]\n ];\n tokens[tokenIndexFrom].safeTransferFrom(\n msg.sender,\n address(this),\n dx\n );\n // swap\n\n uint256 swappedAmount = ISwap(swapMap[address(token)]).swap(tokenIndexFrom, tokenIndexTo, dx, minDy, deadline);\n // deposit into bridge, gets nUSD\n if (\n token.allowance(address(this), address(synapseBridge)) <\n swappedAmount\n ) {\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n }\n synapseBridge.redeemAndSwap(\n to,\n chainId,\n token,\n swappedAmount,\n swapTokenIndexFrom,\n swapTokenIndexTo,\n swapMinDy,\n swapDeadline\n );\n }\n\n function swapAndRedeemAndRemove(\n address to,\n uint256 chainId,\n IERC20 token,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx,\n uint256 minDy,\n uint256 deadline,\n uint8 liqTokenIndex,\n uint256 liqMinAmount,\n uint256 liqDeadline\n ) external {\n ISwap swap = ISwap(swapMap[address(token)]);\n require(address(swap) != address(0), \"Swap is 0x00\");\n IERC20[] memory tokens = swapTokensMap[address(swap)];\n tokens[tokenIndexFrom].safeTransferFrom(\n msg.sender,\n address(this),\n dx\n );\n // swap\n\n uint256 swappedAmount = swap.swap(\n tokenIndexFrom,\n tokenIndexTo,\n dx,\n minDy,\n deadline\n );\n // deposit into bridge, gets nUSD\n if (\n token.allowance(address(this), address(synapseBridge)) <\n swappedAmount\n ) {\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n }\n synapseBridge.redeemAndRemove(\n to,\n chainId,\n token,\n swappedAmount,\n liqTokenIndex,\n liqMinAmount,\n liqDeadline\n );\n }\n\n /**\n * @notice wraps SynapseBridge redeem()\n * @param to address on other chain to redeem underlying assets to\n * @param chainId which underlying chain to bridge assets onto\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n **/\n function redeem(\n address to,\n uint256 chainId,\n IERC20 token,\n uint256 amount\n ) external {\n token.safeTransferFrom(msg.sender, address(this), amount);\n if (token.allowance(address(this), address(synapseBridge)) < amount) {\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n }\n synapseBridge.redeem(to, chainId, token, amount);\n }\n\n /**\n * @notice wraps SynapseBridge redeem()\n * @param to address on other chain to redeem underlying assets to\n * @param chainId which underlying chain to bridge assets onto\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n **/\n function deposit(\n address to,\n uint256 chainId,\n IERC20 token,\n uint256 amount\n ) external {\n token.safeTransferFrom(msg.sender, address(this), amount);\n if (token.allowance(address(this), address(synapseBridge)) < amount) {\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n }\n synapseBridge.deposit(to, chainId, token, amount);\n }\n\n /**\n * @notice Wraps SynapseBridge deposit() function to make it compatible w/ ETH -> WETH conversions\n * @param to address on other chain to bridge assets to\n * @param chainId which chain to bridge assets onto\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n **/\n function depositETH(\n address to,\n uint256 chainId,\n uint256 amount\n ) external payable {\n require(msg.value > 0 && msg.value == amount, 'INCORRECT MSG VALUE');\n IWETH9(WETH_ADDRESS).deposit{value: msg.value}();\n synapseBridge.deposit(to, chainId, IERC20(WETH_ADDRESS), amount);\n }\n\n\n /**\n * @notice Wraps SynapseBridge depositAndSwap() function to make it compatible w/ ETH -> WETH conversions\n * @param to address on other chain to bridge assets to\n * @param chainId which chain to bridge assets onto\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n * @param tokenIndexFrom the token the user wants to swap from\n * @param tokenIndexTo the token the user wants to swap to\n * @param minDy the min amount the user would like to receive, or revert to only minting the SynERC20 token crosschain.\n * @param deadline latest timestamp to accept this transaction\n **/\n function depositETHAndSwap(\n address to,\n uint256 chainId,\n uint256 amount,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 minDy,\n uint256 deadline\n ) external payable {\n require(msg.value > 0 && msg.value == amount, 'INCORRECT MSG VALUE');\n IWETH9(WETH_ADDRESS).deposit{value: msg.value}();\n synapseBridge.depositAndSwap(to, chainId, IERC20(WETH_ADDRESS), amount, tokenIndexFrom, tokenIndexTo, minDy, deadline);\n }\n\n\n function swapETHAndRedeem(\n address to,\n uint256 chainId,\n IERC20 token,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx,\n uint256 minDy,\n uint256 deadline\n ) external payable {\n require(WETH_ADDRESS != address(0), \"WETH 0\");\n require(msg.value > 0 && msg.value == dx, \"INCORRECT MSG VALUE\");\n ISwap swap = ISwap(swapMap[address(token)]);\n require(address(swap) != address(0), \"Swap is 0x00\");\n IWETH9(WETH_ADDRESS).deposit{value: msg.value}();\n\n // swap\n uint256 swappedAmount = swap.swap(\n tokenIndexFrom,\n tokenIndexTo,\n dx,\n minDy,\n deadline\n );\n synapseBridge.redeem(to, chainId, token, swappedAmount);\n }\n\n\n function swapETHAndRedeemAndSwap(\n address to,\n uint256 chainId,\n IERC20 token,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx,\n uint256 minDy,\n uint256 deadline,\n uint8 swapTokenIndexFrom,\n uint8 swapTokenIndexTo,\n uint256 swapMinDy,\n uint256 swapDeadline\n ) external payable {\n require(WETH_ADDRESS != address(0), \"WETH 0\");\n require(msg.value > 0 && msg.value == dx, \"INCORRECT MSG VALUE\");\n ISwap swap = ISwap(swapMap[address(token)]);\n require(address(swap) != address(0), \"Swap is 0x00\");\n IWETH9(WETH_ADDRESS).deposit{value: msg.value}();\n\n // swap\n uint256 swappedAmount = swap.swap(\n tokenIndexFrom,\n tokenIndexTo,\n dx,\n minDy,\n deadline\n );\n synapseBridge.redeemAndSwap(to, chainId, token, swappedAmount,swapTokenIndexFrom,\n swapTokenIndexTo,\n swapMinDy,\n swapDeadline);\n }\n\n\n /**\n * @notice Wraps redeemAndSwap on SynapseBridge.sol\n * Relays to nodes that (typically) a wrapped synAsset ERC20 token has been burned and the underlying needs to be redeeemed on the native chain. This function indicates to the nodes that they should attempt to redeem the LP token for the underlying assets (E.g \"swap\" out of the LP token)\n * @param to address on other chain to redeem underlying assets to\n * @param chainId which underlying chain to bridge assets onto\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n * @param tokenIndexFrom the token the user wants to swap from\n * @param tokenIndexTo the token the user wants to swap to\n * @param minDy the min amount the user would like to receive, or revert to only minting the SynERC20 token crosschain.\n * @param deadline latest timestamp to accept this transaction\n **/\n function redeemAndSwap(\n address to,\n uint256 chainId,\n IERC20 token,\n uint256 amount,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 minDy,\n uint256 deadline\n ) external {\n token.safeTransferFrom(msg.sender, address(this), amount);\n if (token.allowance(address(this), address(synapseBridge)) < amount) {\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n }\n synapseBridge.redeemAndSwap(\n to,\n chainId,\n token,\n amount,\n tokenIndexFrom,\n tokenIndexTo,\n minDy,\n deadline\n );\n }\n\n /**\n * @notice Wraps redeemAndRemove on SynapseBridge\n * Relays to nodes that (typically) a wrapped synAsset ERC20 token has been burned and the underlying needs to be redeeemed on the native chain. This function indicates to the nodes that they should attempt to redeem the LP token for the underlying assets (E.g \"swap\" out of the LP token)\n * @param to address on other chain to redeem underlying assets to\n * @param chainId which underlying chain to bridge assets onto\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount of (typically) LP token to pass to the nodes to attempt to removeLiquidity() with to redeem for the underlying assets of the LP token\n * @param liqTokenIndex Specifies which of the underlying LP assets the nodes should attempt to redeem for\n * @param liqMinAmount Specifies the minimum amount of the underlying asset needed for the nodes to execute the redeem/swap\n * @param liqDeadline Specificies the deadline that the nodes are allowed to try to redeem/swap the LP token\n **/\n function redeemAndRemove(\n address to,\n uint256 chainId,\n IERC20 token,\n uint256 amount,\n uint8 liqTokenIndex,\n uint256 liqMinAmount,\n uint256 liqDeadline\n ) external {\n token.safeTransferFrom(msg.sender, address(this), amount);\n if (token.allowance(address(this), address(synapseBridge)) < amount) {\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n }\n synapseBridge.redeemAndRemove(\n to,\n chainId,\n token,\n amount,\n liqTokenIndex,\n liqMinAmount,\n liqDeadline\n );\n }\n\n /**\n * @notice Wraps SynapseBridge redeemv2() function\n * @param to address on other chain to bridge assets to\n * @param chainId which chain to bridge assets onto\n * @param token ERC20 compatible token to redeem into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n **/\n function redeemv2(\n bytes32 to,\n uint256 chainId,\n IERC20 token,\n uint256 amount\n ) external {\n token.safeTransferFrom(msg.sender, address(this), amount);\n\n if (token.allowance(address(this), address(synapseBridge)) < amount) {\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n }\n synapseBridge.redeemv2(to, chainId, token, amount);\n }\n}\n" + }, + "contracts/bridge/wrappers/L1BridgeZap.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.6.12;\n\nimport '@openzeppelin/contracts/token/ERC20/IERC20.sol';\nimport '@openzeppelin/contracts/token/ERC20/SafeERC20.sol';\nimport '../interfaces/ISwap.sol';\nimport '../interfaces/ISynapseBridge.sol';\nimport \"../interfaces/IWETH9.sol\";\n\n\n/**\n * @title L1BridgeZap\n * @notice This contract is responsible for handling user Zaps into the SynapseBridge contract, through the Synapse Swap contracts. It does so\n * It does so by combining the action of addLiquidity() to the base swap pool, and then calling either deposit() or depositAndSwap() on the bridge.\n * This is done in hopes of automating portions of the bridge user experience to users, while keeping the SynapseBridge contract logic small.\n *\n * @dev This contract should be deployed with a base Swap.sol address and a SynapseBridge.sol address, otherwise, it will not function.\n */\ncontract L1BridgeZap {\n using SafeERC20 for IERC20;\n\n uint256 constant MAX_UINT256 = 2**256 - 1;\n \n ISwap baseSwap;\n ISynapseBridge synapseBridge;\n IERC20[] public baseTokens;\n address payable public immutable WETH_ADDRESS;\n \n\n /**\n * @notice Constructs the contract, approves each token inside of baseSwap to be used by baseSwap (needed for addLiquidity())\n */\n constructor(address payable _wethAddress, ISwap _baseSwap, ISynapseBridge _synapseBridge) public {\n WETH_ADDRESS = _wethAddress;\n baseSwap = _baseSwap;\n synapseBridge = _synapseBridge;\n IERC20(_wethAddress).safeIncreaseAllowance(address(_synapseBridge), MAX_UINT256);\n if (address(_baseSwap) != address(0)) {\n {\n uint8 i;\n for (; i < 32; i++) {\n try _baseSwap.getToken(i) returns (IERC20 token) {\n baseTokens.push(token);\n token.safeIncreaseAllowance(address(_baseSwap), MAX_UINT256);\n } catch {\n break;\n }\n }\n require(i > 1, 'baseSwap must have at least 2 tokens');\n }\n }\n }\n \n /**\n * @notice Wraps SynapseBridge deposit() function to make it compatible w/ ETH -> WETH conversions\n * @param to address on other chain to bridge assets to\n * @param chainId which chain to bridge assets onto\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n **/\n function depositETH(\n address to,\n uint256 chainId,\n uint256 amount\n ) external payable {\n require(msg.value > 0 && msg.value == amount, 'INCORRECT MSG VALUE');\n IWETH9(WETH_ADDRESS).deposit{value: msg.value}();\n synapseBridge.deposit(to, chainId, IERC20(WETH_ADDRESS), amount);\n }\n\n /**\n * @notice Wraps SynapseBridge depositAndSwap() function to make it compatible w/ ETH -> WETH conversions\n * @param to address on other chain to bridge assets to\n * @param chainId which chain to bridge assets onto\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n * @param tokenIndexFrom the token the user wants to swap from\n * @param tokenIndexTo the token the user wants to swap to\n * @param minDy the min amount the user would like to receive, or revert to only minting the SynERC20 token crosschain.\n * @param deadline latest timestamp to accept this transaction\n **/\n function depositETHAndSwap(\n address to,\n uint256 chainId,\n uint256 amount,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 minDy,\n uint256 deadline\n ) external payable {\n require(msg.value > 0 && msg.value == amount, 'INCORRECT MSG VALUE');\n IWETH9(WETH_ADDRESS).deposit{value: msg.value}();\n synapseBridge.depositAndSwap(to, chainId, IERC20(WETH_ADDRESS), amount, tokenIndexFrom, tokenIndexTo, minDy, deadline);\n }\n\n\n /**\n * @notice A simple method to calculate prices from deposits or\n * withdrawals, excluding fees but including slippage. This is\n * helpful as an input into the various \"min\" parameters on calls\n * to fight front-running\n *\n * @dev This shouldn't be used outside frontends for user estimates.\n *\n * @param amounts an array of token amounts to deposit or withdrawal,\n * corresponding to pooledTokens. The amount should be in each\n * pooled token's native precision.\n * @param deposit whether this is a deposit or a withdrawal\n * @return token amount the user will receive\n */\n function calculateTokenAmount(uint256[] calldata amounts, bool deposit)\n external\n view\n virtual\n returns (uint256)\n {\n return baseSwap.calculateTokenAmount(amounts, deposit);\n }\n\n /**\n * @notice Calculate the amount of underlying token available to withdraw\n * when withdrawing via only single token\n * @param tokenAmount the amount of LP token to burn\n * @param tokenIndex index of which token will be withdrawn\n * @return availableTokenAmount calculated amount of underlying token\n * available to withdraw\n */\n function calculateRemoveLiquidityOneToken(\n uint256 tokenAmount,\n uint8 tokenIndex\n ) external view virtual returns (uint256 availableTokenAmount) {\n return baseSwap.calculateRemoveLiquidityOneToken(tokenAmount, tokenIndex);\n }\n\n\n /**\n * @notice Combines adding liquidity to the given Swap, and calls deposit() on the bridge using that LP token\n * @param to address on other chain to bridge assets to\n * @param chainId which chain to bridge assets onto\n * @param token ERC20 compatible token to deposit into the bridge\n * @param liquidityAmounts the amounts of each token to add, in their native precision\n * @param minToMint the minimum LP tokens adding this amount of liquidity\n * should mint, otherwise revert. Handy for front-running mitigation\n * @param deadline latest timestamp to accept this transaction\n **/\n function zapAndDeposit(\n address to,\n uint256 chainId,\n IERC20 token,\n uint256[] calldata liquidityAmounts,\n uint256 minToMint,\n uint256 deadline\n ) external {\n // add liquidity\n for (uint256 i = 0; i < baseTokens.length; i++) {\n if (liquidityAmounts[i] != 0) {\n baseTokens[i].safeTransferFrom(\n msg.sender,\n address(this),\n liquidityAmounts[i]\n );\n }\n }\n\n uint256 liqAdded = baseSwap.addLiquidity(\n liquidityAmounts,\n minToMint,\n deadline\n );\n // deposit into bridge, gets nUSD\n if (token.allowance(address(this), address(synapseBridge)) < liqAdded) {\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n }\n synapseBridge.deposit(to, chainId, token, liqAdded);\n }\n\n /**\n * @notice Combines adding liquidity to the given Swap, and calls depositAndSwap() on the bridge using that LP token\n * @param to address on other chain to bridge assets to\n * @param chainId which chain to bridge assets onto\n * @param token ERC20 compatible token to deposit into the bridge\n * @param liquidityAmounts the amounts of each token to add, in their native precision\n * @param minToMint the minimum LP tokens adding this amount of liquidity\n * should mint, otherwise revert. Handy for front-running mitigation\n * @param liqDeadline latest timestamp to accept this transaction\n * @param tokenIndexFrom the token the user wants to swap from\n * @param tokenIndexTo the token the user wants to swap to\n * @param minDy the min amount the user would like to receive, or revert to only minting the SynERC20 token crosschain.\n * @param swapDeadline latest timestamp to accept this transaction\n **/\n function zapAndDepositAndSwap(\n address to,\n uint256 chainId,\n IERC20 token,\n uint256[] calldata liquidityAmounts,\n uint256 minToMint,\n uint256 liqDeadline,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 minDy,\n uint256 swapDeadline\n ) external {\n // add liquidity\n for (uint256 i = 0; i < baseTokens.length; i++) {\n if (liquidityAmounts[i] != 0) {\n baseTokens[i].safeTransferFrom(\n msg.sender,\n address(this),\n liquidityAmounts[i]\n );\n }\n }\n\n uint256 liqAdded = baseSwap.addLiquidity(\n liquidityAmounts,\n minToMint,\n liqDeadline\n );\n // deposit into bridge, bridge attemps to swap into desired asset\n if (token.allowance(address(this), address(synapseBridge)) < liqAdded) {\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n }\n synapseBridge.depositAndSwap(\n to,\n chainId,\n token,\n liqAdded,\n tokenIndexFrom,\n tokenIndexTo,\n minDy,\n swapDeadline\n );\n }\n\n /**\n * @notice Wraps SynapseBridge deposit() function\n * @param to address on other chain to bridge assets to\n * @param chainId which chain to bridge assets onto\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n **/\n function deposit(\n address to,\n uint256 chainId,\n IERC20 token,\n uint256 amount\n ) external {\n token.safeTransferFrom(msg.sender, address(this), amount);\n\n if (token.allowance(address(this), address(synapseBridge)) < amount) {\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n }\n synapseBridge.deposit(to, chainId, token, amount);\n }\n \n /**\n * @notice Wraps SynapseBridge depositAndSwap() function\n * @param to address on other chain to bridge assets to\n * @param chainId which chain to bridge assets onto\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n * @param tokenIndexFrom the token the user wants to swap from\n * @param tokenIndexTo the token the user wants to swap to\n * @param minDy the min amount the user would like to receive, or revert to only minting the SynERC20 token crosschain.\n * @param deadline latest timestamp to accept this transaction\n **/\n function depositAndSwap(\n address to,\n uint256 chainId,\n IERC20 token,\n uint256 amount,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 minDy,\n uint256 deadline\n ) external {\n token.safeTransferFrom(msg.sender, address(this), amount);\n \n if (token.allowance(address(this), address(synapseBridge)) < amount) {\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n }\n synapseBridge.depositAndSwap(to, chainId, token, amount, tokenIndexFrom, tokenIndexTo, minDy, deadline);\n }\n\n\n /**\n * @notice Wraps SynapseBridge redeem() function\n * @param to address on other chain to bridge assets to\n * @param chainId which chain to bridge assets onto\n * @param token ERC20 compatible token to redeem into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n **/\n function redeem(\n address to,\n uint256 chainId,\n IERC20 token,\n uint256 amount\n ) external {\n token.safeTransferFrom(msg.sender, address(this), amount);\n\n if (token.allowance(address(this), address(synapseBridge)) < amount) {\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n }\n synapseBridge.redeem(to, chainId, token, amount);\n }\n\n /**\n * @notice Wraps redeemAndSwap on SynapseBridge.sol\n * Relays to nodes that (typically) a wrapped synAsset ERC20 token has been burned and the underlying needs to be redeeemed on the native chain. This function indicates to the nodes that they should attempt to redeem the LP token for the underlying assets (E.g \"swap\" out of the LP token)\n * @param to address on other chain to redeem underlying assets to\n * @param chainId which underlying chain to bridge assets onto\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n * @param tokenIndexFrom the token the user wants to swap from\n * @param tokenIndexTo the token the user wants to swap to\n * @param minDy the min amount the user would like to receive, or revert to only minting the SynERC20 token crosschain.\n * @param deadline latest timestamp to accept this transaction\n **/\n function redeemAndSwap(\n address to,\n uint256 chainId,\n IERC20 token,\n uint256 amount,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 minDy,\n uint256 deadline\n ) external {\n token.safeTransferFrom(msg.sender, address(this), amount);\n if (token.allowance(address(this), address(synapseBridge)) < amount) {\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n }\n synapseBridge.redeemAndSwap(\n to,\n chainId,\n token,\n amount,\n tokenIndexFrom,\n tokenIndexTo,\n minDy,\n deadline\n );\n }\n\n /**\n * @notice Wraps redeemAndRemove on SynapseBridge\n * Relays to nodes that (typically) a wrapped synAsset ERC20 token has been burned and the underlying needs to be redeeemed on the native chain. This function indicates to the nodes that they should attempt to redeem the LP token for the underlying assets (E.g \"swap\" out of the LP token)\n * @param to address on other chain to redeem underlying assets to\n * @param chainId which underlying chain to bridge assets onto\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount of (typically) LP token to pass to the nodes to attempt to removeLiquidity() with to redeem for the underlying assets of the LP token\n * @param liqTokenIndex Specifies which of the underlying LP assets the nodes should attempt to redeem for\n * @param liqMinAmount Specifies the minimum amount of the underlying asset needed for the nodes to execute the redeem/swap\n * @param liqDeadline Specificies the deadline that the nodes are allowed to try to redeem/swap the LP token\n **/\n function redeemAndRemove(\n address to,\n uint256 chainId,\n IERC20 token,\n uint256 amount,\n uint8 liqTokenIndex,\n uint256 liqMinAmount,\n uint256 liqDeadline\n ) external {\n token.safeTransferFrom(msg.sender, address(this), amount);\n if (token.allowance(address(this), address(synapseBridge)) < amount) {\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n }\n synapseBridge.redeemAndRemove(\n to,\n chainId,\n token,\n amount,\n liqTokenIndex,\n liqMinAmount,\n liqDeadline\n );\n }\n\n\n /**\n * @notice Wraps SynapseBridge redeemv2() function\n * @param to address on other chain to bridge assets to\n * @param chainId which chain to bridge assets onto\n * @param token ERC20 compatible token to redeem into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n **/\n function redeemv2(\n bytes32 to,\n uint256 chainId,\n IERC20 token,\n uint256 amount\n ) external {\n token.safeTransferFrom(msg.sender, address(this), amount);\n\n if (token.allowance(address(this), address(synapseBridge)) < amount) {\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n }\n synapseBridge.redeemv2(to, chainId, token, amount);\n }\n\n}\n" + }, + "contracts/bridge/wrappers/MigratorBridgeZap.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.6.12;\n\nimport '@openzeppelin/contracts/token/ERC20/IERC20.sol';\nimport '@openzeppelin/contracts/token/ERC20/SafeERC20.sol';\nimport '@openzeppelin/contracts/math/SafeMath.sol';\n\nimport '../interfaces/ISynapseBridge.sol';\nimport '../interfaces/IERC20Migrator.sol';\n\ncontract MigratorBridgeZap {\n using SafeERC20 for IERC20;\n using SafeMath for uint256;\n \n ISynapseBridge constant synapseBridge = ISynapseBridge(0xd123f70AE324d34A9E76b67a27bf77593bA8749f);\n IERC20Migrator constant erc20Migrator = IERC20Migrator(0xf0284FB86adA5E4D82555C529677eEA3B2C3E022); \n IERC20 constant legacyToken = IERC20(0x42F6f551ae042cBe50C739158b4f0CAC0Edb9096);\n IERC20 constant newToken = IERC20(0xa4080f1778e69467E905B8d6F72f6e441f9e9484);\n uint256 constant MAX_UINT256 = 2**256 - 1;\n\n constructor() public {\n legacyToken.safeApprove(address(erc20Migrator), MAX_UINT256);\n newToken.safeApprove(address(synapseBridge), MAX_UINT256);\n }\n\n function migrate(uint256 amount) external {\n legacyToken.safeTransferFrom(msg.sender, address(this), amount);\n erc20Migrator.migrate(amount);\n newToken.safeTransfer(msg.sender, amount.mul(5).div(2));\n }\n\n function migrateAndBridge(uint256 amount, address to, uint256 chainId) external {\n legacyToken.safeTransferFrom(msg.sender, address(this), amount);\n erc20Migrator.migrate(amount);\n synapseBridge.redeem(to, chainId, newToken, amount.mul(5).div(2));\n }\n}" + }, + "contracts/bridge/interfaces/IERC20Migrator.sol": { + "content": "// SPDX-License-Identifier: MIT\n\n\npragma solidity 0.6.12;\n\ninterface IERC20Migrator { \n function migrate(uint256 amount) external;\n}\n\n" + }, + "contracts/bridge/wrappers/GMXWrapper.sol": { + "content": "// SPDX-License-Identifier: MIT\n\nimport '@openzeppelin/contracts/math/SafeMath.sol';\n\npragma solidity 0.6.12;\n\ninterface IGMX {\n function burn(address _account, uint256 _amount) external;\n function balanceOf(address account) external view returns (uint256);\n function mint(address _account, uint256 _amount) external;\n}\n\ncontract GMXWrapper {\n using SafeMath for uint256;\n\n address constant public gmx = 0x62edc0692BD897D2295872a9FFCac5425011c661;\n address constant public bridge = 0xC05e61d0E7a63D27546389B7aD62FdFf5A91aACE;\n\n function transfer(address _recipient, uint256 _amount) external returns (bool) {\n require(msg.sender == bridge);\n _transfer(msg.sender, _recipient, _amount);\n return true;\n }\n\n function _transfer(address _sender, address _recipient, uint256 _amount) private {\n require(_sender != address(0), \"BaseToken: transfer from the zero address\");\n require(_recipient != address(0), \"BaseToken: transfer to the zero address\");\n IGMX(gmx).burn(_sender, _amount);\n IGMX(gmx).mint(_recipient, _amount);\n }\n\n function mint(address _addr, uint256 _amount) external {\n require(msg.sender == bridge);\n uint256 preMint = IGMX(gmx).balanceOf(_addr);\n IGMX(gmx).mint(_addr, _amount);\n uint256 postMint = IGMX(gmx).balanceOf(_addr);\n require(preMint.add(_amount) == postMint, \"Mint incomplete\");\n }\n\n function burnFrom(address _addr, uint256 _amount) external {\n require(msg.sender == bridge);\n uint256 preBurn = IGMX(gmx).balanceOf(_addr);\n IGMX(gmx).burn(_addr, _amount);\n uint256 postBurn = IGMX(gmx).balanceOf(_addr);\n require(postBurn.add(_amount) == preBurn, \"Burn incomplete\");\n }\n}" + }, + "@openzeppelin/contracts/utils/Counters.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <0.8.0;\n\nimport \"../math/SafeMath.sol\";\n\n/**\n * @title Counters\n * @author Matt Condon (@shrugs)\n * @dev Provides counters that can only be incremented or decremented by one. This can be used e.g. to track the number\n * of elements in a mapping, issuing ERC721 ids, or counting request ids.\n *\n * Include with `using Counters for Counters.Counter;`\n * Since it is not possible to overflow a 256 bit integer with increments of one, `increment` can skip the {SafeMath}\n * overflow check, thereby saving gas. This does assume however correct usage, in that the underlying `_value` is never\n * directly accessed.\n */\nlibrary Counters {\n using SafeMath for uint256;\n\n struct Counter {\n // This variable should never be directly accessed by users of the library: interactions must be restricted to\n // the library's function. As of Solidity v0.5.2, this cannot be enforced, though there is a proposal to add\n // this feature: see https://github.com/ethereum/solidity/issues/4637\n uint256 _value; // default: 0\n }\n\n function current(Counter storage counter) internal view returns (uint256) {\n return counter._value;\n }\n\n function increment(Counter storage counter) internal {\n // The {SafeMath} overflow check can be skipped here, see the comment at the top\n counter._value += 1;\n }\n\n function decrement(Counter storage counter) internal {\n counter._value = counter._value.sub(1);\n }\n}\n" + }, + "@openzeppelin/contracts/drafts/ERC20Permit.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.5 <0.8.0;\n\nimport \"../token/ERC20/ERC20.sol\";\nimport \"./IERC20Permit.sol\";\nimport \"../cryptography/ECDSA.sol\";\nimport \"../utils/Counters.sol\";\nimport \"./EIP712.sol\";\n\n/**\n * @dev Implementation of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in\n * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612].\n *\n * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by\n * presenting a message signed by the account. By not relying on `{IERC20-approve}`, the token holder account doesn't\n * need to send a transaction, and thus is not required to hold Ether at all.\n *\n * _Available since v3.4._\n */\nabstract contract ERC20Permit is ERC20, IERC20Permit, EIP712 {\n using Counters for Counters.Counter;\n\n mapping (address => Counters.Counter) private _nonces;\n\n // solhint-disable-next-line var-name-mixedcase\n bytes32 private immutable _PERMIT_TYPEHASH = keccak256(\"Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)\");\n\n /**\n * @dev Initializes the {EIP712} domain separator using the `name` parameter, and setting `version` to `\"1\"`.\n *\n * It's a good idea to use the same `name` that is defined as the ERC20 token name.\n */\n constructor(string memory name) internal EIP712(name, \"1\") {\n }\n\n /**\n * @dev See {IERC20Permit-permit}.\n */\n function permit(address owner, address spender, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s) public virtual override {\n // solhint-disable-next-line not-rely-on-time\n require(block.timestamp <= deadline, \"ERC20Permit: expired deadline\");\n\n bytes32 structHash = keccak256(\n abi.encode(\n _PERMIT_TYPEHASH,\n owner,\n spender,\n value,\n _nonces[owner].current(),\n deadline\n )\n );\n\n bytes32 hash = _hashTypedDataV4(structHash);\n\n address signer = ECDSA.recover(hash, v, r, s);\n require(signer == owner, \"ERC20Permit: invalid signature\");\n\n _nonces[owner].increment();\n _approve(owner, spender, value);\n }\n\n /**\n * @dev See {IERC20Permit-nonces}.\n */\n function nonces(address owner) public view override returns (uint256) {\n return _nonces[owner].current();\n }\n\n /**\n * @dev See {IERC20Permit-DOMAIN_SEPARATOR}.\n */\n // solhint-disable-next-line func-name-mixedcase\n function DOMAIN_SEPARATOR() external view override returns (bytes32) {\n return _domainSeparatorV4();\n }\n}\n" + }, + "@openzeppelin/contracts/drafts/IERC20Permit.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <0.8.0;\n\n/**\n * @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in\n * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612].\n *\n * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by\n * presenting a message signed by the account. By not relying on `{IERC20-approve}`, the token holder account doesn't\n * need to send a transaction, and thus is not required to hold Ether at all.\n */\ninterface IERC20Permit {\n /**\n * @dev Sets `value` as the allowance of `spender` over `owner`'s tokens,\n * given `owner`'s signed approval.\n *\n * IMPORTANT: The same issues {IERC20-approve} has related to transaction\n * ordering also apply here.\n *\n * Emits an {Approval} event.\n *\n * Requirements:\n *\n * - `spender` cannot be the zero address.\n * - `deadline` must be a timestamp in the future.\n * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner`\n * over the EIP712-formatted function arguments.\n * - the signature must use ``owner``'s current nonce (see {nonces}).\n *\n * For more information on the signature format, see the\n * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP\n * section].\n */\n function permit(address owner, address spender, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s) external;\n\n /**\n * @dev Returns the current nonce for `owner`. This value must be\n * included whenever a signature is generated for {permit}.\n *\n * Every successful call to {permit} increases ``owner``'s nonce by one. This\n * prevents a signature from being used multiple times.\n */\n function nonces(address owner) external view returns (uint256);\n\n /**\n * @dev Returns the domain separator used in the encoding of the signature for `permit`, as defined by {EIP712}.\n */\n // solhint-disable-next-line func-name-mixedcase\n function DOMAIN_SEPARATOR() external view returns (bytes32);\n}\n" + }, + "@openzeppelin/contracts/cryptography/ECDSA.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <0.8.0;\n\n/**\n * @dev Elliptic Curve Digital Signature Algorithm (ECDSA) operations.\n *\n * These functions can be used to verify that a message was signed by the holder\n * of the private keys of a given address.\n */\nlibrary ECDSA {\n /**\n * @dev Returns the address that signed a hashed message (`hash`) with\n * `signature`. This address can then be used for verification purposes.\n *\n * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:\n * this function rejects them by requiring the `s` value to be in the lower\n * half order, and the `v` value to be either 27 or 28.\n *\n * IMPORTANT: `hash` _must_ be the result of a hash operation for the\n * verification to be secure: it is possible to craft signatures that\n * recover to arbitrary addresses for non-hashed data. A safe way to ensure\n * this is by receiving a hash of the original message (which may otherwise\n * be too long), and then calling {toEthSignedMessageHash} on it.\n */\n function recover(bytes32 hash, bytes memory signature) internal pure returns (address) {\n // Check the signature length\n if (signature.length != 65) {\n revert(\"ECDSA: invalid signature length\");\n }\n\n // Divide the signature in r, s and v variables\n bytes32 r;\n bytes32 s;\n uint8 v;\n\n // ecrecover takes the signature parameters, and the only way to get them\n // currently is to use assembly.\n // solhint-disable-next-line no-inline-assembly\n assembly {\n r := mload(add(signature, 0x20))\n s := mload(add(signature, 0x40))\n v := byte(0, mload(add(signature, 0x60)))\n }\n\n return recover(hash, v, r, s);\n }\n\n /**\n * @dev Overload of {ECDSA-recover-bytes32-bytes-} that receives the `v`,\n * `r` and `s` signature fields separately.\n */\n function recover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) internal pure returns (address) {\n // EIP-2 still allows signature malleability for ecrecover(). Remove this possibility and make the signature\n // unique. Appendix F in the Ethereum Yellow paper (https://ethereum.github.io/yellowpaper/paper.pdf), defines\n // the valid range for s in (281): 0 < s < secp256k1n ÷ 2 + 1, and for v in (282): v ∈ {27, 28}. Most\n // signatures from current libraries generate a unique signature with an s-value in the lower half order.\n //\n // If your library generates malleable signatures, such as s-values in the upper range, calculate a new s-value\n // with 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 - s1 and flip v from 27 to 28 or\n // vice versa. If your library also generates signatures with 0/1 for v instead 27/28, add 27 to v to accept\n // these malleable signatures as well.\n require(uint256(s) <= 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0, \"ECDSA: invalid signature 's' value\");\n require(v == 27 || v == 28, \"ECDSA: invalid signature 'v' value\");\n\n // If the signature is valid (and not malleable), return the signer address\n address signer = ecrecover(hash, v, r, s);\n require(signer != address(0), \"ECDSA: invalid signature\");\n\n return signer;\n }\n\n /**\n * @dev Returns an Ethereum Signed Message, created from a `hash`. This\n * replicates the behavior of the\n * https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_sign[`eth_sign`]\n * JSON-RPC method.\n *\n * See {recover}.\n */\n function toEthSignedMessageHash(bytes32 hash) internal pure returns (bytes32) {\n // 32 is the length in bytes of hash,\n // enforced by the type signature above\n return keccak256(abi.encodePacked(\"\\x19Ethereum Signed Message:\\n32\", hash));\n }\n}\n" + }, + "@openzeppelin/contracts/drafts/EIP712.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <0.8.0;\n\n/**\n * @dev https://eips.ethereum.org/EIPS/eip-712[EIP 712] is a standard for hashing and signing of typed structured data.\n *\n * The encoding specified in the EIP is very generic, and such a generic implementation in Solidity is not feasible,\n * thus this contract does not implement the encoding itself. Protocols need to implement the type-specific encoding\n * they need in their contracts using a combination of `abi.encode` and `keccak256`.\n *\n * This contract implements the EIP 712 domain separator ({_domainSeparatorV4}) that is used as part of the encoding\n * scheme, and the final step of the encoding to obtain the message digest that is then signed via ECDSA\n * ({_hashTypedDataV4}).\n *\n * The implementation of the domain separator was designed to be as efficient as possible while still properly updating\n * the chain id to protect against replay attacks on an eventual fork of the chain.\n *\n * NOTE: This contract implements the version of the encoding known as \"v4\", as implemented by the JSON RPC method\n * https://docs.metamask.io/guide/signing-data.html[`eth_signTypedDataV4` in MetaMask].\n *\n * _Available since v3.4._\n */\nabstract contract EIP712 {\n /* solhint-disable var-name-mixedcase */\n // Cache the domain separator as an immutable value, but also store the chain id that it corresponds to, in order to\n // invalidate the cached domain separator if the chain id changes.\n bytes32 private immutable _CACHED_DOMAIN_SEPARATOR;\n uint256 private immutable _CACHED_CHAIN_ID;\n\n bytes32 private immutable _HASHED_NAME;\n bytes32 private immutable _HASHED_VERSION;\n bytes32 private immutable _TYPE_HASH;\n /* solhint-enable var-name-mixedcase */\n\n /**\n * @dev Initializes the domain separator and parameter caches.\n *\n * The meaning of `name` and `version` is specified in\n * https://eips.ethereum.org/EIPS/eip-712#definition-of-domainseparator[EIP 712]:\n *\n * - `name`: the user readable name of the signing domain, i.e. the name of the DApp or the protocol.\n * - `version`: the current major version of the signing domain.\n *\n * NOTE: These parameters cannot be changed except through a xref:learn::upgrading-smart-contracts.adoc[smart\n * contract upgrade].\n */\n constructor(string memory name, string memory version) internal {\n bytes32 hashedName = keccak256(bytes(name));\n bytes32 hashedVersion = keccak256(bytes(version));\n bytes32 typeHash = keccak256(\"EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)\");\n _HASHED_NAME = hashedName;\n _HASHED_VERSION = hashedVersion;\n _CACHED_CHAIN_ID = _getChainId();\n _CACHED_DOMAIN_SEPARATOR = _buildDomainSeparator(typeHash, hashedName, hashedVersion);\n _TYPE_HASH = typeHash;\n }\n\n /**\n * @dev Returns the domain separator for the current chain.\n */\n function _domainSeparatorV4() internal view virtual returns (bytes32) {\n if (_getChainId() == _CACHED_CHAIN_ID) {\n return _CACHED_DOMAIN_SEPARATOR;\n } else {\n return _buildDomainSeparator(_TYPE_HASH, _HASHED_NAME, _HASHED_VERSION);\n }\n }\n\n function _buildDomainSeparator(bytes32 typeHash, bytes32 name, bytes32 version) private view returns (bytes32) {\n return keccak256(\n abi.encode(\n typeHash,\n name,\n version,\n _getChainId(),\n address(this)\n )\n );\n }\n\n /**\n * @dev Given an already https://eips.ethereum.org/EIPS/eip-712#definition-of-hashstruct[hashed struct], this\n * function returns the hash of the fully encoded EIP712 message for this domain.\n *\n * This hash can be used together with {ECDSA-recover} to obtain the signer of a message. For example:\n *\n * ```solidity\n * bytes32 digest = _hashTypedDataV4(keccak256(abi.encode(\n * keccak256(\"Mail(address to,string contents)\"),\n * mailTo,\n * keccak256(bytes(mailContents))\n * )));\n * address signer = ECDSA.recover(digest, signature);\n * ```\n */\n function _hashTypedDataV4(bytes32 structHash) internal view virtual returns (bytes32) {\n return keccak256(abi.encodePacked(\"\\x19\\x01\", _domainSeparatorV4(), structHash));\n }\n\n function _getChainId() private view returns (uint256 chainId) {\n this; // silence state mutability warning without generating bytecode - see https://github.com/ethereum/solidity/issues/2691\n // solhint-disable-next-line no-inline-assembly\n assembly {\n chainId := chainid()\n }\n }\n}\n" + }, + "contracts/bridge/wrappers/AvaxJewelMigration.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.6.12;\n\nimport '@openzeppelin/contracts/token/ERC20/ERC20.sol';\nimport \"@openzeppelin/contracts/token/ERC20/SafeERC20.sol\";\nimport \"@openzeppelin/contracts/access/Ownable.sol\";\n\nimport '../interfaces/ISynapseBridge.sol';\n\ninterface IERC20Mintable is IERC20 {\n function mint(address to, uint256 amount) external;\n}\n\ncontract AvaxJewelMigration is Ownable {\n using SafeERC20 for IERC20;\n using SafeERC20 for IERC20Mintable;\n\n\n ISynapseBridge constant synapseBridge = ISynapseBridge(0xC05e61d0E7a63D27546389B7aD62FdFf5A91aACE);\n // MULTICHAIN JEWEL \n IERC20 constant legacyToken = IERC20(0x4f60a160D8C2DDdaAfe16FCC57566dB84D674BD6);\n // SYNAPSE JEWEL\n IERC20 constant newToken = IERC20(0x997Ddaa07d716995DE90577C123Db411584E5E46);\n uint256 constant MAX_UINT256 = 2**256 - 1;\n\n constructor() public {\n newToken.safeApprove(address(synapseBridge), MAX_UINT256);\n }\n\n function migrate(uint256 amount) public {\n legacyToken.safeTransferFrom(msg.sender, address(this), amount);\n IERC20Mintable(address(newToken)).mint(msg.sender, amount);\n }\n\n function migrateAndBridge(uint256 amount, address to, uint256 chainId) external {\n migrate(amount);\n synapseBridge.redeem(to, chainId, newToken, amount);\n }\n\n function redeemLegacy() external onlyOwner {\n uint256 legacyBalance = legacyToken.balanceOf(address(this));\n legacyToken.safeTransfer(owner(), legacyBalance);\n }\n} " + }, + "contracts/bridge/testing/SynapseToken.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity >=0.6.0 <0.8.0;\n\n\nimport \"@openzeppelin/contracts/token/ERC20/ERC20.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/ERC20Burnable.sol\";\nimport \"@openzeppelin/contracts/access/AccessControl.sol\";\nimport \"@openzeppelin/contracts/drafts/ERC20Permit.sol\";\n\ncontract Synapse is ERC20, ERC20Burnable, AccessControl, ERC20Permit {\n bytes32 public constant MINTER_ROLE = keccak256(\"MINTER_ROLE\");\n\n constructor() public ERC20(\"Synapse\", \"SYN\") ERC20Permit(\"Synapse\") {\n _setupRole(DEFAULT_ADMIN_ROLE, msg.sender);\n _setupRole(MINTER_ROLE, msg.sender);\n }\n\n function mint(address to, uint256 amount) external {\n require(hasRole(MINTER_ROLE, msg.sender));\n _mint(to, amount);\n }\n}" + }, + "@openzeppelin/contracts/access/AccessControl.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <0.8.0;\n\nimport \"../utils/EnumerableSet.sol\";\nimport \"../utils/Address.sol\";\nimport \"../utils/Context.sol\";\n\n/**\n * @dev Contract module that allows children to implement role-based access\n * control mechanisms.\n *\n * Roles are referred to by their `bytes32` identifier. These should be exposed\n * in the external API and be unique. The best way to achieve this is by\n * using `public constant` hash digests:\n *\n * ```\n * bytes32 public constant MY_ROLE = keccak256(\"MY_ROLE\");\n * ```\n *\n * Roles can be used to represent a set of permissions. To restrict access to a\n * function call, use {hasRole}:\n *\n * ```\n * function foo() public {\n * require(hasRole(MY_ROLE, msg.sender));\n * ...\n * }\n * ```\n *\n * Roles can be granted and revoked dynamically via the {grantRole} and\n * {revokeRole} functions. Each role has an associated admin role, and only\n * accounts that have a role's admin role can call {grantRole} and {revokeRole}.\n *\n * By default, the admin role for all roles is `DEFAULT_ADMIN_ROLE`, which means\n * that only accounts with this role will be able to grant or revoke other\n * roles. More complex role relationships can be created by using\n * {_setRoleAdmin}.\n *\n * WARNING: The `DEFAULT_ADMIN_ROLE` is also its own admin: it has permission to\n * grant and revoke this role. Extra precautions should be taken to secure\n * accounts that have been granted it.\n */\nabstract contract AccessControl is Context {\n using EnumerableSet for EnumerableSet.AddressSet;\n using Address for address;\n\n struct RoleData {\n EnumerableSet.AddressSet members;\n bytes32 adminRole;\n }\n\n mapping (bytes32 => RoleData) private _roles;\n\n bytes32 public constant DEFAULT_ADMIN_ROLE = 0x00;\n\n /**\n * @dev Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole`\n *\n * `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite\n * {RoleAdminChanged} not being emitted signaling this.\n *\n * _Available since v3.1._\n */\n event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole);\n\n /**\n * @dev Emitted when `account` is granted `role`.\n *\n * `sender` is the account that originated the contract call, an admin role\n * bearer except when using {_setupRole}.\n */\n event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender);\n\n /**\n * @dev Emitted when `account` is revoked `role`.\n *\n * `sender` is the account that originated the contract call:\n * - if using `revokeRole`, it is the admin role bearer\n * - if using `renounceRole`, it is the role bearer (i.e. `account`)\n */\n event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender);\n\n /**\n * @dev Returns `true` if `account` has been granted `role`.\n */\n function hasRole(bytes32 role, address account) public view returns (bool) {\n return _roles[role].members.contains(account);\n }\n\n /**\n * @dev Returns the number of accounts that have `role`. Can be used\n * together with {getRoleMember} to enumerate all bearers of a role.\n */\n function getRoleMemberCount(bytes32 role) public view returns (uint256) {\n return _roles[role].members.length();\n }\n\n /**\n * @dev Returns one of the accounts that have `role`. `index` must be a\n * value between 0 and {getRoleMemberCount}, non-inclusive.\n *\n * Role bearers are not sorted in any particular way, and their ordering may\n * change at any point.\n *\n * WARNING: When using {getRoleMember} and {getRoleMemberCount}, make sure\n * you perform all queries on the same block. See the following\n * https://forum.openzeppelin.com/t/iterating-over-elements-on-enumerableset-in-openzeppelin-contracts/2296[forum post]\n * for more information.\n */\n function getRoleMember(bytes32 role, uint256 index) public view returns (address) {\n return _roles[role].members.at(index);\n }\n\n /**\n * @dev Returns the admin role that controls `role`. See {grantRole} and\n * {revokeRole}.\n *\n * To change a role's admin, use {_setRoleAdmin}.\n */\n function getRoleAdmin(bytes32 role) public view returns (bytes32) {\n return _roles[role].adminRole;\n }\n\n /**\n * @dev Grants `role` to `account`.\n *\n * If `account` had not been already granted `role`, emits a {RoleGranted}\n * event.\n *\n * Requirements:\n *\n * - the caller must have ``role``'s admin role.\n */\n function grantRole(bytes32 role, address account) public virtual {\n require(hasRole(_roles[role].adminRole, _msgSender()), \"AccessControl: sender must be an admin to grant\");\n\n _grantRole(role, account);\n }\n\n /**\n * @dev Revokes `role` from `account`.\n *\n * If `account` had been granted `role`, emits a {RoleRevoked} event.\n *\n * Requirements:\n *\n * - the caller must have ``role``'s admin role.\n */\n function revokeRole(bytes32 role, address account) public virtual {\n require(hasRole(_roles[role].adminRole, _msgSender()), \"AccessControl: sender must be an admin to revoke\");\n\n _revokeRole(role, account);\n }\n\n /**\n * @dev Revokes `role` from the calling account.\n *\n * Roles are often managed via {grantRole} and {revokeRole}: this function's\n * purpose is to provide a mechanism for accounts to lose their privileges\n * if they are compromised (such as when a trusted device is misplaced).\n *\n * If the calling account had been granted `role`, emits a {RoleRevoked}\n * event.\n *\n * Requirements:\n *\n * - the caller must be `account`.\n */\n function renounceRole(bytes32 role, address account) public virtual {\n require(account == _msgSender(), \"AccessControl: can only renounce roles for self\");\n\n _revokeRole(role, account);\n }\n\n /**\n * @dev Grants `role` to `account`.\n *\n * If `account` had not been already granted `role`, emits a {RoleGranted}\n * event. Note that unlike {grantRole}, this function doesn't perform any\n * checks on the calling account.\n *\n * [WARNING]\n * ====\n * This function should only be called from the constructor when setting\n * up the initial roles for the system.\n *\n * Using this function in any other way is effectively circumventing the admin\n * system imposed by {AccessControl}.\n * ====\n */\n function _setupRole(bytes32 role, address account) internal virtual {\n _grantRole(role, account);\n }\n\n /**\n * @dev Sets `adminRole` as ``role``'s admin role.\n *\n * Emits a {RoleAdminChanged} event.\n */\n function _setRoleAdmin(bytes32 role, bytes32 adminRole) internal virtual {\n emit RoleAdminChanged(role, _roles[role].adminRole, adminRole);\n _roles[role].adminRole = adminRole;\n }\n\n function _grantRole(bytes32 role, address account) private {\n if (_roles[role].members.add(account)) {\n emit RoleGranted(role, account, _msgSender());\n }\n }\n\n function _revokeRole(bytes32 role, address account) private {\n if (_roles[role].members.remove(account)) {\n emit RoleRevoked(role, account, _msgSender());\n }\n }\n}\n" + }, + "@openzeppelin/contracts/utils/EnumerableSet.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <0.8.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" + }, + "contracts/bridge/testing/NodeEnv.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.6.12;\npragma experimental ABIEncoderV2;\n\nimport '@openzeppelin/contracts/access/AccessControl.sol';\nimport \"../utils/EnumerableStringMap.sol\";\n\n/**\n * @title NodeEnv contract\n * @author Synapse Authors\n * @notice This contract implements a key-value store for storing variables on which synapse nodes must coordinate\n * methods are purposely arbitrary to allow these fields to be defined in synapse improvement proposals.\n * @notice This token is used for configuring different tokens on the bridge and mapping them across chains.\n**/\ncontract NodeEnv is AccessControl {\n using EnumerableStringMap for EnumerableStringMap.StringToStringMap;\n // BRIDGEMANAGER_ROLE owns the bridge. They are the only user that can call setters on this contract\n bytes32 public constant BRIDGEMANAGER_ROLE = keccak256('BRIDGEMANAGER_ROLE');\n // _config stores the config\n EnumerableStringMap.StringToStringMap private _config; // key is tokenAddress,chainID\n\n // ConfigUpdate is emitted when the config is updated by the user\n event ConfigUpdate(\n string key\n );\n\n constructor() public {\n _setupRole(DEFAULT_ADMIN_ROLE, msg.sender);\n _setupRole(BRIDGEMANAGER_ROLE, msg.sender);\n }\n\n /**\n * @notice get the length of the config\n *\n * @dev this is useful for enumerating through all keys in the env\n */\n function keyCount()\n external\n view\n returns (uint256){\n return _config.length();\n }\n\n /**\n * @notice gets the key/value pair by it's index\n *\n * Requirements:\n *\n * - `index` must be strictly less than {length}.\n */\n function keyValueByIndex(uint256 index) external view returns(string memory, string memory){\n return _config.at(index);\n }\n\n /**\n * @notice gets the value associated with the key\n */\n function get(string calldata _key) external view returns(string memory){\n string memory key = _key;\n return _config.get(key);\n }\n\n /**\n * @notice sets the key\n *\n * @dev caller must have bridge manager role\n */\n function set(string calldata _key, string calldata _value) external returns(bool) {\n require(\n hasRole(BRIDGEMANAGER_ROLE, msg.sender),\n 'Caller is not Bridge Manager'\n );\n string memory key = _key;\n string memory value = _value;\n\n return _config.set(key, value);\n }\n}" + }, + "contracts/bridge/utils/EnumerableStringMap.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.6.12;\n\nimport \"@openzeppelin/contracts/utils/EnumerableSet.sol\";\n\n/**\n * @title EnumerableStringMap\n * @dev Library for managing an enumerable variant of Solidity's\n * https://solidity.readthedocs.io/en/latest/types.html#mapping-types[`mapping`]\n * type.\n *\n * Maps have the following properties:\n *\n * - Entries are added, removed, and checked for existence in constant time\n * (O(1)).\n * - Entries are enumerated in O(n). No guarantees are made on the ordering.\n *\n * this isn't a terribly gas efficient implementation because it emphasizes usability over gas efficiency\n * by allowing arbitrary length string memorys. If Gettetrs/Setters are going to be used frequently in contracts\n * consider using the OpenZeppeling Bytes32 implementation\n *\n * this also differs from the OpenZeppelin implementation by keccac256 hashing the string memorys\n * so we can use enumerable bytes32 set\n */\nlibrary EnumerableStringMap {\n using EnumerableSet for EnumerableSet.Bytes32Set;\n\n // To implement this library for multiple types with as little code\n // repetition as possible, we write it in terms of a generic Map type with\n // bytes32 keys and values.\n // The Map implementation uses private functions, and user-facing\n // implementations (such as Uint256ToAddressMap) are just wrappers around\n // the underlying Map.\n // This means that we can only create new EnumerableMaps for types that fit\n // in bytes32.\n\n struct Map {\n // Storage of keys as a set\n EnumerableSet.Bytes32Set _keys;\n // Mapping of keys to resulting values to allow key lookup in the set\n mapping(bytes32 => string) _hashKeyMap;\n // values\n mapping(bytes32 => string) _values;\n }\n\n /**\n * @dev Adds a key-value pair to a map, or updates the value for an existing\n * key. O(1).\n *\n * Returns true if the key was added to the map, that is if it was not\n * already present.\n */\n function _set(\n Map storage map,\n string memory key,\n string memory value\n ) private returns (bool) {\n bytes32 keyHash = keccak256(abi.encodePacked(key));\n map._values[keyHash] = value;\n map._hashKeyMap[keyHash] = key;\n return map._keys.add(keyHash);\n }\n\n /**\n * @dev Removes a key-value pair from a map. O(1).\n *\n * Returns true if the key was removed from the map, that is if it was present.\n */\n function _remove(Map storage map, bytes32 keyHash) private returns (bool) {\n delete map._values[keyHash];\n delete map._hashKeyMap[keyHash];\n return map._keys.remove(keyHash);\n }\n\n /**\n * @dev Returns true if the key is in the map. O(1).\n */\n function _contains(Map storage map, bytes32 keyHash) private view returns (bool) {\n return map._keys.contains(keyHash);\n }\n\n /**\n * @dev Returns the number of key-value pairs in the map. O(1).\n */\n function _length(Map storage map) private view returns (uint256) {\n return map._keys.length();\n }\n\n /**\n * @dev Returns the key-value pair stored at position `index` in the map. O(1).\n *\n * Note that there are no guarantees on the ordering of entries inside the\n * array, and it may change when more entries are added or removed.\n *\n * Requirements:\n *\n * - `index` must be strictly less than {length}.\n */\n function _at(Map storage map, uint256 index) private view returns (string memory, string memory) {\n bytes32 keyHash = map._keys.at(index);\n return (map._hashKeyMap[keyHash], map._values[keyHash]);\n }\n\n /**\n * @dev Tries to returns the value associated with `key`. O(1).\n * Does not revert if `key` is not in the map.\n */\n function _tryGet(Map storage map, bytes32 keyHash) private view returns (bool, string memory) {\n string memory value = map._values[keyHash];\n if (keccak256(bytes(value)) == keccak256(bytes(\"\"))) {\n return (_contains(map, keyHash), \"\");\n } else {\n return (true, value);\n }\n }\n\n /**\n * @dev Returns the value associated with `key`. O(1).\n *\n * Requirements:\n *\n * - `key` must be in the map.\n */\n function _get(Map storage map, bytes32 keyHash) private view returns (string memory) {\n string memory value = map._values[keyHash];\n require(_contains(map, keyHash), \"EnumerableMap: nonexistent key\");\n return value;\n }\n\n // StringToStringMap\n struct StringToStringMap {\n Map _inner;\n }\n\n /**\n * @dev Adds a key-value pair to a map, or updates the value for an existing\n * key. O(1).\n *\n * Returns true if the key was added to the map, that is if it was not\n * already present.\n */\n function set(\n StringToStringMap storage map,\n string memory key,\n string memory value\n ) internal returns (bool) {\n return _set(map._inner, key, value);\n }\n\n /**\n * @dev Removes a value from a set. O(1).\n *\n * Returns true if the key was removed from the map, that is if it was present.\n */\n function remove(StringToStringMap storage map, string memory key) internal returns (bool) {\n return _remove(map._inner, keccak256(abi.encodePacked(key)));\n }\n\n /**\n * @dev Returns true if the key is in the map. O(1).\n */\n function contains(StringToStringMap storage map, string memory key) internal view returns (bool) {\n return _contains(map._inner, keccak256(abi.encodePacked(key)));\n }\n\n /**\n * @dev Returns the number of elements in the map. O(1).\n */\n function length(StringToStringMap storage map) internal view returns (uint256) {\n return _length(map._inner);\n }\n\n /**\n * @dev Returns the element stored at position `index` in the set. O(1).\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(StringToStringMap storage map, uint256 index) internal view returns (string memory, string memory) {\n return _at(map._inner, index);\n }\n\n /**\n * @dev Tries to returns the value associated with `key`. O(1).\n * Does not revert if `key` is not in the map.\n *\n * _Available since v3.4._\n */\n function tryGet(StringToStringMap storage map, uint256 key) internal view returns (bool, string memory) {\n (bool success, string memory value) = _tryGet(map._inner, bytes32(key));\n return (success, value);\n }\n\n /**\n * @dev Returns the value associated with `key`. O(1).\n *\n * Requirements:\n *\n * - `key` must be in the map.\n */\n function get(StringToStringMap storage map, string memory key) internal view returns (string memory) {\n return _get(map._inner, keccak256(abi.encodePacked(key)));\n }\n}" + }, + "contracts/bridge/PoolConfig.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.6.12;\npragma experimental ABIEncoderV2;\n\nimport \"@openzeppelin/contracts/access/AccessControl.sol\";\n\ncontract PoolConfig is AccessControl {\n bytes32 public constant BRIDGEMANAGER_ROLE =\n keccak256(\"BRIDGEMANAGER_ROLE\");\n mapping(address => mapping(uint256 => Pool)) private _pool; // key is tokenAddress,chainID\n\n struct Pool {\n address tokenAddress;\n uint256 chainId;\n address poolAddress;\n bool metaswap;\n }\n\n constructor() public {\n _setupRole(DEFAULT_ADMIN_ROLE, msg.sender);\n _setupRole(BRIDGEMANAGER_ROLE, msg.sender);\n }\n\n function getPoolConfig(address tokenAddress, uint256 chainID)\n external\n view\n returns (Pool memory)\n {\n return _pool[tokenAddress][chainID];\n }\n\n function setPoolConfig(\n address tokenAddress,\n uint256 chainID,\n address poolAddress,\n bool metaswap\n ) external returns (Pool memory) {\n require(\n hasRole(BRIDGEMANAGER_ROLE, msg.sender),\n \"Caller is not Bridge Manager\"\n );\n Pool memory newPool = Pool(\n tokenAddress,\n chainID,\n poolAddress,\n metaswap\n );\n _pool[tokenAddress][chainID] = newPool;\n return newPool;\n }\n}\n" + }, + "contracts/bridge/SynapseBridge.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.6.12;\n\nimport \"@openzeppelin/contracts-upgradeable/proxy/Initializable.sol\";\nimport \"@openzeppelin/contracts-upgradeable/access/AccessControlUpgradeable.sol\";\nimport \"@openzeppelin/contracts-upgradeable/utils/ReentrancyGuardUpgradeable.sol\";\nimport \"@openzeppelin/contracts-upgradeable/utils/PausableUpgradeable.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/SafeERC20.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/ERC20Burnable.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport \"@openzeppelin/contracts/math/SafeMath.sol\";\n\nimport \"./interfaces/ISwap.sol\";\nimport \"./interfaces/IWETH9.sol\";\n\ninterface IERC20Mintable is IERC20 {\n function mint(address to, uint256 amount) external;\n}\n\ncontract SynapseBridge is\n Initializable,\n AccessControlUpgradeable,\n ReentrancyGuardUpgradeable,\n PausableUpgradeable\n{\n using SafeERC20 for IERC20;\n using SafeERC20 for IERC20Mintable;\n using SafeMath for uint256;\n\n bytes32 public constant NODEGROUP_ROLE = keccak256(\"NODEGROUP_ROLE\");\n bytes32 public constant GOVERNANCE_ROLE = keccak256(\"GOVERNANCE_ROLE\");\n\n mapping(address => uint256) private fees;\n\n uint256 public startBlockNumber;\n uint256 public constant bridgeVersion = 6;\n uint256 public chainGasAmount;\n address payable public WETH_ADDRESS;\n\n mapping(bytes32 => bool) private kappaMap;\n\n receive() external payable {}\n\n function initialize() external initializer {\n startBlockNumber = block.number;\n _setupRole(DEFAULT_ADMIN_ROLE, msg.sender);\n __AccessControl_init();\n }\n\n function setChainGasAmount(uint256 amount) external {\n require(hasRole(GOVERNANCE_ROLE, msg.sender), \"Not governance\");\n chainGasAmount = amount;\n }\n\n function setWethAddress(address payable _wethAddress) external {\n require(hasRole(DEFAULT_ADMIN_ROLE, msg.sender), \"Not admin\");\n WETH_ADDRESS = _wethAddress;\n }\n\n function addKappas(bytes32[] calldata kappas) external {\n require(hasRole(GOVERNANCE_ROLE, msg.sender), \"Not governance\");\n for (uint256 i = 0; i < kappas.length; ++i) {\n kappaMap[kappas[i]] = true;\n }\n }\n\n event TokenDeposit(\n address indexed to,\n uint256 chainId,\n IERC20 token,\n uint256 amount\n );\n event TokenRedeem(\n address indexed to,\n uint256 chainId,\n IERC20 token,\n uint256 amount\n );\n event TokenWithdraw(\n address indexed to,\n IERC20 token,\n uint256 amount,\n uint256 fee,\n bytes32 indexed kappa\n );\n event TokenMint(\n address indexed to,\n IERC20Mintable token,\n uint256 amount,\n uint256 fee,\n bytes32 indexed kappa\n );\n event TokenDepositAndSwap(\n address indexed to,\n uint256 chainId,\n IERC20 token,\n uint256 amount,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 minDy,\n uint256 deadline\n );\n event TokenMintAndSwap(\n address indexed to,\n IERC20Mintable token,\n uint256 amount,\n uint256 fee,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 minDy,\n uint256 deadline,\n bool swapSuccess,\n bytes32 indexed kappa\n );\n event TokenRedeemAndSwap(\n address indexed to,\n uint256 chainId,\n IERC20 token,\n uint256 amount,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 minDy,\n uint256 deadline\n );\n event TokenRedeemAndRemove(\n address indexed to,\n uint256 chainId,\n IERC20 token,\n uint256 amount,\n uint8 swapTokenIndex,\n uint256 swapMinAmount,\n uint256 swapDeadline\n );\n event TokenWithdrawAndRemove(\n address indexed to,\n IERC20 token,\n uint256 amount,\n uint256 fee,\n uint8 swapTokenIndex,\n uint256 swapMinAmount,\n uint256 swapDeadline,\n bool swapSuccess,\n bytes32 indexed kappa\n );\n\n // v2 events\n event TokenRedeemV2(\n bytes32 indexed to,\n uint256 chainId,\n IERC20 token,\n uint256 amount\n );\n\n // VIEW FUNCTIONS ***/\n function getFeeBalance(address tokenAddress)\n external\n view\n returns (uint256)\n {\n return fees[tokenAddress];\n }\n\n function kappaExists(bytes32 kappa) external view returns (bool) {\n return kappaMap[kappa];\n }\n\n // FEE FUNCTIONS ***/\n /**\n * * @notice withdraw specified ERC20 token fees to a given address\n * * @param token ERC20 token in which fees acccumulated to transfer\n * * @param to Address to send the fees to\n */\n function withdrawFees(IERC20 token, address to) external whenNotPaused {\n require(hasRole(GOVERNANCE_ROLE, msg.sender), \"Not governance\");\n require(to != address(0), \"Address is 0x000\");\n if (fees[address(token)] != 0) {\n token.safeTransfer(to, fees[address(token)]);\n fees[address(token)] = 0;\n }\n }\n\n // PAUSABLE FUNCTIONS ***/\n function pause() external {\n require(hasRole(GOVERNANCE_ROLE, msg.sender), \"Not governance\");\n _pause();\n }\n\n function unpause() external {\n require(hasRole(GOVERNANCE_ROLE, msg.sender), \"Not governance\");\n _unpause();\n }\n\n /**\n * @notice Relays to nodes to transfers an ERC20 token cross-chain\n * @param to address on other chain to bridge assets to\n * @param chainId which chain to bridge assets onto\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n **/\n function deposit(\n address to,\n uint256 chainId,\n IERC20 token,\n uint256 amount\n ) external nonReentrant whenNotPaused {\n emit TokenDeposit(to, chainId, token, amount);\n token.safeTransferFrom(msg.sender, address(this), amount);\n }\n\n /**\n * @notice Relays to nodes that (typically) a wrapped synAsset ERC20 token has been burned and the underlying needs to be redeeemed on the native chain\n * @param to address on other chain to redeem underlying assets to\n * @param chainId which underlying chain to bridge assets onto\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n **/\n function redeem(\n address to,\n uint256 chainId,\n ERC20Burnable token,\n uint256 amount\n ) external nonReentrant whenNotPaused {\n emit TokenRedeem(to, chainId, token, amount);\n token.burnFrom(msg.sender, amount);\n }\n\n /**\n * @notice Function to be called by the node group to withdraw the underlying assets from the contract\n * @param to address on chain to send underlying assets to\n * @param token ERC20 compatible token to withdraw from the bridge\n * @param amount Amount in native token decimals to withdraw\n * @param fee Amount in native token decimals to save to the contract as fees\n * @param kappa kappa\n **/\n function withdraw(\n address to,\n IERC20 token,\n uint256 amount,\n uint256 fee,\n bytes32 kappa\n ) external nonReentrant whenNotPaused {\n require(\n hasRole(NODEGROUP_ROLE, msg.sender),\n \"Caller is not a node group\"\n );\n require(amount > fee, \"Amount must be greater than fee\");\n require(!kappaMap[kappa], \"Kappa is already present\");\n kappaMap[kappa] = true;\n fees[address(token)] = fees[address(token)].add(fee);\n if (address(token) == WETH_ADDRESS && WETH_ADDRESS != address(0)) {\n IWETH9(WETH_ADDRESS).withdraw(amount.sub(fee));\n (bool success, ) = to.call{value: amount.sub(fee)}(\"\");\n require(success, \"ETH_TRANSFER_FAILED\");\n emit TokenWithdraw(to, token, amount, fee, kappa);\n } else {\n emit TokenWithdraw(to, token, amount, fee, kappa);\n token.safeTransfer(to, amount.sub(fee));\n }\n }\n\n /**\n * @notice Nodes call this function to mint a SynERC20 (or any asset that the bridge is given minter access to). This is called by the nodes after a TokenDeposit event is emitted.\n * @dev This means the SynapseBridge.sol contract must have minter access to the token attempting to be minted\n * @param to address on other chain to redeem underlying assets to\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain post-fees\n * @param fee Amount in native token decimals to save to the contract as fees\n * @param kappa kappa\n **/\n function mint(\n address payable to,\n IERC20Mintable token,\n uint256 amount,\n uint256 fee,\n bytes32 kappa\n ) external nonReentrant whenNotPaused {\n require(\n hasRole(NODEGROUP_ROLE, msg.sender),\n \"Caller is not a node group\"\n );\n require(amount > fee, \"Amount must be greater than fee\");\n require(!kappaMap[kappa], \"Kappa is already present\");\n kappaMap[kappa] = true;\n fees[address(token)] = fees[address(token)].add(fee);\n emit TokenMint(to, token, amount.sub(fee), fee, kappa);\n token.mint(address(this), amount);\n IERC20(token).safeTransfer(to, amount.sub(fee));\n if (chainGasAmount != 0 && address(this).balance > chainGasAmount) {\n to.call.value(chainGasAmount)(\"\");\n }\n }\n\n /**\n * @notice Relays to nodes to both transfer an ERC20 token cross-chain, and then have the nodes execute a swap through a liquidity pool on behalf of the user.\n * @param to address on other chain to bridge assets to\n * @param chainId which chain to bridge assets onto\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n * @param tokenIndexFrom the token the user wants to swap from\n * @param tokenIndexTo the token the user wants to swap to\n * @param minDy the min amount the user would like to receive, or revert to only minting the SynERC20 token crosschain.\n * @param deadline latest timestamp to accept this transaction\n **/\n function depositAndSwap(\n address to,\n uint256 chainId,\n IERC20 token,\n uint256 amount,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 minDy,\n uint256 deadline\n ) external nonReentrant whenNotPaused {\n emit TokenDepositAndSwap(\n to,\n chainId,\n token,\n amount,\n tokenIndexFrom,\n tokenIndexTo,\n minDy,\n deadline\n );\n token.safeTransferFrom(msg.sender, address(this), amount);\n }\n\n /**\n * @notice Relays to nodes that (typically) a wrapped synAsset ERC20 token has been burned and the underlying needs to be redeeemed on the native chain. This function indicates to the nodes that they should attempt to redeem the LP token for the underlying assets (E.g \"swap\" out of the LP token)\n * @param to address on other chain to redeem underlying assets to\n * @param chainId which underlying chain to bridge assets onto\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n * @param tokenIndexFrom the token the user wants to swap from\n * @param tokenIndexTo the token the user wants to swap to\n * @param minDy the min amount the user would like to receive, or revert to only minting the SynERC20 token crosschain.\n * @param deadline latest timestamp to accept this transaction\n **/\n function redeemAndSwap(\n address to,\n uint256 chainId,\n ERC20Burnable token,\n uint256 amount,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 minDy,\n uint256 deadline\n ) external nonReentrant whenNotPaused {\n emit TokenRedeemAndSwap(\n to,\n chainId,\n token,\n amount,\n tokenIndexFrom,\n tokenIndexTo,\n minDy,\n deadline\n );\n token.burnFrom(msg.sender, amount);\n }\n\n /**\n * @notice Relays to nodes that (typically) a wrapped synAsset ERC20 token has been burned and the underlying needs to be redeeemed on the native chain. This function indicates to the nodes that they should attempt to redeem the LP token for the underlying assets (E.g \"swap\" out of the LP token)\n * @param to address on other chain to redeem underlying assets to\n * @param chainId which underlying chain to bridge assets onto\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n * @param swapTokenIndex Specifies which of the underlying LP assets the nodes should attempt to redeem for\n * @param swapMinAmount Specifies the minimum amount of the underlying asset needed for the nodes to execute the redeem/swap\n * @param swapDeadline Specificies the deadline that the nodes are allowed to try to redeem/swap the LP token\n **/\n function redeemAndRemove(\n address to,\n uint256 chainId,\n ERC20Burnable token,\n uint256 amount,\n uint8 swapTokenIndex,\n uint256 swapMinAmount,\n uint256 swapDeadline\n ) external nonReentrant whenNotPaused {\n emit TokenRedeemAndRemove(\n to,\n chainId,\n token,\n amount,\n swapTokenIndex,\n swapMinAmount,\n swapDeadline\n );\n token.burnFrom(msg.sender, amount);\n }\n\n /**\n * @notice Nodes call this function to mint a SynERC20 (or any asset that the bridge is given minter access to), and then attempt to swap the SynERC20 into the desired destination asset. This is called by the nodes after a TokenDepositAndSwap event is emitted.\n * @dev This means the BridgeDeposit.sol contract must have minter access to the token attempting to be minted\n * @param to address on other chain to redeem underlying assets to\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain post-fees\n * @param fee Amount in native token decimals to save to the contract as fees\n * @param pool Destination chain's pool to use to swap SynERC20 -> Asset. The nodes determine this by using PoolConfig.sol.\n * @param tokenIndexFrom Index of the SynERC20 asset in the pool\n * @param tokenIndexTo Index of the desired final asset\n * @param minDy Minumum amount (in final asset decimals) that must be swapped for, otherwise the user will receive the SynERC20.\n * @param deadline Epoch time of the deadline that the swap is allowed to be executed.\n * @param kappa kappa\n **/\n function mintAndSwap(\n address payable to,\n IERC20Mintable token,\n uint256 amount,\n uint256 fee,\n ISwap pool,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 minDy,\n uint256 deadline,\n bytes32 kappa\n ) external nonReentrant whenNotPaused {\n require(\n hasRole(NODEGROUP_ROLE, msg.sender),\n \"Caller is not a node group\"\n );\n require(amount > fee, \"Amount must be greater than fee\");\n require(!kappaMap[kappa], \"Kappa is already present\");\n kappaMap[kappa] = true;\n fees[address(token)] = fees[address(token)].add(fee);\n // Transfer gas airdrop\n if (chainGasAmount != 0 && address(this).balance > chainGasAmount) {\n to.call.value(chainGasAmount)(\"\");\n }\n // first check to make sure more will be given than min amount required\n uint256 expectedOutput = ISwap(pool).calculateSwap(\n tokenIndexFrom,\n tokenIndexTo,\n amount.sub(fee)\n );\n\n if (expectedOutput >= minDy) {\n // proceed with swap\n token.mint(address(this), amount);\n token.safeIncreaseAllowance(address(pool), amount);\n try\n ISwap(pool).swap(\n tokenIndexFrom,\n tokenIndexTo,\n amount.sub(fee),\n minDy,\n deadline\n )\n returns (uint256 finalSwappedAmount) {\n // Swap succeeded, transfer swapped asset\n IERC20 swappedTokenTo = ISwap(pool).getToken(tokenIndexTo);\n if (\n address(swappedTokenTo) == WETH_ADDRESS &&\n WETH_ADDRESS != address(0)\n ) {\n IWETH9(WETH_ADDRESS).withdraw(finalSwappedAmount);\n (bool success, ) = to.call{value: finalSwappedAmount}(\"\");\n require(success, \"ETH_TRANSFER_FAILED\");\n emit TokenMintAndSwap(\n to,\n token,\n finalSwappedAmount,\n fee,\n tokenIndexFrom,\n tokenIndexTo,\n minDy,\n deadline,\n true,\n kappa\n );\n } else {\n swappedTokenTo.safeTransfer(to, finalSwappedAmount);\n emit TokenMintAndSwap(\n to,\n token,\n finalSwappedAmount,\n fee,\n tokenIndexFrom,\n tokenIndexTo,\n minDy,\n deadline,\n true,\n kappa\n );\n }\n } catch {\n IERC20(token).safeTransfer(to, amount.sub(fee));\n emit TokenMintAndSwap(\n to,\n token,\n amount.sub(fee),\n fee,\n tokenIndexFrom,\n tokenIndexTo,\n minDy,\n deadline,\n false,\n kappa\n );\n }\n } else {\n token.mint(address(this), amount);\n IERC20(token).safeTransfer(to, amount.sub(fee));\n emit TokenMintAndSwap(\n to,\n token,\n amount.sub(fee),\n fee,\n tokenIndexFrom,\n tokenIndexTo,\n minDy,\n deadline,\n false,\n kappa\n );\n }\n }\n\n /**\n * @notice Function to be called by the node group to withdraw the underlying assets from the contract\n * @param to address on chain to send underlying assets to\n * @param token ERC20 compatible token to withdraw from the bridge\n * @param amount Amount in native token decimals to withdraw\n * @param fee Amount in native token decimals to save to the contract as fees\n * @param pool Destination chain's pool to use to swap SynERC20 -> Asset. The nodes determine this by using PoolConfig.sol.\n * @param swapTokenIndex Specifies which of the underlying LP assets the nodes should attempt to redeem for\n * @param swapMinAmount Specifies the minimum amount of the underlying asset needed for the nodes to execute the redeem/swap\n * @param swapDeadline Specificies the deadline that the nodes are allowed to try to redeem/swap the LP token\n * @param kappa kappa\n **/\n function withdrawAndRemove(\n address to,\n IERC20 token,\n uint256 amount,\n uint256 fee,\n ISwap pool,\n uint8 swapTokenIndex,\n uint256 swapMinAmount,\n uint256 swapDeadline,\n bytes32 kappa\n ) external nonReentrant whenNotPaused {\n require(\n hasRole(NODEGROUP_ROLE, msg.sender),\n \"Caller is not a node group\"\n );\n require(amount > fee, \"Amount must be greater than fee\");\n require(!kappaMap[kappa], \"Kappa is already present\");\n kappaMap[kappa] = true;\n fees[address(token)] = fees[address(token)].add(fee);\n // first check to make sure more will be given than min amount required\n uint256 expectedOutput = ISwap(pool).calculateRemoveLiquidityOneToken(\n amount.sub(fee),\n swapTokenIndex\n );\n\n if (expectedOutput >= swapMinAmount) {\n token.safeIncreaseAllowance(address(pool), amount.sub(fee));\n try\n ISwap(pool).removeLiquidityOneToken(\n amount.sub(fee),\n swapTokenIndex,\n swapMinAmount,\n swapDeadline\n )\n returns (uint256 finalSwappedAmount) {\n // Swap succeeded, transfer swapped asset\n IERC20 swappedTokenTo = ISwap(pool).getToken(swapTokenIndex);\n swappedTokenTo.safeTransfer(to, finalSwappedAmount);\n emit TokenWithdrawAndRemove(\n to,\n token,\n finalSwappedAmount,\n fee,\n swapTokenIndex,\n swapMinAmount,\n swapDeadline,\n true,\n kappa\n );\n } catch {\n IERC20(token).safeTransfer(to, amount.sub(fee));\n emit TokenWithdrawAndRemove(\n to,\n token,\n amount.sub(fee),\n fee,\n swapTokenIndex,\n swapMinAmount,\n swapDeadline,\n false,\n kappa\n );\n }\n } else {\n token.safeTransfer(to, amount.sub(fee));\n emit TokenWithdrawAndRemove(\n to,\n token,\n amount.sub(fee),\n fee,\n swapTokenIndex,\n swapMinAmount,\n swapDeadline,\n false,\n kappa\n );\n }\n }\n\n // BRIDGE FUNCTIONS TO HANDLE DIFF ADDRESSES\n /**\n * @notice Relays to nodes that (typically) a wrapped synAsset ERC20 token has been burned and the underlying needs to be redeeemed on the native chain\n * @param to address on other chain to redeem underlying assets to\n * @param chainId which underlying chain to bridge assets onto\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n **/\n function redeemV2(\n bytes32 to,\n uint256 chainId,\n ERC20Burnable token,\n uint256 amount\n ) external nonReentrant whenNotPaused {\n emit TokenRedeemV2(to, chainId, token, amount);\n token.burnFrom(msg.sender, amount);\n }\n}\n" + }, + "@openzeppelin/contracts-upgradeable/access/AccessControlUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <0.8.0;\n\nimport \"../utils/EnumerableSetUpgradeable.sol\";\nimport \"../utils/AddressUpgradeable.sol\";\nimport \"../utils/ContextUpgradeable.sol\";\nimport \"../proxy/Initializable.sol\";\n\n/**\n * @dev Contract module that allows children to implement role-based access\n * control mechanisms.\n *\n * Roles are referred to by their `bytes32` identifier. These should be exposed\n * in the external API and be unique. The best way to achieve this is by\n * using `public constant` hash digests:\n *\n * ```\n * bytes32 public constant MY_ROLE = keccak256(\"MY_ROLE\");\n * ```\n *\n * Roles can be used to represent a set of permissions. To restrict access to a\n * function call, use {hasRole}:\n *\n * ```\n * function foo() public {\n * require(hasRole(MY_ROLE, msg.sender));\n * ...\n * }\n * ```\n *\n * Roles can be granted and revoked dynamically via the {grantRole} and\n * {revokeRole} functions. Each role has an associated admin role, and only\n * accounts that have a role's admin role can call {grantRole} and {revokeRole}.\n *\n * By default, the admin role for all roles is `DEFAULT_ADMIN_ROLE`, which means\n * that only accounts with this role will be able to grant or revoke other\n * roles. More complex role relationships can be created by using\n * {_setRoleAdmin}.\n *\n * WARNING: The `DEFAULT_ADMIN_ROLE` is also its own admin: it has permission to\n * grant and revoke this role. Extra precautions should be taken to secure\n * accounts that have been granted it.\n */\nabstract contract AccessControlUpgradeable is Initializable, ContextUpgradeable {\n function __AccessControl_init() internal initializer {\n __Context_init_unchained();\n __AccessControl_init_unchained();\n }\n\n function __AccessControl_init_unchained() internal initializer {\n }\n using EnumerableSetUpgradeable for EnumerableSetUpgradeable.AddressSet;\n using AddressUpgradeable for address;\n\n struct RoleData {\n EnumerableSetUpgradeable.AddressSet members;\n bytes32 adminRole;\n }\n\n mapping (bytes32 => RoleData) private _roles;\n\n bytes32 public constant DEFAULT_ADMIN_ROLE = 0x00;\n\n /**\n * @dev Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole`\n *\n * `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite\n * {RoleAdminChanged} not being emitted signaling this.\n *\n * _Available since v3.1._\n */\n event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole);\n\n /**\n * @dev Emitted when `account` is granted `role`.\n *\n * `sender` is the account that originated the contract call, an admin role\n * bearer except when using {_setupRole}.\n */\n event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender);\n\n /**\n * @dev Emitted when `account` is revoked `role`.\n *\n * `sender` is the account that originated the contract call:\n * - if using `revokeRole`, it is the admin role bearer\n * - if using `renounceRole`, it is the role bearer (i.e. `account`)\n */\n event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender);\n\n /**\n * @dev Returns `true` if `account` has been granted `role`.\n */\n function hasRole(bytes32 role, address account) public view returns (bool) {\n return _roles[role].members.contains(account);\n }\n\n /**\n * @dev Returns the number of accounts that have `role`. Can be used\n * together with {getRoleMember} to enumerate all bearers of a role.\n */\n function getRoleMemberCount(bytes32 role) public view returns (uint256) {\n return _roles[role].members.length();\n }\n\n /**\n * @dev Returns one of the accounts that have `role`. `index` must be a\n * value between 0 and {getRoleMemberCount}, non-inclusive.\n *\n * Role bearers are not sorted in any particular way, and their ordering may\n * change at any point.\n *\n * WARNING: When using {getRoleMember} and {getRoleMemberCount}, make sure\n * you perform all queries on the same block. See the following\n * https://forum.openzeppelin.com/t/iterating-over-elements-on-enumerableset-in-openzeppelin-contracts/2296[forum post]\n * for more information.\n */\n function getRoleMember(bytes32 role, uint256 index) public view returns (address) {\n return _roles[role].members.at(index);\n }\n\n /**\n * @dev Returns the admin role that controls `role`. See {grantRole} and\n * {revokeRole}.\n *\n * To change a role's admin, use {_setRoleAdmin}.\n */\n function getRoleAdmin(bytes32 role) public view returns (bytes32) {\n return _roles[role].adminRole;\n }\n\n /**\n * @dev Grants `role` to `account`.\n *\n * If `account` had not been already granted `role`, emits a {RoleGranted}\n * event.\n *\n * Requirements:\n *\n * - the caller must have ``role``'s admin role.\n */\n function grantRole(bytes32 role, address account) public virtual {\n require(hasRole(_roles[role].adminRole, _msgSender()), \"AccessControl: sender must be an admin to grant\");\n\n _grantRole(role, account);\n }\n\n /**\n * @dev Revokes `role` from `account`.\n *\n * If `account` had been granted `role`, emits a {RoleRevoked} event.\n *\n * Requirements:\n *\n * - the caller must have ``role``'s admin role.\n */\n function revokeRole(bytes32 role, address account) public virtual {\n require(hasRole(_roles[role].adminRole, _msgSender()), \"AccessControl: sender must be an admin to revoke\");\n\n _revokeRole(role, account);\n }\n\n /**\n * @dev Revokes `role` from the calling account.\n *\n * Roles are often managed via {grantRole} and {revokeRole}: this function's\n * purpose is to provide a mechanism for accounts to lose their privileges\n * if they are compromised (such as when a trusted device is misplaced).\n *\n * If the calling account had been granted `role`, emits a {RoleRevoked}\n * event.\n *\n * Requirements:\n *\n * - the caller must be `account`.\n */\n function renounceRole(bytes32 role, address account) public virtual {\n require(account == _msgSender(), \"AccessControl: can only renounce roles for self\");\n\n _revokeRole(role, account);\n }\n\n /**\n * @dev Grants `role` to `account`.\n *\n * If `account` had not been already granted `role`, emits a {RoleGranted}\n * event. Note that unlike {grantRole}, this function doesn't perform any\n * checks on the calling account.\n *\n * [WARNING]\n * ====\n * This function should only be called from the constructor when setting\n * up the initial roles for the system.\n *\n * Using this function in any other way is effectively circumventing the admin\n * system imposed by {AccessControl}.\n * ====\n */\n function _setupRole(bytes32 role, address account) internal virtual {\n _grantRole(role, account);\n }\n\n /**\n * @dev Sets `adminRole` as ``role``'s admin role.\n *\n * Emits a {RoleAdminChanged} event.\n */\n function _setRoleAdmin(bytes32 role, bytes32 adminRole) internal virtual {\n emit RoleAdminChanged(role, _roles[role].adminRole, adminRole);\n _roles[role].adminRole = adminRole;\n }\n\n function _grantRole(bytes32 role, address account) private {\n if (_roles[role].members.add(account)) {\n emit RoleGranted(role, account, _msgSender());\n }\n }\n\n function _revokeRole(bytes32 role, address account) private {\n if (_roles[role].members.remove(account)) {\n emit RoleRevoked(role, account, _msgSender());\n }\n }\n uint256[49] private __gap;\n}\n" + }, + "@openzeppelin/contracts-upgradeable/utils/EnumerableSetUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <0.8.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 EnumerableSetUpgradeable {\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" + }, + "contracts/bridge/wrappers/HarmonyBridgeZap.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.6.12;\n\nimport \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/SafeERC20.sol\";\nimport \"../interfaces/ISwap.sol\";\nimport \"../interfaces/ISynapseBridge.sol\";\nimport \"../interfaces/IWETH9.sol\";\n\ninterface IFrax {\n function exchangeCanonicalForOld(address bridge_token_address, uint256 token_amount) external returns (uint256);\n}\n\ncontract HarmonyBridgeZap {\n using SafeERC20 for IERC20;\n\n ISynapseBridge synapseBridge;\n address payable public immutable WETH_ADDRESS;\n IFrax private constant CANOLICAL_FRAX = IFrax(0xFa7191D292d5633f702B0bd7E3E3BcCC0e633200);\n IERC20 private constant SYN_FRAX = IERC20(0x1852F70512298d56e9c8FDd905e02581E04ddb2a);\n\n mapping(address => address) public swapMap;\n mapping(address => IERC20[]) public swapTokensMap;\n\n uint256 constant MAX_UINT256 = 2**256 - 1;\n\n constructor(\n address payable _wethAddress,\n address _swapOne,\n address tokenOne,\n address _swapTwo,\n address tokenTwo,\n address _swapThree,\n address tokenThree,\n address _swapFour,\n address tokenFour,\n ISynapseBridge _synapseBridge\n ) public {\n WETH_ADDRESS = _wethAddress;\n synapseBridge = _synapseBridge;\n swapMap[tokenOne] = _swapOne;\n swapMap[tokenTwo] = _swapTwo;\n swapMap[tokenThree] = _swapThree;\n swapMap[tokenFour] = _swapFour;\n\n if (address(_swapOne) != address(0)) {\n {\n uint8 i;\n for (; i < 32; i++) {\n try ISwap(_swapOne).getToken(i) returns (\n IERC20 token\n ) {\n swapTokensMap[_swapOne].push(token);\n token.safeApprove(address(_swapOne), MAX_UINT256);\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n } catch {\n break;\n }\n }\n require(i > 1, \"swap must have at least 2 tokens\");\n }\n }\n if (address(_swapTwo) != address(0)) {\n {\n uint8 i;\n for (; i < 32; i++) {\n try ISwap(_swapTwo).getToken(i) returns (\n IERC20 token\n ) {\n swapTokensMap[_swapTwo].push(token);\n token.safeApprove(address(_swapTwo), MAX_UINT256);\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n } catch {\n break;\n }\n }\n require(i > 1, \"swap must have at least 2 tokens\");\n }\n }\n\n if (address(_swapThree) != address(0)) {\n {\n uint8 i;\n for (; i < 32; i++) {\n try ISwap(_swapThree).getToken(i) returns (\n IERC20 token\n ) {\n swapTokensMap[_swapThree].push(token);\n token.safeApprove(address(_swapThree), MAX_UINT256);\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n } catch {\n break;\n }\n }\n require(i > 1, \"swap must have at least 2 tokens\");\n }\n }\n\n if (address(_swapFour) != address(0)) {\n {\n uint8 i;\n for (; i < 32; i++) {\n try ISwap(_swapFour).getToken(i) returns (\n IERC20 token\n ) {\n swapTokensMap[_swapFour].push(token);\n token.safeApprove(address(_swapFour), MAX_UINT256);\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n } catch {\n break;\n }\n }\n require(i > 1, \"swap must have at least 2 tokens\");\n }\n }\n }\n\n /**\n * @notice Calculate amount of tokens you receive on swap\n * @param tokenIndexFrom the token the user wants to sell\n * @param tokenIndexTo the token the user wants to buy\n * @param dx the amount of tokens the user wants to sell. If the token charges\n * a fee on transfers, use the amount that gets transferred after the fee.\n * @return amount of tokens the user will receive\n */\n function calculateSwap(\n IERC20 token,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx\n ) external view virtual returns (uint256) {\n ISwap swap = ISwap(\n swapMap[address(token)]\n );\n return swap.calculateSwap(tokenIndexFrom, tokenIndexTo, dx);\n }\n\n function swapAndRedeem(\n address to,\n uint256 chainId,\n IERC20 token,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx,\n uint256 minDy,\n uint256 deadline\n ) external {\n ISwap swap = ISwap(swapMap[address(token)]);\n require(address(swap) != address(0), \"Swap is 0x00\");\n IERC20[] memory tokens = swapTokensMap[address(swap)];\n tokens[tokenIndexFrom].safeTransferFrom(\n msg.sender,\n address(this),\n dx\n );\n // swap\n\n uint256 swappedAmount = swap.swap(\n tokenIndexFrom,\n tokenIndexTo,\n dx,\n minDy,\n deadline\n );\n // deposit into bridge, gets nUSD\n if (\n token.allowance(address(this), address(synapseBridge)) <\n swappedAmount\n ) {\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n }\n synapseBridge.redeem(to, chainId, token, swappedAmount);\n }\n\n function swapAndRedeemAndSwap(\n address to,\n uint256 chainId,\n IERC20 token,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx,\n uint256 minDy,\n uint256 deadline,\n uint8 swapTokenIndexFrom,\n uint8 swapTokenIndexTo,\n uint256 swapMinDy,\n uint256 swapDeadline\n ) external {\n require(\n address(swapMap[address(token)]) != address(0),\n \"Swap is 0x00\"\n );\n IERC20[] memory tokens = swapTokensMap[\n swapMap[address(token)]\n ];\n tokens[tokenIndexFrom].safeTransferFrom(\n msg.sender,\n address(this),\n dx\n );\n // swap\n\n uint256 swappedAmount = ISwap(swapMap[address(token)]).swap(tokenIndexFrom, tokenIndexTo, dx, minDy, deadline);\n // deposit into bridge, gets nUSD\n if (\n token.allowance(address(this), address(synapseBridge)) <\n swappedAmount\n ) {\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n }\n synapseBridge.redeemAndSwap(\n to,\n chainId,\n token,\n swappedAmount,\n swapTokenIndexFrom,\n swapTokenIndexTo,\n swapMinDy,\n swapDeadline\n );\n }\n\n function swapAndRedeemAndRemove(\n address to,\n uint256 chainId,\n IERC20 token,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx,\n uint256 minDy,\n uint256 deadline,\n uint8 liqTokenIndex,\n uint256 liqMinAmount,\n uint256 liqDeadline\n ) external {\n ISwap swap = ISwap(swapMap[address(token)]);\n require(address(swap) != address(0), \"Swap is 0x00\");\n IERC20[] memory tokens = swapTokensMap[address(swap)];\n tokens[tokenIndexFrom].safeTransferFrom(\n msg.sender,\n address(this),\n dx\n );\n // swap\n\n uint256 swappedAmount = swap.swap(\n tokenIndexFrom,\n tokenIndexTo,\n dx,\n minDy,\n deadline\n );\n // deposit into bridge, gets nUSD\n if (\n token.allowance(address(this), address(synapseBridge)) <\n swappedAmount\n ) {\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n }\n synapseBridge.redeemAndRemove(\n to,\n chainId,\n token,\n swappedAmount,\n liqTokenIndex,\n liqMinAmount,\n liqDeadline\n );\n }\n\n /**\n * @notice wraps SynapseBridge redeem()\n * @param to address on other chain to redeem underlying assets to\n * @param chainId which underlying chain to bridge assets onto\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n **/\n function redeem(\n address to,\n uint256 chainId,\n IERC20 token,\n uint256 amount\n ) external {\n token.safeTransferFrom(msg.sender, address(this), amount);\n if (address(token) == address(CANOLICAL_FRAX)) {\n uint256 swappedAmount = CANOLICAL_FRAX.exchangeCanonicalForOld(address(SYN_FRAX), amount);\n if (SYN_FRAX.allowance(address(this), address(synapseBridge)) < amount) {\n SYN_FRAX.safeApprove(address(synapseBridge), MAX_UINT256);\n }\n synapseBridge.redeem(to, chainId, SYN_FRAX, swappedAmount);\n } else {\n if (token.allowance(address(this), address(synapseBridge)) < amount) {\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n }\n synapseBridge.redeem(to, chainId, token, amount);\n }\n \n }\n\n /**\n * @notice Wraps SynapseBridge redeemv2() function\n * @param to address on other chain to bridge assets to\n * @param chainId which chain to bridge assets onto\n * @param token ERC20 compatible token to redeem into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n **/\n function redeemv2(\n bytes32 to,\n uint256 chainId,\n IERC20 token,\n uint256 amount\n ) external {\n token.safeTransferFrom(msg.sender, address(this), amount);\n\n if (token.allowance(address(this), address(synapseBridge)) < amount) {\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n }\n synapseBridge.redeemv2(to, chainId, token, amount);\n }\n\n /**\n * @notice wraps SynapseBridge redeem()\n * @param to address on other chain to redeem underlying assets to\n * @param chainId which underlying chain to bridge assets onto\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n **/\n function deposit(\n address to,\n uint256 chainId,\n IERC20 token,\n uint256 amount\n ) external {\n token.safeTransferFrom(msg.sender, address(this), amount);\n if (token.allowance(address(this), address(synapseBridge)) < amount) {\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n }\n synapseBridge.deposit(to, chainId, token, amount);\n }\n\n function swapETHAndRedeem(\n address to,\n uint256 chainId,\n IERC20 token,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx,\n uint256 minDy,\n uint256 deadline\n ) external payable {\n require(WETH_ADDRESS != address(0), \"WETH 0\");\n require(msg.value > 0 && msg.value == dx, \"INCORRECT MSG VALUE\");\n ISwap swap = ISwap(swapMap[address(token)]);\n require(address(swap) != address(0), \"Swap is 0x00\");\n IWETH9(WETH_ADDRESS).deposit{value: msg.value}();\n\n // swap\n uint256 swappedAmount = swap.swap(\n tokenIndexFrom,\n tokenIndexTo,\n dx,\n minDy,\n deadline\n );\n synapseBridge.redeem(to, chainId, token, swappedAmount);\n }\n\n /**\n * @notice Wraps redeemAndSwap on SynapseBridge.sol\n * Relays to nodes that (typically) a wrapped synAsset ERC20 token has been burned and the underlying needs to be redeeemed on the native chain. This function indicates to the nodes that they should attempt to redeem the LP token for the underlying assets (E.g \"swap\" out of the LP token)\n * @param to address on other chain to redeem underlying assets to\n * @param chainId which underlying chain to bridge assets onto\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n * @param tokenIndexFrom the token the user wants to swap from\n * @param tokenIndexTo the token the user wants to swap to\n * @param minDy the min amount the user would like to receive, or revert to only minting the SynERC20 token crosschain.\n * @param deadline latest timestamp to accept this transaction\n **/\n function redeemAndSwap(\n address to,\n uint256 chainId,\n IERC20 token,\n uint256 amount,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 minDy,\n uint256 deadline\n ) external {\n token.safeTransferFrom(msg.sender, address(this), amount);\n if (token.allowance(address(this), address(synapseBridge)) < amount) {\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n }\n synapseBridge.redeemAndSwap(\n to,\n chainId,\n token,\n amount,\n tokenIndexFrom,\n tokenIndexTo,\n minDy,\n deadline\n );\n }\n\n /**\n * @notice Wraps redeemAndRemove on SynapseBridge\n * Relays to nodes that (typically) a wrapped synAsset ERC20 token has been burned and the underlying needs to be redeeemed on the native chain. This function indicates to the nodes that they should attempt to redeem the LP token for the underlying assets (E.g \"swap\" out of the LP token)\n * @param to address on other chain to redeem underlying assets to\n * @param chainId which underlying chain to bridge assets onto\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount of (typically) LP token to pass to the nodes to attempt to removeLiquidity() with to redeem for the underlying assets of the LP token\n * @param liqTokenIndex Specifies which of the underlying LP assets the nodes should attempt to redeem for\n * @param liqMinAmount Specifies the minimum amount of the underlying asset needed for the nodes to execute the redeem/swap\n * @param liqDeadline Specificies the deadline that the nodes are allowed to try to redeem/swap the LP token\n **/\n function redeemAndRemove(\n address to,\n uint256 chainId,\n IERC20 token,\n uint256 amount,\n uint8 liqTokenIndex,\n uint256 liqMinAmount,\n uint256 liqDeadline\n ) external {\n token.safeTransferFrom(msg.sender, address(this), amount);\n if (token.allowance(address(this), address(synapseBridge)) < amount) {\n token.safeApprove(address(synapseBridge), MAX_UINT256);\n }\n synapseBridge.redeemAndRemove(\n to,\n chainId,\n token,\n amount,\n liqTokenIndex,\n liqMinAmount,\n liqDeadline\n );\n }\n}\n" + }, + "contracts/bridge/MoonriverSynapseBridge.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.6.12;\n\nimport \"@openzeppelin/contracts-upgradeable/proxy/Initializable.sol\";\nimport \"@openzeppelin/contracts-upgradeable/access/AccessControlUpgradeable.sol\";\nimport \"@openzeppelin/contracts-upgradeable/utils/ReentrancyGuardUpgradeable.sol\";\nimport \"@openzeppelin/contracts-upgradeable/utils/PausableUpgradeable.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/SafeERC20.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/ERC20Burnable.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport \"@openzeppelin/contracts/math/SafeMath.sol\";\n\nimport \"./interfaces/ISwap.sol\";\nimport \"./interfaces/IWETH9.sol\";\n\ninterface IERC20Mintable is IERC20 {\n function mint(address to, uint256 amount) external;\n}\n\ninterface IFrax {\n function exchangeOldForCanonical(\n address bridge_token_address,\n uint256 token_amount\n ) external returns (uint256);\n}\n\ncontract MRSynapseBridge is\n Initializable,\n AccessControlUpgradeable,\n ReentrancyGuardUpgradeable,\n PausableUpgradeable\n{\n using SafeERC20 for IERC20;\n using SafeERC20 for IERC20Mintable;\n using SafeMath for uint256;\n\n bytes32 public constant NODEGROUP_ROLE = keccak256(\"NODEGROUP_ROLE\");\n bytes32 public constant GOVERNANCE_ROLE = keccak256(\"GOVERNANCE_ROLE\");\n\n mapping(address => uint256) private fees;\n\n uint256 public startBlockNumber;\n uint256 public constant bridgeVersion = 6;\n uint256 public chainGasAmount;\n address payable public WETH_ADDRESS;\n\n mapping(bytes32 => bool) private kappaMap;\n\n receive() external payable {}\n\n function initialize() external initializer {\n startBlockNumber = block.number;\n _setupRole(DEFAULT_ADMIN_ROLE, msg.sender);\n __AccessControl_init();\n }\n\n function setChainGasAmount(uint256 amount) external {\n require(hasRole(GOVERNANCE_ROLE, msg.sender), \"Not governance\");\n chainGasAmount = amount;\n }\n\n function setWethAddress(address payable _wethAddress) external {\n require(hasRole(DEFAULT_ADMIN_ROLE, msg.sender), \"Not admin\");\n WETH_ADDRESS = _wethAddress;\n }\n\n function addKappas(bytes32[] calldata kappas) external {\n require(hasRole(GOVERNANCE_ROLE, msg.sender), \"Not governance\");\n for (uint256 i = 0; i < kappas.length; ++i) {\n kappaMap[kappas[i]] = true;\n }\n }\n\n event TokenDeposit(\n address indexed to,\n uint256 chainId,\n IERC20 token,\n uint256 amount\n );\n event TokenRedeem(\n address indexed to,\n uint256 chainId,\n IERC20 token,\n uint256 amount\n );\n event TokenWithdraw(\n address indexed to,\n IERC20 token,\n uint256 amount,\n uint256 fee,\n bytes32 indexed kappa\n );\n event TokenMint(\n address indexed to,\n IERC20Mintable token,\n uint256 amount,\n uint256 fee,\n bytes32 indexed kappa\n );\n event TokenDepositAndSwap(\n address indexed to,\n uint256 chainId,\n IERC20 token,\n uint256 amount,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 minDy,\n uint256 deadline\n );\n event TokenMintAndSwap(\n address indexed to,\n IERC20Mintable token,\n uint256 amount,\n uint256 fee,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 minDy,\n uint256 deadline,\n bool swapSuccess,\n bytes32 indexed kappa\n );\n event TokenRedeemAndSwap(\n address indexed to,\n uint256 chainId,\n IERC20 token,\n uint256 amount,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 minDy,\n uint256 deadline\n );\n event TokenRedeemAndRemove(\n address indexed to,\n uint256 chainId,\n IERC20 token,\n uint256 amount,\n uint8 swapTokenIndex,\n uint256 swapMinAmount,\n uint256 swapDeadline\n );\n event TokenWithdrawAndRemove(\n address indexed to,\n IERC20 token,\n uint256 amount,\n uint256 fee,\n uint8 swapTokenIndex,\n uint256 swapMinAmount,\n uint256 swapDeadline,\n bool swapSuccess,\n bytes32 indexed kappa\n );\n\n // v2 events\n event TokenRedeemV2(\n bytes32 indexed to,\n uint256 chainId,\n IERC20 token,\n uint256 amount\n );\n\n // VIEW FUNCTIONS ***/\n function getFeeBalance(address tokenAddress)\n external\n view\n returns (uint256)\n {\n return fees[tokenAddress];\n }\n\n function kappaExists(bytes32 kappa) external view returns (bool) {\n return kappaMap[kappa];\n }\n\n // FEE FUNCTIONS ***/\n /**\n * * @notice withdraw specified ERC20 token fees to a given address\n * * @param token ERC20 token in which fees acccumulated to transfer\n * * @param to Address to send the fees to\n */\n function withdrawFees(IERC20 token, address to) external whenNotPaused {\n require(hasRole(GOVERNANCE_ROLE, msg.sender), \"Not governance\");\n require(to != address(0), \"Address is 0x000\");\n if (fees[address(token)] != 0) {\n token.safeTransfer(to, fees[address(token)]);\n fees[address(token)] = 0;\n }\n }\n\n // PAUSABLE FUNCTIONS ***/\n function pause() external {\n require(hasRole(GOVERNANCE_ROLE, msg.sender), \"Not governance\");\n _pause();\n }\n\n function unpause() external {\n require(hasRole(GOVERNANCE_ROLE, msg.sender), \"Not governance\");\n _unpause();\n }\n\n /**\n * @notice Relays to nodes to transfers an ERC20 token cross-chain\n * @param to address on other chain to bridge assets to\n * @param chainId which chain to bridge assets onto\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n **/\n function deposit(\n address to,\n uint256 chainId,\n IERC20 token,\n uint256 amount\n ) external nonReentrant whenNotPaused {\n emit TokenDeposit(to, chainId, token, amount);\n token.safeTransferFrom(msg.sender, address(this), amount);\n }\n\n /**\n * @notice Relays to nodes that (typically) a wrapped synAsset ERC20 token has been burned and the underlying needs to be redeeemed on the native chain\n * @param to address on other chain to redeem underlying assets to\n * @param chainId which underlying chain to bridge assets onto\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n **/\n function redeem(\n address to,\n uint256 chainId,\n ERC20Burnable token,\n uint256 amount\n ) external nonReentrant whenNotPaused {\n emit TokenRedeem(to, chainId, token, amount);\n token.burnFrom(msg.sender, amount);\n }\n\n /**\n * @notice Function to be called by the node group to withdraw the underlying assets from the contract\n * @param to address on chain to send underlying assets to\n * @param token ERC20 compatible token to withdraw from the bridge\n * @param amount Amount in native token decimals to withdraw\n * @param fee Amount in native token decimals to save to the contract as fees\n * @param kappa kappa\n **/\n function withdraw(\n address to,\n IERC20 token,\n uint256 amount,\n uint256 fee,\n bytes32 kappa\n ) external nonReentrant whenNotPaused {\n require(\n hasRole(NODEGROUP_ROLE, msg.sender),\n \"Caller is not a node group\"\n );\n require(amount > fee, \"Amount must be greater than fee\");\n require(!kappaMap[kappa], \"Kappa is already present\");\n kappaMap[kappa] = true;\n fees[address(token)] = fees[address(token)].add(fee);\n if (address(token) == WETH_ADDRESS && WETH_ADDRESS != address(0)) {\n IWETH9(WETH_ADDRESS).withdraw(amount.sub(fee));\n (bool success, ) = to.call{value: amount.sub(fee)}(\"\");\n require(success, \"ETH_TRANSFER_FAILED\");\n emit TokenWithdraw(to, token, amount, fee, kappa);\n } else {\n emit TokenWithdraw(to, token, amount, fee, kappa);\n token.safeTransfer(to, amount.sub(fee));\n }\n }\n\n /**\n * @notice Nodes call this function to mint a SynERC20 (or any asset that the bridge is given minter access to). This is called by the nodes after a TokenDeposit event is emitted.\n * @dev This means the SynapseBridge.sol contract must have minter access to the token attempting to be minted\n * @param to address on other chain to redeem underlying assets to\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain post-fees\n * @param fee Amount in native token decimals to save to the contract as fees\n * @param kappa kappa\n **/\n function mint(\n address payable to,\n IERC20Mintable token,\n uint256 amount,\n uint256 fee,\n bytes32 kappa\n ) external nonReentrant whenNotPaused {\n require(\n hasRole(NODEGROUP_ROLE, msg.sender),\n \"Caller is not a node group\"\n );\n require(amount > fee, \"Amount must be greater than fee\");\n require(!kappaMap[kappa], \"Kappa is already present\");\n kappaMap[kappa] = true;\n fees[address(token)] = fees[address(token)].add(fee);\n emit TokenMint(to, token, amount.sub(fee), fee, kappa);\n token.mint(address(this), amount);\n // checks if synFRAX\n if (address(token) == 0xE96AC70907ffF3Efee79f502C985A7A21Bce407d) {\n token.safeIncreaseAllowance(\n 0x1A93B23281CC1CDE4C4741353F3064709A16197d,\n amount.sub(fee)\n );\n try\n IFrax(0x1A93B23281CC1CDE4C4741353F3064709A16197d)\n .exchangeOldForCanonical(address(token), amount.sub(fee))\n returns (uint256 canolical_tokens_out) {\n IERC20(0x1A93B23281CC1CDE4C4741353F3064709A16197d).safeTransfer(\n to,\n canolical_tokens_out\n );\n } catch {\n IERC20(token).safeTransfer(to, amount.sub(fee));\n }\n } else {\n IERC20(token).safeTransfer(to, amount.sub(fee));\n }\n if (chainGasAmount != 0 && address(this).balance > chainGasAmount) {\n to.call.value(chainGasAmount)(\"\");\n }\n }\n\n /**\n * @notice Relays to nodes to both transfer an ERC20 token cross-chain, and then have the nodes execute a swap through a liquidity pool on behalf of the user.\n * @param to address on other chain to bridge assets to\n * @param chainId which chain to bridge assets onto\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n * @param tokenIndexFrom the token the user wants to swap from\n * @param tokenIndexTo the token the user wants to swap to\n * @param minDy the min amount the user would like to receive, or revert to only minting the SynERC20 token crosschain.\n * @param deadline latest timestamp to accept this transaction\n **/\n function depositAndSwap(\n address to,\n uint256 chainId,\n IERC20 token,\n uint256 amount,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 minDy,\n uint256 deadline\n ) external nonReentrant whenNotPaused {\n emit TokenDepositAndSwap(\n to,\n chainId,\n token,\n amount,\n tokenIndexFrom,\n tokenIndexTo,\n minDy,\n deadline\n );\n token.safeTransferFrom(msg.sender, address(this), amount);\n }\n\n /**\n * @notice Relays to nodes that (typically) a wrapped synAsset ERC20 token has been burned and the underlying needs to be redeeemed on the native chain. This function indicates to the nodes that they should attempt to redeem the LP token for the underlying assets (E.g \"swap\" out of the LP token)\n * @param to address on other chain to redeem underlying assets to\n * @param chainId which underlying chain to bridge assets onto\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n * @param tokenIndexFrom the token the user wants to swap from\n * @param tokenIndexTo the token the user wants to swap to\n * @param minDy the min amount the user would like to receive, or revert to only minting the SynERC20 token crosschain.\n * @param deadline latest timestamp to accept this transaction\n **/\n function redeemAndSwap(\n address to,\n uint256 chainId,\n ERC20Burnable token,\n uint256 amount,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 minDy,\n uint256 deadline\n ) external nonReentrant whenNotPaused {\n emit TokenRedeemAndSwap(\n to,\n chainId,\n token,\n amount,\n tokenIndexFrom,\n tokenIndexTo,\n minDy,\n deadline\n );\n token.burnFrom(msg.sender, amount);\n }\n\n /**\n * @notice Relays to nodes that (typically) a wrapped synAsset ERC20 token has been burned and the underlying needs to be redeeemed on the native chain. This function indicates to the nodes that they should attempt to redeem the LP token for the underlying assets (E.g \"swap\" out of the LP token)\n * @param to address on other chain to redeem underlying assets to\n * @param chainId which underlying chain to bridge assets onto\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n * @param swapTokenIndex Specifies which of the underlying LP assets the nodes should attempt to redeem for\n * @param swapMinAmount Specifies the minimum amount of the underlying asset needed for the nodes to execute the redeem/swap\n * @param swapDeadline Specificies the deadline that the nodes are allowed to try to redeem/swap the LP token\n **/\n function redeemAndRemove(\n address to,\n uint256 chainId,\n ERC20Burnable token,\n uint256 amount,\n uint8 swapTokenIndex,\n uint256 swapMinAmount,\n uint256 swapDeadline\n ) external nonReentrant whenNotPaused {\n emit TokenRedeemAndRemove(\n to,\n chainId,\n token,\n amount,\n swapTokenIndex,\n swapMinAmount,\n swapDeadline\n );\n token.burnFrom(msg.sender, amount);\n }\n\n /**\n * @notice Nodes call this function to mint a SynERC20 (or any asset that the bridge is given minter access to), and then attempt to swap the SynERC20 into the desired destination asset. This is called by the nodes after a TokenDepositAndSwap event is emitted.\n * @dev This means the BridgeDeposit.sol contract must have minter access to the token attempting to be minted\n * @param to address on other chain to redeem underlying assets to\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain post-fees\n * @param fee Amount in native token decimals to save to the contract as fees\n * @param pool Destination chain's pool to use to swap SynERC20 -> Asset. The nodes determine this by using PoolConfig.sol.\n * @param tokenIndexFrom Index of the SynERC20 asset in the pool\n * @param tokenIndexTo Index of the desired final asset\n * @param minDy Minumum amount (in final asset decimals) that must be swapped for, otherwise the user will receive the SynERC20.\n * @param deadline Epoch time of the deadline that the swap is allowed to be executed.\n * @param kappa kappa\n **/\n function mintAndSwap(\n address payable to,\n IERC20Mintable token,\n uint256 amount,\n uint256 fee,\n ISwap pool,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 minDy,\n uint256 deadline,\n bytes32 kappa\n ) external nonReentrant whenNotPaused {\n require(\n hasRole(NODEGROUP_ROLE, msg.sender),\n \"Caller is not a node group\"\n );\n require(amount > fee, \"Amount must be greater than fee\");\n require(!kappaMap[kappa], \"Kappa is already present\");\n kappaMap[kappa] = true;\n fees[address(token)] = fees[address(token)].add(fee);\n // Transfer gas airdrop\n if (chainGasAmount != 0 && address(this).balance > chainGasAmount) {\n to.call.value(chainGasAmount)(\"\");\n }\n // first check to make sure more will be given than min amount required\n uint256 expectedOutput = ISwap(pool).calculateSwap(\n tokenIndexFrom,\n tokenIndexTo,\n amount.sub(fee)\n );\n\n if (expectedOutput >= minDy) {\n // proceed with swap\n token.mint(address(this), amount);\n token.safeIncreaseAllowance(address(pool), amount);\n try\n ISwap(pool).swap(\n tokenIndexFrom,\n tokenIndexTo,\n amount.sub(fee),\n minDy,\n deadline\n )\n returns (uint256 finalSwappedAmount) {\n // Swap succeeded, transfer swapped asset\n IERC20 swappedTokenTo = ISwap(pool).getToken(tokenIndexTo);\n if (\n address(swappedTokenTo) == WETH_ADDRESS &&\n WETH_ADDRESS != address(0)\n ) {\n IWETH9(WETH_ADDRESS).withdraw(finalSwappedAmount);\n (bool success, ) = to.call{value: finalSwappedAmount}(\"\");\n require(success, \"ETH_TRANSFER_FAILED\");\n emit TokenMintAndSwap(\n to,\n token,\n finalSwappedAmount,\n fee,\n tokenIndexFrom,\n tokenIndexTo,\n minDy,\n deadline,\n true,\n kappa\n );\n } else {\n swappedTokenTo.safeTransfer(to, finalSwappedAmount);\n emit TokenMintAndSwap(\n to,\n token,\n finalSwappedAmount,\n fee,\n tokenIndexFrom,\n tokenIndexTo,\n minDy,\n deadline,\n true,\n kappa\n );\n }\n } catch {\n IERC20(token).safeTransfer(to, amount.sub(fee));\n emit TokenMintAndSwap(\n to,\n token,\n amount.sub(fee),\n fee,\n tokenIndexFrom,\n tokenIndexTo,\n minDy,\n deadline,\n false,\n kappa\n );\n }\n } else {\n token.mint(address(this), amount);\n IERC20(token).safeTransfer(to, amount.sub(fee));\n emit TokenMintAndSwap(\n to,\n token,\n amount.sub(fee),\n fee,\n tokenIndexFrom,\n tokenIndexTo,\n minDy,\n deadline,\n false,\n kappa\n );\n }\n }\n\n /**\n * @notice Function to be called by the node group to withdraw the underlying assets from the contract\n * @param to address on chain to send underlying assets to\n * @param token ERC20 compatible token to withdraw from the bridge\n * @param amount Amount in native token decimals to withdraw\n * @param fee Amount in native token decimals to save to the contract as fees\n * @param pool Destination chain's pool to use to swap SynERC20 -> Asset. The nodes determine this by using PoolConfig.sol.\n * @param swapTokenIndex Specifies which of the underlying LP assets the nodes should attempt to redeem for\n * @param swapMinAmount Specifies the minimum amount of the underlying asset needed for the nodes to execute the redeem/swap\n * @param swapDeadline Specificies the deadline that the nodes are allowed to try to redeem/swap the LP token\n * @param kappa kappa\n **/\n function withdrawAndRemove(\n address to,\n IERC20 token,\n uint256 amount,\n uint256 fee,\n ISwap pool,\n uint8 swapTokenIndex,\n uint256 swapMinAmount,\n uint256 swapDeadline,\n bytes32 kappa\n ) external nonReentrant whenNotPaused {\n require(\n hasRole(NODEGROUP_ROLE, msg.sender),\n \"Caller is not a node group\"\n );\n require(amount > fee, \"Amount must be greater than fee\");\n require(!kappaMap[kappa], \"Kappa is already present\");\n kappaMap[kappa] = true;\n fees[address(token)] = fees[address(token)].add(fee);\n // first check to make sure more will be given than min amount required\n uint256 expectedOutput = ISwap(pool).calculateRemoveLiquidityOneToken(\n amount.sub(fee),\n swapTokenIndex\n );\n\n if (expectedOutput >= swapMinAmount) {\n token.safeIncreaseAllowance(address(pool), amount.sub(fee));\n try\n ISwap(pool).removeLiquidityOneToken(\n amount.sub(fee),\n swapTokenIndex,\n swapMinAmount,\n swapDeadline\n )\n returns (uint256 finalSwappedAmount) {\n // Swap succeeded, transfer swapped asset\n IERC20 swappedTokenTo = ISwap(pool).getToken(swapTokenIndex);\n swappedTokenTo.safeTransfer(to, finalSwappedAmount);\n emit TokenWithdrawAndRemove(\n to,\n token,\n finalSwappedAmount,\n fee,\n swapTokenIndex,\n swapMinAmount,\n swapDeadline,\n true,\n kappa\n );\n } catch {\n IERC20(token).safeTransfer(to, amount.sub(fee));\n emit TokenWithdrawAndRemove(\n to,\n token,\n amount.sub(fee),\n fee,\n swapTokenIndex,\n swapMinAmount,\n swapDeadline,\n false,\n kappa\n );\n }\n } else {\n token.safeTransfer(to, amount.sub(fee));\n emit TokenWithdrawAndRemove(\n to,\n token,\n amount.sub(fee),\n fee,\n swapTokenIndex,\n swapMinAmount,\n swapDeadline,\n false,\n kappa\n );\n }\n }\n\n // BRIDGE FUNCTIONS TO HANDLE DIFF ADDRESSES\n /**\n * @notice Relays to nodes that (typically) a wrapped synAsset ERC20 token has been burned and the underlying needs to be redeeemed on the native chain\n * @param to address on other chain to redeem underlying assets to\n * @param chainId which underlying chain to bridge assets onto\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n **/\n function redeemV2(\n bytes32 to,\n uint256 chainId,\n ERC20Burnable token,\n uint256 amount\n ) external nonReentrant whenNotPaused {\n emit TokenRedeemV2(to, chainId, token, amount);\n token.burnFrom(msg.sender, amount);\n }\n}\n" + }, + "contracts/bridge/HarmonySynapseBridge.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.6.12;\n\nimport \"@openzeppelin/contracts-upgradeable/proxy/Initializable.sol\";\nimport \"@openzeppelin/contracts-upgradeable/access/AccessControlUpgradeable.sol\";\nimport \"@openzeppelin/contracts-upgradeable/utils/ReentrancyGuardUpgradeable.sol\";\nimport \"@openzeppelin/contracts-upgradeable/utils/PausableUpgradeable.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/SafeERC20.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/ERC20Burnable.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport \"@openzeppelin/contracts/math/SafeMath.sol\";\n\nimport \"./interfaces/ISwap.sol\";\nimport \"./interfaces/IWETH9.sol\";\n\ninterface IERC20Mintable is IERC20 {\n function mint(address to, uint256 amount) external;\n}\n\ninterface IFrax {\n function exchangeOldForCanonical(\n address bridge_token_address,\n uint256 token_amount\n ) external returns (uint256);\n}\n\ncontract HarmonySynapseBridge is\n Initializable,\n AccessControlUpgradeable,\n ReentrancyGuardUpgradeable,\n PausableUpgradeable\n{\n using SafeERC20 for IERC20;\n using SafeERC20 for IERC20Mintable;\n using SafeMath for uint256;\n\n bytes32 public constant NODEGROUP_ROLE = keccak256(\"NODEGROUP_ROLE\");\n bytes32 public constant GOVERNANCE_ROLE = keccak256(\"GOVERNANCE_ROLE\");\n\n mapping(address => uint256) private fees;\n\n uint256 public startBlockNumber;\n uint256 public constant bridgeVersion = 6;\n uint256 public chainGasAmount;\n address payable public WETH_ADDRESS;\n\n mapping(bytes32 => bool) private kappaMap;\n\n receive() external payable {}\n\n function initialize() external initializer {\n startBlockNumber = block.number;\n _setupRole(DEFAULT_ADMIN_ROLE, msg.sender);\n __AccessControl_init();\n }\n\n function setChainGasAmount(uint256 amount) external {\n require(hasRole(GOVERNANCE_ROLE, msg.sender), \"Not governance\");\n chainGasAmount = amount;\n }\n\n function setWethAddress(address payable _wethAddress) external {\n require(hasRole(DEFAULT_ADMIN_ROLE, msg.sender), \"Not admin\");\n WETH_ADDRESS = _wethAddress;\n }\n\n function addKappas(bytes32[] calldata kappas) external {\n require(hasRole(GOVERNANCE_ROLE, msg.sender), \"Not governance\");\n for (uint256 i = 0; i < kappas.length; ++i) {\n kappaMap[kappas[i]] = true;\n }\n }\n\n event TokenDeposit(\n address indexed to,\n uint256 chainId,\n IERC20 token,\n uint256 amount\n );\n event TokenRedeem(\n address indexed to,\n uint256 chainId,\n IERC20 token,\n uint256 amount\n );\n event TokenWithdraw(\n address indexed to,\n IERC20 token,\n uint256 amount,\n uint256 fee,\n bytes32 indexed kappa\n );\n event TokenMint(\n address indexed to,\n IERC20Mintable token,\n uint256 amount,\n uint256 fee,\n bytes32 indexed kappa\n );\n event TokenDepositAndSwap(\n address indexed to,\n uint256 chainId,\n IERC20 token,\n uint256 amount,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 minDy,\n uint256 deadline\n );\n event TokenMintAndSwap(\n address indexed to,\n IERC20Mintable token,\n uint256 amount,\n uint256 fee,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 minDy,\n uint256 deadline,\n bool swapSuccess,\n bytes32 indexed kappa\n );\n event TokenRedeemAndSwap(\n address indexed to,\n uint256 chainId,\n IERC20 token,\n uint256 amount,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 minDy,\n uint256 deadline\n );\n event TokenRedeemAndRemove(\n address indexed to,\n uint256 chainId,\n IERC20 token,\n uint256 amount,\n uint8 swapTokenIndex,\n uint256 swapMinAmount,\n uint256 swapDeadline\n );\n event TokenWithdrawAndRemove(\n address indexed to,\n IERC20 token,\n uint256 amount,\n uint256 fee,\n uint8 swapTokenIndex,\n uint256 swapMinAmount,\n uint256 swapDeadline,\n bool swapSuccess,\n bytes32 indexed kappa\n );\n\n // v2 events\n event TokenRedeemV2(\n bytes32 indexed to,\n uint256 chainId,\n IERC20 token,\n uint256 amount\n );\n\n // VIEW FUNCTIONS ***/\n function getFeeBalance(address tokenAddress)\n external\n view\n returns (uint256)\n {\n return fees[tokenAddress];\n }\n\n function kappaExists(bytes32 kappa) external view returns (bool) {\n return kappaMap[kappa];\n }\n\n // FEE FUNCTIONS ***/\n /**\n * * @notice withdraw specified ERC20 token fees to a given address\n * * @param token ERC20 token in which fees acccumulated to transfer\n * * @param to Address to send the fees to\n */\n function withdrawFees(IERC20 token, address to) external whenNotPaused {\n require(hasRole(GOVERNANCE_ROLE, msg.sender), \"Not governance\");\n require(to != address(0), \"Address is 0x000\");\n if (fees[address(token)] != 0) {\n token.safeTransfer(to, fees[address(token)]);\n fees[address(token)] = 0;\n }\n }\n\n // PAUSABLE FUNCTIONS ***/\n function pause() external {\n require(hasRole(GOVERNANCE_ROLE, msg.sender), \"Not governance\");\n _pause();\n }\n\n function unpause() external {\n require(hasRole(GOVERNANCE_ROLE, msg.sender), \"Not governance\");\n _unpause();\n }\n\n /**\n * @notice Relays to nodes to transfers an ERC20 token cross-chain\n * @param to address on other chain to bridge assets to\n * @param chainId which chain to bridge assets onto\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n **/\n function deposit(\n address to,\n uint256 chainId,\n IERC20 token,\n uint256 amount\n ) external nonReentrant whenNotPaused {\n emit TokenDeposit(to, chainId, token, amount);\n token.safeTransferFrom(msg.sender, address(this), amount);\n }\n\n /**\n * @notice Relays to nodes that (typically) a wrapped synAsset ERC20 token has been burned and the underlying needs to be redeeemed on the native chain\n * @param to address on other chain to redeem underlying assets to\n * @param chainId which underlying chain to bridge assets onto\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n **/\n function redeem(\n address to,\n uint256 chainId,\n ERC20Burnable token,\n uint256 amount\n ) external nonReentrant whenNotPaused {\n emit TokenRedeem(to, chainId, token, amount);\n token.burnFrom(msg.sender, amount);\n }\n\n /**\n * @notice Function to be called by the node group to withdraw the underlying assets from the contract\n * @param to address on chain to send underlying assets to\n * @param token ERC20 compatible token to withdraw from the bridge\n * @param amount Amount in native token decimals to withdraw\n * @param fee Amount in native token decimals to save to the contract as fees\n * @param kappa kappa\n **/\n function withdraw(\n address to,\n IERC20 token,\n uint256 amount,\n uint256 fee,\n bytes32 kappa\n ) external nonReentrant whenNotPaused {\n require(\n hasRole(NODEGROUP_ROLE, msg.sender),\n \"Caller is not a node group\"\n );\n require(amount > fee, \"Amount must be greater than fee\");\n require(!kappaMap[kappa], \"Kappa is already present\");\n kappaMap[kappa] = true;\n fees[address(token)] = fees[address(token)].add(fee);\n if (address(token) == WETH_ADDRESS && WETH_ADDRESS != address(0)) {\n IWETH9(WETH_ADDRESS).withdraw(amount.sub(fee));\n (bool success, ) = to.call{value: amount.sub(fee)}(\"\");\n require(success, \"ETH_TRANSFER_FAILED\");\n emit TokenWithdraw(to, token, amount, fee, kappa);\n } else {\n emit TokenWithdraw(to, token, amount, fee, kappa);\n token.safeTransfer(to, amount.sub(fee));\n }\n }\n\n /**\n * @notice Nodes call this function to mint a SynERC20 (or any asset that the bridge is given minter access to). This is called by the nodes after a TokenDeposit event is emitted.\n * @dev This means the SynapseBridge.sol contract must have minter access to the token attempting to be minted\n * @param to address on other chain to redeem underlying assets to\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain post-fees\n * @param fee Amount in native token decimals to save to the contract as fees\n * @param kappa kappa\n **/\n function mint(\n address payable to,\n IERC20Mintable token,\n uint256 amount,\n uint256 fee,\n bytes32 kappa\n ) external nonReentrant whenNotPaused {\n require(\n hasRole(NODEGROUP_ROLE, msg.sender),\n \"Caller is not a node group\"\n );\n require(amount > fee, \"Amount must be greater than fee\");\n require(!kappaMap[kappa], \"Kappa is already present\");\n kappaMap[kappa] = true;\n fees[address(token)] = fees[address(token)].add(fee);\n emit TokenMint(to, token, amount.sub(fee), fee, kappa);\n token.mint(address(this), amount);\n // checks if synFRAX\n if (address(token) == 0x1852F70512298d56e9c8FDd905e02581E04ddb2a) {\n if (\n token.allowance(\n address(this),\n 0xFa7191D292d5633f702B0bd7E3E3BcCC0e633200\n ) < amount.sub(fee)\n ) {\n token.safeApprove(\n address(0xFa7191D292d5633f702B0bd7E3E3BcCC0e633200),\n 0\n );\n token.safeApprove(\n address(0xFa7191D292d5633f702B0bd7E3E3BcCC0e633200),\n type(uint256).max\n );\n }\n try\n IFrax(0xFa7191D292d5633f702B0bd7E3E3BcCC0e633200)\n .exchangeOldForCanonical(address(token), amount.sub(fee))\n returns (uint256 canolical_tokens_out) {\n IERC20(0xFa7191D292d5633f702B0bd7E3E3BcCC0e633200).safeTransfer(\n to,\n canolical_tokens_out\n );\n } catch {\n IERC20(token).safeTransfer(to, amount.sub(fee));\n }\n } else {\n IERC20(token).safeTransfer(to, amount.sub(fee));\n }\n if (chainGasAmount != 0 && address(this).balance > chainGasAmount) {\n to.call.value(chainGasAmount)(\"\");\n }\n }\n\n /**\n * @notice Relays to nodes to both transfer an ERC20 token cross-chain, and then have the nodes execute a swap through a liquidity pool on behalf of the user.\n * @param to address on other chain to bridge assets to\n * @param chainId which chain to bridge assets onto\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n * @param tokenIndexFrom the token the user wants to swap from\n * @param tokenIndexTo the token the user wants to swap to\n * @param minDy the min amount the user would like to receive, or revert to only minting the SynERC20 token crosschain.\n * @param deadline latest timestamp to accept this transaction\n **/\n function depositAndSwap(\n address to,\n uint256 chainId,\n IERC20 token,\n uint256 amount,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 minDy,\n uint256 deadline\n ) external nonReentrant whenNotPaused {\n emit TokenDepositAndSwap(\n to,\n chainId,\n token,\n amount,\n tokenIndexFrom,\n tokenIndexTo,\n minDy,\n deadline\n );\n token.safeTransferFrom(msg.sender, address(this), amount);\n }\n\n /**\n * @notice Relays to nodes that (typically) a wrapped synAsset ERC20 token has been burned and the underlying needs to be redeeemed on the native chain. This function indicates to the nodes that they should attempt to redeem the LP token for the underlying assets (E.g \"swap\" out of the LP token)\n * @param to address on other chain to redeem underlying assets to\n * @param chainId which underlying chain to bridge assets onto\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n * @param tokenIndexFrom the token the user wants to swap from\n * @param tokenIndexTo the token the user wants to swap to\n * @param minDy the min amount the user would like to receive, or revert to only minting the SynERC20 token crosschain.\n * @param deadline latest timestamp to accept this transaction\n **/\n function redeemAndSwap(\n address to,\n uint256 chainId,\n ERC20Burnable token,\n uint256 amount,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 minDy,\n uint256 deadline\n ) external nonReentrant whenNotPaused {\n emit TokenRedeemAndSwap(\n to,\n chainId,\n token,\n amount,\n tokenIndexFrom,\n tokenIndexTo,\n minDy,\n deadline\n );\n token.burnFrom(msg.sender, amount);\n }\n\n /**\n * @notice Relays to nodes that (typically) a wrapped synAsset ERC20 token has been burned and the underlying needs to be redeeemed on the native chain. This function indicates to the nodes that they should attempt to redeem the LP token for the underlying assets (E.g \"swap\" out of the LP token)\n * @param to address on other chain to redeem underlying assets to\n * @param chainId which underlying chain to bridge assets onto\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n * @param swapTokenIndex Specifies which of the underlying LP assets the nodes should attempt to redeem for\n * @param swapMinAmount Specifies the minimum amount of the underlying asset needed for the nodes to execute the redeem/swap\n * @param swapDeadline Specificies the deadline that the nodes are allowed to try to redeem/swap the LP token\n **/\n function redeemAndRemove(\n address to,\n uint256 chainId,\n ERC20Burnable token,\n uint256 amount,\n uint8 swapTokenIndex,\n uint256 swapMinAmount,\n uint256 swapDeadline\n ) external nonReentrant whenNotPaused {\n emit TokenRedeemAndRemove(\n to,\n chainId,\n token,\n amount,\n swapTokenIndex,\n swapMinAmount,\n swapDeadline\n );\n token.burnFrom(msg.sender, amount);\n }\n\n /**\n * @notice Nodes call this function to mint a SynERC20 (or any asset that the bridge is given minter access to), and then attempt to swap the SynERC20 into the desired destination asset. This is called by the nodes after a TokenDepositAndSwap event is emitted.\n * @dev This means the BridgeDeposit.sol contract must have minter access to the token attempting to be minted\n * @param to address on other chain to redeem underlying assets to\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain post-fees\n * @param fee Amount in native token decimals to save to the contract as fees\n * @param pool Destination chain's pool to use to swap SynERC20 -> Asset. The nodes determine this by using PoolConfig.sol.\n * @param tokenIndexFrom Index of the SynERC20 asset in the pool\n * @param tokenIndexTo Index of the desired final asset\n * @param minDy Minumum amount (in final asset decimals) that must be swapped for, otherwise the user will receive the SynERC20.\n * @param deadline Epoch time of the deadline that the swap is allowed to be executed.\n * @param kappa kappa\n **/\n function mintAndSwap(\n address payable to,\n IERC20Mintable token,\n uint256 amount,\n uint256 fee,\n ISwap pool,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 minDy,\n uint256 deadline,\n bytes32 kappa\n ) external nonReentrant whenNotPaused {\n require(\n hasRole(NODEGROUP_ROLE, msg.sender),\n \"Caller is not a node group\"\n );\n require(amount > fee, \"Amount must be greater than fee\");\n require(!kappaMap[kappa], \"Kappa is already present\");\n kappaMap[kappa] = true;\n fees[address(token)] = fees[address(token)].add(fee);\n // Transfer gas airdrop\n if (chainGasAmount != 0 && address(this).balance > chainGasAmount) {\n to.call.value(chainGasAmount)(\"\");\n }\n // first check to make sure more will be given than min amount required\n uint256 expectedOutput = ISwap(pool).calculateSwap(\n tokenIndexFrom,\n tokenIndexTo,\n amount.sub(fee)\n );\n\n if (expectedOutput >= minDy) {\n // proceed with swap\n token.mint(address(this), amount);\n token.safeIncreaseAllowance(address(pool), amount);\n try\n ISwap(pool).swap(\n tokenIndexFrom,\n tokenIndexTo,\n amount.sub(fee),\n minDy,\n deadline\n )\n returns (uint256 finalSwappedAmount) {\n // Swap succeeded, transfer swapped asset\n IERC20 swappedTokenTo = ISwap(pool).getToken(tokenIndexTo);\n if (\n address(swappedTokenTo) == WETH_ADDRESS &&\n WETH_ADDRESS != address(0)\n ) {\n IWETH9(WETH_ADDRESS).withdraw(finalSwappedAmount);\n (bool success, ) = to.call{value: finalSwappedAmount}(\"\");\n require(success, \"ETH_TRANSFER_FAILED\");\n emit TokenMintAndSwap(\n to,\n token,\n finalSwappedAmount,\n fee,\n tokenIndexFrom,\n tokenIndexTo,\n minDy,\n deadline,\n true,\n kappa\n );\n } else {\n swappedTokenTo.safeTransfer(to, finalSwappedAmount);\n emit TokenMintAndSwap(\n to,\n token,\n finalSwappedAmount,\n fee,\n tokenIndexFrom,\n tokenIndexTo,\n minDy,\n deadline,\n true,\n kappa\n );\n }\n } catch {\n IERC20(token).safeTransfer(to, amount.sub(fee));\n emit TokenMintAndSwap(\n to,\n token,\n amount.sub(fee),\n fee,\n tokenIndexFrom,\n tokenIndexTo,\n minDy,\n deadline,\n false,\n kappa\n );\n }\n } else {\n token.mint(address(this), amount);\n IERC20(token).safeTransfer(to, amount.sub(fee));\n emit TokenMintAndSwap(\n to,\n token,\n amount.sub(fee),\n fee,\n tokenIndexFrom,\n tokenIndexTo,\n minDy,\n deadline,\n false,\n kappa\n );\n }\n }\n\n /**\n * @notice Function to be called by the node group to withdraw the underlying assets from the contract\n * @param to address on chain to send underlying assets to\n * @param token ERC20 compatible token to withdraw from the bridge\n * @param amount Amount in native token decimals to withdraw\n * @param fee Amount in native token decimals to save to the contract as fees\n * @param pool Destination chain's pool to use to swap SynERC20 -> Asset. The nodes determine this by using PoolConfig.sol.\n * @param swapTokenIndex Specifies which of the underlying LP assets the nodes should attempt to redeem for\n * @param swapMinAmount Specifies the minimum amount of the underlying asset needed for the nodes to execute the redeem/swap\n * @param swapDeadline Specificies the deadline that the nodes are allowed to try to redeem/swap the LP token\n * @param kappa kappa\n **/\n function withdrawAndRemove(\n address to,\n IERC20 token,\n uint256 amount,\n uint256 fee,\n ISwap pool,\n uint8 swapTokenIndex,\n uint256 swapMinAmount,\n uint256 swapDeadline,\n bytes32 kappa\n ) external nonReentrant whenNotPaused {\n require(\n hasRole(NODEGROUP_ROLE, msg.sender),\n \"Caller is not a node group\"\n );\n require(amount > fee, \"Amount must be greater than fee\");\n require(!kappaMap[kappa], \"Kappa is already present\");\n kappaMap[kappa] = true;\n fees[address(token)] = fees[address(token)].add(fee);\n // first check to make sure more will be given than min amount required\n uint256 expectedOutput = ISwap(pool).calculateRemoveLiquidityOneToken(\n amount.sub(fee),\n swapTokenIndex\n );\n\n if (expectedOutput >= swapMinAmount) {\n token.safeIncreaseAllowance(address(pool), amount.sub(fee));\n try\n ISwap(pool).removeLiquidityOneToken(\n amount.sub(fee),\n swapTokenIndex,\n swapMinAmount,\n swapDeadline\n )\n returns (uint256 finalSwappedAmount) {\n // Swap succeeded, transfer swapped asset\n IERC20 swappedTokenTo = ISwap(pool).getToken(swapTokenIndex);\n swappedTokenTo.safeTransfer(to, finalSwappedAmount);\n emit TokenWithdrawAndRemove(\n to,\n token,\n finalSwappedAmount,\n fee,\n swapTokenIndex,\n swapMinAmount,\n swapDeadline,\n true,\n kappa\n );\n } catch {\n IERC20(token).safeTransfer(to, amount.sub(fee));\n emit TokenWithdrawAndRemove(\n to,\n token,\n amount.sub(fee),\n fee,\n swapTokenIndex,\n swapMinAmount,\n swapDeadline,\n false,\n kappa\n );\n }\n } else {\n token.safeTransfer(to, amount.sub(fee));\n emit TokenWithdrawAndRemove(\n to,\n token,\n amount.sub(fee),\n fee,\n swapTokenIndex,\n swapMinAmount,\n swapDeadline,\n false,\n kappa\n );\n }\n }\n\n // BRIDGE FUNCTIONS TO HANDLE DIFF ADDRESSES\n /**\n * @notice Relays to nodes that (typically) a wrapped synAsset ERC20 token has been burned and the underlying needs to be redeeemed on the native chain\n * @param to address on other chain to redeem underlying assets to\n * @param chainId which underlying chain to bridge assets onto\n * @param token ERC20 compatible token to deposit into the bridge\n * @param amount Amount in native token decimals to transfer cross-chain pre-fees\n **/\n function redeemV2(\n bytes32 to,\n uint256 chainId,\n ERC20Burnable token,\n uint256 amount\n ) external nonReentrant whenNotPaused {\n emit TokenRedeemV2(to, chainId, token, amount);\n token.burnFrom(msg.sender, amount);\n }\n}\n" + }, + "@openzeppelin/contracts-upgradeable/drafts/EIP712Upgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <0.8.0;\nimport \"../proxy/Initializable.sol\";\n\n/**\n * @dev https://eips.ethereum.org/EIPS/eip-712[EIP 712] is a standard for hashing and signing of typed structured data.\n *\n * The encoding specified in the EIP is very generic, and such a generic implementation in Solidity is not feasible,\n * thus this contract does not implement the encoding itself. Protocols need to implement the type-specific encoding\n * they need in their contracts using a combination of `abi.encode` and `keccak256`.\n *\n * This contract implements the EIP 712 domain separator ({_domainSeparatorV4}) that is used as part of the encoding\n * scheme, and the final step of the encoding to obtain the message digest that is then signed via ECDSA\n * ({_hashTypedDataV4}).\n *\n * The implementation of the domain separator was designed to be as efficient as possible while still properly updating\n * the chain id to protect against replay attacks on an eventual fork of the chain.\n *\n * NOTE: This contract implements the version of the encoding known as \"v4\", as implemented by the JSON RPC method\n * https://docs.metamask.io/guide/signing-data.html[`eth_signTypedDataV4` in MetaMask].\n *\n * _Available since v3.4._\n */\nabstract contract EIP712Upgradeable is Initializable {\n /* solhint-disable var-name-mixedcase */\n bytes32 private _HASHED_NAME;\n bytes32 private _HASHED_VERSION;\n bytes32 private constant _TYPE_HASH = keccak256(\"EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)\");\n /* solhint-enable var-name-mixedcase */\n\n /**\n * @dev Initializes the domain separator and parameter caches.\n *\n * The meaning of `name` and `version` is specified in\n * https://eips.ethereum.org/EIPS/eip-712#definition-of-domainseparator[EIP 712]:\n *\n * - `name`: the user readable name of the signing domain, i.e. the name of the DApp or the protocol.\n * - `version`: the current major version of the signing domain.\n *\n * NOTE: These parameters cannot be changed except through a xref:learn::upgrading-smart-contracts.adoc[smart\n * contract upgrade].\n */\n function __EIP712_init(string memory name, string memory version) internal initializer {\n __EIP712_init_unchained(name, version);\n }\n\n function __EIP712_init_unchained(string memory name, string memory version) internal initializer {\n bytes32 hashedName = keccak256(bytes(name));\n bytes32 hashedVersion = keccak256(bytes(version));\n _HASHED_NAME = hashedName;\n _HASHED_VERSION = hashedVersion;\n }\n\n /**\n * @dev Returns the domain separator for the current chain.\n */\n function _domainSeparatorV4() internal view returns (bytes32) {\n return _buildDomainSeparator(_TYPE_HASH, _EIP712NameHash(), _EIP712VersionHash());\n }\n\n function _buildDomainSeparator(bytes32 typeHash, bytes32 name, bytes32 version) private view returns (bytes32) {\n return keccak256(\n abi.encode(\n typeHash,\n name,\n version,\n _getChainId(),\n address(this)\n )\n );\n }\n\n /**\n * @dev Given an already https://eips.ethereum.org/EIPS/eip-712#definition-of-hashstruct[hashed struct], this\n * function returns the hash of the fully encoded EIP712 message for this domain.\n *\n * This hash can be used together with {ECDSA-recover} to obtain the signer of a message. For example:\n *\n * ```solidity\n * bytes32 digest = _hashTypedDataV4(keccak256(abi.encode(\n * keccak256(\"Mail(address to,string contents)\"),\n * mailTo,\n * keccak256(bytes(mailContents))\n * )));\n * address signer = ECDSA.recover(digest, signature);\n * ```\n */\n function _hashTypedDataV4(bytes32 structHash) internal view virtual returns (bytes32) {\n return keccak256(abi.encodePacked(\"\\x19\\x01\", _domainSeparatorV4(), structHash));\n }\n\n function _getChainId() private view returns (uint256 chainId) {\n this; // silence state mutability warning without generating bytecode - see https://github.com/ethereum/solidity/issues/2691\n // solhint-disable-next-line no-inline-assembly\n assembly {\n chainId := chainid()\n }\n }\n\n /**\n * @dev The hash of the name parameter for the EIP712 domain.\n *\n * NOTE: This function reads from storage by default, but can be redefined to return a constant value if gas costs\n * are a concern.\n */\n function _EIP712NameHash() internal virtual view returns (bytes32) {\n return _HASHED_NAME;\n }\n\n /**\n * @dev The hash of the version parameter for the EIP712 domain.\n *\n * NOTE: This function reads from storage by default, but can be redefined to return a constant value if gas costs\n * are a concern.\n */\n function _EIP712VersionHash() internal virtual view returns (bytes32) {\n return _HASHED_VERSION;\n }\n uint256[50] private __gap;\n}\n" + }, + "@openzeppelin/contracts-upgradeable/drafts/ERC20PermitUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.5 <0.8.0;\n\nimport \"../token/ERC20/ERC20Upgradeable.sol\";\nimport \"./IERC20PermitUpgradeable.sol\";\nimport \"../cryptography/ECDSAUpgradeable.sol\";\nimport \"../utils/CountersUpgradeable.sol\";\nimport \"./EIP712Upgradeable.sol\";\nimport \"../proxy/Initializable.sol\";\n\n/**\n * @dev Implementation of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in\n * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612].\n *\n * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by\n * presenting a message signed by the account. By not relying on `{IERC20-approve}`, the token holder account doesn't\n * need to send a transaction, and thus is not required to hold Ether at all.\n *\n * _Available since v3.4._\n */\nabstract contract ERC20PermitUpgradeable is Initializable, ERC20Upgradeable, IERC20PermitUpgradeable, EIP712Upgradeable {\n using CountersUpgradeable for CountersUpgradeable.Counter;\n\n mapping (address => CountersUpgradeable.Counter) private _nonces;\n\n // solhint-disable-next-line var-name-mixedcase\n bytes32 private _PERMIT_TYPEHASH;\n\n /**\n * @dev Initializes the {EIP712} domain separator using the `name` parameter, and setting `version` to `\"1\"`.\n *\n * It's a good idea to use the same `name` that is defined as the ERC20 token name.\n */\n function __ERC20Permit_init(string memory name) internal initializer {\n __Context_init_unchained();\n __EIP712_init_unchained(name, \"1\");\n __ERC20Permit_init_unchained(name);\n }\n\n function __ERC20Permit_init_unchained(string memory name) internal initializer {\n _PERMIT_TYPEHASH = keccak256(\"Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)\");\n }\n\n /**\n * @dev See {IERC20Permit-permit}.\n */\n function permit(address owner, address spender, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s) public virtual override {\n // solhint-disable-next-line not-rely-on-time\n require(block.timestamp <= deadline, \"ERC20Permit: expired deadline\");\n\n bytes32 structHash = keccak256(\n abi.encode(\n _PERMIT_TYPEHASH,\n owner,\n spender,\n value,\n _nonces[owner].current(),\n deadline\n )\n );\n\n bytes32 hash = _hashTypedDataV4(structHash);\n\n address signer = ECDSAUpgradeable.recover(hash, v, r, s);\n require(signer == owner, \"ERC20Permit: invalid signature\");\n\n _nonces[owner].increment();\n _approve(owner, spender, value);\n }\n\n /**\n * @dev See {IERC20Permit-nonces}.\n */\n function nonces(address owner) public view override returns (uint256) {\n return _nonces[owner].current();\n }\n\n /**\n * @dev See {IERC20Permit-DOMAIN_SEPARATOR}.\n */\n // solhint-disable-next-line func-name-mixedcase\n function DOMAIN_SEPARATOR() external view override returns (bytes32) {\n return _domainSeparatorV4();\n }\n uint256[49] private __gap;\n}\n" + }, + "@openzeppelin/contracts-upgradeable/drafts/IERC20PermitUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <0.8.0;\n\n/**\n * @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in\n * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612].\n *\n * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by\n * presenting a message signed by the account. By not relying on `{IERC20-approve}`, the token holder account doesn't\n * need to send a transaction, and thus is not required to hold Ether at all.\n */\ninterface IERC20PermitUpgradeable {\n /**\n * @dev Sets `value` as the allowance of `spender` over `owner`'s tokens,\n * given `owner`'s signed approval.\n *\n * IMPORTANT: The same issues {IERC20-approve} has related to transaction\n * ordering also apply here.\n *\n * Emits an {Approval} event.\n *\n * Requirements:\n *\n * - `spender` cannot be the zero address.\n * - `deadline` must be a timestamp in the future.\n * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner`\n * over the EIP712-formatted function arguments.\n * - the signature must use ``owner``'s current nonce (see {nonces}).\n *\n * For more information on the signature format, see the\n * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP\n * section].\n */\n function permit(address owner, address spender, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s) external;\n\n /**\n * @dev Returns the current nonce for `owner`. This value must be\n * included whenever a signature is generated for {permit}.\n *\n * Every successful call to {permit} increases ``owner``'s nonce by one. This\n * prevents a signature from being used multiple times.\n */\n function nonces(address owner) external view returns (uint256);\n\n /**\n * @dev Returns the domain separator used in the encoding of the signature for `permit`, as defined by {EIP712}.\n */\n // solhint-disable-next-line func-name-mixedcase\n function DOMAIN_SEPARATOR() external view returns (bytes32);\n}\n" + }, + "@openzeppelin/contracts-upgradeable/cryptography/ECDSAUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <0.8.0;\n\n/**\n * @dev Elliptic Curve Digital Signature Algorithm (ECDSA) operations.\n *\n * These functions can be used to verify that a message was signed by the holder\n * of the private keys of a given address.\n */\nlibrary ECDSAUpgradeable {\n /**\n * @dev Returns the address that signed a hashed message (`hash`) with\n * `signature`. This address can then be used for verification purposes.\n *\n * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:\n * this function rejects them by requiring the `s` value to be in the lower\n * half order, and the `v` value to be either 27 or 28.\n *\n * IMPORTANT: `hash` _must_ be the result of a hash operation for the\n * verification to be secure: it is possible to craft signatures that\n * recover to arbitrary addresses for non-hashed data. A safe way to ensure\n * this is by receiving a hash of the original message (which may otherwise\n * be too long), and then calling {toEthSignedMessageHash} on it.\n */\n function recover(bytes32 hash, bytes memory signature) internal pure returns (address) {\n // Check the signature length\n if (signature.length != 65) {\n revert(\"ECDSA: invalid signature length\");\n }\n\n // Divide the signature in r, s and v variables\n bytes32 r;\n bytes32 s;\n uint8 v;\n\n // ecrecover takes the signature parameters, and the only way to get them\n // currently is to use assembly.\n // solhint-disable-next-line no-inline-assembly\n assembly {\n r := mload(add(signature, 0x20))\n s := mload(add(signature, 0x40))\n v := byte(0, mload(add(signature, 0x60)))\n }\n\n return recover(hash, v, r, s);\n }\n\n /**\n * @dev Overload of {ECDSA-recover-bytes32-bytes-} that receives the `v`,\n * `r` and `s` signature fields separately.\n */\n function recover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) internal pure returns (address) {\n // EIP-2 still allows signature malleability for ecrecover(). Remove this possibility and make the signature\n // unique. Appendix F in the Ethereum Yellow paper (https://ethereum.github.io/yellowpaper/paper.pdf), defines\n // the valid range for s in (281): 0 < s < secp256k1n ÷ 2 + 1, and for v in (282): v ∈ {27, 28}. Most\n // signatures from current libraries generate a unique signature with an s-value in the lower half order.\n //\n // If your library generates malleable signatures, such as s-values in the upper range, calculate a new s-value\n // with 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 - s1 and flip v from 27 to 28 or\n // vice versa. If your library also generates signatures with 0/1 for v instead 27/28, add 27 to v to accept\n // these malleable signatures as well.\n require(uint256(s) <= 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0, \"ECDSA: invalid signature 's' value\");\n require(v == 27 || v == 28, \"ECDSA: invalid signature 'v' value\");\n\n // If the signature is valid (and not malleable), return the signer address\n address signer = ecrecover(hash, v, r, s);\n require(signer != address(0), \"ECDSA: invalid signature\");\n\n return signer;\n }\n\n /**\n * @dev Returns an Ethereum Signed Message, created from a `hash`. This\n * replicates the behavior of the\n * https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_sign[`eth_sign`]\n * JSON-RPC method.\n *\n * See {recover}.\n */\n function toEthSignedMessageHash(bytes32 hash) internal pure returns (bytes32) {\n // 32 is the length in bytes of hash,\n // enforced by the type signature above\n return keccak256(abi.encodePacked(\"\\x19Ethereum Signed Message:\\n32\", hash));\n }\n}\n" + }, + "@openzeppelin/contracts-upgradeable/utils/CountersUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <0.8.0;\n\nimport \"../math/SafeMathUpgradeable.sol\";\n\n/**\n * @title Counters\n * @author Matt Condon (@shrugs)\n * @dev Provides counters that can only be incremented or decremented by one. This can be used e.g. to track the number\n * of elements in a mapping, issuing ERC721 ids, or counting request ids.\n *\n * Include with `using Counters for Counters.Counter;`\n * Since it is not possible to overflow a 256 bit integer with increments of one, `increment` can skip the {SafeMath}\n * overflow check, thereby saving gas. This does assume however correct usage, in that the underlying `_value` is never\n * directly accessed.\n */\nlibrary CountersUpgradeable {\n using SafeMathUpgradeable for uint256;\n\n struct Counter {\n // This variable should never be directly accessed by users of the library: interactions must be restricted to\n // the library's function. As of Solidity v0.5.2, this cannot be enforced, though there is a proposal to add\n // this feature: see https://github.com/ethereum/solidity/issues/4637\n uint256 _value; // default: 0\n }\n\n function current(Counter storage counter) internal view returns (uint256) {\n return counter._value;\n }\n\n function increment(Counter storage counter) internal {\n // The {SafeMath} overflow check can be skipped here, see the comment at the top\n counter._value += 1;\n }\n\n function decrement(Counter storage counter) internal {\n counter._value = counter._value.sub(1);\n }\n}\n" + }, + "contracts/bridge/SynapseERC20.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.6.12;\n\nimport \"@openzeppelin/contracts-upgradeable/token/ERC20/ERC20Upgradeable.sol\";\nimport \"@openzeppelin/contracts-upgradeable/token/ERC20/ERC20BurnableUpgradeable.sol\";\nimport \"@openzeppelin/contracts-upgradeable/drafts/ERC20PermitUpgradeable.sol\";\nimport \"@openzeppelin/contracts-upgradeable/access/AccessControlUpgradeable.sol\";\nimport \"@openzeppelin/contracts-upgradeable/proxy/Initializable.sol\";\n\ncontract SynapseERC20 is\n Initializable,\n ContextUpgradeable,\n AccessControlUpgradeable,\n ERC20BurnableUpgradeable,\n ERC20PermitUpgradeable\n{\n bytes32 public constant MINTER_ROLE = keccak256(\"MINTER_ROLE\");\n\n /**\n * @notice Initializes this ERC20 contract with the given parameters.\n * @param name Token name\n * @param symbol Token symbol\n * @param decimals Token name\n * @param owner admin address to be initialized with\n */\n function initialize(\n string memory name,\n string memory symbol,\n uint8 decimals,\n address owner\n ) external initializer {\n __Context_init_unchained();\n __AccessControl_init_unchained();\n __ERC20_init_unchained(name, symbol);\n __ERC20Burnable_init_unchained();\n _setupDecimals(decimals);\n __ERC20Permit_init(name);\n _setupRole(DEFAULT_ADMIN_ROLE, owner);\n }\n\n function mint(address to, uint256 amount) external {\n require(hasRole(MINTER_ROLE, msg.sender), \"Not a minter\");\n _mint(to, amount);\n }\n}\n" + }, + "contracts/auxiliary/DummyWethProxy.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.6.12;\nimport \"@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol\";\nimport \"@openzeppelin/contracts-upgradeable/proxy/Initializable.sol\";\n\ninterface IWETH9 {\n function name() external view returns (string memory);\n\n function symbol() external view returns (string memory);\n\n function decimals() external view returns (uint8);\n\n function balanceOf(address) external view returns (uint256);\n\n function allowance(address, address) external view returns (uint256);\n\n receive() external payable;\n\n function deposit() external payable;\n\n function withdraw(uint256 wad) external;\n\n function totalSupply() external view returns (uint256);\n\n function approve(address guy, uint256 wad) external returns (bool);\n\n function transfer(address dst, uint256 wad) external returns (bool);\n\n function transferFrom(\n address src,\n address dst,\n uint256 wad\n ) external returns (bool);\n}\n\ncontract DummyWethProxy is Initializable, OwnableUpgradeable {\n function initialize() external initializer {\n __Ownable_init();\n }\n\n IWETH9 public WETH;\n\n function setWETHAddress(address payable _weth) external onlyOwner {\n WETH = IWETH9(_weth);\n }\n\n function withdrawToSelf(uint256 amount) external {\n WETH.withdraw(amount);\n }\n\n function rescue(uint256 amount) external onlyOwner {\n WETH.transfer(owner(), amount);\n }\n\n receive() external payable {}\n\n fallback() external payable {}\n}\n" + }, + "contracts/amm/helper/test/TestMathUtils.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.6.12;\n\nimport \"../../MathUtils.sol\";\n\ncontract TestMathUtils {\n using MathUtils for uint256;\n\n function difference(uint256 a, uint256 b) public pure returns (uint256) {\n return a.difference(b);\n }\n\n function within1(uint256 a, uint256 b) public pure returns (bool) {\n return a.within1(b);\n }\n}\n" + }, + "contracts/bridge/ERC20Migrator.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.6.12;\n\nimport \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/SafeERC20.sol\";\nimport \"@openzeppelin/contracts/math/SafeMath.sol\";\n\n/**\n * @title ERC20Migrator\n * @dev This contract can be used to migrate an ERC20 token from one\n * contract to another, where each token holder has to opt-in to the migration.\n * To opt-in, users must approve for this contract the number of tokens they\n * want to migrate. Once the allowance is set up, anyone can trigger the\n * migration to the new token contract. In this way, token holders \"turn in\"\n * their old balance and will be minted an equal amount in the new token.\n * The new token contract must be mintable.\n * ```\n */\n\ninterface IERC20Mintable is IERC20 {\n function mint(address to, uint256 amount) external;\n}\n\ncontract ERC20Migrator {\n using SafeERC20 for IERC20;\n using SafeMath for uint256;\n\n // Address of the old token contract\n IERC20 private _legacyToken;\n\n // Address of the new token contract\n IERC20Mintable private _newToken;\n\n /**\n * @param legacyToken address of the old token contract\n */\n constructor(IERC20 legacyToken, IERC20Mintable newToken) public {\n _legacyToken = legacyToken;\n _newToken = newToken;\n }\n\n /**\n * @dev Returns the legacy token that is being migrated.\n */\n function legacyToken() external view returns (IERC20) {\n return _legacyToken;\n }\n\n /**\n * @dev Returns the new token to which we are migrating.\n */\n function newToken() external view returns (IERC20) {\n return _newToken;\n }\n\n /**\n * @dev Transfers part of an account's balance in the old token to this\n * contract, and mints the same amount of new tokens for that account.\n * @param amount amount of tokens to be migrated\n */\n function migrate(uint256 amount) external {\n _legacyToken.safeTransferFrom(msg.sender, address(this), amount);\n uint256 amountToMint = amount.mul(5).div(2);\n _newToken.mint(msg.sender, amountToMint);\n }\n}\n" + }, + "contracts/bridge/ECDSANodeManagement.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.6.12;\n\nimport \"./utils/AddressArrayUtils.sol\";\nimport \"@openzeppelin/contracts/math/SafeMath.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/SafeERC20.sol\";\n\ncontract ECDSANodeManagement {\n using AddressArrayUtils for address[];\n using SafeMath for uint256;\n using SafeERC20 for IERC20;\n\n // Status of the keep.\n // Active means the keep is active.\n // Closed means the keep was closed happily.\n // Terminated means the keep was closed due to misbehavior.\n enum Status {\n Active,\n Closed,\n Terminated\n }\n\n // Address of the keep's owner.\n address public owner;\n\n // List of keep members' addresses.\n address[] public members;\n\n // Minimum number of honest keep members required to produce a signature.\n uint256 public honestThreshold;\n\n // Keep's ECDSA public key serialized to 64-bytes, where X and Y coordinates\n // are padded with zeros to 32-byte each.\n bytes public publicKey;\n\n // The timestamp at which keep has been created and key generation process\n // started.\n uint256 internal keyGenerationStartTimestamp;\n\n // Map stores public key by member addresses. All members should submit the\n // same public key.\n mapping(address => bytes) internal submittedPublicKeys;\n\n // The current status of the keep.\n // If the keep is Active members monitor it and support requests from the\n // keep owner.\n // If the owner decides to close the keep the flag is set to Closed.\n // If the owner seizes member bonds the flag is set to Terminated.\n Status internal status;\n\n // Flags execution of contract initialization.\n bool internal isInitialized;\n\n // Notification that the submitted public key does not match a key submitted\n // by other member. The event contains address of the member who tried to\n // submit a public key and a conflicting public key submitted already by other\n // member.\n event ConflictingPublicKeySubmitted(\n address indexed submittingMember,\n bytes conflictingPublicKey\n );\n\n // Notification that keep's ECDSA public key has been successfully established.\n event PublicKeyPublished(bytes publicKey);\n\n // Notification that the keep was closed by the owner.\n // Members no longer need to support this keep.\n event KeepClosed();\n\n // Notification that the keep has been terminated by the owner.\n // Members no longer need to support this keep.\n event KeepTerminated();\n\n /// @notice Returns keep's ECDSA public key.\n /// @return Keep's ECDSA public key.\n function getPublicKey() external view returns (bytes memory) {\n return publicKey;\n }\n\n /// @notice Submits a public key to the keep.\n /// @dev Public key is published successfully if all members submit the same\n /// value. In case of conflicts with others members submissions it will emit\n /// `ConflictingPublicKeySubmitted` event. When all submitted keys match\n /// it will store the key as keep's public key and emit a `PublicKeyPublished`\n /// event.\n /// @param _publicKey Signer's public key.\n function submitPublicKey(bytes calldata _publicKey) external onlyMember {\n require(\n !hasMemberSubmittedPublicKey(msg.sender),\n \"Member already submitted a public key\"\n );\n\n require(_publicKey.length == 64, \"Public key must be 64 bytes long\");\n\n submittedPublicKeys[msg.sender] = _publicKey;\n\n // Check if public keys submitted by all keep members are the same as\n // the currently submitted one.\n uint256 matchingPublicKeysCount = 0;\n for (uint256 i = 0; i < members.length; i++) {\n if (\n keccak256(submittedPublicKeys[members[i]]) !=\n keccak256(_publicKey)\n ) {\n // Emit an event only if compared member already submitted a value.\n if (hasMemberSubmittedPublicKey(members[i])) {\n emit ConflictingPublicKeySubmitted(\n msg.sender,\n submittedPublicKeys[members[i]]\n );\n }\n } else {\n matchingPublicKeysCount++;\n }\n }\n\n if (matchingPublicKeysCount != members.length) {\n return;\n }\n\n // All submitted signatures match.\n publicKey = _publicKey;\n emit PublicKeyPublished(_publicKey);\n }\n\n /// @notice Gets the owner of the keep.\n /// @return Address of the keep owner.\n function getOwner() external view returns (address) {\n return owner;\n }\n\n /// @notice Gets the timestamp the keep was opened at.\n /// @return Timestamp the keep was opened at.\n function getOpenedTimestamp() external view returns (uint256) {\n return keyGenerationStartTimestamp;\n }\n\n /// @notice Closes keep when owner decides that they no longer need it.\n /// Releases bonds to the keep members.\n /// @dev The function can be called only by the owner of the keep and only\n /// if the keep has not been already closed.\n function closeKeep() public onlyOwner onlyWhenActive {\n markAsClosed();\n }\n\n /// @notice Returns true if the keep is active.\n /// @return true if the keep is active, false otherwise.\n function isActive() public view returns (bool) {\n return status == Status.Active;\n }\n\n /// @notice Returns true if the keep is closed and members no longer support\n /// this keep.\n /// @return true if the keep is closed, false otherwise.\n function isClosed() public view returns (bool) {\n return status == Status.Closed;\n }\n\n /// @notice Returns true if the keep has been terminated.\n /// Keep is terminated when bonds are seized and members no longer support\n /// this keep.\n /// @return true if the keep has been terminated, false otherwise.\n function isTerminated() public view returns (bool) {\n return status == Status.Terminated;\n }\n\n /// @notice Returns members of the keep.\n /// @return List of the keep members' addresses.\n function getMembers() public view returns (address[] memory) {\n return members;\n }\n\n /// @notice Initialization function.\n /// @dev We use clone factory to create new keep. That is why this contract\n /// doesn't have a constructor. We provide keep parameters for each instance\n /// function after cloning instances from the master contract.\n /// Initialization must happen in the same transaction in which the clone is\n /// created.\n /// @param _owner Address of the keep owner.\n /// @param _members Addresses of the keep members.\n /// @param _honestThreshold Minimum number of honest keep members.\n function initialize(\n address _owner,\n address[] memory _members,\n uint256 _honestThreshold\n ) public {\n require(!isInitialized, \"Contract already initialized\");\n require(_owner != address(0));\n owner = _owner;\n members = _members;\n honestThreshold = _honestThreshold;\n\n status = Status.Active;\n isInitialized = true;\n\n /* solium-disable-next-line security/no-block-members*/\n keyGenerationStartTimestamp = block.timestamp;\n }\n\n /// @notice Checks if the member already submitted a public key.\n /// @param _member Address of the member.\n /// @return True if member already submitted a public key, else false.\n function hasMemberSubmittedPublicKey(address _member)\n internal\n view\n returns (bool)\n {\n return submittedPublicKeys[_member].length != 0;\n }\n\n /// @notice Marks the keep as closed.\n /// Keep can be marked as closed only when there is no signing in progress\n /// or the requested signing process has timed out.\n function markAsClosed() internal {\n status = Status.Closed;\n emit KeepClosed();\n }\n\n /// @notice Marks the keep as terminated.\n /// Keep can be marked as terminated only when there is no signing in progress\n /// or the requested signing process has timed out.\n function markAsTerminated() internal {\n status = Status.Terminated;\n emit KeepTerminated();\n }\n\n /// @notice Coverts a public key to an ethereum address.\n /// @param _publicKey Public key provided as 64-bytes concatenation of\n /// X and Y coordinates (32-bytes each).\n /// @return Ethereum address.\n function publicKeyToAddress(bytes memory _publicKey)\n internal\n pure\n returns (address)\n {\n // We hash the public key and then truncate last 20 bytes of the digest\n // which is the ethereum address.\n return address(uint160(uint256(keccak256(_publicKey))));\n }\n\n /// @notice Terminates the keep.\n function terminateKeep() internal {\n markAsTerminated();\n }\n\n /// @notice Checks if the caller is the keep's owner.\n /// @dev Throws an error if called by any account other than owner.\n modifier onlyOwner() {\n require(owner == msg.sender, \"Caller is not the keep owner\");\n _;\n }\n\n /// @notice Checks if the caller is a keep member.\n /// @dev Throws an error if called by any account other than one of the members.\n modifier onlyMember() {\n require(members.contains(msg.sender), \"Caller is not the keep member\");\n _;\n }\n\n /// @notice Checks if the keep is currently active.\n /// @dev Throws an error if called when the keep has been already closed.\n modifier onlyWhenActive() {\n require(isActive(), \"Keep is not active\");\n _;\n }\n}\n" + }, + "contracts/bridge/utils/AddressArrayUtils.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.6.12;\n\nlibrary AddressArrayUtils {\n function contains(address[] memory self, address _address)\n internal\n pure\n returns (bool)\n {\n for (uint256 i = 0; i < self.length; i++) {\n if (_address == self[i]) {\n return true;\n }\n }\n return false;\n }\n}" + }, + "contracts/bridge/BridgeConfigV3.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.6.12;\npragma experimental ABIEncoderV2;\n\nimport \"@openzeppelin/contracts/access/AccessControl.sol\";\nimport \"@openzeppelin/contracts/math/SafeMath.sol\";\n\n/**\n * @title BridgeConfig contract\n * @notice This token is used for configuring different tokens on the bridge and mapping them across chains.\n **/\n\ncontract BridgeConfigV3 is AccessControl {\n using SafeMath for uint256;\n bytes32 public constant BRIDGEMANAGER_ROLE =\n keccak256(\"BRIDGEMANAGER_ROLE\");\n bytes32[] private _allTokenIDs;\n mapping(bytes32 => Token[]) private _allTokens; // key is tokenID\n mapping(uint256 => mapping(string => bytes32)) private _tokenIDMap; // key is chainID,tokenAddress\n mapping(bytes32 => mapping(uint256 => Token)) private _tokens; // key is tokenID,chainID\n mapping(address => mapping(uint256 => Pool)) private _pool; // key is tokenAddress,chainID\n mapping(uint256 => uint256) private _maxGasPrice; // key is tokenID,chainID\n uint256 public constant bridgeConfigVersion = 3;\n\n // the denominator used to calculate fees. For example, an\n // LP fee might be something like tradeAmount.mul(fee).div(FEE_DENOMINATOR)\n uint256 private constant FEE_DENOMINATOR = 10**10;\n\n // this struct must be initialized using setTokenConfig for each token that directly interacts with the bridge\n struct Token {\n uint256 chainId;\n string tokenAddress;\n uint8 tokenDecimals;\n uint256 maxSwap;\n uint256 minSwap;\n uint256 swapFee;\n uint256 maxSwapFee;\n uint256 minSwapFee;\n bool hasUnderlying;\n bool isUnderlying;\n }\n\n struct Pool {\n address tokenAddress;\n uint256 chainId;\n address poolAddress;\n bool metaswap;\n }\n\n constructor() public {\n _setupRole(DEFAULT_ADMIN_ROLE, msg.sender);\n }\n\n /**\n * @notice Returns a list of all existing token IDs converted to strings\n */\n function getAllTokenIDs() public view returns (string[] memory result) {\n uint256 length = _allTokenIDs.length;\n result = new string[](length);\n for (uint256 i = 0; i < length; ++i) {\n result[i] = toString(_allTokenIDs[i]);\n }\n }\n\n function _getTokenID(string memory tokenAddress, uint256 chainID)\n internal\n view\n returns (string memory)\n {\n return toString(_tokenIDMap[chainID][tokenAddress]);\n }\n\n function getTokenID(string memory tokenAddress, uint256 chainID)\n public\n view\n returns (string memory)\n {\n return _getTokenID(_toLower(tokenAddress), chainID);\n }\n\n /**\n * @notice Returns the token ID (string) of the cross-chain token inputted\n * @param tokenAddress address of token to get ID for\n * @param chainID chainID of which to get token ID for\n */\n function getTokenID(address tokenAddress, uint256 chainID)\n public\n view\n returns (string memory)\n {\n return _getTokenID(_toLower(toString(tokenAddress)), chainID);\n }\n\n /**\n * @notice Returns the full token config struct\n * @param tokenID String input of the token ID for the token\n * @param chainID Chain ID of which token address + config to get\n */\n function getToken(string memory tokenID, uint256 chainID)\n public\n view\n returns (Token memory token)\n {\n return _tokens[toBytes32(tokenID)][chainID];\n }\n\n /**\n * @notice Returns the full token config struct\n * @param tokenID String input of the token ID for the token\n * @param chainID Chain ID of which token address + config to get\n */\n function getTokenByID(string memory tokenID, uint256 chainID)\n public\n view\n returns (Token memory token)\n {\n return _tokens[toBytes32(tokenID)][chainID];\n }\n\n /**\n * @notice Returns token config struct, given an address and chainID\n * @param tokenAddress Matches the token ID by using a combo of address + chain ID\n * @param chainID Chain ID of which token to get config for\n */\n function getTokenByAddress(string memory tokenAddress, uint256 chainID)\n public\n view\n returns (Token memory token)\n {\n return _tokens[_tokenIDMap[chainID][_toLower(tokenAddress)]][chainID];\n }\n\n function getTokenByEVMAddress(address tokenAddress, uint256 chainID)\n public\n view\n returns (Token memory token)\n {\n return\n _tokens[_tokenIDMap[chainID][_toLower(toString(tokenAddress))]][\n chainID\n ];\n }\n\n /**\n * @notice Returns true if the token has an underlying token -- meaning the token is deposited into the bridge\n * @param tokenID String to check if it is a withdraw/underlying token\n */\n function hasUnderlyingToken(string memory tokenID)\n public\n view\n returns (bool)\n {\n bytes32 bytesTokenID = toBytes32(tokenID);\n Token[] memory _mcTokens = _allTokens[bytesTokenID];\n for (uint256 i = 0; i < _mcTokens.length; ++i) {\n if (_mcTokens[i].hasUnderlying) {\n return true;\n }\n }\n return false;\n }\n\n /**\n * @notice Returns which token is the underlying token to withdraw\n * @param tokenID string token ID\n */\n function getUnderlyingToken(string memory tokenID)\n public\n view\n returns (Token memory token)\n {\n bytes32 bytesTokenID = toBytes32(tokenID);\n Token[] memory _mcTokens = _allTokens[bytesTokenID];\n for (uint256 i = 0; i < _mcTokens.length; ++i) {\n if (_mcTokens[i].isUnderlying) {\n return _mcTokens[i];\n }\n }\n }\n\n /**\n @notice Public function returning if token ID exists given a string\n */\n function isTokenIDExist(string memory tokenID) public view returns (bool) {\n return _isTokenIDExist(toBytes32(tokenID));\n }\n\n /**\n @notice Internal function returning if token ID exists given bytes32 version of the ID\n */\n function _isTokenIDExist(bytes32 tokenID) internal view returns (bool) {\n for (uint256 i = 0; i < _allTokenIDs.length; ++i) {\n if (_allTokenIDs[i] == tokenID) {\n return true;\n }\n }\n return false;\n }\n\n /**\n * @notice Internal function which handles logic of setting token ID and dealing with mappings\n * @param tokenID bytes32 version of ID\n * @param chainID which chain to set the token config for\n * @param tokenToAdd Token object to set the mapping to\n */\n function _setTokenConfig(\n bytes32 tokenID,\n uint256 chainID,\n Token memory tokenToAdd\n ) internal returns (bool) {\n _tokens[tokenID][chainID] = tokenToAdd;\n if (!_isTokenIDExist(tokenID)) {\n _allTokenIDs.push(tokenID);\n }\n\n Token[] storage _mcTokens = _allTokens[tokenID];\n for (uint256 i = 0; i < _mcTokens.length; ++i) {\n if (_mcTokens[i].chainId == chainID) {\n string memory oldToken = _mcTokens[i].tokenAddress;\n if (!compareStrings(tokenToAdd.tokenAddress, oldToken)) {\n _mcTokens[i].tokenAddress = tokenToAdd.tokenAddress;\n _tokenIDMap[chainID][oldToken] = keccak256(\"\");\n _tokenIDMap[chainID][tokenToAdd.tokenAddress] = tokenID;\n }\n }\n }\n _mcTokens.push(tokenToAdd);\n _tokenIDMap[chainID][tokenToAdd.tokenAddress] = tokenID;\n return true;\n }\n\n /**\n * @notice Main write function of this contract - Handles creating the struct and passing it to the internal logic function\n * @param tokenID string ID to set the token config object form\n * @param chainID chain ID to use for the token config object\n * @param tokenAddress token address of the token on the given chain\n * @param tokenDecimals decimals of token\n * @param maxSwap maximum amount of token allowed to be transferred at once - in native token decimals\n * @param minSwap minimum amount of token needed to be transferred at once - in native token decimals\n * @param swapFee percent based swap fee -- 10e6 == 10bps\n * @param maxSwapFee max swap fee to be charged - in native token decimals\n * @param minSwapFee min swap fee to be charged - in native token decimals - especially useful for mainnet ETH\n * @param hasUnderlying bool which represents whether this is a global mint token or one to withdraw()\n * @param isUnderlying bool which represents if this token is the one to withdraw on the given chain\n */\n function setTokenConfig(\n string calldata tokenID,\n uint256 chainID,\n address tokenAddress,\n uint8 tokenDecimals,\n uint256 maxSwap,\n uint256 minSwap,\n uint256 swapFee,\n uint256 maxSwapFee,\n uint256 minSwapFee,\n bool hasUnderlying,\n bool isUnderlying\n ) public returns (bool) {\n require(hasRole(BRIDGEMANAGER_ROLE, msg.sender));\n return\n setTokenConfig(\n tokenID,\n chainID,\n toString(tokenAddress),\n tokenDecimals,\n maxSwap,\n minSwap,\n swapFee,\n maxSwapFee,\n minSwapFee,\n hasUnderlying,\n isUnderlying\n );\n }\n\n /**\n * @notice Main write function of this contract - Handles creating the struct and passing it to the internal logic function\n * @param tokenID string ID to set the token config object form\n * @param chainID chain ID to use for the token config object\n * @param tokenAddress token address of the token on the given chain\n * @param tokenDecimals decimals of token\n * @param maxSwap maximum amount of token allowed to be transferred at once - in native token decimals\n * @param minSwap minimum amount of token needed to be transferred at once - in native token decimals\n * @param swapFee percent based swap fee -- 10e6 == 10bps\n * @param maxSwapFee max swap fee to be charged - in native token decimals\n * @param minSwapFee min swap fee to be charged - in native token decimals - especially useful for mainnet ETH\n * @param hasUnderlying bool which represents whether this is a global mint token or one to withdraw()\n * @param isUnderlying bool which represents if this token is the one to withdraw on the given chain\n */\n function setTokenConfig(\n string calldata tokenID,\n uint256 chainID,\n string memory tokenAddress,\n uint8 tokenDecimals,\n uint256 maxSwap,\n uint256 minSwap,\n uint256 swapFee,\n uint256 maxSwapFee,\n uint256 minSwapFee,\n bool hasUnderlying,\n bool isUnderlying\n ) public returns (bool) {\n require(hasRole(BRIDGEMANAGER_ROLE, msg.sender));\n Token memory tokenToAdd;\n tokenToAdd.tokenAddress = _toLower(tokenAddress);\n tokenToAdd.tokenDecimals = tokenDecimals;\n tokenToAdd.maxSwap = maxSwap;\n tokenToAdd.minSwap = minSwap;\n tokenToAdd.swapFee = swapFee;\n tokenToAdd.maxSwapFee = maxSwapFee;\n tokenToAdd.minSwapFee = minSwapFee;\n tokenToAdd.hasUnderlying = hasUnderlying;\n tokenToAdd.isUnderlying = isUnderlying;\n tokenToAdd.chainId = chainID;\n\n return _setTokenConfig(toBytes32(tokenID), chainID, tokenToAdd);\n }\n\n function _calculateSwapFee(\n string memory tokenAddress,\n uint256 chainID,\n uint256 amount\n ) internal view returns (uint256) {\n Token memory token = _tokens[_tokenIDMap[chainID][tokenAddress]][\n chainID\n ];\n uint256 calculatedSwapFee = amount.mul(token.swapFee).div(\n FEE_DENOMINATOR\n );\n if (\n calculatedSwapFee > token.minSwapFee &&\n calculatedSwapFee < token.maxSwapFee\n ) {\n return calculatedSwapFee;\n } else if (calculatedSwapFee > token.maxSwapFee) {\n return token.maxSwapFee;\n } else {\n return token.minSwapFee;\n }\n }\n\n /**\n * @notice Calculates bridge swap fee based on the destination chain's token transfer.\n * @dev This means the fee should be calculated based on the chain that the nodes emit a tx on\n * @param tokenAddress address of the destination token to query token config for\n * @param chainID destination chain ID to query the token config for\n * @param amount in native token decimals\n * @return Fee calculated in token decimals\n */\n function calculateSwapFee(\n string memory tokenAddress,\n uint256 chainID,\n uint256 amount\n ) external view returns (uint256) {\n return _calculateSwapFee(_toLower(tokenAddress), chainID, amount);\n }\n\n /**\n * @notice Calculates bridge swap fee based on the destination chain's token transfer.\n * @dev This means the fee should be calculated based on the chain that the nodes emit a tx on\n * @param tokenAddress address of the destination token to query token config for\n * @param chainID destination chain ID to query the token config for\n * @param amount in native token decimals\n * @return Fee calculated in token decimals\n */\n function calculateSwapFee(\n address tokenAddress,\n uint256 chainID,\n uint256 amount\n ) external view returns (uint256) {\n return\n _calculateSwapFee(\n _toLower(toString(tokenAddress)),\n chainID,\n amount\n );\n }\n\n // GAS PRICING\n\n /**\n * @notice sets the max gas price for a chain\n */\n function setMaxGasPrice(uint256 chainID, uint256 maxPrice) public {\n require(hasRole(BRIDGEMANAGER_ROLE, msg.sender));\n _maxGasPrice[chainID] = maxPrice;\n }\n\n /**\n * @notice gets the max gas price for a chain\n */\n function getMaxGasPrice(uint256 chainID) public view returns (uint256) {\n return _maxGasPrice[chainID];\n }\n\n // POOL CONFIG\n\n function getPoolConfig(address tokenAddress, uint256 chainID)\n external\n view\n returns (Pool memory)\n {\n return _pool[tokenAddress][chainID];\n }\n\n function setPoolConfig(\n address tokenAddress,\n uint256 chainID,\n address poolAddress,\n bool metaswap\n ) external returns (Pool memory) {\n require(\n hasRole(BRIDGEMANAGER_ROLE, msg.sender),\n \"Caller is not Bridge Manager\"\n );\n Pool memory newPool = Pool(\n tokenAddress,\n chainID,\n poolAddress,\n metaswap\n );\n _pool[tokenAddress][chainID] = newPool;\n return newPool;\n }\n\n // UTILITY FUNCTIONS\n\n function toString(bytes32 data) internal pure returns (string memory) {\n uint8 i = 0;\n while (i < 32 && data[i] != 0) {\n ++i;\n }\n bytes memory bs = new bytes(i);\n for (uint8 j = 0; j < i; ++j) {\n bs[j] = data[j];\n }\n return string(bs);\n }\n\n // toBytes32 converts a string to a bytes 32\n function toBytes32(string memory str)\n internal\n pure\n returns (bytes32 result)\n {\n require(bytes(str).length <= 32);\n assembly {\n result := mload(add(str, 32))\n }\n }\n\n function toString(address x) internal pure returns (string memory) {\n bytes memory s = new bytes(40);\n for (uint256 i = 0; i < 20; i++) {\n bytes1 b = bytes1(uint8(uint256(uint160(x)) / (2**(8 * (19 - i)))));\n bytes1 hi = bytes1(uint8(b) / 16);\n bytes1 lo = bytes1(uint8(b) - 16 * uint8(hi));\n s[2 * i] = char(hi);\n s[2 * i + 1] = char(lo);\n }\n\n string memory addrPrefix = \"0x\";\n\n return concat(addrPrefix, string(s));\n }\n\n function concat(string memory _x, string memory _y)\n internal\n pure\n returns (string memory)\n {\n bytes memory _xBytes = bytes(_x);\n bytes memory _yBytes = bytes(_y);\n\n string memory _tmpValue = new string(_xBytes.length + _yBytes.length);\n bytes memory _newValue = bytes(_tmpValue);\n\n uint256 i;\n uint256 j;\n\n for (i = 0; i < _xBytes.length; i++) {\n _newValue[j++] = _xBytes[i];\n }\n\n for (i = 0; i < _yBytes.length; i++) {\n _newValue[j++] = _yBytes[i];\n }\n\n return string(_newValue);\n }\n\n function char(bytes1 b) internal pure returns (bytes1 c) {\n if (uint8(b) < 10) {\n c = bytes1(uint8(b) + 0x30);\n } else {\n c = bytes1(uint8(b) + 0x57);\n }\n }\n\n function compareStrings(string memory a, string memory b)\n internal\n pure\n returns (bool)\n {\n return (keccak256(abi.encodePacked((a))) ==\n keccak256(abi.encodePacked((b))));\n }\n\n function _toLower(string memory str) internal pure returns (string memory) {\n bytes memory bStr = bytes(str);\n bytes memory bLower = new bytes(bStr.length);\n for (uint256 i = 0; i < bStr.length; i++) {\n // Uppercase character...\n if ((uint8(bStr[i]) >= 65) && (uint8(bStr[i]) <= 90)) {\n // So we add 32 to make it lowercase\n bLower[i] = bytes1(uint8(bStr[i]) + 32);\n } else {\n bLower[i] = bStr[i];\n }\n }\n return string(bLower);\n }\n}\n" + }, + "contracts/bridge/mocks/ERC20Mock.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.6.12;\n\nimport \"@openzeppelin/contracts/token/ERC20/ERC20.sol\";\n\ncontract ERC20Mock is ERC20 {\n constructor(\n string memory name,\n string memory symbol,\n uint256 supply\n ) public ERC20(name, symbol) {\n _mint(msg.sender, supply);\n }\n\n function mint(address to, uint256 amount) external {\n _mint(to, amount);\n }\n}" + }, + "contracts/bridge/interfaces/IMetaSwapDeposit.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.6.12;\nimport '@openzeppelin/contracts/token/ERC20/ERC20.sol';\n\n/**\n * @title IMetaSwapDeposit interface\n * @notice Interface for the meta swap contract.\n * @dev implement this interface to develop a a factory-patterned ECDSA node management contract\n **/\ninterface IMetaSwapDeposit {\n // min return calculation functions\n function calculateSwap(\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx\n ) external view returns (uint256);\n\n function swap(\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx,\n uint256 minDy,\n uint256 deadline\n ) external returns (uint256);\n\n function getToken(uint256 index) external view returns (IERC20);\n}\n" + }, + "contracts/amm/interfaces/IMetaSwapDeposit.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.6.12;\n\nimport \"@openzeppelin/contracts/token/ERC20/ERC20.sol\";\nimport \"./ISwap.sol\";\nimport \"./IMetaSwap.sol\";\n\ninterface IMetaSwapDeposit {\n function initialize(\n ISwap baseSwap_,\n IMetaSwap metaSwap_,\n IERC20 metaLPToken_\n ) external;\n}\n" + }, + "contracts/amm/interfaces/IMetaSwap.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.6.12;\n\nimport \"@openzeppelin/contracts/token/ERC20/ERC20.sol\";\n\ninterface IMetaSwap {\n // pool data view functions\n function getA() external view returns (uint256);\n\n function getToken(uint8 index) external view returns (IERC20);\n\n function getTokenIndex(address tokenAddress) external view returns (uint8);\n\n function getTokenBalance(uint8 index) external view returns (uint256);\n\n function getVirtualPrice() external view returns (uint256);\n\n function isGuarded() external view returns (bool);\n\n // min return calculation functions\n function calculateSwap(\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx\n ) external view returns (uint256);\n\n function calculateSwapUnderlying(\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx\n ) external view returns (uint256);\n\n function calculateTokenAmount(uint256[] calldata amounts, bool deposit)\n external\n view\n returns (uint256);\n\n function calculateRemoveLiquidity(uint256 amount)\n external\n view\n returns (uint256[] memory);\n\n function calculateRemoveLiquidityOneToken(\n uint256 tokenAmount,\n uint8 tokenIndex\n ) external view returns (uint256 availableTokenAmount);\n\n // state modifying functions\n function initializeMetaSwap(\n IERC20[] memory pooledTokens,\n uint8[] memory decimals,\n string memory lpTokenName,\n string memory lpTokenSymbol,\n uint256 a,\n uint256 fee,\n uint256 adminFee,\n address lpTokenTargetAddress,\n address baseSwap\n ) external;\n\n function swap(\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx,\n uint256 minDy,\n uint256 deadline\n ) external returns (uint256);\n\n function swapUnderlying(\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx,\n uint256 minDy,\n uint256 deadline\n ) external returns (uint256);\n\n function addLiquidity(\n uint256[] calldata amounts,\n uint256 minToMint,\n uint256 deadline\n ) external returns (uint256);\n\n function removeLiquidity(\n uint256 amount,\n uint256[] calldata minAmounts,\n uint256 deadline\n ) external returns (uint256[] memory);\n\n function removeLiquidityOneToken(\n uint256 tokenAmount,\n uint8 tokenIndex,\n uint256 minAmount,\n uint256 deadline\n ) external returns (uint256);\n\n function removeLiquidityImbalance(\n uint256[] calldata amounts,\n uint256 maxBurnAmount,\n uint256 deadline\n ) external returns (uint256);\n\n function swapStorage()\n external\n view\n returns (\n uint256 initialA,\n uint256 futureA,\n uint256 initialATime,\n uint256 futureATime,\n uint256 swapFee,\n uint256 adminFee,\n address lpToken\n );\n}\n" + }, + "contracts/amm/helper/GenericERC20.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.6.12;\n\nimport \"@openzeppelin/contracts/token/ERC20/ERC20.sol\";\nimport \"@openzeppelin/contracts/access/Ownable.sol\";\n\n/**\n * @title Generic ERC20 token\n * @notice This contract simulates a generic ERC20 token that is mintable and burnable.\n */\ncontract GenericERC20 is ERC20, Ownable {\n /**\n * @notice Deploy this contract with given name, symbol, and decimals\n * @dev the caller of this constructor will become the owner of this contract\n * @param name_ name of this token\n * @param symbol_ symbol of this token\n * @param decimals_ number of decimals this token will be based on\n */\n constructor(\n string memory name_,\n string memory symbol_,\n uint8 decimals_\n ) public ERC20(name_, symbol_) {\n _setupDecimals(decimals_);\n }\n\n /**\n * @notice Mints given amount of tokens to recipient\n * @dev only owner can call this mint function\n * @param recipient address of account to receive the tokens\n * @param amount amount of tokens to mint\n */\n function mint(address recipient, uint256 amount) external onlyOwner {\n require(amount != 0, \"amount == 0\");\n _mint(recipient, amount);\n }\n}\n" + }, + "contracts/amm/SwapEthWrapper.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.6.12;\n\nimport \"@openzeppelin/contracts/math/SafeMath.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/SafeERC20.sol\";\nimport \"./Swap.sol\";\nimport \"./interfaces/IWETH9.sol\";\n\n/**\n * @title SwapEthWrapper\n * @notice A wrapper contract for Swap contracts that have WETH as one of the pooled tokens.\n * @author Jongseung Lim (@weeb_mcgee)\n */\ncontract SwapEthWrapper {\n using SafeERC20 for IERC20;\n using SafeMath for uint256;\n\n // constants\n uint8 private constant MAX_UINT8 = 2**8 - 1;\n uint256 private constant MAX_UINT256 = 2**256 - 1;\n\n // immutables\n Swap public immutable SWAP;\n LPToken public immutable LP_TOKEN;\n address payable public immutable WETH_ADDRESS;\n address public immutable OWNER;\n uint8 public immutable WETH_INDEX;\n\n IERC20[] public pooledTokens;\n\n /**\n * @notice Deploys this contract with given WETH9 address and Swap address. It will attempt to\n * fetch information about the given Swap pool. If the Swap pool does not contain WETH9,\n * this call will be reverted. Owner address must be given so that `rescue()` function\n * can be limited.\n * @param wethAddress address to the WETH9 contract\n * @param swap address to the Swap contract that has WETH9 as one of the tokens\n * @param owner address that will be allowed to call `rescue()`\n */\n constructor(\n address payable wethAddress,\n Swap swap,\n address owner\n ) public {\n (, , , , , , LPToken lpToken) = swap.swapStorage();\n uint8 wethIndex = MAX_UINT8;\n\n for (uint8 i = 0; i < MAX_UINT8; i++) {\n try swap.getToken(i) returns (IERC20 token) {\n pooledTokens.push(token);\n if (address(token) == wethAddress) {\n wethIndex = i;\n }\n // Approve pooled tokens to be used by Swap\n token.approve(address(swap), MAX_UINT256);\n } catch {\n break;\n }\n }\n require(wethIndex != MAX_UINT8, \"WETH was not found in the swap pool\");\n\n // Set immutable variables\n WETH_INDEX = wethIndex;\n WETH_ADDRESS = wethAddress;\n SWAP = swap;\n LP_TOKEN = lpToken;\n OWNER = owner;\n\n // Approve LPToken to be used by Swap\n lpToken.approve(address(swap), MAX_UINT256);\n }\n\n /**\n * @notice Add liquidity to the pool with the given amounts of tokens.\n * @dev The msg.value of this call should match the value in amounts array\n * in position of WETH9.\n * @param amounts the amounts of each token to add, in their native precision\n * @param minToMint the minimum LP tokens adding this amount of liquidity\n * should mint, otherwise revert. Handy for front-running mitigation\n * @param deadline latest timestamp to accept this transaction\n * @return amount of LP token user minted and received\n */\n function addLiquidity(\n uint256[] memory amounts,\n uint256 minToMint,\n uint256 deadline\n ) external payable returns (uint256) {\n // If using ETH, deposit them to WETH.\n require(msg.value == amounts[WETH_INDEX], \"INCORRECT_MSG_VALUE\");\n if (msg.value > 0) {\n IWETH9(WETH_ADDRESS).deposit{value: msg.value}();\n }\n // Go through amounts array and transfer respective tokens to this contract.\n for (uint256 i = 0; i < amounts.length; i++) {\n uint256 amount = amounts[i];\n if (i != WETH_INDEX && amount > 0) {\n pooledTokens[i].safeTransferFrom(\n msg.sender,\n address(this),\n amount\n );\n }\n }\n // Add the assets to the pool\n uint256 lpTokenAmount = SWAP.addLiquidity(amounts, minToMint, deadline);\n // Send the LPToken to msg.sender\n IERC20(address(LP_TOKEN)).safeTransfer(msg.sender, lpTokenAmount);\n return lpTokenAmount;\n }\n\n /**\n * @notice Burn LP tokens to remove liquidity from the pool.\n * @dev Liquidity can always be removed, even when the pool is paused. Caller\n * will receive ETH instead of WETH9.\n * @param amount the amount of LP tokens to burn\n * @param minAmounts the minimum amounts of each token in the pool\n * acceptable for this burn. Useful as a front-running mitigation\n * @param deadline latest timestamp to accept this transaction\n * @return amounts of tokens user received\n */\n function removeLiquidity(\n uint256 amount,\n uint256[] calldata minAmounts,\n uint256 deadline\n ) external returns (uint256[] memory) {\n // Transfer LPToken from msg.sender to this contract.\n IERC20(address(LP_TOKEN)).safeTransferFrom(\n msg.sender,\n address(this),\n amount\n );\n // Remove liquidity\n uint256[] memory amounts = SWAP.removeLiquidity(\n amount,\n minAmounts,\n deadline\n );\n // Send the tokens back to the user\n for (uint256 i = 0; i < amounts.length; i++) {\n if (i != WETH_INDEX) {\n pooledTokens[i].safeTransfer(msg.sender, amounts[i]);\n } else {\n IWETH9(WETH_ADDRESS).withdraw(amounts[i]);\n // slither-disable-next-line arbitrary-send\n (bool success, ) = msg.sender.call{value: amounts[i]}(\"\");\n require(success, \"ETH_TRANSFER_FAILED\");\n }\n }\n return amounts;\n }\n\n /**\n * @notice Remove liquidity from the pool all in one token.\n * @dev Caller will receive ETH instead of WETH9.\n * @param tokenAmount the amount of the token you want to receive\n * @param tokenIndex the index of the token you want to receive\n * @param minAmount the minimum amount to withdraw, otherwise revert\n * @param deadline latest timestamp to accept this transaction\n * @return amount of chosen token user received\n */\n function removeLiquidityOneToken(\n uint256 tokenAmount,\n uint8 tokenIndex,\n uint256 minAmount,\n uint256 deadline\n ) external returns (uint256) {\n // Transfer LPToken from msg.sender to this contract.\n IERC20(address(LP_TOKEN)).safeTransferFrom(\n msg.sender,\n address(this),\n tokenAmount\n );\n // Withdraw via single token\n uint256 amount = SWAP.removeLiquidityOneToken(\n tokenAmount,\n tokenIndex,\n minAmount,\n deadline\n );\n // Transfer the token to msg.sender accordingly\n if (tokenIndex != WETH_INDEX) {\n pooledTokens[tokenIndex].safeTransfer(msg.sender, amount);\n } else {\n IWETH9(WETH_ADDRESS).withdraw(amount);\n // slither-disable-next-line arbitrary-send\n (bool success, ) = msg.sender.call{value: amount}(\"\");\n require(success, \"ETH_TRANSFER_FAILED\");\n }\n return amount;\n }\n\n /**\n * @notice Remove liquidity from the pool, weighted differently than the\n * pool's current balances.\n * @dev Caller will receive ETH instead of WETH9.\n * @param amounts how much of each token to withdraw\n * @param maxBurnAmount the max LP token provider is willing to pay to\n * remove liquidity. Useful as a front-running mitigation.\n * @param deadline latest timestamp to accept this transaction\n * @return amount of LP tokens burned\n */\n function removeLiquidityImbalance(\n uint256[] calldata amounts,\n uint256 maxBurnAmount,\n uint256 deadline\n ) external returns (uint256) {\n // Transfer LPToken from msg.sender to this contract.\n IERC20(address(LP_TOKEN)).safeTransferFrom(\n msg.sender,\n address(this),\n maxBurnAmount\n );\n // Withdraw in imbalanced ratio\n uint256 burnedLpTokenAmount = SWAP.removeLiquidityImbalance(\n amounts,\n maxBurnAmount,\n deadline\n );\n // Send the tokens back to the user\n for (uint256 i = 0; i < amounts.length; i++) {\n if (i != WETH_INDEX) {\n pooledTokens[i].safeTransfer(msg.sender, amounts[i]);\n } else {\n IWETH9(WETH_ADDRESS).withdraw(amounts[i]);\n // slither-disable-next-line arbitrary-send\n (bool success, ) = msg.sender.call{value: amounts[i]}(\"\");\n require(success, \"ETH_TRANSFER_FAILED\");\n }\n }\n // Send any extra LP tokens back as well\n uint256 extraLpTokenAmount = maxBurnAmount.sub(burnedLpTokenAmount);\n if (extraLpTokenAmount > 0) {\n IERC20(address(LP_TOKEN)).safeTransfer(\n msg.sender,\n extraLpTokenAmount\n );\n }\n return burnedLpTokenAmount;\n }\n\n /**\n * @notice Swap two tokens using the underlying pool. If tokenIndexFrom\n * represents WETH9 in the pool, the caller must set msg.value equal to dx.\n * If the user is swapping to WETH9 in the pool, the user will receive ETH instead.\n * @param tokenIndexFrom the token the user wants to swap from\n * @param tokenIndexTo the token the user wants to swap to\n * @param dx the amount of tokens the user wants to swap from\n * @param minDy the min amount the user would like to receive, or revert.\n * @param deadline latest timestamp to accept this transaction\n */\n function swap(\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx,\n uint256 minDy,\n uint256 deadline\n ) external payable returns (uint256) {\n // Transfer tokens from msg.sender to this contract\n if (tokenIndexFrom != WETH_INDEX) {\n IERC20(pooledTokens[tokenIndexFrom]).safeTransferFrom(\n msg.sender,\n address(this),\n dx\n );\n } else {\n require(msg.value == dx, \"INCORRECT_MSG_VALUE\");\n IWETH9(WETH_ADDRESS).deposit{value: msg.value}();\n }\n // Execute swap\n uint256 dy = SWAP.swap(\n tokenIndexFrom,\n tokenIndexTo,\n dx,\n minDy,\n deadline\n );\n // Transfer the swapped tokens to msg.sender\n if (tokenIndexTo != WETH_INDEX) {\n IERC20(pooledTokens[tokenIndexTo]).safeTransfer(msg.sender, dy);\n } else {\n IWETH9(WETH_ADDRESS).withdraw(dy);\n // slither-disable-next-line arbitrary-send\n (bool success, ) = msg.sender.call{value: dy}(\"\");\n require(success, \"ETH_TRANSFER_FAILED\");\n }\n return dy;\n }\n\n /**\n * @notice Rescues any of the ETH, the pooled tokens, or the LPToken that may be stuck\n * in this contract. Only the OWNER can call this function.\n */\n function rescue() external {\n require(msg.sender == OWNER, \"CALLED_BY_NON_OWNER\");\n IERC20[] memory tokens = pooledTokens;\n for (uint256 i = 0; i < tokens.length; i++) {\n tokens[i].safeTransfer(\n msg.sender,\n tokens[i].balanceOf(address(this))\n );\n }\n IERC20 lpToken_ = IERC20(address(LP_TOKEN));\n lpToken_.safeTransfer(msg.sender, lpToken_.balanceOf(address(this)));\n // slither-disable-next-line arbitrary-send\n (bool success, ) = msg.sender.call{value: address(this).balance}(\"\");\n require(success, \"ETH_TRANSFER_FAILED\");\n }\n\n receive() external payable {}\n\n // VIEW FUNCTIONS\n\n /**\n * @notice A simple method to calculate prices from deposits or\n * withdrawals, excluding fees but including slippage. This is\n * helpful as an input into the various \"min\" parameters on calls\n * to fight front-running\n *\n * @dev This shouldn't be used outside frontends for user estimates.\n *\n * @param amounts an array of token amounts to deposit or withdrawal,\n * corresponding to pooledTokens. The amount should be in each\n * pooled token's native precision. If a token charges a fee on transfers,\n * use the amount that gets transferred after the fee.\n * @param deposit whether this is a deposit or a withdrawal\n * @return token amount the user will receive\n */\n function calculateTokenAmount(uint256[] calldata amounts, bool deposit)\n external\n view\n returns (uint256)\n {\n return SWAP.calculateTokenAmount(amounts, deposit);\n }\n\n /**\n * @notice A simple method to calculate amount of each underlying\n * tokens that is returned upon burning given amount of LP tokens\n * @param amount the amount of LP tokens that would be burned on withdrawal\n * @return array of token balances that the user will receive\n */\n function calculateRemoveLiquidity(uint256 amount)\n external\n view\n returns (uint256[] memory)\n {\n return SWAP.calculateRemoveLiquidity(amount);\n }\n\n /**\n * @notice Calculate the amount of underlying token available to withdraw\n * when withdrawing via only single token\n * @param tokenAmount the amount of LP token to burn\n * @param tokenIndex index of which token will be withdrawn\n * @return availableTokenAmount calculated amount of underlying token\n * available to withdraw\n */\n function calculateRemoveLiquidityOneToken(\n uint256 tokenAmount,\n uint8 tokenIndex\n ) external view returns (uint256 availableTokenAmount) {\n return SWAP.calculateRemoveLiquidityOneToken(tokenAmount, tokenIndex);\n }\n}\n" + }, + "contracts/amm/interfaces/IWETH9.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.4.0;\n\ninterface IWETH9 {\n function name() external view returns (string memory);\n\n function symbol() external view returns (string memory);\n\n function decimals() external view returns (uint8);\n\n function balanceOf(address) external view returns (uint256);\n\n function allowance(address, address) external view returns (uint256);\n\n receive() external payable;\n\n function deposit() external payable;\n\n function withdraw(uint256 wad) external;\n\n function totalSupply() external view returns (uint256);\n\n function approve(address guy, uint256 wad) external returns (bool);\n\n function transfer(address dst, uint256 wad) external returns (bool);\n\n function transferFrom(\n address src,\n address dst,\n uint256 wad\n ) external returns (bool);\n}\n" + }, + "contracts/amm/helper/BaseSwapDeposit.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.6.12;\n\nimport \"@openzeppelin/contracts/math/SafeMath.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/SafeERC20.sol\";\nimport \"../interfaces/ISwap.sol\";\nimport \"@openzeppelin/contracts/utils/ReentrancyGuard.sol\";\n\ncontract BaseSwapDeposit is ReentrancyGuard {\n using SafeERC20 for IERC20;\n using SafeMath for uint256;\n\n ISwap public baseSwap;\n IERC20[] public baseTokens;\n\n uint256 constant MAX_UINT256 = 2**256 - 1;\n\n constructor(ISwap _baseSwap) public {\n baseSwap = _baseSwap;\n // Check and approve base level tokens to be deposited to the base Swap contract\n {\n uint8 i;\n for (; i < 32; i++) {\n try _baseSwap.getToken(i) returns (IERC20 token) {\n baseTokens.push(token);\n token.safeApprove(address(_baseSwap), MAX_UINT256);\n } catch {\n break;\n }\n }\n require(i > 1, \"baseSwap must have at least 2 tokens\");\n }\n }\n\n // Mutative functions\n\n /**\n * @notice Swap two underlying tokens using the meta pool and the base pool\n * @param tokenIndexFrom the token the user wants to swap from\n * @param tokenIndexTo the token the user wants to swap to\n * @param dx the amount of tokens the user wants to swap from\n * @param minDy the min amount the user would like to receive, or revert.\n * @param deadline latest timestamp to accept this transaction\n */\n function swap(\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx,\n uint256 minDy,\n uint256 deadline\n ) external nonReentrant returns (uint256) {\n baseTokens[tokenIndexFrom].safeTransferFrom(msg.sender, address(this), dx);\n uint256 tokenToAmount =\n baseSwap.swap(\n tokenIndexFrom,\n tokenIndexTo,\n dx,\n minDy,\n deadline\n );\n baseTokens[tokenIndexTo].safeTransfer(msg.sender, tokenToAmount);\n return tokenToAmount;\n }\n\n /**\n * @notice Calculate amount of tokens you receive on swap\n * @param tokenIndexFrom the token the user wants to sell\n * @param tokenIndexTo the token the user wants to buy\n * @param dx the amount of tokens the user wants to sell. If the token charges\n * a fee on transfers, use the amount that gets transferred after the fee.\n * @return amount of tokens the user will receive\n */\n function calculateSwap(\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx\n ) external view returns (uint256) {\n return\n baseSwap.calculateSwap(tokenIndexFrom, tokenIndexTo, dx);\n }\n\n /**\n * @notice Returns the address of the pooled token at given index. Reverts if tokenIndex is out of range.\n * @param index the index of the token\n * @return address of the token at given index\n */\n function getToken(uint256 index) external view returns (IERC20) {\n require(index < baseTokens.length, \"index out of range\");\n return baseTokens[index];\n }\n\n}" + }, + "@openzeppelin/contracts/utils/ReentrancyGuard.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <0.8.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 () internal {\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" + }, + "contracts/amm/AaveSwapWrapper.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.6.12;\n\nimport \"@openzeppelin/contracts/math/SafeMath.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/SafeERC20.sol\";\nimport \"./Swap.sol\";\n\ninterface ILendingPool {\n /**\n * @dev Deposits an `amount` of underlying asset into the reserve, receiving in return overlying aTokens.\n * - E.g. User deposits 100 USDC and gets in return 100 aUSDC\n * @param asset The address of the underlying asset to deposit\n * @param amount The amount to be deposited\n * @param onBehalfOf The address that will receive the aTokens, same as msg.sender if the user\n * wants to receive them on his own wallet, or a different address if the beneficiary of aTokens\n * is a different wallet\n * @param referralCode Code used to register the integrator originating the operation, for potential rewards.\n * 0 if the action is executed directly by the user, without any middle-man\n **/\n function deposit(\n address asset,\n uint256 amount,\n address onBehalfOf,\n uint16 referralCode\n ) external;\n\n /**\n * @dev Withdraws an `amount` of underlying asset from the reserve, burning the equivalent aTokens owned\n * E.g. User has 100 aUSDC, calls withdraw() and receives 100 USDC, burning the 100 aUSDC\n * @param asset The address of the underlying asset to withdraw\n * @param amount The underlying amount to be withdrawn\n * - Send the value type(uint256).max in order to withdraw the whole aToken balance\n * @param to Address that will receive the underlying, same as msg.sender if the user\n * wants to receive it on his own wallet, or a different address if the beneficiary is a\n * different wallet\n * @return The final amount withdrawn\n **/\n function withdraw(\n address asset,\n uint256 amount,\n address to\n ) external returns (uint256);\n}\n\n/**\n * @title AaveSwapWrapper\n * @notice A wrapper contract for interacting with aTokens\n */\ncontract AaveSwapWrapper {\n using SafeERC20 for IERC20;\n using SafeMath for uint256;\n mapping(uint8 => bool) private isUnderlyingIndex;\n\n // constants\n uint8 private constant MAX_UINT8 = 2**8 - 1;\n uint256 private constant MAX_UINT256 = 2**256 - 1;\n\n // immutables\n Swap public immutable SWAP;\n LPToken public immutable LP_TOKEN;\n address public immutable OWNER;\n IERC20[] public POOLED_TOKENS;\n IERC20[] public UNDERLYING_TOKENS;\n ILendingPool public LENDING_POOL;\n\n constructor(\n Swap swap,\n IERC20[] memory underlyingTokens,\n address lendingPool,\n address owner\n ) public {\n (, , , , , , LPToken lpToken) = swap.swapStorage();\n for (uint8 i = 0; i < MAX_UINT8; i++) {\n try swap.getToken(i) returns (IERC20 token) {\n POOLED_TOKENS.push(token);\n // Approve pooled tokens to be used by Swap\n token.approve(address(swap), MAX_UINT256);\n } catch {\n break;\n }\n }\n\n for (uint8 i = 0; i < POOLED_TOKENS.length; i++) {\n if (POOLED_TOKENS[i] == underlyingTokens[i]) {\n isUnderlyingIndex[i] = true;\n } else {\n isUnderlyingIndex[i] = false;\n underlyingTokens[i].approve(lendingPool, MAX_UINT256);\n }\n }\n\n // Set immutable variables\n SWAP = swap;\n LP_TOKEN = lpToken;\n OWNER = owner;\n UNDERLYING_TOKENS = underlyingTokens;\n LENDING_POOL = ILendingPool(lendingPool);\n\n // Approve LPToken to be used by Swap\n lpToken.approve(address(swap), MAX_UINT256);\n }\n\n /**\n * @notice Add liquidity to the pool with the given amounts of tokens.\n * @param amounts the amounts of each token to add, in their native precision\n * @param minToMint the minimum LP tokens adding this amount of liquidity\n * should mint, otherwise revert. Handy for front-running mitigation\n * @param deadline latest timestamp to accept this transaction\n * @return amount of LP token user minted and received\n */\n function addLiquidity(\n uint256[] memory amounts,\n uint256 minToMint,\n uint256 deadline\n ) external returns (uint256) {\n // Go through amounts array and transfer respective tokens to this contract.\n for (uint8 i = 0; i < amounts.length; i++) {\n uint256 amount = amounts[i];\n if (amount > 0) {\n UNDERLYING_TOKENS[i].safeTransferFrom(\n msg.sender,\n address(this),\n amount\n );\n if (isUnderlyingIndex[i] == false) {\n LENDING_POOL.deposit(\n address(UNDERLYING_TOKENS[i]),\n amount,\n address(this),\n 0\n );\n }\n }\n }\n\n // Add the assets to the pool\n uint256 lpTokenAmount = SWAP.addLiquidity(amounts, minToMint, deadline);\n // Send the LPToken to msg.sender\n IERC20(address(LP_TOKEN)).safeTransfer(msg.sender, lpTokenAmount);\n return lpTokenAmount;\n }\n\n /**\n * @notice Burn LP tokens to remove liquidity from the pool.\n * @dev Liquidity can always be removed, even when the pool is paused. Caller\n * will receive ETH instead of WETH9.\n * @param amount the amount of LP tokens to burn\n * @param minAmounts the minimum amounts of each token in the pool\n * acceptable for this burn. Useful as a front-running mitigation\n * @param deadline latest timestamp to accept this transaction\n * @return amounts of tokens user received\n */\n function removeLiquidity(\n uint256 amount,\n uint256[] calldata minAmounts,\n uint256 deadline\n ) external returns (uint256[] memory) {\n // Transfer LPToken from msg.sender to this contract.\n IERC20(address(LP_TOKEN)).safeTransferFrom(\n msg.sender,\n address(this),\n amount\n );\n // Remove liquidity\n uint256[] memory amounts = SWAP.removeLiquidity(\n amount,\n minAmounts,\n deadline\n );\n // Send the tokens back to the user\n for (uint8 i = 0; i < amounts.length; i++) {\n if (isUnderlyingIndex[i] == true) {\n UNDERLYING_TOKENS[i].safeTransfer(msg.sender, amounts[i]);\n } else {\n LENDING_POOL.withdraw(\n address(UNDERLYING_TOKENS[i]),\n amounts[i],\n msg.sender\n );\n // underlyingTokens[i].safeTransfer(msg.sender, amounts[i]);\n }\n }\n return amounts;\n }\n\n /**\n * @notice Remove liquidity from the pool all in one token.\n * @dev Caller will receive ETH instead of WETH9.\n * @param tokenAmount the amount of the token you want to receive\n * @param tokenIndex the index of the token you want to receive\n * @param minAmount the minimum amount to withdraw, otherwise revert\n * @param deadline latest timestamp to accept this transaction\n * @return amount of chosen token user received\n */\n function removeLiquidityOneToken(\n uint256 tokenAmount,\n uint8 tokenIndex,\n uint256 minAmount,\n uint256 deadline\n ) external returns (uint256) {\n // Transfer LPToken from msg.sender to this contract.\n IERC20(address(LP_TOKEN)).safeTransferFrom(\n msg.sender,\n address(this),\n tokenAmount\n );\n // Withdraw via single token\n uint256 amount = SWAP.removeLiquidityOneToken(\n tokenAmount,\n tokenIndex,\n minAmount,\n deadline\n );\n // Transfer the token to msg.sender accordingly\n if (isUnderlyingIndex[tokenIndex] == true) {\n UNDERLYING_TOKENS[tokenIndex].safeTransfer(msg.sender, amount);\n } else {\n LENDING_POOL.withdraw(\n address(UNDERLYING_TOKENS[tokenIndex]),\n amount,\n msg.sender\n );\n }\n return amount;\n }\n\n /**\n * @notice Swap two tokens using the underlying pool. If tokenIndexFrom\n * represents WETH9 in the pool, the caller must set msg.value equal to dx.\n * If the user is swapping to WETH9 in the pool, the user will receive ETH instead.\n * @param tokenIndexFrom the token the user wants to swap from\n * @param tokenIndexTo the token the user wants to swap to\n * @param dx the amount of tokens the user wants to swap from\n * @param minDy the min amount the user would like to receive, or revert.\n * @param deadline latest timestamp to accept this transaction\n */\n function swap(\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx,\n uint256 minDy,\n uint256 deadline\n ) external returns (uint256) {\n // Transfer tokens from msg.sender to this contract\n UNDERLYING_TOKENS[tokenIndexFrom].safeTransferFrom(\n msg.sender,\n address(this),\n dx\n );\n if (isUnderlyingIndex[tokenIndexFrom] == false) {\n LENDING_POOL.deposit(\n address(UNDERLYING_TOKENS[tokenIndexFrom]),\n dx,\n address(this),\n 0\n );\n }\n // Execute swap\n uint256 dy = SWAP.swap(\n tokenIndexFrom,\n tokenIndexTo,\n dx,\n minDy,\n deadline\n );\n // Transfer the swapped tokens to msg.sender\n if (isUnderlyingIndex[tokenIndexTo] == false) {\n LENDING_POOL.withdraw(\n address(UNDERLYING_TOKENS[tokenIndexTo]),\n dy,\n msg.sender\n );\n } else {\n UNDERLYING_TOKENS[tokenIndexTo].safeTransfer(msg.sender, dy);\n }\n return dy;\n }\n\n /**\n * @notice Rescues any of the ETH, the pooled tokens, or the LPToken that may be stuck\n * in this contract. Only the OWNER can call this function.\n */\n function rescue() external {\n require(msg.sender == OWNER, \"CALLED_BY_NON_OWNER\");\n IERC20[] memory tokens = POOLED_TOKENS;\n for (uint256 i = 0; i < tokens.length; i++) {\n tokens[i].safeTransfer(\n msg.sender,\n tokens[i].balanceOf(address(this))\n );\n }\n\n for (uint256 i = 0; i < UNDERLYING_TOKENS.length; i++) {\n UNDERLYING_TOKENS[i].safeTransfer(\n msg.sender,\n UNDERLYING_TOKENS[i].balanceOf(address(this))\n );\n }\n\n IERC20 lpToken_ = IERC20(address(LP_TOKEN));\n lpToken_.safeTransfer(msg.sender, lpToken_.balanceOf(address(this)));\n }\n\n // VIEW FUNCTIONS\n\n /**\n * @notice Calculate amount of tokens you receive on swap\n * @param tokenIndexFrom the token the user wants to sell\n * @param tokenIndexTo the token the user wants to buy\n * @param dx the amount of tokens the user wants to sell. If the token charges\n * a fee on transfers, use the amount that gets transferred after the fee.\n * @return amount of tokens the user will receive\n */\n function calculateSwap(\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx\n ) external view virtual returns (uint256) {\n return SWAP.calculateSwap(tokenIndexFrom, tokenIndexTo, dx);\n }\n\n /**\n * @notice A simple method to calculate prices from deposits or\n * withdrawals, excluding fees but including slippage. This is\n * helpful as an input into the various \"min\" parameters on calls\n * to fight front-running\n *\n * @dev This shouldn't be used outside frontends for user estimates.\n *\n * @param amounts an array of token amounts to deposit or withdrawal,\n * corresponding to pooledTokens. The amount should be in each\n * pooled token's native precision. If a token charges a fee on transfers,\n * use the amount that gets transferred after the fee.\n * @param deposit whether this is a deposit or a withdrawal\n * @return token amount the user will receive\n */\n function calculateTokenAmount(uint256[] calldata amounts, bool deposit)\n external\n view\n returns (uint256)\n {\n return SWAP.calculateTokenAmount(amounts, deposit);\n }\n\n /**\n * @notice A simple method to calculate amount of each underlying\n * tokens that is returned upon burning given amount of LP tokens\n * @param amount the amount of LP tokens that would be burned on withdrawal\n * @return array of token balances that the user will receive\n */\n function calculateRemoveLiquidity(uint256 amount)\n external\n view\n returns (uint256[] memory)\n {\n return SWAP.calculateRemoveLiquidity(amount);\n }\n\n /**\n * @notice Calculate the amount of underlying token available to withdraw\n * when withdrawing via only single token\n * @param tokenAmount the amount of LP token to burn\n * @param tokenIndex index of which token will be withdrawn\n * @return availableTokenAmount calculated amount of underlying token\n * available to withdraw\n */\n function calculateRemoveLiquidityOneToken(\n uint256 tokenAmount,\n uint8 tokenIndex\n ) external view returns (uint256 availableTokenAmount) {\n return SWAP.calculateRemoveLiquidityOneToken(tokenAmount, tokenIndex);\n }\n\n /**\n * @notice Return address of the pooled token at given index. Reverts if tokenIndex is out of range.\n * @param index the index of the token\n * @return address of the token at given index\n */\n function getToken(uint8 index) public view virtual returns (IERC20) {\n if (index < UNDERLYING_TOKENS.length) {\n return UNDERLYING_TOKENS[index];\n } else {\n revert();\n }\n }\n}\n" + }, + "contracts/bridge/ECDSAFactory.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.6.12;\n\nimport \"@openzeppelin/contracts/access/Ownable.sol\";\nimport \"@openzeppelin/contracts/proxy/Clones.sol\";\nimport \"./interfaces/IECDSANodeManagement.sol\";\n\ncontract ECDSAFactory is Ownable {\n event ECDSANodeGroupCreated(\n address indexed keepAddress,\n address[] members,\n address indexed owner,\n uint256 honestThreshold\n );\n\n struct LatestNodeGroup {\n address keepAddress;\n address[] members;\n address owner;\n uint256 honestThreshold;\n }\n\n LatestNodeGroup public latestNodeGroup;\n\n constructor() public Ownable() {}\n\n /// @notice Returns members of the keep.\n /// @return List of the keep members' addresses.\n function getMembers() public view returns (address[] memory) {\n return latestNodeGroup.members;\n }\n\n /**\n @notice Deploys a new node \n @param nodeMgmtAddress address of the ECDSANodeManagement contract to initialize with\n @param owner Owner of the ECDSANodeManagement contract who can determine if the node group is closed or active\n @param members Array of node group members addresses\n @param honestThreshold Number of signers to process a transaction \n @return Address of the newest node management contract created\n **/\n function deploy(\n address nodeMgmtAddress,\n address owner,\n address[] memory members,\n uint256 honestThreshold\n ) external onlyOwner returns (address) {\n address nodeClone = Clones.clone(nodeMgmtAddress);\n IECDSANodeManagement(nodeClone).initialize(\n owner,\n members,\n honestThreshold\n );\n\n latestNodeGroup.keepAddress = nodeClone;\n latestNodeGroup.members = members;\n latestNodeGroup.owner = owner;\n latestNodeGroup.honestThreshold = honestThreshold;\n\n emit ECDSANodeGroupCreated(nodeClone, members, owner, honestThreshold);\n return nodeClone;\n }\n}\n" + }, + "contracts/bridge/interfaces/IECDSANodeManagement.sol": { + "content": "// SPDX-License-Identifier: MIT\n\n\npragma solidity 0.6.12;\n\n/**\n * @title IECDSANodeManagement interface\n * @notice Interface for the ECDSA node management interface.\n * @dev implement this interface to develop a a factory-patterned ECDSA node management contract\n **/\ninterface IECDSANodeManagement { \n function initialize(\n address _owner,\n address[] memory _members,\n uint256 _honestThreshold) external;\n}\n\n" + }, + "contracts/auxiliary/DummyWeth.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.6.12;\nimport \"@openzeppelin/contracts/access/Ownable.sol\";\n\ninterface IWETH9 {\n function name() external view returns (string memory);\n\n function symbol() external view returns (string memory);\n\n function decimals() external view returns (uint8);\n\n function balanceOf(address) external view returns (uint256);\n\n function allowance(address, address) external view returns (uint256);\n\n receive() external payable;\n\n function deposit() external payable;\n\n function withdraw(uint256 wad) external;\n\n function totalSupply() external view returns (uint256);\n\n function approve(address guy, uint256 wad) external returns (bool);\n\n function transfer(address dst, uint256 wad) external returns (bool);\n\n function transferFrom(\n address src,\n address dst,\n uint256 wad\n ) external returns (bool);\n}\n\ncontract DummyWeth is Ownable {\n IWETH9 public WETH;\n\n function setWETHAddress(address payable _weth) external onlyOwner {\n WETH = IWETH9(_weth);\n }\n\n function withdrawToSelf(uint256 amount) external {\n WETH.withdraw(amount);\n }\n\n function rescue(uint256 amount) external onlyOwner {\n WETH.transfer(owner(), amount);\n }\n\n receive() external payable {}\n\n fallback() external payable {}\n}\n" + } + }, + "settings": { + "optimizer": { + "enabled": true, + "runs": 10000 + }, + "outputSelection": { + "*": { + "*": [ + "abi", + "evm.bytecode", + "evm.deployedBytecode", + "evm.methodIdentifiers", + "metadata", + "devdoc", + "userdoc", + "storageLayout", + "evm.gasEstimates", + "devdoc", + "userdoc" + ], + "": [ + "ast" + ] + } + }, + "metadata": { + "useLiteralContent": true + } + } +} \ No newline at end of file diff --git a/docs/bridge/wrappers/AvaxJewelMigration.md b/docs/bridge/wrappers/AvaxJewelMigration.md new file mode 100644 index 000000000..4e01cc6dd --- /dev/null +++ b/docs/bridge/wrappers/AvaxJewelMigration.md @@ -0,0 +1,124 @@ +# AvaxJewelMigration + + + + + + + + + +## Methods + +### migrate + +```solidity +function migrate(uint256 amount) external nonpayable +``` + + + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| amount | uint256 | undefined | + +### migrateAndBridge + +```solidity +function migrateAndBridge(uint256 amount, address to, uint256 chainId) external nonpayable +``` + + + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| amount | uint256 | undefined | +| to | address | undefined | +| chainId | uint256 | undefined | + +### owner + +```solidity +function owner() external view returns (address) +``` + + + +*Returns the address of the current owner.* + + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | address | undefined | + +### redeemLegacy + +```solidity +function redeemLegacy() external nonpayable +``` + + + + + + +### renounceOwnership + +```solidity +function renounceOwnership() external nonpayable +``` + + + +*Leaves the contract without owner. It will not be possible to call `onlyOwner` functions anymore. Can only be called by the current owner. NOTE: Renouncing ownership will leave the contract without an owner, thereby removing any functionality that is only available to the owner.* + + +### transferOwnership + +```solidity +function transferOwnership(address newOwner) external nonpayable +``` + + + +*Transfers ownership of the contract to a new account (`newOwner`). Can only be called by the current owner.* + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| newOwner | address | undefined | + + + +## Events + +### OwnershipTransferred + +```solidity +event OwnershipTransferred(address indexed previousOwner, address indexed newOwner) +``` + + + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| previousOwner `indexed` | address | undefined | +| newOwner `indexed` | address | undefined | + + + diff --git a/docs/bridge/wrappers/AvaxJewelMigrationV2.md b/docs/bridge/wrappers/AvaxJewelMigrationV2.md new file mode 100644 index 000000000..05843a458 --- /dev/null +++ b/docs/bridge/wrappers/AvaxJewelMigrationV2.md @@ -0,0 +1,175 @@ +# AvaxJewelMigrationV2 + + + + + + + + + +## Methods + +### LEGACY_TOKEN + +```solidity +function LEGACY_TOKEN() external view returns (contract IERC20) +``` + + + + + + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | contract IERC20 | undefined | + +### NEW_TOKEN + +```solidity +function NEW_TOKEN() external view returns (contract IERC20Mintable) +``` + + + + + + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | contract IERC20Mintable | undefined | + +### SYNAPSE_BRIDGE + +```solidity +function SYNAPSE_BRIDGE() external view returns (contract ISynapseBridge) +``` + + + + + + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | contract ISynapseBridge | undefined | + +### migrate + +```solidity +function migrate(uint256 amount) external nonpayable +``` + + + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| amount | uint256 | undefined | + +### migrateAndBridge + +```solidity +function migrateAndBridge(uint256 amount, address to, uint256 chainId) external nonpayable +``` + + + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| amount | uint256 | undefined | +| to | address | undefined | +| chainId | uint256 | undefined | + +### owner + +```solidity +function owner() external view returns (address) +``` + + + +*Returns the address of the current owner.* + + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | address | undefined | + +### redeemLegacy + +```solidity +function redeemLegacy() external nonpayable +``` + + + + + + +### renounceOwnership + +```solidity +function renounceOwnership() external nonpayable +``` + + + +*Leaves the contract without owner. It will not be possible to call `onlyOwner` functions anymore. Can only be called by the current owner. NOTE: Renouncing ownership will leave the contract without an owner, thereby removing any functionality that is only available to the owner.* + + +### transferOwnership + +```solidity +function transferOwnership(address newOwner) external nonpayable +``` + + + +*Transfers ownership of the contract to a new account (`newOwner`). Can only be called by the current owner.* + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| newOwner | address | undefined | + + + +## Events + +### OwnershipTransferred + +```solidity +event OwnershipTransferred(address indexed previousOwner, address indexed newOwner) +``` + + + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| previousOwner `indexed` | address | undefined | +| newOwner `indexed` | address | undefined | + + + diff --git a/docs/bridge/wrappers/AvaxJewelSwap.md b/docs/bridge/wrappers/AvaxJewelSwap.md new file mode 100644 index 000000000..bdf78a4a9 --- /dev/null +++ b/docs/bridge/wrappers/AvaxJewelSwap.md @@ -0,0 +1,65 @@ +# AvaxJewelSwap + + + + + + + + + +## Methods + +### calculateSwap + +```solidity +function calculateSwap(uint8 tokenIndexFrom, uint8 tokenIndexTo, uint256 dx) external view returns (uint256) +``` + + + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| tokenIndexFrom | uint8 | undefined | +| tokenIndexTo | uint8 | undefined | +| dx | uint256 | undefined | + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | uint256 | undefined | + +### swap + +```solidity +function swap(uint8 tokenIndexFrom, uint8 tokenIndexTo, uint256 dx, uint256 minDy, uint256 deadline) external nonpayable returns (uint256) +``` + + + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| tokenIndexFrom | uint8 | undefined | +| tokenIndexTo | uint8 | undefined | +| dx | uint256 | undefined | +| minDy | uint256 | undefined | +| deadline | uint256 | undefined | + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | uint256 | undefined | + + + + diff --git a/docs/bridge/wrappers/IERC20Mintable.md b/docs/bridge/wrappers/IERC20Mintable.md new file mode 100644 index 000000000..40e9fa272 --- /dev/null +++ b/docs/bridge/wrappers/IERC20Mintable.md @@ -0,0 +1,203 @@ +# IERC20Mintable + + + + + + + + + +## Methods + +### allowance + +```solidity +function allowance(address owner, address spender) external view returns (uint256) +``` + + + +*Returns the remaining number of tokens that `spender` will be allowed to spend on behalf of `owner` through {transferFrom}. This is zero by default. This value changes when {approve} or {transferFrom} are called.* + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| owner | address | undefined | +| spender | address | undefined | + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | uint256 | undefined | + +### approve + +```solidity +function approve(address spender, uint256 amount) external nonpayable returns (bool) +``` + + + +*Sets `amount` as the allowance of `spender` over the caller's tokens. Returns a boolean value indicating whether the operation succeeded. IMPORTANT: Beware that changing an allowance with this method brings the risk that someone may use both the old and the new allowance by unfortunate transaction ordering. One possible solution to mitigate this race condition is to first reduce the spender's allowance to 0 and set the desired value afterwards: https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729 Emits an {Approval} event.* + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| spender | address | undefined | +| amount | uint256 | undefined | + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | bool | undefined | + +### balanceOf + +```solidity +function balanceOf(address account) external view returns (uint256) +``` + + + +*Returns the amount of tokens owned by `account`.* + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| account | address | undefined | + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | uint256 | undefined | + +### mint + +```solidity +function mint(address to, uint256 amount) external nonpayable +``` + + + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| to | address | undefined | +| amount | uint256 | undefined | + +### totalSupply + +```solidity +function totalSupply() external view returns (uint256) +``` + + + +*Returns the amount of tokens in existence.* + + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | uint256 | undefined | + +### transfer + +```solidity +function transfer(address recipient, uint256 amount) external nonpayable returns (bool) +``` + + + +*Moves `amount` tokens from the caller's account to `recipient`. Returns a boolean value indicating whether the operation succeeded. Emits a {Transfer} event.* + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| recipient | address | undefined | +| amount | uint256 | undefined | + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | bool | undefined | + +### transferFrom + +```solidity +function transferFrom(address sender, address recipient, uint256 amount) external nonpayable returns (bool) +``` + + + +*Moves `amount` tokens from `sender` to `recipient` using the allowance mechanism. `amount` is then deducted from the caller's allowance. Returns a boolean value indicating whether the operation succeeded. Emits a {Transfer} event.* + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| sender | address | undefined | +| recipient | address | undefined | +| amount | uint256 | undefined | + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | bool | undefined | + + + +## Events + +### Approval + +```solidity +event Approval(address indexed owner, address indexed spender, uint256 value) +``` + + + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| owner `indexed` | address | undefined | +| spender `indexed` | address | undefined | +| value | uint256 | undefined | + +### Transfer + +```solidity +event Transfer(address indexed from, address indexed to, uint256 value) +``` + + + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| from `indexed` | address | undefined | +| to `indexed` | address | undefined | +| value | uint256 | undefined | + + + diff --git a/docs/bridge/wrappers/L1BridgeZap.md b/docs/bridge/wrappers/L1BridgeZap.md index a4066af8a..a28cd5105 100644 --- a/docs/bridge/wrappers/L1BridgeZap.md +++ b/docs/bridge/wrappers/L1BridgeZap.md @@ -196,6 +196,51 @@ Wraps SynapseBridge redeem() function | token | contract IERC20 | ERC20 compatible token to redeem into the bridge | | amount | uint256 | Amount in native token decimals to transfer cross-chain pre-fees* | +### redeemAndRemove + +```solidity +function redeemAndRemove(address to, uint256 chainId, contract IERC20 token, uint256 amount, uint8 liqTokenIndex, uint256 liqMinAmount, uint256 liqDeadline) external nonpayable +``` + +Wraps redeemAndRemove on SynapseBridge Relays to nodes that (typically) a wrapped synAsset ERC20 token has been burned and the underlying needs to be redeeemed on the native chain. This function indicates to the nodes that they should attempt to redeem the LP token for the underlying assets (E.g "swap" out of the LP token) + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| to | address | address on other chain to redeem underlying assets to | +| chainId | uint256 | which underlying chain to bridge assets onto | +| token | contract IERC20 | ERC20 compatible token to deposit into the bridge | +| amount | uint256 | Amount of (typically) LP token to pass to the nodes to attempt to removeLiquidity() with to redeem for the underlying assets of the LP token | +| liqTokenIndex | uint8 | Specifies which of the underlying LP assets the nodes should attempt to redeem for | +| liqMinAmount | uint256 | Specifies the minimum amount of the underlying asset needed for the nodes to execute the redeem/swap | +| liqDeadline | uint256 | Specificies the deadline that the nodes are allowed to try to redeem/swap the LP token* | + +### redeemAndSwap + +```solidity +function redeemAndSwap(address to, uint256 chainId, contract IERC20 token, uint256 amount, uint8 tokenIndexFrom, uint8 tokenIndexTo, uint256 minDy, uint256 deadline) external nonpayable +``` + +Wraps redeemAndSwap on SynapseBridge.sol Relays to nodes that (typically) a wrapped synAsset ERC20 token has been burned and the underlying needs to be redeeemed on the native chain. This function indicates to the nodes that they should attempt to redeem the LP token for the underlying assets (E.g "swap" out of the LP token) + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| to | address | address on other chain to redeem underlying assets to | +| chainId | uint256 | which underlying chain to bridge assets onto | +| token | contract IERC20 | ERC20 compatible token to deposit into the bridge | +| amount | uint256 | Amount in native token decimals to transfer cross-chain pre-fees | +| tokenIndexFrom | uint8 | the token the user wants to swap from | +| tokenIndexTo | uint8 | the token the user wants to swap to | +| minDy | uint256 | the min amount the user would like to receive, or revert to only minting the SynERC20 token crosschain. | +| deadline | uint256 | latest timestamp to accept this transaction* | + ### redeemv2 ```solidity diff --git a/docs/bridge/wrappers/L2BridgeZap.md b/docs/bridge/wrappers/L2BridgeZap.md index 6df9a67de..429896270 100644 --- a/docs/bridge/wrappers/L2BridgeZap.md +++ b/docs/bridge/wrappers/L2BridgeZap.md @@ -89,6 +89,28 @@ Wraps SynapseBridge deposit() function to make it compatible w/ ETH -> WETH c | chainId | uint256 | which chain to bridge assets onto | | amount | uint256 | Amount in native token decimals to transfer cross-chain pre-fees* | +### depositETHAndSwap + +```solidity +function depositETHAndSwap(address to, uint256 chainId, uint256 amount, uint8 tokenIndexFrom, uint8 tokenIndexTo, uint256 minDy, uint256 deadline) external payable +``` + +Wraps SynapseBridge depositAndSwap() function to make it compatible w/ ETH -> WETH conversions + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| to | address | address on other chain to bridge assets to | +| chainId | uint256 | which chain to bridge assets onto | +| amount | uint256 | Amount in native token decimals to transfer cross-chain pre-fees | +| tokenIndexFrom | uint8 | the token the user wants to swap from | +| tokenIndexTo | uint8 | the token the user wants to swap to | +| minDy | uint256 | the min amount the user would like to receive, or revert to only minting the SynERC20 token crosschain. | +| deadline | uint256 | latest timestamp to accept this transaction* | + ### redeem ```solidity diff --git a/hardhat.config.ts b/hardhat.config.ts index f873b5af9..467c3c426 100644 --- a/hardhat.config.ts +++ b/hardhat.config.ts @@ -61,10 +61,10 @@ let config: HardhatUserConfig = { }, avalanche: { url: "https://api.avax.network/ext/bc/C/rpc", - // gasPrice: 750 * 1000000000, + gasPrice: 200 * 1000000000, }, harmony: { - url: "https://harmony-0-rpc.gateway.pokt.network/", + url: "https://a.api.s0.t.hmny.io/", }, boba: { url: "https://mainnet.boba.network", @@ -82,6 +82,9 @@ let config: HardhatUserConfig = { metis: { url: 'https://andromeda.metis.io/?owner=1088', }, + dfk: { + url: 'https://subnets.avax.network/defi-kingdoms/dfk-chain/rpc', + }, mainnet: { url: process.env.ALCHEMY_API || "https://main-light.eth.linkpool.io/", }, @@ -150,6 +153,7 @@ let config: HardhatUserConfig = { default: 0, // here this will by default take the first account as deployer 1: 0, // similarly on mainnet it will take the first account as deployer. Note though that depending on how hardhat network are configured, the account 0 on one network can be different than on another 42161: 0, + 53935: 3 }, libraryDeployer: { default: 0, // use a different account for deploying libraries on the hardhat network @@ -189,7 +193,8 @@ if (process.env.PRIVATE_KEYS) { "optimism", "aurora", "cronos", - "metis" + "metis", + "dfk" ] Object.keys(config.networks).forEach((network) => { if (PROD_NETWORKS.includes(network)) { diff --git a/test/bridge/BridgeConfigV3.ts b/test/bridge/BridgeConfigV3.ts index fbf3f23b5..92d0565ce 100644 --- a/test/bridge/BridgeConfigV3.ts +++ b/test/bridge/BridgeConfigV3.ts @@ -56,10 +56,12 @@ describe("Bridge Config V3", () => { it("should set max gas price for multiple chains", async () => { const mainnetGasPrice = BigNumber.from(10 ** 9) - expect(bridgeConfigV3.setMaxGasPrice(CHAIN_ID.BSC, bscGasPrice)).to.be.not - .reverted - expect(bridgeConfigV3.setMaxGasPrice(CHAIN_ID.MAINNET, mainnetGasPrice)) - .to.be.not.reverted + await expect(bridgeConfigV3.setMaxGasPrice(CHAIN_ID.BSC, bscGasPrice)).to + .be.not.reverted + + await expect( + bridgeConfigV3.setMaxGasPrice(CHAIN_ID.MAINNET, mainnetGasPrice), + ).to.be.not.reverted expect(await bridgeConfigV3.getMaxGasPrice(CHAIN_ID.BSC)).to.be.eq( bscGasPrice, @@ -362,7 +364,7 @@ describe("Bridge Config V3", () => { testToken.minSwapFee = BigNumber.from("1000000000000000000") testToken.maxSwapFee = BigNumber.from("10000000000000000000") - expect( + await expect( bridgeConfigV3[ "setTokenConfig(string,uint256,string,uint8,uint256,uint256,uint256,uint256,uint256,bool,bool)" ]( diff --git a/test/bridge/wrappers/AvaxJewelMigration.ts b/test/bridge/wrappers/AvaxJewelMigration.ts new file mode 100644 index 000000000..0c341869c --- /dev/null +++ b/test/bridge/wrappers/AvaxJewelMigration.ts @@ -0,0 +1,257 @@ +import { Signer } from "ethers" +import { impersonateAccount, asyncForEach, MAX_UINT256 } from "../../utils" +import { solidity } from "ethereum-waffle" +import { ethers, network } from "hardhat" + +import chai from "chai" +import { getBigNumber } from "../utilities" +import { + ERC20, + SynapseERC20, + AvaxJewelMigrationV2, + SynapseBridge, +} from "../../../build/typechain" + +chai.use(solidity) +const { expect } = chai + +describe("Avax Jewel Migration", async function () { + let signers: Array + + let owner: Signer + let ownerAddress: string + let dude: Signer + let dudeAddress: string + + let multiJewel: ERC20 + let synJewel: SynapseERC20 + + let migrator: AvaxJewelMigrationV2 + + let adminSigner: Signer + + let bridge: SynapseBridge + + const AMOUNT = getBigNumber(100) + + const MULTI_JEWEL = "0x4f60a160D8C2DDdaAfe16FCC57566dB84D674BD6" + const SYN_JEWEL = "0x997Ddaa07d716995DE90577C123Db411584E5E46" + const BRIDGE = "0xC05e61d0E7a63D27546389B7aD62FdFf5A91aACE" + + const FAT_CAT = "0x9aa76ae9f804e7a70ba3fb8395d0042079238e9c" + + const DFK_CHAIN_ID = 53935 + const HARMONY_ID = 1666600000 + + before(async function () { + // 2022-03-26 + await network.provider.request({ + method: "hardhat_reset", + params: [ + { + forking: { + jsonRpcUrl: process.env.AVAX_API, + blockNumber: 12600000, + }, + }, + ], + }) + + multiJewel = (await ethers.getContractAt("ERC20", MULTI_JEWEL)) as ERC20 + synJewel = (await ethers.getContractAt( + "SynapseERC20", + SYN_JEWEL, + )) as SynapseERC20 + bridge = (await ethers.getContractAt( + "SynapseBridge", + BRIDGE, + )) as SynapseBridge + }) + + beforeEach(async function () { + signers = await ethers.getSigners() + owner = signers[0] + ownerAddress = await owner.getAddress() + dude = signers[1] + dudeAddress = await dude.getAddress() + + let migratorFactory = await ethers.getContractFactory("AvaxJewelMigrationV2") + migrator = (await migratorFactory.deploy()) as AvaxJewelMigrationV2 + + let fatCat = await impersonateAccount(FAT_CAT) + + let adminRole = await synJewel.DEFAULT_ADMIN_ROLE() + let minterRole = await synJewel.MINTER_ROLE() + let admin = await synJewel.getRoleMember(adminRole, 0) + adminSigner = await impersonateAccount(admin) + + await asyncForEach([FAT_CAT, admin], async (address) => { + await network.provider.send("hardhat_setBalance", [ + address, + "0xFFFFFFFFFFFFFFFFFFFF", + ]) + }) + + // It's time the fat cats had a heart attack + await multiJewel.connect(fatCat).transfer(ownerAddress, AMOUNT) + await multiJewel.connect(fatCat).transfer(dudeAddress, AMOUNT) + await synJewel.connect(adminSigner).grantRole(minterRole, migrator.address) + }) + + describe("Sanity checks", function () { + it("Migration contract is deployed correctly", async function () { + expect(await migrator.LEGACY_TOKEN()).to.eq(MULTI_JEWEL) + expect(await migrator.NEW_TOKEN()).to.eq(SYN_JEWEL) + expect(await migrator.SYNAPSE_BRIDGE()).to.eq(BRIDGE) + }) + + it("Migration reverts when minting rights are revoked", async function () { + let minterRole = await synJewel.MINTER_ROLE() + await synJewel + .connect(adminSigner) + .revokeRole(minterRole, migrator.address) + + let ownerBalance = await multiJewel.balanceOf(ownerAddress) + await multiJewel.approve(migrator.address, ownerBalance) + let ownerAmount = getBigNumber(42) + await expect(migrator.migrate(ownerAmount)).to.be.reverted + }) + + it("Migrating zero tokens reverts", async function () { + let ownerBalance = await multiJewel.balanceOf(ownerAddress) + await multiJewel.approve(migrator.address, ownerBalance) + await expect(migrator.migrate(0)).to.be.reverted + }) + + it("Only owner can withdraw legacy tokens", async function () { + let ownerBalance = await multiJewel.balanceOf(ownerAddress) + let dudeBalance = await multiJewel.balanceOf(dudeAddress) + let ownerAmount = getBigNumber(42) + let dudeAmount = getBigNumber(13) + + await multiJewel.approve(migrator.address, ownerBalance) + await multiJewel.connect(dude).approve(migrator.address, dudeBalance) + + await migrator.migrate(ownerAmount) + await migrator + .connect(dude) + .migrateAndBridge(dudeAmount, dudeAddress, DFK_CHAIN_ID) + + await expect(migrator.connect(dude).redeemLegacy()).to.be.reverted + + await expect(() => migrator.redeemLegacy()).to.changeTokenBalance( + multiJewel, + owner, + ownerAmount.add(dudeAmount), + ) + }) + }) + + describe("Migration", function () { + it("Single-chain migration", async function () { + let ownerBalance = await multiJewel.balanceOf(ownerAddress) + let dudeBalance = await multiJewel.balanceOf(dudeAddress) + let ownerAmount = getBigNumber(42) + let dudeAmount = getBigNumber(13) + + await multiJewel.approve(migrator.address, ownerBalance) + await multiJewel.connect(dude).approve(migrator.address, dudeBalance) + + await expect(() => migrator.migrate(ownerAmount)).to.changeTokenBalance( + synJewel, + owner, + ownerAmount, + ) + expect(await multiJewel.balanceOf(ownerAddress)).to.eq( + ownerBalance.sub(ownerAmount), + ) + + await expect(() => + migrator.connect(dude).migrate(dudeAmount), + ).to.changeTokenBalance(synJewel, dude, dudeAmount) + expect(await multiJewel.balanceOf(dudeAddress)).to.eq( + dudeBalance.sub(dudeAmount), + ) + }) + + it("Cross-chain migration to DFK (Bridge event emitted)", async function () { + let ownerBalance = await multiJewel.balanceOf(ownerAddress) + let dudeBalance = await multiJewel.balanceOf(dudeAddress) + let ownerAmount = getBigNumber(42) + let dudeAmount = getBigNumber(13) + + await multiJewel.approve(migrator.address, ownerBalance) + await multiJewel.connect(dude).approve(migrator.address, dudeBalance) + + await expect( + migrator.migrateAndBridge(ownerAmount, ownerAddress, DFK_CHAIN_ID), + ) + .to.emit(bridge, "TokenRedeem") + .withArgs(ownerAddress, DFK_CHAIN_ID, synJewel.address, ownerAmount) + + expect(await multiJewel.balanceOf(ownerAddress)).to.eq( + ownerBalance.sub(ownerAmount), + ) + + await expect( + migrator + .connect(dude) + .migrateAndBridge(dudeAmount, dudeAddress, DFK_CHAIN_ID), + ) + .to.emit(bridge, "TokenRedeem") + .withArgs(dudeAddress, DFK_CHAIN_ID, synJewel.address, dudeAmount) + expect(await multiJewel.balanceOf(dudeAddress)).to.eq( + dudeBalance.sub(dudeAmount), + ) + }) + + it("Cross-chain migration to Harmony (Bridge event emitted)", async function () { + let ownerBalance = await multiJewel.balanceOf(ownerAddress) + let dudeBalance = await multiJewel.balanceOf(dudeAddress) + let ownerAmount = getBigNumber(42) + let dudeAmount = getBigNumber(13) + + await multiJewel.approve(migrator.address, ownerBalance) + await multiJewel.connect(dude).approve(migrator.address, dudeBalance) + + await expect( + migrator.migrateAndBridge(ownerAmount, ownerAddress, HARMONY_ID), + ) + .to.emit(bridge, "TokenRedeemAndSwap") + .withArgs( + ownerAddress, + HARMONY_ID, + synJewel.address, + ownerAmount, + 1, + 0, + 0, + MAX_UINT256, + ) + + expect(await multiJewel.balanceOf(ownerAddress)).to.eq( + ownerBalance.sub(ownerAmount), + ) + + await expect( + migrator + .connect(dude) + .migrateAndBridge(dudeAmount, dudeAddress, HARMONY_ID), + ) + .to.emit(bridge, "TokenRedeemAndSwap") + .withArgs( + dudeAddress, + HARMONY_ID, + synJewel.address, + dudeAmount, + 1, + 0, + 0, + MAX_UINT256, + ) + expect(await multiJewel.balanceOf(dudeAddress)).to.eq( + dudeBalance.sub(dudeAmount), + ) + }) + }) +}) diff --git a/test/bridge/wrappers/AvaxJewelSwap.ts b/test/bridge/wrappers/AvaxJewelSwap.ts new file mode 100644 index 000000000..cde0567f5 --- /dev/null +++ b/test/bridge/wrappers/AvaxJewelSwap.ts @@ -0,0 +1,129 @@ +import { Signer } from "ethers" +import { impersonateAccount, MAX_UINT256 } from "../../utils" +import { solidity } from "ethereum-waffle" +import { ethers, network, web3 } from "hardhat" + +import chai from "chai" +import { getBigNumber } from "../utilities" +import { + SynapseERC20, + AvaxJewelSwap, + SynapseBridge, +} from "../../../build/typechain" + +chai.use(solidity) +const { expect } = chai + +describe("Avax Jewel Migration", async function () { + let signers: Array + + let owner: Signer + let ownerAddress: string + let dude: Signer + let dudeAddress: string + + let synJewel: SynapseERC20 + + let swap: AvaxJewelSwap + + let validatorSigner: Signer + + let bridge: SynapseBridge + + const AMOUNT = getBigNumber(420) + const FEE = getBigNumber(69) + + const SYN_JEWEL = "0x997Ddaa07d716995DE90577C123Db411584E5E46" + + const BRIDGE = "0xC05e61d0E7a63D27546389B7aD62FdFf5A91aACE" + + const VALIDATOR = "0x230A1AC45690B9Ae1176389434610B9526d2f21b" + + const DFK_CHAIN_ID = 53935 + + before(async function () { + // 2022-03-26 + await network.provider.request({ + method: "hardhat_reset", + params: [ + { + forking: { + jsonRpcUrl: process.env.AVAX_API, + blockNumber: 12600000, + }, + }, + ], + }) + + synJewel = (await ethers.getContractAt( + "SynapseERC20", + SYN_JEWEL, + )) as SynapseERC20 + bridge = (await ethers.getContractAt( + "SynapseBridge", + BRIDGE, + )) as SynapseBridge + }) + + beforeEach(async function () { + signers = await ethers.getSigners() + owner = signers[0] + ownerAddress = await owner.getAddress() + dude = signers[1] + dudeAddress = await dude.getAddress() + + let swapFactory = await ethers.getContractFactory("AvaxJewelSwap") + swap = (await swapFactory.deploy()) as AvaxJewelSwap + + validatorSigner = await impersonateAccount(VALIDATOR) + + await network.provider.send("hardhat_setBalance", [ + VALIDATOR, + "0xFFFFFFFFFFFFFFFFFFFF", + ]) + }) + + it("Swap reverts", async function () { + await expect(swap.swap(0, 1, 1, 0, MAX_UINT256)).to.be.revertedWith( + "There is no swap", + ) + }) + + it("Bridging completes with minDy > 0", async function () { + await expect(() => + bridge + .connect(validatorSigner) + .mintAndSwap( + dudeAddress, + SYN_JEWEL, + AMOUNT, + FEE, + swap.address, + 1, + 0, + 420, + 0, + web3.utils.keccak256("I am unique"), + ), + ).to.changeTokenBalance(synJewel, dude, AMOUNT.sub(FEE)) + }) + + it("Bridging completes with minDy = 0", async function () { + await expect(() => + bridge + .connect(validatorSigner) + .mintAndSwap( + dudeAddress, + SYN_JEWEL, + AMOUNT, + FEE, + swap.address, + 1, + 0, + 0, + 0, + web3.utils.keccak256("I am also unique"), + ), + ).to.changeTokenBalance(synJewel, dude, AMOUNT.sub(FEE)) + }) +}) diff --git a/utils/network.ts b/utils/network.ts index 0f97bf250..2f69b46aa 100644 --- a/utils/network.ts +++ b/utils/network.ts @@ -13,6 +13,7 @@ export const CHAIN_ID = { HARDHAT: "31337", AVALANCHE: "43114", ARBITRUM: "42161", + DFK: "53935", AURORA: "1313161554", HARMONY: "1666600000", } From 0137b784b05e4fa1fbca6efa793dc2f991363e87 Mon Sep 17 00:00:00 2001 From: ChiTimesChi <88190723+ChiTimesChi@users.noreply.github.com> Date: Sat, 23 Apr 2022 18:09:43 +0300 Subject: [PATCH 062/135] frax wrapper --- contracts/bridge/interfaces/IFrax.sol | 33 +++++ contracts/bridge/wrappers/FraxWrapper.sol | 146 ++++++++++++++++++++++ 2 files changed, 179 insertions(+) create mode 100644 contracts/bridge/interfaces/IFrax.sol create mode 100644 contracts/bridge/wrappers/FraxWrapper.sol diff --git a/contracts/bridge/interfaces/IFrax.sol b/contracts/bridge/interfaces/IFrax.sol new file mode 100644 index 000000000..f9b877cb2 --- /dev/null +++ b/contracts/bridge/interfaces/IFrax.sol @@ -0,0 +1,33 @@ +// SPDX-License-Identifier: MIT +pragma solidity >=0.6.12; + +interface IFrax { + // -- VIEWS -- + + function canSwap(address bridgeTokenAddress) external view returns (bool); + + function exchangesPaused() external view returns (bool); + + // solhint-disable-next-line + function fee_exempt_list(address swapper) external view returns (bool); + + // solhint-disable-next-line + function swap_fees(address bridgeTokenAddress, uint256 direction) + external + view + returns (uint256); + + // solhint-disable-next-line + function mint_cap() external view returns (uint256); + + // -- SWAP -- + function exchangeCanonicalForOld( + address bridgeTokenAddress, + uint256 tokenAmount + ) external returns (uint256 amountOut); + + function exchangeOldForCanonical( + address bridgeTokenAddress, + uint256 tokenAmount + ) external returns (uint256 amountOut); +} diff --git a/contracts/bridge/wrappers/FraxWrapper.sol b/contracts/bridge/wrappers/FraxWrapper.sol new file mode 100644 index 000000000..67e1a0f94 --- /dev/null +++ b/contracts/bridge/wrappers/FraxWrapper.sol @@ -0,0 +1,146 @@ +// SPDX-License-Identifier: MIT + +pragma solidity 0.8.11; + +import {IFrax} from "../interfaces/IFrax.sol"; + +import {IERC20} from "@openzeppelin/contracts-4.3.1/token/ERC20/IERC20.sol"; +import {SafeERC20} from "@openzeppelin/contracts-4.3.1/token/ERC20/utils/SafeERC20.sol"; + +contract FraxWrapper { + using SafeERC20 for IERC20; + + // tokens[0]: + address public immutable synFrax; + + // tokens[1]: + address public immutable frax; + + // Constant for FRAX price precision + uint256 private constant PRICE_PRECISION = 1e6; + + constructor(address _frax, address _synFrax) { + frax = _frax; + synFrax = _synFrax; + + // Approve FRAX contract to spend our precious synFRAX + IERC20(synFrax).safeApprove(_frax, type(uint256).max); + + // Chad (FRAX) doesn't need our approval to spend FRAX + } + + /** + * @notice Return address of the pooled token at given index. Reverts if tokenIndex is out of range. + * @param index the index of the token + * @return address of the token at given index + */ + function getToken(uint8 index) external view returns (IERC20) { + require(index < 2, "Out of range"); + return IERC20(index == 0 ? synFrax : frax); + } + + /** + * @notice Return the index of the given token address. Reverts if no matching + * token is found. + * @param tokenAddress address of the token + * @return index index of the given token address + */ + function getTokenIndex(address tokenAddress) + external + view + returns (uint8 index) + { + if (tokenAddress == synFrax) { + index = 0; + } else if (tokenAddress == synFrax) { + index = 1; + } else { + revert("Token does not exist"); + } + } + + /** + * @notice Calculate amount of tokens you receive on swap + * @param tokenIndexFrom the token the user wants to sell + * @param tokenIndexTo the token the user wants to buy + * @param dx the amount of tokens the user wants to swap. + * @return amount amount of tokens the user will receive + */ + function calculateSwap( + uint8 tokenIndexFrom, + uint8 tokenIndexTo, + uint256 dx + ) external view returns (uint256 amount) { + if (tokenIndexFrom == 0 && tokenIndexTo == 1) { + // synFRAX -> FRAX + amount = dx; + if (!IFrax(frax).fee_exempt_list(address(this))) { + amount -= + (amount * IFrax(frax).swap_fees(synFrax, 0)) / + PRICE_PRECISION; + } + uint256 _newTotalSupply = IERC20(frax).totalSupply() + amount; + if (IFrax(frax).mint_cap() < _newTotalSupply) { + // Can't mint more FRAX than mint cap specifies, swap will fail + amount = 0; + } + } else if (tokenIndexFrom == 1 && tokenIndexTo == 0) { + // FRAX -> synFRAX + amount = dx; + if (!IFrax(frax).fee_exempt_list(address(this))) { + amount -= + (amount * IFrax(frax).swap_fees(synFrax, 1)) / + PRICE_PRECISION; + } + if (IERC20(synFrax).balanceOf(frax) < amount) { + // if FRAX contract doesn't have enough synFRAX, swap will fail + amount = 0; + } + } else { + // Unsupported direction + amount = 0; + } + } + + /** + * @notice Swap two tokens using this pool + * @param tokenIndexFrom the token the user wants to swap from + * @param tokenIndexTo the token the user wants to swap to + * @param dx the amount of tokens the user wants to swap from + * @param minDy the min amount the user would like to receive, or revert. + * @param deadline latest timestamp to accept this transaction + */ + function swap( + uint8 tokenIndexFrom, + uint8 tokenIndexTo, + uint256 dx, + uint256 minDy, + uint256 deadline + ) external returns (uint256 amount) { + // solhint-disable-next-line + require(block.timestamp <= deadline, "Deadline not met"); + + IERC20 swappedToken; + + if (tokenIndexFrom == 0 && tokenIndexTo == 1) { + // synFRAX -> FRAX + // First, pull tokens from user + IERC20(synFrax).safeTransferFrom(msg.sender, address(this), dx); + // Then, swap using FRAX logic + amount = IFrax(frax).exchangeOldForCanonical(synFrax, dx); + swappedToken = IERC20(frax); + } else if (tokenIndexFrom == 1 && tokenIndexTo == 0) { + // FRAX -> synFRAX + // First, pull tokens from user + IERC20(frax).safeTransferFrom(msg.sender, address(this), dx); + // Then, swap using FRAX logic + amount = IFrax(frax).exchangeCanonicalForOld(synFrax, dx); + swappedToken = IERC20(synFrax); + } else { + revert("Unsupported direction"); + } + + require(amount >= minDy, "Insufficient output"); + swappedToken.safeTransfer(msg.sender, amount); + } +} From d52909bfc5dca89be3c1b84fb5c721e910ba097d Mon Sep 17 00:00:00 2001 From: ChiTimesChi <88190723+ChiTimesChi@users.noreply.github.com> Date: Sat, 23 Apr 2022 18:12:43 +0300 Subject: [PATCH 063/135] lint L2BridgeZap --- contracts/bridge/wrappers/L2BridgeZap.sol | 162 +++++++++++----------- deploy/007_L2BridgeZap.ts | 11 +- 2 files changed, 83 insertions(+), 90 deletions(-) diff --git a/contracts/bridge/wrappers/L2BridgeZap.sol b/contracts/bridge/wrappers/L2BridgeZap.sol index 7523eb1f6..212504eaa 100644 --- a/contracts/bridge/wrappers/L2BridgeZap.sol +++ b/contracts/bridge/wrappers/L2BridgeZap.sol @@ -10,13 +10,14 @@ import "../interfaces/IWETH9.sol"; contract L2BridgeZap { using SafeERC20 for IERC20; - ISynapseBridge synapseBridge; + ISynapseBridge public immutable synapseBridge; + // solhint-disable-next-line address payable public immutable WETH_ADDRESS; mapping(address => address) public swapMap; mapping(address => IERC20[]) public swapTokensMap; - uint256 constant MAX_UINT256 = 2**256 - 1; + uint256 private constant MAX_UINT256 = 2**256 - 1; constructor( address payable _wethAddress, @@ -31,18 +32,19 @@ contract L2BridgeZap { swapMap[tokenOne] = _swapOne; swapMap[tokenTwo] = _swapTwo; if (_wethAddress != address(0)) { - IERC20(_wethAddress).safeIncreaseAllowance(address(_synapseBridge), MAX_UINT256); + IERC20(_wethAddress).safeIncreaseAllowance( + address(_synapseBridge), + MAX_UINT256 + ); } if (address(_swapOne) != address(0)) { { uint8 i; for (; i < 32; i++) { - try ISwap(_swapOne).getToken(i) returns ( - IERC20 token - ) { + try ISwap(_swapOne).getToken(i) returns (IERC20 token) { swapTokensMap[_swapOne].push(token); token.safeApprove(address(_swapOne), MAX_UINT256); - token.safeApprove(address(synapseBridge), MAX_UINT256); + token.safeApprove(address(_synapseBridge), MAX_UINT256); } catch { break; } @@ -54,12 +56,10 @@ contract L2BridgeZap { { uint8 i; for (; i < 32; i++) { - try ISwap(_swapTwo).getToken(i) returns ( - IERC20 token - ) { + try ISwap(_swapTwo).getToken(i) returns (IERC20 token) { swapTokensMap[_swapTwo].push(token); token.safeApprove(address(_swapTwo), MAX_UINT256); - token.safeApprove(address(synapseBridge), MAX_UINT256); + token.safeApprove(address(_synapseBridge), MAX_UINT256); } catch { break; } @@ -83,9 +83,7 @@ contract L2BridgeZap { uint8 tokenIndexTo, uint256 dx ) external view virtual returns (uint256) { - ISwap swap = ISwap( - swapMap[address(token)] - ); + ISwap swap = ISwap(swapMap[address(token)]); return swap.calculateSwap(tokenIndexFrom, tokenIndexTo, dx); } @@ -102,11 +100,7 @@ contract L2BridgeZap { ISwap swap = ISwap(swapMap[address(token)]); require(address(swap) != address(0), "Swap is 0x00"); IERC20[] memory tokens = swapTokensMap[address(swap)]; - tokens[tokenIndexFrom].safeTransferFrom( - msg.sender, - address(this), - dx - ); + tokens[tokenIndexFrom].safeTransferFrom(msg.sender, address(this), dx); // swap uint256 swappedAmount = swap.swap( @@ -140,21 +134,18 @@ contract L2BridgeZap { uint256 swapMinDy, uint256 swapDeadline ) external { - require( - address(swapMap[address(token)]) != address(0), - "Swap is 0x00" - ); - IERC20[] memory tokens = swapTokensMap[ - swapMap[address(token)] - ]; - tokens[tokenIndexFrom].safeTransferFrom( - msg.sender, - address(this), - dx - ); + require(address(swapMap[address(token)]) != address(0), "Swap is 0x00"); + IERC20[] memory tokens = swapTokensMap[swapMap[address(token)]]; + tokens[tokenIndexFrom].safeTransferFrom(msg.sender, address(this), dx); // swap - uint256 swappedAmount = ISwap(swapMap[address(token)]).swap(tokenIndexFrom, tokenIndexTo, dx, minDy, deadline); + uint256 swappedAmount = ISwap(swapMap[address(token)]).swap( + tokenIndexFrom, + tokenIndexTo, + dx, + minDy, + deadline + ); // deposit into bridge, gets nUSD if ( token.allowance(address(this), address(synapseBridge)) < @@ -190,11 +181,7 @@ contract L2BridgeZap { ISwap swap = ISwap(swapMap[address(token)]); require(address(swap) != address(0), "Swap is 0x00"); IERC20[] memory tokens = swapTokensMap[address(swap)]; - tokens[tokenIndexFrom].safeTransferFrom( - msg.sender, - address(this), - dx - ); + tokens[tokenIndexFrom].safeTransferFrom(msg.sender, address(this), dx); // swap uint256 swappedAmount = swap.swap( @@ -263,47 +250,54 @@ contract L2BridgeZap { } /** - * @notice Wraps SynapseBridge deposit() function to make it compatible w/ ETH -> WETH conversions - * @param to address on other chain to bridge assets to - * @param chainId which chain to bridge assets onto - * @param amount Amount in native token decimals to transfer cross-chain pre-fees - **/ - function depositETH( - address to, - uint256 chainId, - uint256 amount + * @notice Wraps SynapseBridge deposit() function to make it compatible w/ ETH -> WETH conversions + * @param to address on other chain to bridge assets to + * @param chainId which chain to bridge assets onto + * @param amount Amount in native token decimals to transfer cross-chain pre-fees + **/ + function depositETH( + address to, + uint256 chainId, + uint256 amount ) external payable { - require(msg.value > 0 && msg.value == amount, 'INCORRECT MSG VALUE'); - IWETH9(WETH_ADDRESS).deposit{value: msg.value}(); - synapseBridge.deposit(to, chainId, IERC20(WETH_ADDRESS), amount); + require(msg.value > 0 && msg.value == amount, "INCORRECT MSG VALUE"); + IWETH9(WETH_ADDRESS).deposit{value: msg.value}(); + synapseBridge.deposit(to, chainId, IERC20(WETH_ADDRESS), amount); } - - /** - * @notice Wraps SynapseBridge depositAndSwap() function to make it compatible w/ ETH -> WETH conversions - * @param to address on other chain to bridge assets to - * @param chainId which chain to bridge assets onto - * @param amount Amount in native token decimals to transfer cross-chain pre-fees - * @param tokenIndexFrom the token the user wants to swap from - * @param tokenIndexTo the token the user wants to swap to - * @param minDy the min amount the user would like to receive, or revert to only minting the SynERC20 token crosschain. - * @param deadline latest timestamp to accept this transaction - **/ - function depositETHAndSwap( - address to, - uint256 chainId, - uint256 amount, - uint8 tokenIndexFrom, - uint8 tokenIndexTo, - uint256 minDy, - uint256 deadline + /** + * @notice Wraps SynapseBridge depositAndSwap() function to make it compatible w/ ETH -> WETH conversions + * @param to address on other chain to bridge assets to + * @param chainId which chain to bridge assets onto + * @param amount Amount in native token decimals to transfer cross-chain pre-fees + * @param tokenIndexFrom the token the user wants to swap from + * @param tokenIndexTo the token the user wants to swap to + * @param minDy the min amount the user would like to receive, or revert to only minting the SynERC20 token crosschain. + * @param deadline latest timestamp to accept this transaction + **/ + function depositETHAndSwap( + address to, + uint256 chainId, + uint256 amount, + uint8 tokenIndexFrom, + uint8 tokenIndexTo, + uint256 minDy, + uint256 deadline ) external payable { - require(msg.value > 0 && msg.value == amount, 'INCORRECT MSG VALUE'); - IWETH9(WETH_ADDRESS).deposit{value: msg.value}(); - synapseBridge.depositAndSwap(to, chainId, IERC20(WETH_ADDRESS), amount, tokenIndexFrom, tokenIndexTo, minDy, deadline); + require(msg.value > 0 && msg.value == amount, "INCORRECT MSG VALUE"); + IWETH9(WETH_ADDRESS).deposit{value: msg.value}(); + synapseBridge.depositAndSwap( + to, + chainId, + IERC20(WETH_ADDRESS), + amount, + tokenIndexFrom, + tokenIndexTo, + minDy, + deadline + ); } - function swapETHAndRedeem( address to, uint256 chainId, @@ -331,7 +325,6 @@ contract L2BridgeZap { synapseBridge.redeem(to, chainId, token, swappedAmount); } - function swapETHAndRedeemAndSwap( address to, uint256 chainId, @@ -360,13 +353,18 @@ contract L2BridgeZap { minDy, deadline ); - synapseBridge.redeemAndSwap(to, chainId, token, swappedAmount,swapTokenIndexFrom, + synapseBridge.redeemAndSwap( + to, + chainId, + token, + swappedAmount, + swapTokenIndexFrom, swapTokenIndexTo, swapMinDy, - swapDeadline); + swapDeadline + ); } - /** * @notice Wraps redeemAndSwap on SynapseBridge.sol * Relays to nodes that (typically) a wrapped synAsset ERC20 token has been burned and the underlying needs to be redeeemed on the native chain. This function indicates to the nodes that they should attempt to redeem the LP token for the underlying assets (E.g "swap" out of the LP token) @@ -441,12 +439,12 @@ contract L2BridgeZap { } /** - * @notice Wraps SynapseBridge redeemv2() function - * @param to address on other chain to bridge assets to - * @param chainId which chain to bridge assets onto - * @param token ERC20 compatible token to redeem into the bridge - * @param amount Amount in native token decimals to transfer cross-chain pre-fees - **/ + * @notice Wraps SynapseBridge redeemv2() function + * @param to address on other chain to bridge assets to + * @param chainId which chain to bridge assets onto + * @param token ERC20 compatible token to redeem into the bridge + * @param amount Amount in native token decimals to transfer cross-chain pre-fees + **/ function redeemv2( bytes32 to, uint256 chainId, diff --git a/deploy/007_L2BridgeZap.ts b/deploy/007_L2BridgeZap.ts index 0b9249856..bf1c236bf 100644 --- a/deploy/007_L2BridgeZap.ts +++ b/deploy/007_L2BridgeZap.ts @@ -1,6 +1,6 @@ import { HardhatRuntimeEnvironment } from "hardhat/types" import { DeployFunction } from "hardhat-deploy/types" -import {CHAIN_ID} from "../utils/network"; +import { CHAIN_ID } from "../utils/network" const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) { const { deployments, getNamedAccounts, getChainId } = hre @@ -119,7 +119,6 @@ const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) { }) } - if ((await getChainId()) === CHAIN_ID.CRONOS) { await deploy("L2BridgeZap", { from: deployer, @@ -136,8 +135,6 @@ const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) { }) } - - if ((await getChainId()) === CHAIN_ID.MOONRIVER) { await deploy("L2BridgeZap", { contract: "MoonriverBridgeZap", @@ -171,7 +168,6 @@ const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) { }) } - if ((await getChainId()) === CHAIN_ID.OPTIMISM) { await deploy("L2BridgeZap", { from: deployer, @@ -189,10 +185,9 @@ const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) { }) } - if ((await getChainId()) === CHAIN_ID.HARMONY) { await deploy("L2BridgeZap", { - contract: 'HarmonyBridgeZap', + contract: "HarmonyBridgeZap", from: deployer, log: true, skipIfAlreadyDeployed: true, @@ -224,7 +219,7 @@ const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) { (await get("nUSD")).address, (await get("SynapseBridge")).address, ], - gasLimit: 5000000 + gasLimit: 5000000, }) } From 9eb4f8b7d2c28a5d341b0f5bad1e0996f3bc3e0a Mon Sep 17 00:00:00 2001 From: ChiTimesChi <88190723+ChiTimesChi@users.noreply.github.com> Date: Sat, 23 Apr 2022 18:18:25 +0300 Subject: [PATCH 064/135] Allow L2BridgeZap to have any amount of pools --- contracts/bridge/wrappers/L2BridgeZap.sol | 56 ++++++++++------------- 1 file changed, 23 insertions(+), 33 deletions(-) diff --git a/contracts/bridge/wrappers/L2BridgeZap.sol b/contracts/bridge/wrappers/L2BridgeZap.sol index 212504eaa..40b439e97 100644 --- a/contracts/bridge/wrappers/L2BridgeZap.sol +++ b/contracts/bridge/wrappers/L2BridgeZap.sol @@ -21,52 +21,42 @@ contract L2BridgeZap { constructor( address payable _wethAddress, - address _swapOne, - address tokenOne, - address _swapTwo, - address tokenTwo, + address[] memory _swaps, + address[] memory _tokens, ISynapseBridge _synapseBridge ) public { + require(_swaps.length == _tokens.length, "Arrays length differs"); WETH_ADDRESS = _wethAddress; synapseBridge = _synapseBridge; - swapMap[tokenOne] = _swapOne; - swapMap[tokenTwo] = _swapTwo; if (_wethAddress != address(0)) { IERC20(_wethAddress).safeIncreaseAllowance( address(_synapseBridge), MAX_UINT256 ); } - if (address(_swapOne) != address(0)) { - { - uint8 i; - for (; i < 32; i++) { - try ISwap(_swapOne).getToken(i) returns (IERC20 token) { - swapTokensMap[_swapOne].push(token); - token.safeApprove(address(_swapOne), MAX_UINT256); - token.safeApprove(address(_synapseBridge), MAX_UINT256); - } catch { - break; - } - } - require(i > 1, "swap must have at least 2 tokens"); - } + for (uint256 i = 0; i < _swaps.length; ++i) { + _saveSwap(_swaps[i], _tokens[i], address(_synapseBridge)); } - if (address(_swapTwo) != address(0)) { - { - uint8 i; - for (; i < 32; i++) { - try ISwap(_swapTwo).getToken(i) returns (IERC20 token) { - swapTokensMap[_swapTwo].push(token); - token.safeApprove(address(_swapTwo), MAX_UINT256); - token.safeApprove(address(_synapseBridge), MAX_UINT256); - } catch { - break; - } - } - require(i > 1, "swap must have at least 2 tokens"); + } + + function _saveSwap( + address _swap, + address _token, + address _synapseBridge + ) internal { + swapMap[_token] = _swap; + + uint8 i; + for (; i < 32; i++) { + try ISwap(_swap).getToken(i) returns (IERC20 token) { + swapTokensMap[_swap].push(token); + token.safeApprove(address(_swap), MAX_UINT256); + token.safeApprove(_synapseBridge, MAX_UINT256); + } catch { + break; } } + require(i > 1, "swap must have at least 2 tokens"); } /** From 83a737b01d6826de6103a0b52551c5df9679a9d2 Mon Sep 17 00:00:00 2001 From: ChiTimesChi <88190723+ChiTimesChi@users.noreply.github.com> Date: Sat, 23 Apr 2022 18:48:47 +0300 Subject: [PATCH 065/135] deploy script for FraxWrapper, new L2Zaps --- deploy/006_deploy_FraxWrapper.ts | 25 +++++++ deploy/007_L2BridgeZap.ts | 115 ++++++++++++++----------------- 2 files changed, 77 insertions(+), 63 deletions(-) create mode 100644 deploy/006_deploy_FraxWrapper.ts diff --git a/deploy/006_deploy_FraxWrapper.ts b/deploy/006_deploy_FraxWrapper.ts new file mode 100644 index 000000000..0f9da3f3e --- /dev/null +++ b/deploy/006_deploy_FraxWrapper.ts @@ -0,0 +1,25 @@ +import { HardhatRuntimeEnvironment } from "hardhat/types" +import { DeployFunction } from "hardhat-deploy/types" +import { CHAIN_ID } from "../utils/network" + +const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) { + const { deployments, getNamedAccounts, getChainId } = hre + const { deploy, get } = deployments + const { deployer } = await getNamedAccounts() + + if ( + [CHAIN_ID.FANTOM, CHAIN_ID.HARMONY, CHAIN_ID.MOONRIVER].includes( + await getChainId(), + ) + ) { + const deployResult = await deploy("FraxWrapper", { + from: deployer, + log: true, + skipIfAlreadyDeployed: true, + args: [(await get("FRAX")).address, (await get("synFRAX")).address], + }) + } +} + +export default func +func.tags = ["FraxWrapper"] diff --git a/deploy/007_L2BridgeZap.ts b/deploy/007_L2BridgeZap.ts index bf1c236bf..40ffa7fe5 100644 --- a/deploy/007_L2BridgeZap.ts +++ b/deploy/007_L2BridgeZap.ts @@ -13,10 +13,8 @@ const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) { skipIfAlreadyDeployed: true, args: [ "0x0000000000000000000000000000000000000000", - (await get("nUSDPoolV2")).address, - (await get("nUSD")).address, - "0x0000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000", + [(await get("nUSDPoolV2")).address], + [(await get("nUSD")).address], (await get("SynapseBridge")).address, ], }) @@ -29,10 +27,8 @@ const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) { skipIfAlreadyDeployed: true, args: [ "0x0000000000000000000000000000000000000000", - (await get("nUSDPoolV2")).address, - (await get("nUSD")).address, - "0x0000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000", + [(await get("nUSDPoolV2")).address], + [(await get("nUSD")).address], (await get("SynapseBridge")).address, ], }) @@ -45,10 +41,8 @@ const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) { skipIfAlreadyDeployed: true, args: [ "0x0000000000000000000000000000000000000000", - (await get("nUSDPoolV2")).address, - (await get("nUSD")).address, - "0x0000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000", + [(await get("nUSDPoolV2")).address], + [(await get("nUSD")).address], (await get("SynapseBridge")).address, ], }) @@ -61,10 +55,16 @@ const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) { skipIfAlreadyDeployed: true, args: [ "0x0000000000000000000000000000000000000000", - (await get("nUSDPoolV3")).address, - (await get("nUSD")).address, - (await get("ETHPool")).address, - (await get("nETH")).address, + [ + (await get("nUSDPoolV3")).address, + (await get("ETHPool")).address, + (await get("FraxWrapper")).address, + ], + [ + (await get("nUSD")).address, + (await get("nETH")).address, + (await get("synFRAX")).address, + ], (await get("SynapseBridge")).address, ], }) @@ -77,10 +77,8 @@ const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) { skipIfAlreadyDeployed: true, args: [ "0x0000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000", + [], + [], (await get("SynapseBridge")).address, ], }) @@ -93,16 +91,13 @@ const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) { skipIfAlreadyDeployed: true, args: [ "0x0000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000", + [], + [], (await get("SynapseBridge")).address, ], }) } - if ((await getChainId()) === CHAIN_ID.METIS) { await deploy("L2BridgeZap", { from: deployer, @@ -110,10 +105,8 @@ const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) { skipIfAlreadyDeployed: true, args: [ "0x0000000000000000000000000000000000000000", - (await get("nUSDPoolV3")).address, - (await get("nUSD")).address, - (await get("ETHPool")).address, - (await get("nETH")).address, + [(await get("nUSDPoolV3")).address, (await get("ETHPool")).address], + [(await get("nUSD")).address, (await get("nETH")).address], (await get("SynapseBridge")).address, ], }) @@ -126,10 +119,8 @@ const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) { skipIfAlreadyDeployed: true, args: [ "0x0000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000", + [], + [], (await get("SynapseBridge")).address, ], }) @@ -137,16 +128,13 @@ const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) { if ((await getChainId()) === CHAIN_ID.MOONRIVER) { await deploy("L2BridgeZap", { - contract: "MoonriverBridgeZap", from: deployer, log: true, skipIfAlreadyDeployed: true, args: [ (await get("WMOVR")).address, - "0x0000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000", + [(await get("FraxWrapper")).address], + [(await get("synFRAX")).address], (await get("SynapseBridge")).address, ], }) @@ -159,10 +147,8 @@ const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) { skipIfAlreadyDeployed: true, args: [ (await get("WETH")).address, - (await get("ETHPool")).address, - (await get("nETH")).address, - (await get("nUSDPoolV2")).address, - (await get("nUSD")).address, + [(await get("nUSDPoolV2")).address, (await get("ETHPool")).address], + [(await get("nUSD")).address, (await get("nETH")).address], (await get("SynapseBridge")).address, ], }) @@ -175,10 +161,8 @@ const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) { skipIfAlreadyDeployed: true, args: [ (await get("WETH")).address, - (await get("ETHPool")).address, - (await get("nETH")).address, - (await get("nUSDPoolV3")).address, - (await get("nUSD")).address, + [(await get("nUSDPoolV3")).address, (await get("ETHPool")).address], + [(await get("nUSD")).address, (await get("nETH")).address], (await get("SynapseBridge")).address, ], gasLimit: 5000000, @@ -187,20 +171,25 @@ const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) { if ((await getChainId()) === CHAIN_ID.HARMONY) { await deploy("L2BridgeZap", { - contract: "HarmonyBridgeZap", from: deployer, log: true, skipIfAlreadyDeployed: true, args: [ "0x0000000000000000000000000000000000000000", - (await get("nUSDPoolV2")).address, - (await get("nUSD")).address, - (await get("ETHPool")).address, - (await get("nETH")).address, - (await get("JewelBridgeSwap")).address, - (await get("synJEWEL")).address, - (await get("BridgedAVAXPool")).address, - (await get("AVAX")).address, + [ + (await get("nUSDPoolV2")).address, + (await get("ETHPool")).address, + (await get("FraxWrapper")).address, + (await get("JewelBridgeSwap")).address, + (await get("BridgedAVAXPool")).address, + ], + [ + (await get("nUSD")).address, + (await get("nETH")).address, + (await get("synFRAX")).address, + (await get("synJEWEL")).address, + (await get("AVAX")).address, + ], (await get("SynapseBridge")).address, ], }) @@ -213,10 +202,12 @@ const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) { skipIfAlreadyDeployed: true, args: [ (await get("WAVAX")).address, - (await get("AaveSwapWrapper")).address, - (await get("nETH")).address, - (await get("nUSDPoolV2")).address, - (await get("nUSD")).address, + [ + (await get("nUSDPoolV2")).address, + (await get("AaveSwapWrapper")).address, + ], + [(await get("nUSD")).address, (await get("nETH")).address], + (await get("SynapseBridge")).address, ], gasLimit: 5000000, @@ -230,10 +221,8 @@ const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) { skipIfAlreadyDeployed: true, args: [ (await get("WETH")).address, - (await get("nETHPool")).address, - (await get("nETH")).address, - (await get("nUSDPoolV3")).address, - (await get("nUSD")).address, + [(await get("nUSDPoolV3")).address, (await get("nETHPool")).address], + [(await get("nUSD")).address, (await get("nETH")).address], (await get("SynapseBridge")).address, ], }) From 5a933888062ed8f21b102d6566b3b4a42e725897 Mon Sep 17 00:00:00 2001 From: ChiTimesChi <88190723+ChiTimesChi@users.noreply.github.com> Date: Sat, 23 Apr 2022 21:03:08 +0300 Subject: [PATCH 066/135] Frax wrapper tests --- test/bridge/wrappers/FraxWrapperMovr.t.sol | 240 +++++++++++++++++++++ 1 file changed, 240 insertions(+) create mode 100644 test/bridge/wrappers/FraxWrapperMovr.t.sol diff --git a/test/bridge/wrappers/FraxWrapperMovr.t.sol b/test/bridge/wrappers/FraxWrapperMovr.t.sol new file mode 100644 index 000000000..c6d3b8853 --- /dev/null +++ b/test/bridge/wrappers/FraxWrapperMovr.t.sol @@ -0,0 +1,240 @@ +// SPDX-License-Identifier: MIT +pragma solidity >=0.8.0; + +import "forge-std/Test.sol"; +import {FraxWrapper} from "contracts/bridge/wrappers/FraxWrapper.sol"; +import {IFrax} from "contracts/bridge/interfaces/IFrax.sol"; +import {IERC20} from "@openzeppelin/contracts-4.3.1/token/ERC20/IERC20.sol"; + +/** + * Usage: forge test --match-path "test/bridge/wrappers/*" --fork-url https://moonriver.api.onfinality.io/public --fork-block-number 1730000 + */ + +interface IL2BridgeZap { + function swapAndRedeem( + address to, + uint256 chainId, + IERC20 token, + uint8 tokenIndexFrom, + uint8 tokenIndexTo, + uint256 dx, + uint256 minDy, + uint256 deadline + ) external; + + function swapAndRedeemAndSwap( + address to, + uint256 chainId, + IERC20 token, + uint8 tokenIndexFrom, + uint8 tokenIndexTo, + uint256 dx, + uint256 minDy, + uint256 deadline, + uint8 swapTokenIndexFrom, + uint8 swapTokenIndexTo, + uint256 swapMinDy, + uint256 swapDeadline + ) external; +} + +interface IBridge { + function mintAndSwap( + address to, + address token, + uint256 amount, + uint256 fee, + address pool, + uint8 tokenIndexFrom, + uint8 tokenIndexTo, + uint256 minDy, + uint256 deadline, + bytes32 kappa + ) external; +} + +contract FraxMovrTest is Test { + uint256 private constant SWAP_FEE = 4; // in bps + uint256 private constant SWAP_DENOMINATOR = 10000; + + address private constant FRAX = 0x1A93B23281CC1CDE4C4741353F3064709A16197d; + address private constant SYN_FRAX = + 0xE96AC70907ffF3Efee79f502C985A7A21Bce407d; + + address private constant WMOVR = 0x98878B06940aE243284CA214f92Bb71a2b032B8A; + address private constant BRIDGE = + 0xaeD5b25BE1c3163c907a471082640450F928DDFE; + + address private constant NODE = 0x230A1AC45690B9Ae1176389434610B9526d2f21b; + + uint256 private constant TEST_AMOUNT = 10**20; + uint256 private constant UINT_MAX = type(uint256).max; + + FraxWrapper public immutable pool; + IL2BridgeZap public immutable zap; + + event TokenRedeem( + address indexed to, + uint256 chainId, + IERC20 token, + uint256 amount + ); + + constructor() { + pool = new FraxWrapper(FRAX, SYN_FRAX); + zap = IL2BridgeZap(_deployZap()); + + IERC20(FRAX).approve(address(pool), UINT_MAX); + IERC20(SYN_FRAX).approve(address(pool), UINT_MAX); + } + + function _deployZap() internal returns (address _zap) { + address[] memory swaps = new address[](1); + address[] memory tokens = new address[](1); + swaps[0] = address(pool); + tokens[0] = SYN_FRAX; + + _zap = deployCode( + "L2BridgeZap.sol", + abi.encode(WMOVR, swaps, tokens, BRIDGE) + ); + } + + function setUp() public { + deal(FRAX, address(this), TEST_AMOUNT); + deal(SYN_FRAX, address(this), TEST_AMOUNT); + } + + function testEdgeCases() public { + uint256 balance = IERC20(SYN_FRAX).balanceOf(FRAX); + uint256 tooMuch = _getAmountIn(balance); + + assertTrue( + pool.calculateSwap(1, 0, tooMuch) > 0, + "FRAX -> synFRAX (max amount) failed" + ); + assertEq( + pool.calculateSwap(1, 0, tooMuch + 1), + 0, + "FRAX -> synFRAX (max amount + 1) not failed" + ); + + uint256 remainingCap = IFrax(FRAX).mint_cap() - + IERC20(FRAX).totalSupply(); + tooMuch = _getAmountIn(remainingCap); + + assertTrue( + pool.calculateSwap(0, 1, tooMuch) > 0, + "synFRAX -> FRAX (max amount) failed" + ); + assertEq( + pool.calculateSwap(0, 1, tooMuch + 1), + 0, + "synFRAX -> FRAX (max amount + 1) not failed" + ); + } + + function testSwapFromFrax(uint256 amount) public { + vm.assume(amount <= TEST_AMOUNT); + + uint256 expected = amount - (amount * SWAP_FEE) / SWAP_DENOMINATOR; + uint256 quote = pool.calculateSwap(1, 0, amount); + assertEq(quote, expected, "Wrong quote"); + + uint256 pre = IERC20(SYN_FRAX).balanceOf(address(this)); + uint256 received = pool.swap(1, 0, amount, 0, UINT_MAX); + assertEq( + IERC20(SYN_FRAX).balanceOf(address(this)), + pre + received, + "Returned wrong amount" + ); + assertEq(received, quote, "Failed to give correct quote"); + } + + function testSwapFromSynFrax(uint256 amount) public { + vm.assume(amount <= TEST_AMOUNT); + + uint256 expected = amount - (amount * SWAP_FEE) / SWAP_DENOMINATOR; + uint256 quote = pool.calculateSwap(0, 1, amount); + assertEq(quote, expected, "Wrong quote"); + + uint256 pre = IERC20(FRAX).balanceOf(address(this)); + uint256 received = pool.swap(0, 1, amount, 0, UINT_MAX); + assertEq( + IERC20(FRAX).balanceOf(address(this)), + pre + received, + "Returned wrong amount" + ); + assertEq(received, quote, "Failed to give correct quote"); + } + + function testSwapAndRedeem(uint256 amountOut) public { + vm.assume(amountOut <= TEST_AMOUNT); + uint256 amount = _getAmountIn(amountOut); + vm.assume(amount > 0); + vm.assume(amount <= TEST_AMOUNT); + + console.log(address(zap)); + IERC20(FRAX).approve(address(zap), amount); + + vm.expectEmit(true, false, false, true); + emit TokenRedeem(address(this), 1, IERC20(SYN_FRAX), amountOut); + + zap.swapAndRedeem( + address(this), + 1, + IERC20(SYN_FRAX), + 1, + 0, + amount, + amountOut, + UINT_MAX + ); + } + + function testMintAndSwap(uint256 amount) public { + vm.assume(amount > 0); + vm.assume(amount <= TEST_AMOUNT); + uint256 amountOut = pool.calculateSwap(0, 1, amount); + vm.assume(amountOut > 0); + + vm.startPrank(NODE); + + uint256 pre = IERC20(FRAX).balanceOf(address(this)); + + bytes32 kappa = keccak256(bytes("much kappa very wow")); + IBridge(BRIDGE).mintAndSwap( + address(this), + SYN_FRAX, + amount, + 0, + address(pool), + 0, + 1, + amountOut, + UINT_MAX, + kappa + ); + vm.stopPrank(); + + assertTrue( + IERC20(FRAX).balanceOf(address(this)) > pre, + "No FRAX received" + ); + assertEq( + IERC20(FRAX).balanceOf(address(this)), + pre + amountOut, + "Wrong amount of FRAX received" + ); + } + + function _getAmountIn(uint256 amountOut) + internal + pure + returns (uint256 amountIn) + { + amountIn = + (amountOut * SWAP_DENOMINATOR) / + (SWAP_DENOMINATOR - SWAP_FEE); + } +} From 3c2818e42f1d0d2ee5c8be004144bd11b47613a4 Mon Sep 17 00:00:00 2001 From: ChiTimesChi <88190723+ChiTimesChi@users.noreply.github.com> Date: Sat, 23 Apr 2022 21:11:59 +0300 Subject: [PATCH 067/135] test cleanup --- test/bridge/wrappers/FraxWrapperMovr.t.sol | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/test/bridge/wrappers/FraxWrapperMovr.t.sol b/test/bridge/wrappers/FraxWrapperMovr.t.sol index c6d3b8853..89104165a 100644 --- a/test/bridge/wrappers/FraxWrapperMovr.t.sol +++ b/test/bridge/wrappers/FraxWrapperMovr.t.sol @@ -135,6 +135,7 @@ contract FraxMovrTest is Test { } function testSwapFromFrax(uint256 amount) public { + vm.assume(amount > 0); vm.assume(amount <= TEST_AMOUNT); uint256 expected = amount - (amount * SWAP_FEE) / SWAP_DENOMINATOR; @@ -152,6 +153,7 @@ contract FraxMovrTest is Test { } function testSwapFromSynFrax(uint256 amount) public { + vm.assume(amount > 0); vm.assume(amount <= TEST_AMOUNT); uint256 expected = amount - (amount * SWAP_FEE) / SWAP_DENOMINATOR; @@ -174,7 +176,6 @@ contract FraxMovrTest is Test { vm.assume(amount > 0); vm.assume(amount <= TEST_AMOUNT); - console.log(address(zap)); IERC20(FRAX).approve(address(zap), amount); vm.expectEmit(true, false, false, true); From 1cc88282adca6a254915af8a7d65eac01b3dae6d Mon Sep 17 00:00:00 2001 From: Trajan0x Date: Sat, 23 Apr 2022 17:13:09 -0400 Subject: [PATCH 068/135] foundry tests --- .github/workflows/coveralls.yaml | 3 --- .github/workflows/test.yaml | 34 ++++++++++++++++++++++++++++++-- 2 files changed, 32 insertions(+), 5 deletions(-) diff --git a/.github/workflows/coveralls.yaml b/.github/workflows/coveralls.yaml index 9ce2a2ead..7431fdfd6 100644 --- a/.github/workflows/coveralls.yaml +++ b/.github/workflows/coveralls.yaml @@ -42,9 +42,6 @@ jobs: - name: build run: npm run build -# - name: Setup tmate session -# uses: mxschmitt/action-tmate@v3 - - name: run test:coverage run: npm run test:coverage diff --git a/.github/workflows/test.yaml b/.github/workflows/test.yaml index 1ad2cc941..cede065cd 100644 --- a/.github/workflows/test.yaml +++ b/.github/workflows/test.yaml @@ -4,7 +4,7 @@ name: Test on: ["push", "pull_request"] jobs: - test: + hardhat-test: runs-on: ubuntu-latest env: AVAX_API: https://api.avax.network/ext/bc/C/rpc @@ -32,4 +32,34 @@ jobs: - name: Test run: | - npm run test \ No newline at end of file + npm run test + foundry-test: + runs-on: ubuntu-latest + steps: + - name: Cache node modules + uses: actions/cache@v2 + env: + cache-name: cache-node-modules + with: + # npm cache files are stored in `~/.npm` on Linux/macOS + path: ~/.npm + key: ${{ runner.os }}-build-${{ env.cache-name }}-${{ hashFiles('**/package-lock.json') }} + restore-keys: | + ${{ runner.os }}-build-${{ env.cache-name }}- + ${{ runner.os }}-build- + ${{ runner.os }}- + + - name: Installing dependencies + run: npm install + + - uses: actions/checkout@v3 + with: + submodules: recursive + + - name: Install Foundry + uses: foundry-rs/foundry-toolchain@v1 + with: + version: nightly + + - name: Run tests + run: forge test -vvv \ No newline at end of file From 76537081835eb3115d4ef68ddf0ef17656263012 Mon Sep 17 00:00:00 2001 From: Trajan0x Date: Sat, 23 Apr 2022 17:18:23 -0400 Subject: [PATCH 069/135] workflow fix --- .github/workflows/test.yaml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/test.yaml b/.github/workflows/test.yaml index cede065cd..7894e2b91 100644 --- a/.github/workflows/test.yaml +++ b/.github/workflows/test.yaml @@ -36,6 +36,10 @@ jobs: foundry-test: runs-on: ubuntu-latest steps: + - uses: actions/checkout@v3 + with: + submodules: recursive + - name: Cache node modules uses: actions/cache@v2 env: @@ -52,10 +56,6 @@ jobs: - name: Installing dependencies run: npm install - - uses: actions/checkout@v3 - with: - submodules: recursive - - name: Install Foundry uses: foundry-rs/foundry-toolchain@v1 with: From 11ddf7d8ce9585b28a6631a742b159e4c9cc1a73 Mon Sep 17 00:00:00 2001 From: Trajan0x Date: Sat, 23 Apr 2022 17:47:05 -0400 Subject: [PATCH 070/135] relint --- contracts/bridge/wrappers/L2BridgeZap.sol | 25 ----------------------- 1 file changed, 25 deletions(-) diff --git a/contracts/bridge/wrappers/L2BridgeZap.sol b/contracts/bridge/wrappers/L2BridgeZap.sol index 237c9f791..40b439e97 100644 --- a/contracts/bridge/wrappers/L2BridgeZap.sol +++ b/contracts/bridge/wrappers/L2BridgeZap.sol @@ -288,31 +288,6 @@ contract L2BridgeZap { ); } - /** - * @notice Wraps SynapseBridge depositAndSwap() function to make it compatible w/ ETH -> WETH conversions - * @param to address on other chain to bridge assets to - * @param chainId which chain to bridge assets onto - * @param amount Amount in native token decimals to transfer cross-chain pre-fees - * @param tokenIndexFrom the token the user wants to swap from - * @param tokenIndexTo the token the user wants to swap to - * @param minDy the min amount the user would like to receive, or revert to only minting the SynERC20 token crosschain. - * @param deadline latest timestamp to accept this transaction - **/ - function depositETHAndSwap( - address to, - uint256 chainId, - uint256 amount, - uint8 tokenIndexFrom, - uint8 tokenIndexTo, - uint256 minDy, - uint256 deadline - ) external payable { - require(msg.value > 0 && msg.value == amount, 'INCORRECT MSG VALUE'); - IWETH9(WETH_ADDRESS).deposit{value: msg.value}(); - synapseBridge.depositAndSwap(to, chainId, IERC20(WETH_ADDRESS), amount, tokenIndexFrom, tokenIndexTo, minDy, deadline); - } - - function swapETHAndRedeem( address to, uint256 chainId, From 608d7fcecb82975d2cb4f4ab6cd0e8a5b87e1bd6 Mon Sep 17 00:00:00 2001 From: Trajan0x Date: Sat, 23 Apr 2022 18:05:34 -0400 Subject: [PATCH 071/135] fix test --- test/bridge/SynapseBridgeETH.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/bridge/SynapseBridgeETH.ts b/test/bridge/SynapseBridgeETH.ts index 346e04c52..09f79201c 100644 --- a/test/bridge/SynapseBridgeETH.ts +++ b/test/bridge/SynapseBridgeETH.ts @@ -367,7 +367,7 @@ describe("SynapseBridgeETH", async () => { it("SetRateLimiter: should reject non-governance roles", async () => { await expect( bridge.connect(attacker).setRateLimiter(rateLimiter.address), - ).to.be.revertedWith("Not admin") + ).to.be.revertedWith("Not governance") }) it("AddKappas: should reject non-admin roles", async () => { From fe36e1952431c00082a709c2974363670fe86907 Mon Sep 17 00:00:00 2001 From: Trajan0x Date: Sat, 23 Apr 2022 18:13:04 -0400 Subject: [PATCH 072/135] run foundry tests --- .github/workflows/test.yaml | 2 +- scripts/foundry.sh | 4 +++ scripts/test-boba.js | 61 ------------------------------------- 3 files changed, 5 insertions(+), 62 deletions(-) create mode 100755 scripts/foundry.sh delete mode 100644 scripts/test-boba.js diff --git a/.github/workflows/test.yaml b/.github/workflows/test.yaml index 7894e2b91..ca644d360 100644 --- a/.github/workflows/test.yaml +++ b/.github/workflows/test.yaml @@ -62,4 +62,4 @@ jobs: version: nightly - name: Run tests - run: forge test -vvv \ No newline at end of file + run: ./scripts/foundry.sh \ No newline at end of file diff --git a/scripts/foundry.sh b/scripts/foundry.sh new file mode 100755 index 000000000..af1020168 --- /dev/null +++ b/scripts/foundry.sh @@ -0,0 +1,4 @@ +#!/usr/bin/env bash + +forge test --match-contract "FraxMovrTest" --fork-url https://moonriver.api.onfinality.io/public --fork-block-number 1730000 -vvvv +forge test --no-match-contract "FraxMovrTest" -vvvv \ No newline at end of file diff --git a/scripts/test-boba.js b/scripts/test-boba.js deleted file mode 100644 index a04d0fcd0..000000000 --- a/scripts/test-boba.js +++ /dev/null @@ -1,61 +0,0 @@ -// We require the Hardhat Runtime Environment explicitly here. This is optional -// but useful for running the script in a standalone fashion through `node